优化比赛卡片显示,添加球队名称和logo,调整样式;更新实时比分功能,简化数据处理逻辑
This commit is contained in:
@@ -322,11 +322,6 @@ export default function HomeScreen() {
|
|||||||
deviceTimeZone,
|
deviceTimeZone,
|
||||||
);
|
);
|
||||||
|
|
||||||
//将isLive全改为true
|
|
||||||
list.forEach((m) => {
|
|
||||||
(m as Match).isLive = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
const normalizeDate = (d: Date) => {
|
const normalizeDate = (d: Date) => {
|
||||||
const year = d.getFullYear();
|
const year = d.getFullYear();
|
||||||
const month = String(d.getMonth() + 1).padStart(2, "0");
|
const month = String(d.getMonth() + 1).padStart(2, "0");
|
||||||
@@ -340,8 +335,8 @@ export default function HomeScreen() {
|
|||||||
|
|
||||||
let merged: Match[] = list.map((m) => ({
|
let merged: Match[] = list.map((m) => ({
|
||||||
...m,
|
...m,
|
||||||
date: (m as any).date || selectedStr,
|
date: m.date || selectedStr,
|
||||||
sportId: (m as any).sportId ?? sportId,
|
sportId: m.sportId ?? sportId,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if (shouldMergeLive) {
|
if (shouldMergeLive) {
|
||||||
@@ -368,10 +363,16 @@ export default function HomeScreen() {
|
|||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
league: item.league_name,
|
league: item.league_name,
|
||||||
|
leagueName: item.league_name,
|
||||||
|
leagueLogo: item.league_logo,
|
||||||
time: formatLiveTime(item.event_status, item.event_time),
|
time: formatLiveTime(item.event_status, item.event_time),
|
||||||
date: item.event_date,
|
date: item.event_date,
|
||||||
home: item.event_home_team,
|
home: item.event_home_team,
|
||||||
away: item.event_away_team,
|
away: item.event_away_team,
|
||||||
|
homeTeamName: item.event_home_team,
|
||||||
|
awayTeamName: item.event_away_team,
|
||||||
|
homeTeamLogo: item.home_team_logo,
|
||||||
|
awayTeamLogo: item.away_team_logo,
|
||||||
scoreText: item.event_final_result || "0 - 0",
|
scoreText: item.event_final_result || "0 - 0",
|
||||||
fav: false,
|
fav: false,
|
||||||
sportId: sportId,
|
sportId: sportId,
|
||||||
@@ -415,18 +416,11 @@ export default function HomeScreen() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const isLiveRow = (m: Match) => {
|
|
||||||
const t = (m.time || "").trim();
|
|
||||||
return (
|
|
||||||
/\d+'$/.test(t) || /^\d{1,3}$/.test(t) || /\b(ht|half)\b/i.test(t)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 收藏置顶,其次直播置顶
|
// 收藏置顶,其次直播置顶
|
||||||
const sortedList = [...listWithFavStatus].sort((a, b) => {
|
const sortedList = [...listWithFavStatus].sort((a, b) => {
|
||||||
if (a.fav !== b.fav) return a.fav ? -1 : 1;
|
if (a.fav !== b.fav) return a.fav ? -1 : 1;
|
||||||
const aLive = isLiveRow(a);
|
const aLive = !!a.isLive;
|
||||||
const bLive = isLiveRow(b);
|
const bLive = !!b.isLive;
|
||||||
if (aLive !== bLive) return aLive ? -1 : 1;
|
if (aLive !== bLive) return aLive ? -1 : 1;
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
@@ -597,7 +591,6 @@ export default function HomeScreen() {
|
|||||||
onSelectDate={updateDate}
|
onSelectDate={updateDate}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
</ThemedView>
|
</ThemedView>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export default function LiveScreen() {
|
|||||||
const liveData = await fetchLiveScore(
|
const liveData = await fetchLiveScore(
|
||||||
state.selectedSportId,
|
state.selectedSportId,
|
||||||
state.selectedLeagueKey ? parseInt(state.selectedLeagueKey) : undefined,
|
state.selectedLeagueKey ? parseInt(state.selectedLeagueKey) : undefined,
|
||||||
state.timezone
|
state.timezone,
|
||||||
);
|
);
|
||||||
|
|
||||||
// 检查返回的数据是否为空或无效
|
// 检查返回的数据是否为空或无效
|
||||||
@@ -56,9 +56,15 @@ export default function LiveScreen() {
|
|||||||
const converted: Match[] = liveData.map((item: LiveScoreMatch) => ({
|
const converted: Match[] = liveData.map((item: LiveScoreMatch) => ({
|
||||||
id: item.event_key.toString(),
|
id: item.event_key.toString(),
|
||||||
league: item.league_name,
|
league: item.league_name,
|
||||||
|
leagueName: item.league_name,
|
||||||
|
leagueLogo: item.league_logo,
|
||||||
time: item.event_time,
|
time: item.event_time,
|
||||||
home: item.event_home_team,
|
home: item.event_home_team,
|
||||||
away: item.event_away_team,
|
away: item.event_away_team,
|
||||||
|
homeTeamName: item.event_home_team,
|
||||||
|
awayTeamName: item.event_away_team,
|
||||||
|
homeTeamLogo: item.home_team_logo,
|
||||||
|
awayTeamLogo: item.away_team_logo,
|
||||||
meta: item.event_status,
|
meta: item.event_status,
|
||||||
scoreText: item.event_final_result || "0 - 0",
|
scoreText: item.event_final_result || "0 - 0",
|
||||||
fav: false,
|
fav: false,
|
||||||
@@ -66,7 +72,6 @@ export default function LiveScreen() {
|
|||||||
sportId: state.selectedSportId ?? undefined,
|
sportId: state.selectedSportId ?? undefined,
|
||||||
isLive: true,
|
isLive: true,
|
||||||
date: item.event_date,
|
date: item.event_date,
|
||||||
// sport: item.sport_name,
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const token = await storage.getAccessToken();
|
const token = await storage.getAccessToken();
|
||||||
@@ -83,7 +88,7 @@ export default function LiveScreen() {
|
|||||||
console.error(`Check favorite failed for match ${m.id}:`, error);
|
console.error(`Check favorite failed for match ${m.id}:`, error);
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,7 +109,7 @@ export default function LiveScreen() {
|
|||||||
const handleFavoriteToggle = (matchId: string, isFav: boolean) => {
|
const handleFavoriteToggle = (matchId: string, isFav: boolean) => {
|
||||||
setMatches((prev) => {
|
setMatches((prev) => {
|
||||||
const updated = prev.map((m) =>
|
const updated = prev.map((m) =>
|
||||||
m.id === matchId ? { ...m, fav: isFav } : m
|
m.id === matchId ? { ...m, fav: isFav } : m,
|
||||||
);
|
);
|
||||||
return [...updated].sort((a, b) => {
|
return [...updated].sort((a, b) => {
|
||||||
if (a.fav === b.fav) return 0;
|
if (a.fav === b.fav) return 0;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Colors } from "@/constants/theme";
|
|||||||
import { useTheme } from "@/context/ThemeContext";
|
import { useTheme } from "@/context/ThemeContext";
|
||||||
import { addFavorite, removeFavorite } from "@/lib/api";
|
import { addFavorite, removeFavorite } from "@/lib/api";
|
||||||
import { Match } from "@/types/api";
|
import { Match } from "@/types/api";
|
||||||
|
import { Image } from "expo-image";
|
||||||
import { LinearGradient } from "expo-linear-gradient";
|
import { LinearGradient } from "expo-linear-gradient";
|
||||||
import { useRouter } from "expo-router";
|
import { useRouter } from "expo-router";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
@@ -50,17 +51,19 @@ export function MatchCard({
|
|||||||
}, [match.time]);
|
}, [match.time]);
|
||||||
|
|
||||||
const leagueShort = React.useMemo(() => {
|
const leagueShort = React.useMemo(() => {
|
||||||
const league = (match.league || "").trim();
|
const league = (match.leagueName || match.league || "").trim();
|
||||||
if (!league) return "--";
|
if (!league) return "--";
|
||||||
const first = league.split(/[^A-Za-z0-9]+/).filter(Boolean)[0] || league;
|
const first = league.split(/[^A-Za-z0-9]+/).filter(Boolean)[0] || league;
|
||||||
return first.slice(0, 3).toUpperCase();
|
return first.slice(0, 3).toUpperCase();
|
||||||
}, [match.league]);
|
}, [match.leagueName, match.league]);
|
||||||
|
|
||||||
const scoreParts = React.useMemo(() => {
|
const scoreParts = React.useMemo(() => {
|
||||||
const s = (match.scoreText || "").trim();
|
const s = (match.scoreText || "").trim();
|
||||||
const m = s.match(/(\d+)\s*[-:]\s*(\d+)/);
|
const m = s.match(/(\d+)\s*[-:]\s*(\d+)/);
|
||||||
if (m) return { home: m[1], away: m[2], hasScore: true };
|
if (m) return { home: m[1], away: m[2], hasScore: true };
|
||||||
if (s && s !== "-") return { home: s, away: "", hasScore: true };
|
if (s && s !== "-" && s !== "0 - 0")
|
||||||
|
return { home: s, away: "", hasScore: true };
|
||||||
|
if (s === "0 - 0") return { home: "0", away: "0", hasScore: true };
|
||||||
return { home: "", away: "", hasScore: false };
|
return { home: "", away: "", hasScore: false };
|
||||||
}, [match.scoreText]);
|
}, [match.scoreText]);
|
||||||
|
|
||||||
@@ -137,22 +140,40 @@ export function MatchCard({
|
|||||||
|
|
||||||
{/* Middle: Teams */}
|
{/* Middle: Teams */}
|
||||||
<View style={styles.middle}>
|
<View style={styles.middle}>
|
||||||
<ThemedText
|
<View style={styles.teamRow}>
|
||||||
type="defaultSemiBold"
|
{match.homeTeamLogo ? (
|
||||||
style={styles.teamLine}
|
<Image
|
||||||
numberOfLines={1}
|
source={{ uri: match.homeTeamLogo }}
|
||||||
ellipsizeMode="tail"
|
style={styles.teamLogo}
|
||||||
>
|
contentFit="contain"
|
||||||
{match.home}
|
/>
|
||||||
</ThemedText>
|
) : null}
|
||||||
<ThemedText
|
<ThemedText
|
||||||
type="defaultSemiBold"
|
type="defaultSemiBold"
|
||||||
style={styles.teamLine}
|
style={styles.teamLine}
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
ellipsizeMode="tail"
|
ellipsizeMode="tail"
|
||||||
>
|
>
|
||||||
{match.away}
|
{match.homeTeamName || match.home}
|
||||||
</ThemedText>
|
</ThemedText>
|
||||||
|
</View>
|
||||||
|
<View style={styles.teamRow}>
|
||||||
|
{match.awayTeamLogo ? (
|
||||||
|
<Image
|
||||||
|
source={{ uri: match.awayTeamLogo }}
|
||||||
|
style={styles.teamLogo}
|
||||||
|
contentFit="contain"
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
<ThemedText
|
||||||
|
type="defaultSemiBold"
|
||||||
|
style={styles.teamLine}
|
||||||
|
numberOfLines={1}
|
||||||
|
ellipsizeMode="tail"
|
||||||
|
>
|
||||||
|
{match.awayTeamName || match.away}
|
||||||
|
</ThemedText>
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Right: Score box + favorite */}
|
{/* Right: Score box + favorite */}
|
||||||
@@ -235,16 +256,27 @@ const styles = StyleSheet.create({
|
|||||||
timeTextLive: {
|
timeTextLive: {
|
||||||
color: "#FF3B30",
|
color: "#FF3B30",
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
|
fontWeight: "bold",
|
||||||
},
|
},
|
||||||
middle: {
|
middle: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
gap: 6,
|
gap: 8,
|
||||||
minWidth: 0,
|
minWidth: 0,
|
||||||
},
|
},
|
||||||
|
teamRow: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: 8,
|
||||||
|
},
|
||||||
|
teamLogo: {
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
},
|
||||||
teamLine: {
|
teamLine: {
|
||||||
fontSize: 16,
|
fontSize: 15,
|
||||||
lineHeight: 18,
|
lineHeight: 18,
|
||||||
|
flex: 1,
|
||||||
},
|
},
|
||||||
right: {
|
right: {
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
|
|||||||
Reference in New Issue
Block a user