优化比赛卡片组件,增加比分领先状态和额外统计信息的显示逻辑

This commit is contained in:
yuchenglong
2026-01-21 09:26:47 +08:00
parent 0c57af1ca8
commit 547c204e88

View File

@@ -123,12 +123,42 @@ export function MatchCard({
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) {
if (s && s !== "-" && s !== "0 - 0") const h = parseInt(m[1]);
return { home: s, away: "", hasScore: true }; const a = parseInt(m[2]);
if (s === "0 - 0" || s === "0-0") return {
return { home: "0", away: "0", hasScore: true }; home: m[1],
return { home: "", away: "", hasScore: false }; away: m[2],
hasScore: true,
homeLead: h > a,
awayLead: a > h,
};
}
if (s && s !== "-" && s !== "0 - 0") {
return {
home: s,
away: "",
hasScore: true,
homeLead: false,
awayLead: false,
};
}
if (s === "0 - 0" || s === "0-0") {
return {
home: "0",
away: "0",
hasScore: true,
homeLead: false,
awayLead: false,
};
}
return {
home: "",
away: "",
hasScore: false,
homeLead: false,
awayLead: false,
};
}, [match.scoreText]); }, [match.scoreText]);
const cardsCount = React.useMemo(() => { const cardsCount = React.useMemo(() => {
@@ -242,50 +272,56 @@ export function MatchCard({
}; };
const renderOddsRow = (bookmakerName: string, isHighlight: boolean) => { const renderOddsRow = (bookmakerName: string, isHighlight: boolean) => {
if (!oddsSettings.enabled || !bookmakerName || odds.length === 0) if (!oddsSettings.enabled || !bookmakerName) return null;
return null;
const item = odds.find((o) => o.odd_bookmakers === bookmakerName);
if (!item) return null;
const val1 = item.odd_1 || item.ah0_1 || "-"; const item = odds.find((o) => o.odd_bookmakers === bookmakerName);
const val2 = item.odd_x || "0" || "-"; const hasOdds = !!item;
const val3 = item.odd_2 || item.ah0_2 || "-";
const val1 = item?.odd_1 || item?.ah0_1 || "-";
const val2 = item?.odd_x || "0" || "-";
const val3 = item?.odd_2 || item?.ah0_2 || "-";
return ( return (
<View style={styles.bookmakerOddsRow}> <View style={styles.bookmakerOddsRow}>
<View style={[styles.oddBadge, { backgroundColor: oddBadgeBg }]}> {hasOdds ? (
<ThemedText <>
style={[ <View style={[styles.oddBadge, { backgroundColor: oddBadgeBg }]}>
styles.oddText, <ThemedText
{ color: isDark ? "#fff" : "#333" }, style={[
isHighlight && styles.oddTextHighlight, styles.oddText,
]} { color: isDark ? "#fff" : "#333" },
> isHighlight && styles.oddTextHighlight,
{val1} ]}
</ThemedText> >
</View> {val1}
<View style={[styles.oddBadge, { backgroundColor: oddBadgeBg }]}> </ThemedText>
<ThemedText </View>
style={[ <View style={[styles.oddBadge, { backgroundColor: oddBadgeBg }]}>
styles.oddText, <ThemedText
{ color: isDark ? "#fff" : "#333" }, style={[
isHighlight && styles.oddTextHighlight, styles.oddText,
]} { color: isDark ? "#fff" : "#333" },
> isHighlight && styles.oddTextHighlight,
{val2} ]}
</ThemedText> >
</View> {val2}
<View style={[styles.oddBadge, { backgroundColor: oddBadgeBg }]}> </ThemedText>
<ThemedText </View>
style={[ <View style={[styles.oddBadge, { backgroundColor: oddBadgeBg }]}>
styles.oddText, <ThemedText
{ color: isDark ? "#fff" : "#333" }, style={[
isHighlight && styles.oddTextHighlight, styles.oddText,
]} { color: isDark ? "#fff" : "#333" },
> isHighlight && styles.oddTextHighlight,
{val3} ]}
</ThemedText> >
</View> {val3}
</ThemedText>
</View>
</>
) : (
<View style={{ width: 98 }} />
)}
</View> </View>
); );
}; };
@@ -395,55 +431,90 @@ export function MatchCard({
</View> </View>
</View> </View>
{/* Right: Score box + favorite */} {/* Right: Score box + extra stats + favorite */}
<View style={styles.right}> <View style={styles.right}>
{scoreParts.hasScore ? ( <View style={styles.scoreContainer}>
<View {scoreParts.hasScore ? (
style={[ <View
styles.scoreBox, style={[
{ styles.scoreBox,
borderColor: isLive ? "#FF9500" : scoreBorder, {
backgroundColor: scoreBg, borderColor:
}, scoreParts.homeLead || scoreParts.awayLead
]} ? "#FF9500"
: scoreBorder,
backgroundColor: scoreBg,
},
]}
>
<View
style={[
styles.scoreHalf,
scoreParts.homeLead && styles.scoreHalfLead,
]}
>
<ThemedText
style={[
styles.scoreBoxText,
scoreParts.homeLead && styles.scoreTextLead,
]}
numberOfLines={1}
>
{scoreParts.home}
</ThemedText>
</View>
<View style={styles.scoreDivider} />
<View
style={[
styles.scoreHalf,
scoreParts.awayLead && styles.scoreHalfLead,
]}
>
<ThemedText
style={[
styles.scoreBoxText,
scoreParts.awayLead && styles.scoreTextLead,
]}
numberOfLines={1}
>
{scoreParts.away}
</ThemedText>
</View>
</View>
) : (
<View style={styles.scoreBoxPlaceholder} />
)}
</View>
<View style={styles.extraStatsContainer}>
{extraStats.home !== "" || extraStats.away !== "" ? (
<View style={styles.extraStatsColumn}>
<ThemedText style={styles.extraStatText}>
{extraStats.home}
</ThemedText>
<ThemedText style={styles.extraStatText}>
{extraStats.away}
</ThemedText>
</View>
) : null}
</View>
<View style={styles.favoriteContainer}>
<TouchableOpacity
onPress={(e) => {
e.stopPropagation();
toggleFavorite();
}}
disabled={loading}
hitSlop={{ top: 12, bottom: 12, left: 12, right: 12 }}
> >
<ThemedText style={styles.scoreBoxText} numberOfLines={1}> <IconSymbol
{scoreParts.home} name={isFav ? "star" : "star-outline"}
</ThemedText> size={15}
<View style={styles.scoreDivider} /> color={isFav ? "#FFD700" : iconColor}
<ThemedText style={styles.scoreBoxText} numberOfLines={1}> />
{scoreParts.away} </TouchableOpacity>
</ThemedText> </View>
</View>
) : (
<View style={styles.scoreBoxPlaceholder} />
)}
{(extraStats.home !== "" || extraStats.away !== "") && (
<View style={styles.extraStatsColumn}>
<ThemedText style={styles.extraStatText}>
{extraStats.home}
</ThemedText>
<ThemedText style={styles.extraStatText}>
{extraStats.away}
</ThemedText>
</View>
)}
<TouchableOpacity
onPress={(e) => {
e.stopPropagation();
toggleFavorite();
}}
disabled={loading}
hitSlop={{ top: 12, bottom: 12, left: 12, right: 12 }}
>
<IconSymbol
name={isFav ? "star" : "star-outline"}
size={15}
color={isFav ? "#FFD700" : iconColor}
/>
</TouchableOpacity>
</View> </View>
</View> </View>
</Pressable> </Pressable>
@@ -505,6 +576,7 @@ const styles = StyleSheet.create({
alignItems: "center", alignItems: "center",
flex: 1, flex: 1,
minWidth: 0, minWidth: 0,
marginRight: 8,
}, },
teamLogo: { teamLogo: {
width: 18, width: 18,
@@ -514,13 +586,14 @@ const styles = StyleSheet.create({
fontSize: 12, fontSize: 12,
fontWeight: "600", fontWeight: "600",
marginLeft: 6, marginLeft: 6,
flex: 1, flexShrink: 1,
minWidth: 0, minWidth: 0,
}, },
bookmakerOddsRow: { bookmakerOddsRow: {
marginLeft: 4, width: 98,
flexDirection: "row", flexDirection: "row",
gap: 4, gap: 4,
justifyContent: "flex-end",
}, },
oddBadge: { oddBadge: {
paddingHorizontal: 5, paddingHorizontal: 5,
@@ -540,35 +613,58 @@ const styles = StyleSheet.create({
right: { right: {
flexDirection: "row", flexDirection: "row",
alignItems: "center", alignItems: "center",
gap: 6, },
scoreContainer: {
width: 25,
alignItems: "center",
},
extraStatsContainer: {
width: 18,
alignItems: "center",
marginHorizontal: 4,
},
favoriteContainer: {
width: 25,
alignItems: "center",
}, },
scoreBox: { scoreBox: {
width: 30, width: 28,
height: 54, height: 55,
borderRadius: 8, borderRadius: 8,
borderWidth: 1.5, borderWidth: 1.2,
alignItems: "stretch",
justifyContent: "center",
overflow: "hidden",
},
scoreHalf: {
flex: 1,
alignItems: "center", alignItems: "center",
justifyContent: "center", justifyContent: "center",
}, },
scoreHalfLead: {
backgroundColor: "rgba(255, 149, 0, 0.08)",
},
scoreBoxText: { scoreBoxText: {
fontSize: 20, fontSize: 15,
fontWeight: "900", fontWeight: "900",
}, },
scoreTextLead: {
color: "#FF9500",
},
scoreDivider: { scoreDivider: {
width: "60%", width: "100%",
height: 1, height: 1,
backgroundColor: "rgba(0,0,0,0.06)", backgroundColor: "rgba(0,0,0,0.06)",
marginVertical: 1,
}, },
scoreBoxPlaceholder: { scoreBoxPlaceholder: {
width: 36, width: 28,
height: 54, height: 48,
}, },
cardsInline: { cardsInline: {
flexDirection: "row", flexDirection: "row",
alignItems: "center", alignItems: "center",
gap: 4, gap: 6,
marginLeft: 6, marginLeft: 8,
flexShrink: 0, flexShrink: 0,
}, },
cardBadge: { cardBadge: {
@@ -577,7 +673,7 @@ const styles = StyleSheet.create({
borderRadius: 3, borderRadius: 3,
alignItems: "center", alignItems: "center",
justifyContent: "center", justifyContent: "center",
paddingHorizontal: 3, paddingHorizontal: 4,
}, },
cardBadgeYellow: { cardBadgeYellow: {
backgroundColor: "#FFC400", backgroundColor: "#FFC400",
@@ -588,13 +684,13 @@ const styles = StyleSheet.create({
extraStatsColumn: { extraStatsColumn: {
alignItems: "center", alignItems: "center",
justifyContent: "space-between", justifyContent: "space-between",
height: 48, height: 55,
paddingVertical: 2, paddingVertical: 2,
}, },
extraStatText: { extraStatText: {
fontSize: 12, fontSize: 11,
fontWeight: "500", fontWeight: "500",
opacity: 0.6, opacity: 0.4,
}, },
cardBadgeText: { cardBadgeText: {
fontSize: 10, fontSize: 10,