Files
shoot-miniprograms/src/pages/my-growth.vue
2025-07-06 12:36:20 +08:00

305 lines
8.1 KiB
Vue

<script setup>
import { onMounted } from "vue";
import Container from "@/components/Container.vue";
import Avatar from "@/components/Avatar.vue";
import BowData from "@/components/BowData.vue";
import ScrollList from "@/components/ScrollList.vue";
import { getBattleListAPI, getPractiseResultListAPI } from "@/apis";
import { meleeAvatarColors } from "@/constants";
import { ref } from "vue";
const selectedIndex = ref(0);
const matchList = ref([]);
const battleList = ref([]);
const practiseList = ref([]);
// const showBowData = ref(false);
// const arrows = ref([]);
const toMatchDetail = (id) => {
uni.navigateTo({
url: `/pages/match-detail?id=${id}`,
});
};
const getPractiseDetail = async (id) => {
uni.navigateTo({
url: `/pages/mine-bow-data?id=${id}`,
});
};
const onMatchLoading = async (page) => {
const result = await getBattleListAPI(page, 2);
if (page === 1) {
matchList.value = result;
} else {
matchList.value = matchList.value.concat(result);
}
return result.length;
};
const onBattleLoading = async (page) => {
const result = await getBattleListAPI(page, 1);
if (page === 1) {
battleList.value = result;
} else {
battleList.value = battleList.value.concat(result);
}
return result.length;
};
const onPractiseLoading = async (page) => {
const result = await getPractiseResultListAPI(page);
if (page === 1) {
practiseList.value = result;
} else {
practiseList.value = practiseList.value.concat(result);
}
return result.length;
};
</script>
<template>
<Container title="我的成长脚印" overflow="hidden">
<view class="tabs">
<view
v-for="(rankType, index) in ['排位赛', '好友约战', '射馆练习']"
:key="index"
:style="{
color: index === selectedIndex ? '#000' : '#fff',
backgroundColor: index === selectedIndex ? '#FFD947' : 'transparent',
}"
@tap="() => (selectedIndex = index)"
>
{{ rankType }}
</view>
</view>
<view class="contents">
<ScrollList :show="selectedIndex === 0" :onLoading="onMatchLoading">
<view
v-for="(item, index) in matchList"
:key="index"
@click="() => toMatchDetail(item.battleId)"
>
<view class="contest-header">
<text>{{ item.name }}</text>
<text>{{ item.createdAt }}</text>
<image src="../static/back.png" mode="widthFix" />
</view>
<view v-if="item.mode === 1" class="contest-team">
<block v-if="item.bluePlayers[0]">
<view class="player">
<Avatar frame :src="item.bluePlayers[0].avatar" />
<text>{{ item.bluePlayers[0].name }}</text>
<image
v-if="item.winner === 1"
src="../static/winner-badge.png"
mode="widthFix"
/>
</view>
</block>
<block v-if="item.redPlayers[0]">
<view class="player">
<Avatar frame :src="item.redPlayers[0].avatar" />
<text>{{ item.redPlayers[0].name }}</text>
<image
v-if="item.winner === 0"
src="../static/winner-badge.png"
mode="widthFix"
/>
</view>
</block>
</view>
<view v-if="item.mode === 2" class="contest-melee">
<view
class="player"
v-for="(p, index2) in item.players"
:key="index2"
:style="{
width: `${Math.max(100 / item.players.length, 18)}vw`,
backgroundColor: meleeAvatarColors[index2],
}"
>
<Avatar :rank="index2 + 1" :src="p.avatar" />
<text>{{ p.name }}</text>
</view>
</view>
</view>
</ScrollList>
<ScrollList :show="selectedIndex === 1" :onLoading="onBattleLoading">
<view
v-for="(item, index) in battleList"
:key="index"
@click="() => toMatchDetail(item.battleId)"
>
<view class="contest-header">
<text>{{ item.name }}</text>
<text>{{ item.createdAt }}</text>
<image src="../static/back.png" mode="widthFix" />
</view>
<view v-if="item.mode === 1" class="contest-team">
<block v-if="item.bluePlayers[0]">
<view class="player">
<Avatar frame :src="item.bluePlayers[0].avatar" />
<text>{{ item.bluePlayers[0].name }}</text>
<image
v-if="item.winner === 1"
src="../static/winner-badge.png"
mode="widthFix"
/>
</view>
</block>
<block v-if="item.redPlayers[0]">
<view class="player">
<Avatar frame :src="item.redPlayers[0].avatar" />
<text>{{ item.redPlayers[0].name }}</text>
<image
v-if="item.winner === 0"
src="../static/winner-badge.png"
mode="widthFix"
/>
</view>
</block>
</view>
<view v-if="item.mode === 2" class="contest-melee">
<view
class="player"
v-for="(p, index2) in item.players"
:key="index2"
:style="{
width: `${Math.max(100 / item.players.length, 18)}vw`,
backgroundColor: meleeAvatarColors[index2],
}"
>
<Avatar :rank="index2 + 1" :src="p.avatar" />
<text>{{ p.name }}</text>
</view>
</view>
</view>
</ScrollList>
<ScrollList
:show="selectedIndex === 2"
:onLoading="onPractiseLoading"
:pageSize="15"
>
<view
v-for="(item, index) in practiseList"
:key="index"
class="practice-record"
@click="() => getPractiseDetail(item.id)"
>
<text>单组练习 {{ item.createdAt }}</text>
<image src="../static/back.png" mode="widthFix" />
</view>
</ScrollList>
</view>
<!-- <BowData
:arrows="arrows"
:show="showBowData"
:onClose="() => (showBowData = false)"
/> -->
</Container>
</template>
<style scoped>
.container {
width: 100%;
}
.tabs {
width: calc(100% - 30px);
display: flex;
justify-content: space-around;
font-size: 15px;
padding: 15px;
padding-top: 0;
}
.tabs > view {
width: 33.3%;
padding: 7px 10px;
text-align: center;
border-radius: 20px;
}
.contents {
width: 100%;
height: calc(100% - 50px);
}
.contents > scroll-view {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
.contest-header {
display: flex;
justify-content: space-between;
padding: 7px 12px;
font-size: 12px;
background: linear-gradient(180deg, #323845 0%, #2e2e39 100%);
position: relative;
}
.contest-header > text:first-child {
color: #ffd947;
font-size: 14px;
}
.contest-header > text:nth-child(2) {
color: #fff9;
margin-right: 20px;
}
.contest-header > image {
position: absolute;
top: 8px;
right: 10px;
width: 15px;
transform: rotate(180deg);
}
.player {
display: flex;
flex-direction: column;
align-items: center;
color: #fff9;
padding-top: 10px;
padding-bottom: 5px;
position: relative;
flex: 0 0 auto;
}
.player > text {
margin-top: 5px;
font-size: 12px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 90%;
text-align: center;
}
.player > image:last-child {
position: absolute;
width: 60px;
right: 0;
bottom: 0;
}
.contest-team,
.contest-melee {
width: 100%;
display: flex;
margin-bottom: 10px;
overflow-x: auto;
}
.contest-team > view {
width: 50%;
}
.contest-team > view:first-child {
background-color: #364469;
}
.contest-team > view:last-child {
background-color: #692735;
}
.practice-record {
color: #fff9;
border-bottom: 1px solid #fff9;
padding: 15px;
display: flex;
align-items: center;
justify-content: space-between;
}
.practice-record > image {
width: 15px;
transform: rotate(180deg);
}
</style>