为多个组件和API添加用户登录状态检查,确保只有在用户登录后才能查询和修改收藏状态

This commit is contained in:
yuchenglong
2026-01-16 18:02:08 +08:00
parent b5fd763c7e
commit 887d205f65
8 changed files with 107 additions and 50 deletions

View File

@@ -5,6 +5,7 @@ import { IconSymbol, IconSymbolName } from "@/components/ui/icon-symbol";
import { Colors } from "@/constants/theme"; import { Colors } from "@/constants/theme";
import { useTheme } from "@/context/ThemeContext"; import { useTheme } from "@/context/ThemeContext";
import { fetchFavorites, removeFavorite } from "@/lib/api"; import { fetchFavorites, removeFavorite } from "@/lib/api";
import { storage } from "@/lib/storage";
import { FavoriteItem, Match } from "@/types/api"; import { FavoriteItem, Match } from "@/types/api";
import { Image } from "expo-image"; import { Image } from "expo-image";
import { useRouter } from "expo-router"; import { useRouter } from "expo-router";
@@ -67,6 +68,13 @@ export default function FavoriteScreen() {
if (loading) return; if (loading) return;
setLoading(true); setLoading(true);
try { try {
const token = await storage.getAccessToken();
if (!token) {
setFavorites([]);
setHasMore(false);
return;
}
const currentPage = isRefresh ? 1 : page; const currentPage = isRefresh ? 1 : page;
const res = await fetchFavorites(activeTab, currentPage); const res = await fetchFavorites(activeTab, currentPage);
if (isRefresh) { if (isRefresh) {

View File

@@ -15,6 +15,7 @@ import {
fetchSports, fetchSports,
fetchTodayMatches, fetchTodayMatches,
} from "@/lib/api"; } from "@/lib/api";
import { storage } from "@/lib/storage";
import { League, Match, Sport } from "@/types/api"; import { League, Match, Sport } from "@/types/api";
import React, { useEffect, useMemo, useState } from "react"; import React, { useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -316,18 +317,23 @@ export default function HomeScreen() {
deviceTimeZone deviceTimeZone
); );
// 直接传递 match.id 查询是否收藏,并更新列表状态 const token = await storage.getAccessToken();
const listWithFavStatus = await Promise.all( let listWithFavStatus = list;
list.map(async (m) => {
try { if (token) {
const favRes = await checkFavorite("match", m.id); // 直接传递 match.id 查询是否收藏,并更新列表状态
return { ...m, fav: favRes.isFavorite }; listWithFavStatus = await Promise.all(
} catch (error) { list.map(async (m) => {
console.error(`Check favorite failed for match ${m.id}:`, error); try {
return m; const favRes = await checkFavorite("match", m.id);
} return { ...m, fav: favRes.isFavorite };
}) } catch (error) {
); console.error(`Check favorite failed for match ${m.id}:`, error);
return m;
}
})
);
}
// 将收藏的比赛置顶 // 将收藏的比赛置顶
const sortedList = [...listWithFavStatus].sort((a, b) => { const sortedList = [...listWithFavStatus].sort((a, b) => {

View File

@@ -15,6 +15,7 @@ import {
fetchSports, fetchSports,
fetchTodayMatches, fetchTodayMatches,
} from "@/lib/api"; } from "@/lib/api";
import { storage } from "@/lib/storage";
import { League, Match, Sport } from "@/types/api"; import { League, Match, Sport } from "@/types/api";
import React, { useEffect, useMemo, useState } from "react"; import React, { useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -316,19 +317,24 @@ export default function HomeScreen() {
deviceTimeZone deviceTimeZone
); );
// 直接传递 match.id 查询是否收藏,并更新列表状态 const token = await storage.getAccessToken();
const listWithFavStatus = await Promise.all( let listWithFavStatus = list;
list.map(async (m) => {
try { if (token) {
// 查询比赛是否已被收藏 // 直接传递 match.id 查询是否收藏,并更新列表状态
const favRes = await checkFavorite("match", m.id); listWithFavStatus = await Promise.all(
return { ...m, fav: favRes.isFavorite }; list.map(async (m) => {
} catch (error) { try {
console.error(`Check favorite failed for match ${m.id}:`, error); // 查询比赛是否已被收藏
return m; const favRes = await checkFavorite("match", m.id);
} return { ...m, fav: favRes.isFavorite };
}) } catch (error) {
); console.error(`Check favorite failed for match ${m.id}:`, error);
return m;
}
})
);
}
// 将收藏的比赛置顶 // 将收藏的比赛置顶
const sortedList = [...listWithFavStatus].sort((a, b) => { const sortedList = [...listWithFavStatus].sort((a, b) => {

View File

@@ -6,6 +6,7 @@ import { Colors } from "@/constants/theme";
import { useAppState } from "@/context/AppStateContext"; import { useAppState } from "@/context/AppStateContext";
import { useTheme } from "@/context/ThemeContext"; import { useTheme } from "@/context/ThemeContext";
import { checkFavorite, fetchLiveScore } from "@/lib/api"; import { checkFavorite, fetchLiveScore } from "@/lib/api";
import { storage } from "@/lib/storage";
import { LiveScoreMatch, Match } from "@/types/api"; import { LiveScoreMatch, Match } from "@/types/api";
import { useRouter } from "expo-router"; import { useRouter } from "expo-router";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
@@ -66,18 +67,23 @@ export default function LiveScreen() {
isLive: true, isLive: true,
})); }));
// 直接传递 match.id 查询是否收藏,并更新列表状态 const token = await storage.getAccessToken();
const listWithFavStatus = await Promise.all( let listWithFavStatus = converted;
converted.map(async (m) => {
try { if (token) {
const favRes = await checkFavorite("match", m.id); // 直接传递 match.id 查询是否收藏,并更新列表状态
return { ...m, fav: favRes.isFavorite }; listWithFavStatus = await Promise.all(
} catch (error) { converted.map(async (m) => {
console.error(`Check favorite failed for match ${m.id}:`, error); try {
return m; const favRes = await checkFavorite("match", m.id);
} return { ...m, fav: favRes.isFavorite };
}) } catch (error) {
); console.error(`Check favorite failed for match ${m.id}:`, error);
return m;
}
})
);
}
// 将收藏的比赛置顶 // 将收藏的比赛置顶
const sortedList = [...listWithFavStatus].sort((a, b) => { const sortedList = [...listWithFavStatus].sort((a, b) => {

View File

@@ -13,6 +13,7 @@ import {
fetchSports, fetchSports,
fetchUpcomingMatches, fetchUpcomingMatches,
} from "@/lib/api"; } from "@/lib/api";
import { storage } from "@/lib/storage";
import { League, Sport, UpcomingMatch } from "@/types/api"; import { League, Sport, UpcomingMatch } from "@/types/api";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -261,7 +262,8 @@ export default function HomeScreen() {
}; };
const loadMatches = async () => { const loadMatches = async () => {
if (selectedSportId === null) return; const token = await storage.getAccessToken();
if (selectedSportId === null || !token) return;
setLoading(true); setLoading(true);
try { try {
@@ -271,18 +273,23 @@ export default function HomeScreen() {
selectedLeagueKey || "" selectedLeagueKey || ""
); );
// 直接传递 match.id 查询是否收藏,并更新列表状态 const token = await storage.getAccessToken();
const listWithFavStatus = await Promise.all( let listWithFavStatus = list;
list.map(async (m) => {
try { if (token) {
const favRes = await checkFavorite("match", m.id.toString()); // 直接传递 match.id 查询是否收藏,并更新列表状态
return { ...m, fav: favRes.isFavorite }; listWithFavStatus = await Promise.all(
} catch (error) { list.map(async (m) => {
console.error(`Check favorite failed for match ${m.id}:`, error); try {
return m; const favRes = await checkFavorite("match", m.id.toString());
} return { ...m, fav: favRes.isFavorite };
}) } catch (error) {
); console.error(`Check favorite failed for match ${m.id}:`, error);
return m;
}
})
);
}
// 将收藏的比赛置顶 // 将收藏的比赛置顶
const sortedList = [...listWithFavStatus].sort((a, b) => { const sortedList = [...listWithFavStatus].sort((a, b) => {

View File

@@ -1,6 +1,7 @@
import { ThemedText } from "@/components/themed-text"; import { ThemedText } from "@/components/themed-text";
import { IconSymbol } from "@/components/ui/icon-symbol"; import { IconSymbol } from "@/components/ui/icon-symbol";
import { addFavorite, checkFavorite, removeFavorite } from "@/lib/api"; import { addFavorite, checkFavorite, removeFavorite } from "@/lib/api";
import { storage } from "@/lib/storage";
import { LiveScoreMatch } from "@/types/api"; import { LiveScoreMatch } from "@/types/api";
import { LinearGradient } from "expo-linear-gradient"; import { LinearGradient } from "expo-linear-gradient";
import { useRouter } from "expo-router"; import { useRouter } from "expo-router";
@@ -46,6 +47,8 @@ export function LiveScoreHeader({ match, topInset }: LiveScoreHeaderProps) {
// 检查收藏状态 // 检查收藏状态
React.useEffect(() => { React.useEffect(() => {
const loadFavStatus = async () => { const loadFavStatus = async () => {
const token = await storage.getAccessToken();
if (!token) return;
try { try {
const res = await checkFavorite("match", match.event_key.toString()); const res = await checkFavorite("match", match.event_key.toString());
setIsFav(res.isFavorite); setIsFav(res.isFavorite);
@@ -59,6 +62,8 @@ export function LiveScoreHeader({ match, topInset }: LiveScoreHeaderProps) {
// 检查主队收藏状态 // 检查主队收藏状态
React.useEffect(() => { React.useEffect(() => {
const loadHomeFav = async () => { const loadHomeFav = async () => {
const token = await storage.getAccessToken();
if (!token) return;
try { try {
const res = await checkFavorite("team", match.home_team_key.toString()); const res = await checkFavorite("team", match.home_team_key.toString());
setIsHomeFav(res.isFavorite); setIsHomeFav(res.isFavorite);
@@ -74,6 +79,8 @@ export function LiveScoreHeader({ match, topInset }: LiveScoreHeaderProps) {
// 检查客队收藏状态 // 检查客队收藏状态
React.useEffect(() => { React.useEffect(() => {
const loadAwayFav = async () => { const loadAwayFav = async () => {
const token = await storage.getAccessToken();
if (!token) return;
try { try {
const res = await checkFavorite("team", match.away_team_key.toString()); const res = await checkFavorite("team", match.away_team_key.toString());
setIsAwayFav(res.isFavorite); setIsAwayFav(res.isFavorite);

View File

@@ -1,6 +1,7 @@
import { ThemedText } from "@/components/themed-text"; import { ThemedText } from "@/components/themed-text";
import { IconSymbol } from "@/components/ui/icon-symbol"; import { IconSymbol } from "@/components/ui/icon-symbol";
import { addFavorite, checkFavorite, removeFavorite } from "@/lib/api"; import { addFavorite, checkFavorite, removeFavorite } from "@/lib/api";
import { storage } from "@/lib/storage";
import { MatchDetailData } from "@/types/api"; import { MatchDetailData } from "@/types/api";
import { LinearGradient } from "expo-linear-gradient"; import { LinearGradient } from "expo-linear-gradient";
import { useRouter } from "expo-router"; import { useRouter } from "expo-router";
@@ -30,6 +31,8 @@ export function ScoreHeader({ data, isDark, topInset }: ScoreHeaderProps) {
// 检查比赛收藏状态 // 检查比赛收藏状态
React.useEffect(() => { React.useEffect(() => {
const loadFavStatus = async () => { const loadFavStatus = async () => {
const token = await storage.getAccessToken();
if (!token) return;
try { try {
const res = await checkFavorite("match", match.eventKey.toString()); const res = await checkFavorite("match", match.eventKey.toString());
setIsFav(res.isFavorite); setIsFav(res.isFavorite);
@@ -45,6 +48,8 @@ export function ScoreHeader({ data, isDark, topInset }: ScoreHeaderProps) {
// 检查主队收藏状态 // 检查主队收藏状态
React.useEffect(() => { React.useEffect(() => {
const loadHomeFav = async () => { const loadHomeFav = async () => {
const token = await storage.getAccessToken();
if (!token) return;
try { try {
const res = await checkFavorite("team", match.homeTeamKey.toString()); const res = await checkFavorite("team", match.homeTeamKey.toString());
setIsHomeFav(res.isFavorite); setIsHomeFav(res.isFavorite);
@@ -60,6 +65,8 @@ export function ScoreHeader({ data, isDark, topInset }: ScoreHeaderProps) {
// 检查客队收藏状态 // 检查客队收藏状态
React.useEffect(() => { React.useEffect(() => {
const loadAwayFav = async () => { const loadAwayFav = async () => {
const token = await storage.getAccessToken();
if (!token) return;
try { try {
const res = await checkFavorite("team", match.awayTeamKey.toString()); const res = await checkFavorite("team", match.awayTeamKey.toString());
setIsAwayFav(res.isFavorite); setIsAwayFav(res.isFavorite);

View File

@@ -431,6 +431,11 @@ export const fetchUserProfile = async (): Promise<UserProfile> => {
export const addFavorite = async (request: FavoriteRequest): Promise<any> => { export const addFavorite = async (request: FavoriteRequest): Promise<any> => {
try { try {
const token = await storage.getAccessToken();
if (!token) {
// throw new Error("Please login first");
return;
}
// console.log("Adding favorite with request:", request); // console.log("Adding favorite with request:", request);
const response = await apiClient.post<ApiResponse<any>>( const response = await apiClient.post<ApiResponse<any>>(
API_ENDPOINTS.FAVORITES, API_ENDPOINTS.FAVORITES,
@@ -451,6 +456,11 @@ export const removeFavorite = async (request: {
typeId: string; typeId: string;
}): Promise<any> => { }): Promise<any> => {
try { try {
const token = await storage.getAccessToken();
if (!token) {
// throw new Error("Please login first");
return;
}
console.log("Removing favorite with request:", request); console.log("Removing favorite with request:", request);
const response = await apiClient.delete<ApiResponse<any>>( const response = await apiClient.delete<ApiResponse<any>>(
API_ENDPOINTS.FAVORITES, API_ENDPOINTS.FAVORITES,