完成数据分页加载
This commit is contained in:
@@ -113,11 +113,12 @@ export const startRoomAPI = (number) => {
|
|||||||
return request("POST", "/user/room/start", { number });
|
return request("POST", "/user/room/start", { number });
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getPractiseResultListAPI = (page = 1, page_size = 10) => {
|
export const getPractiseResultListAPI = async (page = 1, page_size = 15) => {
|
||||||
return request(
|
const reuslt = await request(
|
||||||
"GET",
|
"GET",
|
||||||
`/user/practice/list?page=${page}&page_size=${page_size}`
|
`/user/practice/list?page=${page}&page_size=${page_size}`
|
||||||
);
|
);
|
||||||
|
return reuslt.list;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const matchGameAPI = (match, gameType, teamSize) => {
|
export const matchGameAPI = (match, gameType, teamSize) => {
|
||||||
|
|||||||
@@ -15,6 +15,10 @@ defineProps({
|
|||||||
type: Function,
|
type: Function,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
|
overflow: {
|
||||||
|
type: String,
|
||||||
|
default: "auto",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
const isIos = ref(true);
|
const isIos = ref(true);
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@@ -29,7 +33,7 @@ onMounted(() => {
|
|||||||
<Header :title="title" :onBack="onBack" />
|
<Header :title="title" :onBack="onBack" />
|
||||||
<view
|
<view
|
||||||
class="content"
|
class="content"
|
||||||
:style="{ height: `calc(100vh - ${isIos ? 105 : 95}px)` }"
|
:style="{ height: `calc(100vh - ${isIos ? 98 : 95}px)`, overflow }"
|
||||||
>
|
>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</view>
|
</view>
|
||||||
@@ -40,11 +44,9 @@ onMounted(() => {
|
|||||||
.content {
|
.content {
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overflow-y: auto;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding-bottom: 10px;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ onMounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<view class="container" :style="{ paddingTop: isIos ? '35px' : '25px' }">
|
<view class="container" :style="{ paddingTop: isIos ? '38px' : '25px' }">
|
||||||
<view class="back-btn" @click="onClick">
|
<view class="back-btn" @click="onClick">
|
||||||
<image src="../static/back.png" mode="widthFix" />
|
<image src="../static/back.png" mode="widthFix" />
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
85
src/components/ScrollList.vue
Normal file
85
src/components/ScrollList.vue
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref, watch } from "vue";
|
||||||
|
const props = defineProps({
|
||||||
|
show: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
onLoading: {
|
||||||
|
type: Function,
|
||||||
|
default: async (page) => [],
|
||||||
|
},
|
||||||
|
pageSize: {
|
||||||
|
type: Number,
|
||||||
|
default: 10,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const refreshing = ref(false);
|
||||||
|
const loading = ref(false);
|
||||||
|
const noMore = ref(false);
|
||||||
|
const page = ref(1);
|
||||||
|
const refresherrefresh = async () => {
|
||||||
|
if (refreshing.value) return;
|
||||||
|
try {
|
||||||
|
refreshing.value = true;
|
||||||
|
page.value = 1;
|
||||||
|
const list = await props.onLoading(page.value);
|
||||||
|
if (list.length < props.pageSize) noMore.value = true;
|
||||||
|
} finally {
|
||||||
|
refreshing.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const scrolltolower = async () => {
|
||||||
|
if (loading.value) return;
|
||||||
|
try {
|
||||||
|
loading.value = true;
|
||||||
|
page.value += 1;
|
||||||
|
const list = await props.onLoading(page.value);
|
||||||
|
if (list.length < props.pageSize) noMore.value = true;
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
watch(
|
||||||
|
() => props.show,
|
||||||
|
async (newVal) => {
|
||||||
|
if (newVal) await props.onLoading(1);
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<scroll-view
|
||||||
|
class="scroll-list"
|
||||||
|
scroll-y
|
||||||
|
refresher-default-style="white"
|
||||||
|
:refresher-enabled="true"
|
||||||
|
:refresher-triggered="refreshing"
|
||||||
|
@refresherrefresh="refresherrefresh"
|
||||||
|
@scrolltolower="scrolltolower"
|
||||||
|
:style="{
|
||||||
|
display: show ? 'flex' : 'none',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<slot></slot>
|
||||||
|
<text class="tips" v-if="loading">加载中...</text>
|
||||||
|
<text class="tips" v-if="noMore">我是有底线的</text>
|
||||||
|
</scroll-view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.scroll-list {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.tips {
|
||||||
|
color: #fff9;
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 12px;
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -3,6 +3,7 @@ import { onMounted } from "vue";
|
|||||||
import Container from "@/components/Container.vue";
|
import Container from "@/components/Container.vue";
|
||||||
import Avatar from "@/components/Avatar.vue";
|
import Avatar from "@/components/Avatar.vue";
|
||||||
import BowData from "@/components/BowData.vue";
|
import BowData from "@/components/BowData.vue";
|
||||||
|
import ScrollList from "@/components/ScrollList.vue";
|
||||||
import {
|
import {
|
||||||
getBattleListAPI,
|
getBattleListAPI,
|
||||||
getPractiseResultListAPI,
|
getPractiseResultListAPI,
|
||||||
@@ -12,32 +13,12 @@ import {
|
|||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
|
|
||||||
const selectedIndex = ref(0);
|
const selectedIndex = ref(0);
|
||||||
const matchPage = ref(1);
|
|
||||||
const matchList = ref([]);
|
const matchList = ref([]);
|
||||||
const battlePage = ref(1);
|
|
||||||
const battleList = ref([]);
|
const battleList = ref([]);
|
||||||
const practiseList = ref([]);
|
const practiseList = ref([]);
|
||||||
const showBowData = ref(false);
|
const showBowData = ref(false);
|
||||||
const arrows = ref([]);
|
const arrows = ref([]);
|
||||||
|
|
||||||
const handleSelect = async (index) => {
|
|
||||||
selectedIndex.value = index;
|
|
||||||
if (index === 0 && matchList.value.length === 0) {
|
|
||||||
const result = await getBattleListAPI(matchPage.value, 2);
|
|
||||||
matchList.value = result;
|
|
||||||
matchPage.value += 1;
|
|
||||||
}
|
|
||||||
if (index === 1 && battleList.value.length === 0) {
|
|
||||||
const result = await getBattleListAPI(battlePage.value, 1);
|
|
||||||
battleList.value = result;
|
|
||||||
battlePage.value += 1;
|
|
||||||
}
|
|
||||||
if (index === 2 && practiseList.value.length === 0) {
|
|
||||||
const result = await getPractiseResultListAPI();
|
|
||||||
practiseList.value = result.list;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const toMatchDetail = (id) => {
|
const toMatchDetail = (id) => {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: `/pages/match-detail?id=${id}`,
|
url: `/pages/match-detail?id=${id}`,
|
||||||
@@ -48,146 +29,157 @@ const getPractiseDetail = async (id) => {
|
|||||||
arrows.value = JSON.parse(result.UserPracticeRound.arrows);
|
arrows.value = JSON.parse(result.UserPracticeRound.arrows);
|
||||||
showBowData.value = true;
|
showBowData.value = true;
|
||||||
};
|
};
|
||||||
onMounted(async () => {
|
const onMatchLoading = async (page) => {
|
||||||
const result = await getBattleListAPI(matchPage.value, 2);
|
const result = await getBattleListAPI(page, 2);
|
||||||
matchList.value = result;
|
if (page === 1) {
|
||||||
matchPage.value += 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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Container title="我的成长脚印">
|
<Container title="我的成长脚印" overflow="hidden">
|
||||||
<view class="container">
|
<view class="tabs">
|
||||||
<view class="tabs">
|
<view
|
||||||
<view
|
v-for="(rankType, index) in ['排位赛', '好友约战', '射馆练习']"
|
||||||
v-for="(rankType, index) in ['排位赛', '好友约战', '射馆练习']"
|
:key="index"
|
||||||
:key="index"
|
:style="{
|
||||||
:style="{
|
color: index === selectedIndex ? '#000' : '#fff',
|
||||||
color: index === selectedIndex ? '#000' : '#fff',
|
backgroundColor: index === selectedIndex ? '#FFD947' : 'transparent',
|
||||||
backgroundColor:
|
}"
|
||||||
index === selectedIndex ? '#FFD947' : 'transparent',
|
@tap="() => (selectedIndex = index)"
|
||||||
}"
|
>
|
||||||
@tap="handleSelect(index)"
|
{{ rankType }}
|
||||||
>
|
|
||||||
{{ rankType }}
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
<view class="contents">
|
</view>
|
||||||
|
<view class="contents">
|
||||||
|
<ScrollList :show="selectedIndex === 0" :onLoading="onMatchLoading">
|
||||||
<view
|
<view
|
||||||
:style="{
|
v-for="(item, index) in matchList"
|
||||||
display: selectedIndex === 0 ? 'flex' : 'none',
|
:key="index"
|
||||||
}"
|
@click="() => toMatchDetail(item.battleId)"
|
||||||
>
|
>
|
||||||
<view
|
<view class="contest-header">
|
||||||
v-for="(item, index) in matchList"
|
<text>{{ item.name }}</text>
|
||||||
:key="index"
|
<text>{{ item.createdAt }}</text>
|
||||||
@click="() => toMatchDetail(item.battleId)"
|
<image src="../static/back.png" mode="widthFix" />
|
||||||
>
|
|
||||||
<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-multi">
|
|
||||||
<view
|
|
||||||
class="player"
|
|
||||||
v-for="(p, index2) in item.players"
|
|
||||||
:key="index2"
|
|
||||||
>
|
|
||||||
<Avatar :rank="index2 + 1" :src="p.avatar" />
|
|
||||||
<text>{{ p.name }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
<view v-if="item.mode === 1" class="contest-team">
|
||||||
<view
|
<block v-if="item.bluePlayers[0]">
|
||||||
:style="{
|
<view class="player">
|
||||||
display: selectedIndex === 1 ? 'flex' : 'none',
|
<Avatar frame :src="item.bluePlayers[0].avatar" />
|
||||||
}"
|
<text>{{ item.bluePlayers[0].name }}</text>
|
||||||
>
|
|
||||||
<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">
|
|
||||||
<view
|
|
||||||
class="player"
|
|
||||||
v-for="(p, index2) in item.players"
|
|
||||||
:key="index2"
|
|
||||||
>
|
|
||||||
<Avatar frame :src="p.avatar" />
|
|
||||||
<text>{{ p.name }}</text>
|
|
||||||
<image
|
<image
|
||||||
v-if="index2 === 0"
|
v-if="item.winner === 1"
|
||||||
src="../static/winner-badge.png"
|
src="../static/winner-badge.png"
|
||||||
mode="widthFix"
|
mode="widthFix"
|
||||||
/>
|
/>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</block>
|
||||||
<view v-if="item.mode === 2" class="contest-multi">
|
<block v-if="item.redPlayers[0]">
|
||||||
<view
|
<view class="player">
|
||||||
class="player"
|
<Avatar frame :src="item.redPlayers[0].avatar" />
|
||||||
v-for="(p, index2) in item.players"
|
<text>{{ item.redPlayers[0].name }}</text>
|
||||||
:key="index2"
|
<image
|
||||||
>
|
v-if="item.winner === 0"
|
||||||
<Avatar :rank="index2 + 1" :src="p.avatar" />
|
src="../static/winner-badge.png"
|
||||||
<text>{{ p.name }}</text>
|
mode="widthFix"
|
||||||
|
/>
|
||||||
</view>
|
</view>
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
<view v-if="item.mode === 2" class="contest-multi">
|
||||||
|
<view
|
||||||
|
class="player"
|
||||||
|
v-for="(p, index2) in item.players"
|
||||||
|
:key="index2"
|
||||||
|
>
|
||||||
|
<Avatar :rank="index2 + 1" :src="p.avatar" />
|
||||||
|
<text>{{ p.name }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
</ScrollList>
|
||||||
|
<ScrollList :show="selectedIndex === 1" :onLoading="onBattleLoading">
|
||||||
<view
|
<view
|
||||||
:style="{
|
v-for="(item, index) in battleList"
|
||||||
display: selectedIndex === 2 ? 'flex' : 'none',
|
:key="index"
|
||||||
}"
|
@click="() => toMatchDetail(item.battleId)"
|
||||||
>
|
>
|
||||||
<view
|
<view class="contest-header">
|
||||||
v-for="(item, index) in practiseList"
|
<text>{{ item.name }}</text>
|
||||||
:key="index"
|
<text>{{ item.createdAt }}</text>
|
||||||
class="practice-record"
|
|
||||||
@click="() => getPractiseDetail(item.id)"
|
|
||||||
>
|
|
||||||
<text>单组练习 {{ item.createdAt }}</text>
|
|
||||||
<image src="../static/back.png" mode="widthFix" />
|
<image src="../static/back.png" mode="widthFix" />
|
||||||
</view>
|
</view>
|
||||||
|
<view v-if="item.mode === 1" class="contest-team">
|
||||||
|
<view
|
||||||
|
class="player"
|
||||||
|
v-for="(p, index2) in item.players"
|
||||||
|
:key="index2"
|
||||||
|
>
|
||||||
|
<Avatar frame :src="p.avatar" />
|
||||||
|
<text>{{ p.name }}</text>
|
||||||
|
<image
|
||||||
|
v-if="index2 === 0"
|
||||||
|
src="../static/winner-badge.png"
|
||||||
|
mode="widthFix"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view v-if="item.mode === 2" class="contest-multi">
|
||||||
|
<view
|
||||||
|
class="player"
|
||||||
|
v-for="(p, index2) in item.players"
|
||||||
|
:key="index2"
|
||||||
|
>
|
||||||
|
<Avatar :rank="index2 + 1" :src="p.avatar" />
|
||||||
|
<text>{{ p.name }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</ScrollList>
|
||||||
<BowData
|
<ScrollList
|
||||||
:arrows="arrows"
|
:show="selectedIndex === 2"
|
||||||
:show="showBowData"
|
:onLoading="onPractiseLoading"
|
||||||
:onClose="() => (showBowData = false)"
|
: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>
|
</view>
|
||||||
|
<BowData
|
||||||
|
:arrows="arrows"
|
||||||
|
:show="showBowData"
|
||||||
|
:onClose="() => (showBowData = false)"
|
||||||
|
/>
|
||||||
</Container>
|
</Container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -209,8 +201,13 @@ onMounted(async () => {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
}
|
}
|
||||||
.contents > view {
|
.contents {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
height: calc(100% - 50px);
|
||||||
|
}
|
||||||
|
.contents > scroll-view {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user