import { ThemedText } from "@/components/themed-text"; import { IconSymbol } from "@/components/ui/icon-symbol"; import { addFavorite, checkFavorite, removeFavorite } from "@/lib/api"; import { storage } from "@/lib/storage"; import { LiveScoreMatch } from "@/types/api"; import { LinearGradient } from "expo-linear-gradient"; import { useRouter } from "expo-router"; import React, { useState } from "react"; import { Image, StyleSheet, TouchableOpacity, View } from "react-native"; interface LiveScoreHeaderProps { match: LiveScoreMatch; topInset: number; } export function LiveScoreHeader({ match, topInset }: LiveScoreHeaderProps) { const router = useRouter(); const parseMin = (t: string) => parseInt(t?.match(/(\d+)/)?.[1] || "0"); // 解析初始时间逻辑:(event_status 分钟 - event_time 分钟) : event_time 秒 const getInitialTime = () => { const statusIdx = parseInt(match.event_status) || 0; const timeParts = match.event_time?.split(":") || []; const tMin = parseInt(timeParts[0]) || 0; const tSec = parseInt(timeParts[1]) || 0; // 如果 event_status 是纯数字分钟数 if (!isNaN(statusIdx) && /^\d+$/.test(match.event_status)) { return { min: Math.max(0, statusIdx - tMin), sec: tSec }; } // 回退到解析 event_time 中的数字 return { min: tMin || parseMin(match.event_time), sec: tSec }; }; const initial = getInitialTime(); const [minutes, setMinutes] = useState(initial.min); const [seconds, setSeconds] = useState(initial.sec); const [isFav, setIsFav] = useState(false); const [favLoading, setFavLoading] = useState(false); const [isHomeFav, setIsHomeFav] = useState(false); const [isAwayFav, setIsAwayFav] = useState(false); const [homeFavLoading, setHomeFavLoading] = useState(false); const [awayFavLoading, setAwayFavLoading] = useState(false); // 检查收藏状态 React.useEffect(() => { const loadFavStatus = async () => { const token = await storage.getAccessToken(); if (!token) return; try { const res = await checkFavorite("match", match.event_key.toString()); setIsFav(res.isFavorite); } catch (error) { console.error("Check favorite status error:", error); } }; loadFavStatus(); }, [match.event_key]); // 检查主队收藏状态 React.useEffect(() => { const loadHomeFav = async () => { const token = await storage.getAccessToken(); if (!token) return; try { const res = await checkFavorite("team", match.home_team_key.toString()); setIsHomeFav(res.isFavorite); } catch (error) { console.error("Check home team favorite status error:", error); } }; if (match.home_team_key) { loadHomeFav(); } }, [match.home_team_key]); // 检查客队收藏状态 React.useEffect(() => { const loadAwayFav = async () => { const token = await storage.getAccessToken(); if (!token) return; try { const res = await checkFavorite("team", match.away_team_key.toString()); setIsAwayFav(res.isFavorite); } catch (error) { console.error("Check away team favorite status error:", error); } }; if (match.away_team_key) { loadAwayFav(); } }, [match.away_team_key]); const toggleFavorite = async () => { if (favLoading) return; setFavLoading(true); const newFavState = !isFav; try { if (newFavState) { await addFavorite({ matchId: match.event_key, type: "match", typeId: match.event_key.toString(), notify: true, }); } else { await removeFavorite({ type: "match", typeId: match.event_key.toString(), }); } setIsFav(newFavState); } catch (error) { console.error("Toggle favorite error:", error); } finally { setFavLoading(false); } }; const toggleTeamFavorite = async (teamKey: number, isHome: boolean) => { const isTeamFav = isHome ? isHomeFav : isAwayFav; const setLoading = isHome ? setHomeFavLoading : setAwayFavLoading; const setFav = isHome ? setIsHomeFav : setIsAwayFav; const loading = isHome ? homeFavLoading : awayFavLoading; if (loading) return; setLoading(true); const newFavState = !isTeamFav; try { if (newFavState) { await addFavorite({ teamId: teamKey, type: "team", typeId: teamKey.toString(), notify: true, }); } else { await removeFavorite({ type: "team", typeId: teamKey.toString(), }); } setFav(newFavState); } catch (error) { console.error("Toggle team favorite error:", error); } finally { setLoading(false); } }; const lastServerMatchRef = React.useRef( `${match.event_status}-${match.event_time}` ); // 服务器时间同步 React.useEffect(() => { const currentKey = `${match.event_status}-${match.event_time}`; if (currentKey !== lastServerMatchRef.current) { const updated = getInitialTime(); setMinutes(updated.min); setSeconds(updated.sec); lastServerMatchRef.current = currentKey; } }, [match.event_time, match.event_status]); // 本地秒级自增计时器 React.useEffect(() => { const status = match.event_status?.toLowerCase() || ""; const isLive = String(match.event_live) === "1" || status.includes("live") || status.includes("play") || /^[12][h]$/.test(status) || (parseInt(status) > 0 && parseInt(status) < 120); if (!isLive || status.includes("ht") || status.includes("half")) return; const interval = setInterval(() => { setSeconds((prevSeconds) => { if (prevSeconds >= 59) { setMinutes((prevMinutes) => prevMinutes + 1); return 0; } return prevSeconds + 1; }); }, 1000); return () => clearInterval(interval); }, [match.event_key, match.event_live, match.event_status]); const displayTime = `${minutes}:${seconds.toString().padStart(2, "0")}`; return ( {/* Top Bar */} router.back()} style={styles.iconBtn} > {match.event_status || "Live"} {/* Score Section */} toggleTeamFavorite(match.home_team_key, true)} disabled={homeFavLoading} style={styles.starBtnLeft} > {match.event_home_team} {match.event_final_result?.replace(" - ", "-") || "0-0"} {match.event_status && ( {match.event_status} )} {displayTime} {match.goalscorers && match.goalscorers.length > 0 && ( {match.goalscorers[match.goalscorers.length - 1].home_scorer || match.goalscorers[match.goalscorers.length - 1].away_scorer} )} toggleTeamFavorite(match.away_team_key, false)} disabled={awayFavLoading} style={styles.starBtnRight} > {match.event_away_team} ); } const styles = StyleSheet.create({ container: { paddingBottom: 24, }, topBar: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", paddingHorizontal: 16, marginBottom: 20, }, leftContainer: { width: 60, }, rightActions: { flexDirection: "row", justifyContent: "flex-end", width: 80, }, iconBtn: { padding: 6, marginLeft: 4, }, statusContainer: { backgroundColor: "rgba(255,255,255,0.1)", paddingHorizontal: 12, paddingVertical: 4, borderRadius: 12, }, statusText: { color: "#FFF", fontWeight: "600", fontSize: 14, }, scoreRow: { flexDirection: "row", alignItems: "flex-start", justifyContent: "space-between", paddingHorizontal: 24, }, teamInfo: { alignItems: "center", width: "30%", }, teamLogoRow: { flexDirection: "row", alignItems: "center", justifyContent: "center", marginBottom: 10, }, logoContainer: { width: 70, height: 70, justifyContent: "center", alignItems: "center", }, starBtnLeft: { padding: 8, marginRight: -4, }, starBtnRight: { padding: 8, marginLeft: -4, }, teamLogo: { width: 60, height: 60, resizeMode: "contain", }, teamName: { color: "#FFF", fontSize: 14, fontWeight: "700", textAlign: "center", lineHeight: 18, }, centerScore: { alignItems: "center", justifyContent: "center", width: "40%", paddingTop: 10, }, scoreBox: { backgroundColor: "#FFF", paddingHorizontal: 20, paddingVertical: 10, borderRadius: 14, marginBottom: 8, minWidth: 100, alignItems: "center", }, scoreValue: { color: "#000", fontSize: 25, fontWeight: "700", lineHeight: 30, letterSpacing: 1, }, timeText: { color: "#FF4444", fontWeight: "700", fontSize: 14, }, timeInfoRow: { flexDirection: "row", alignItems: "center", marginBottom: 4, }, statusLabel: { color: "#FFF", fontWeight: "700", fontSize: 14, marginRight: 6, }, lastGoalContainer: { flexDirection: "row", alignItems: "center", marginTop: 4, opacity: 0.9, }, lastGoalText: { color: "#FFF", fontSize: 10, marginLeft: 4, }, });