分页
This commit is contained in:
@@ -49,6 +49,9 @@ export default function HomeScreen() {
|
||||
const [liveLeagueIdByMatchId, setLiveLeagueIdByMatchId] = useState<
|
||||
Record<string, number>
|
||||
>({});
|
||||
const [page, setPage] = useState(1);
|
||||
const [total, setTotal] = useState(0);
|
||||
const [loadingMore, setLoadingMore] = useState(false);
|
||||
|
||||
const deviceTimeZone = useMemo(() => {
|
||||
try {
|
||||
@@ -96,6 +99,11 @@ export default function HomeScreen() {
|
||||
}
|
||||
}, [selectedSportId, selectedDate]);
|
||||
|
||||
useEffect(() => {
|
||||
setPage(1);
|
||||
setTotal(0);
|
||||
}, [selectedSportId, selectedDate, state.selectedLeagueKey]);
|
||||
|
||||
const timezoneLabel = useMemo(() => {
|
||||
// 仅展示 UTC 偏移(不展示时区名)
|
||||
const offsetMin = -now.getTimezoneOffset();
|
||||
@@ -303,8 +311,8 @@ export default function HomeScreen() {
|
||||
try {
|
||||
if (selectedSportId !== null) {
|
||||
setLoadingLeagues(true);
|
||||
const list = await fetchLeagues(selectedSportId, "");
|
||||
setLeagues(list);
|
||||
const res = await fetchLeagues({ sportId: selectedSportId });
|
||||
setLeagues(res.list);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
@@ -316,11 +324,16 @@ export default function HomeScreen() {
|
||||
const loadMatches = async (sportId: number) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const list = await fetchTodayMatches(
|
||||
const res = await fetchTodayMatches({
|
||||
sportId,
|
||||
selectedDate,
|
||||
deviceTimeZone,
|
||||
);
|
||||
date: selectedDate,
|
||||
timezone: deviceTimeZone,
|
||||
leagueKey: state.selectedLeagueKey || "",
|
||||
page: 1,
|
||||
pageSize: 50,
|
||||
});
|
||||
setPage(1);
|
||||
setTotal(res.total);
|
||||
|
||||
const normalizeDate = (d: Date) => {
|
||||
const year = d.getFullYear();
|
||||
@@ -333,7 +346,7 @@ export default function HomeScreen() {
|
||||
const selectedStr = normalizeDate(selectedDate);
|
||||
const shouldMergeLive = selectedStr === todayStr;
|
||||
|
||||
let merged: Match[] = list.map((m) => ({
|
||||
let merged: Match[] = res.list.map((m) => ({
|
||||
...m,
|
||||
date: m.date || selectedStr,
|
||||
sportId: m.sportId ?? sportId,
|
||||
@@ -402,11 +415,9 @@ export default function HomeScreen() {
|
||||
let listWithFavStatus = merged;
|
||||
|
||||
if (token) {
|
||||
// 直接传递 match.id 查询是否收藏,并更新列表状态
|
||||
listWithFavStatus = await Promise.all(
|
||||
merged.map(async (m) => {
|
||||
try {
|
||||
// 查询比赛是否已被收藏
|
||||
const favRes = await checkFavorite("match", m.id);
|
||||
return { ...m, fav: favRes.isFavorite };
|
||||
} catch (error) {
|
||||
@@ -434,6 +445,41 @@ export default function HomeScreen() {
|
||||
}
|
||||
};
|
||||
|
||||
const loadMoreMatches = async () => {
|
||||
if (loadingMore || loading) return;
|
||||
if (!selectedSportId) return;
|
||||
if (matches.length >= total) return;
|
||||
|
||||
setLoadingMore(true);
|
||||
try {
|
||||
const nextPage = page + 1;
|
||||
const res = await fetchTodayMatches({
|
||||
sportId: selectedSportId,
|
||||
date: selectedDate,
|
||||
timezone: deviceTimeZone,
|
||||
leagueKey: state.selectedLeagueKey || "",
|
||||
page: nextPage,
|
||||
pageSize: 50,
|
||||
});
|
||||
|
||||
setPage(nextPage);
|
||||
setTotal(res.total);
|
||||
|
||||
setMatches((prev) => {
|
||||
const byId = new Map<string, Match>();
|
||||
prev.forEach((m) => byId.set(m.id, m));
|
||||
res.list.forEach((m) => {
|
||||
if (!byId.has(m.id)) byId.set(m.id, m);
|
||||
});
|
||||
return Array.from(byId.values());
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
} finally {
|
||||
setLoadingMore(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleFavoriteToggle = (matchId: string, isFav: boolean) => {
|
||||
setMatches((prev) => {
|
||||
const updated = prev.map((m) =>
|
||||
@@ -558,6 +604,15 @@ export default function HomeScreen() {
|
||||
renderItem={({ item }) => (
|
||||
<MatchCard match={item} onFavoriteToggle={handleFavoriteToggle} />
|
||||
)}
|
||||
onEndReached={loadMoreMatches}
|
||||
onEndReachedThreshold={0.4}
|
||||
ListFooterComponent={
|
||||
loadingMore ? (
|
||||
<View style={styles.footer}>
|
||||
<ActivityIndicator size="small" color={Colors[theme].tint} />
|
||||
</View>
|
||||
) : null
|
||||
}
|
||||
contentContainerStyle={styles.listContent}
|
||||
ListEmptyComponent={
|
||||
<View style={styles.center}>
|
||||
@@ -650,4 +705,9 @@ const styles = StyleSheet.create({
|
||||
padding: 16,
|
||||
paddingTop: 8,
|
||||
},
|
||||
footer: {
|
||||
paddingVertical: 16,
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user