232 lines
6.5 KiB
Vue
232 lines
6.5 KiB
Vue
<script setup>
|
||
import { onMounted } from "vue";
|
||
import { onLoad } from "@dcloudio/uni-app";
|
||
import Container from "@/components/Container.vue";
|
||
import Avatar from "@/components/Avatar.vue";
|
||
import BowData from "@/components/BowData.vue";
|
||
import BattleHeader from "@/components/BattleHeader.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 toMatchDetail = (id) => {
|
||
uni.navigateTo({
|
||
url: `/pages/match-detail?battleId=${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;
|
||
};
|
||
const getName = (battle) => {
|
||
if (battle.mode <= 3) return `${battle.mode}V${battle.mode}`;
|
||
// 排位赛大乱斗:mode 数字与实际人数不一致,使用固定映射
|
||
if (battle.way === 2) {
|
||
if (battle.mode === 4) return "5人大乱斗";
|
||
if (battle.mode === 5) return "10人大乱斗";
|
||
}
|
||
// 好友约战大乱斗:从 teams[0].players 取实际参与人数动态展示
|
||
const count = battle.teams?.[0]?.players?.length;
|
||
return count ? `${count}人大乱斗` : "大乱斗";
|
||
};
|
||
|
||
/**
|
||
* 支持通过 URL 参数指定初始 tab
|
||
* @example /pages/my-growth?tab=1 跳转到「好友约战」tab
|
||
*/
|
||
onLoad((options) => {
|
||
if (options && options.tab !== undefined) {
|
||
const tabIndex = parseInt(options.tab, 10);
|
||
if (!isNaN(tabIndex)) selectedIndex.value = tabIndex;
|
||
}
|
||
});
|
||
</script>
|
||
|
||
<template>
|
||
<Container title="我的成长脚印" :scroll="false">
|
||
<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">
|
||
<swiper
|
||
:current="selectedIndex"
|
||
@change="(e) => (selectedIndex = e.detail.current)"
|
||
:style="{ height: '100%' }"
|
||
>
|
||
<swiper-item>
|
||
<ScrollList :onLoading="onMatchLoading">
|
||
<view
|
||
v-for="(item, index) in matchList"
|
||
:key="index"
|
||
@click="() => toMatchDetail(item.id)"
|
||
>
|
||
<view class="contest-header">
|
||
<text>{{ getName(item) }}</text>
|
||
<text>{{ item.createTime }}</text>
|
||
<image src="../static/back.png" mode="widthFix" />
|
||
</view>
|
||
<BattleHeader
|
||
:players="item.teams[0] ? item.teams[0].players : []"
|
||
:blueTeam="item.teams[1] ? item.teams[1].players : []"
|
||
:redTeam="item.teams[2] ? item.teams[2].players : []"
|
||
:winner="item.winTeam"
|
||
:showRank="item.teams[0]"
|
||
:showHeader="false"
|
||
/>
|
||
</view>
|
||
</ScrollList>
|
||
</swiper-item>
|
||
<swiper-item>
|
||
<ScrollList :onLoading="onBattleLoading">
|
||
<view
|
||
v-for="(item, index) in battleList"
|
||
:key="index"
|
||
@click="() => toMatchDetail(item.id)"
|
||
>
|
||
<view class="contest-header">
|
||
<text>{{ getName(item) }}</text>
|
||
<text>{{ item.createTime }}</text>
|
||
<image src="../static/back.png" mode="widthFix" />
|
||
</view>
|
||
<BattleHeader
|
||
:players="item.teams[0] ? item.teams[0].players : []"
|
||
:blueTeam="item.teams[1] ? item.teams[1].players : []"
|
||
:redTeam="item.teams[2] ? item.teams[2].players : []"
|
||
:winner="item.winTeam"
|
||
:showRank="item.teams[0]"
|
||
:showHeader="false"
|
||
/>
|
||
</view>
|
||
</ScrollList>
|
||
</swiper-item>
|
||
<swiper-item>
|
||
<ScrollList :onLoading="onPractiseLoading" :pageSize="15">
|
||
<view
|
||
v-for="(item, index) in practiseList"
|
||
:key="index"
|
||
class="practice-record"
|
||
@click="() => getPractiseDetail(item.id)"
|
||
>
|
||
<text
|
||
>{{ item.completed_arrows === 36 ? "耐力挑战" : "单组练习" }}
|
||
{{ item.createTime }}</text
|
||
>
|
||
<image src="../static/back.png" mode="widthFix" />
|
||
</view>
|
||
</ScrollList>
|
||
</swiper-item>
|
||
</swiper>
|
||
</view>
|
||
</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);
|
||
}
|
||
.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>
|