添加赔率行渲染功能,优化比赛卡片中赔率显示逻辑和样式

This commit is contained in:
yuchenglong
2026-01-20 09:15:37 +08:00
parent 7024b03c30
commit 85c9b666d7

View File

@@ -142,6 +142,55 @@ export function MatchCard({
} }
}; };
const renderOddsRow = (bookmakerName: string, isHighlight: boolean) => {
if (!oddsSettings.enabled || !bookmakerName || odds.length === 0)
return null;
const item = odds.find((o) => o.odd_bookmakers === bookmakerName);
if (!item) return null;
const val1 = item.odd_1 || item.ah0_1 || "-";
const val2 = item.odd_x || "0" || "-";
const val3 = item.odd_2 || item.ah0_2 || "-";
return (
<View style={styles.bookmakerOddsRow}>
<View style={[styles.oddBadge, { backgroundColor: oddBadgeBg }]}>
<ThemedText
style={[
styles.oddText,
{ color: isDark ? "#fff" : "#333" },
isHighlight && styles.oddTextHighlight,
]}
>
{val1}
</ThemedText>
</View>
<View style={[styles.oddBadge, { backgroundColor: oddBadgeBg }]}>
<ThemedText
style={[
styles.oddText,
{ color: isDark ? "#fff" : "#333" },
isHighlight && styles.oddTextHighlight,
]}
>
{val2}
</ThemedText>
</View>
<View style={[styles.oddBadge, { backgroundColor: oddBadgeBg }]}>
<ThemedText
style={[
styles.oddText,
{ color: isDark ? "#fff" : "#333" },
isHighlight && styles.oddTextHighlight,
]}
>
{val3}
</ThemedText>
</View>
</View>
);
};
return ( return (
<Pressable <Pressable
onPress={handlePress} onPress={handlePress}
@@ -176,103 +225,49 @@ export function MatchCard({
</ThemedText> </ThemedText>
</View> </View>
{/* Middle: Teams & Odds */} {/* Middle: Teams & Odds Row Integration */}
<View style={styles.middle}> <View style={styles.middle}>
<View style={styles.teamContainer}> <View style={styles.contentRow}>
<View style={styles.teamRow}> <View style={styles.teamInfo}>
{match.homeTeamLogo ? ( {match.homeTeamLogo && (
<Image <Image
source={{ uri: match.homeTeamLogo }} source={{ uri: match.homeTeamLogo }}
style={styles.teamLogo} style={styles.teamLogo}
contentFit="contain" contentFit="contain"
/> />
) : null} )}
<ThemedText <ThemedText
type="defaultSemiBold" type="defaultSemiBold"
style={styles.teamLine} style={styles.teamName}
numberOfLines={1} numberOfLines={1}
ellipsizeMode="tail" ellipsizeMode="tail"
> >
{match.homeTeamName || match.home} {match.homeTeamName || match.home}
</ThemedText> </ThemedText>
</View> </View>
<View style={styles.teamRow}> {renderOddsRow(oddsSettings.selectedBookmakers[0], true)}
{match.awayTeamLogo ? ( </View>
<View style={styles.contentRow}>
<View style={styles.teamInfo}>
{match.awayTeamLogo && (
<Image <Image
source={{ uri: match.awayTeamLogo }} source={{ uri: match.awayTeamLogo }}
style={styles.teamLogo} style={styles.teamLogo}
contentFit="contain" contentFit="contain"
/> />
) : null} )}
<ThemedText <ThemedText
type="defaultSemiBold" type="defaultSemiBold"
style={styles.teamLine} style={styles.teamName}
numberOfLines={1} numberOfLines={1}
ellipsizeMode="tail" ellipsizeMode="tail"
> >
{match.awayTeamName || match.away} {match.awayTeamName || match.away}
</ThemedText> </ThemedText>
</View> </View>
{renderOddsRow(oddsSettings.selectedBookmakers[1], false)}
</View> </View>
{/* Odds Section */}
{oddsSettings.enabled && odds.length > 0 && (
<View style={styles.oddsContainer}>
{oddsSettings.selectedBookmakers.map((bookmaker, idx) => {
const item = odds.find((o) => o.odd_bookmakers === bookmaker);
if (!item) return null;
// Pick 3 values to display. Using odd_1, odd_x, odd_2 for example.
// Or try to match the screenshot's 3-column style.
const val1 = item.odd_1 || item.ah0_1 || "-";
const val2 = item.odd_x || "0" || "-";
const val3 = item.odd_2 || item.ah0_2 || "-";
return (
<View key={bookmaker} style={styles.bookmakerOddsRow}>
<View
style={[styles.oddBadge, { backgroundColor: oddBadgeBg }]}
>
<ThemedText
style={[
styles.oddText,
{ color: isDark ? "#fff" : "#000" },
idx === 0 && styles.oddTextHighlight,
]}
>
{val1}
</ThemedText>
</View>
<View
style={[styles.oddBadge, { backgroundColor: oddBadgeBg }]}
>
<ThemedText
style={[
styles.oddText,
{ color: isDark ? "#fff" : "#000" },
idx === 0 && styles.oddTextHighlight,
]}
>
{val2}
</ThemedText>
</View>
<View
style={[styles.oddBadge, { backgroundColor: oddBadgeBg }]}
>
<ThemedText
style={[
styles.oddText,
{ color: isDark ? "#fff" : "#000" },
idx === 0 && styles.oddTextHighlight,
]}
>
{val3}
</ThemedText>
</View>
</View>
);
})}
</View>
)}
</View> </View>
{/* Right: Score box + favorite */} {/* Right: Score box + favorite */}
@@ -281,12 +276,16 @@ export function MatchCard({
<View <View
style={[ style={[
styles.scoreBox, styles.scoreBox,
{ borderColor: scoreBorder, backgroundColor: scoreBg }, {
borderColor: isLive ? "#FF9500" : scoreBorder,
backgroundColor: scoreBg,
},
]} ]}
> >
<ThemedText style={styles.scoreBoxText} numberOfLines={1}> <ThemedText style={styles.scoreBoxText} numberOfLines={1}>
{scoreParts.home} {scoreParts.home}
</ThemedText> </ThemedText>
<View style={styles.scoreDivider} />
<ThemedText style={styles.scoreBoxText} numberOfLines={1}> <ThemedText style={styles.scoreBoxText} numberOfLines={1}>
{scoreParts.away} {scoreParts.away}
</ThemedText> </ThemedText>
@@ -305,7 +304,7 @@ export function MatchCard({
> >
<IconSymbol <IconSymbol
name={isFav ? "star" : "star-outline"} name={isFav ? "star" : "star-outline"}
size={22} size={20}
color={isFav ? "#FFD700" : iconColor} color={isFav ? "#FFD700" : iconColor}
/> />
</TouchableOpacity> </TouchableOpacity>
@@ -318,121 +317,114 @@ export function MatchCard({
const styles = StyleSheet.create({ const styles = StyleSheet.create({
card: { card: {
height: 78, height: 78,
paddingHorizontal: 14, paddingHorizontal: 12,
marginBottom: 12, marginBottom: 8,
borderRadius: 14, borderRadius: 14,
borderWidth: 1, borderWidth: 1,
justifyContent: "center", justifyContent: "center",
overflow: "hidden", overflow: "hidden",
// iOS shadow
shadowColor: "#000", shadowColor: "#000",
shadowOffset: { width: 0, height: 0.5 }, shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.03, shadowOpacity: 0.05,
shadowRadius: 2, shadowRadius: 2,
// Android elevation elevation: 2,
elevation: 1,
}, },
row: { row: {
flexDirection: "row", flexDirection: "row",
alignItems: "center", alignItems: "center",
gap: 12,
}, },
left: { left: {
width: 52, width: 44,
alignItems: "center", alignItems: "flex-start",
justifyContent: "center", justifyContent: "center",
gap: 6, gap: 4,
}, },
leagueShortText: { leagueShortText: {
fontSize: 12, fontSize: 12,
fontWeight: "700", fontWeight: "700",
opacity: 0.85, opacity: 0.8,
}, },
timeText: { timeText: {
fontSize: 12, fontSize: 12,
opacity: 0.55, opacity: 0.5,
}, },
timeTextLive: { timeTextLive: {
color: "#FF3B30", color: "#FF3B30",
opacity: 1, opacity: 1,
fontWeight: "bold", fontWeight: "800",
}, },
middle: { middle: {
flex: 1, flex: 1,
justifyContent: "center",
gap: 10,
marginHorizontal: 8,
},
contentRow: {
flexDirection: "row", flexDirection: "row",
alignItems: "center", alignItems: "center",
justifyContent: "space-between", justifyContent: "space-between",
gap: 8,
minWidth: 0,
}, },
teamContainer: { teamInfo: {
flex: 1,
justifyContent: "center",
gap: 8,
minWidth: 0,
},
teamRow: {
flexDirection: "row", flexDirection: "row",
alignItems: "center", alignItems: "center",
gap: 8, flex: 1,
marginRight: 6,
}, },
teamLogo: { teamLogo: {
width: 24, width: 22,
height: 24, height: 22,
}, },
teamLine: { teamName: {
fontSize: 15, fontSize: 14,
lineHeight: 18, fontWeight: "600",
marginLeft: 6,
flex: 1, flex: 1,
}, },
oddsContainer: {
gap: 8,
alignItems: "flex-end",
},
bookmakerOddsRow: { bookmakerOddsRow: {
flexDirection: "row", flexDirection: "row",
gap: 4, gap: 4,
}, },
oddBadge: { oddBadge: {
backgroundColor: "rgba(0,0,0,0.03)", paddingHorizontal: 5,
paddingHorizontal: 6,
paddingVertical: 2, paddingVertical: 2,
borderRadius: 6, borderRadius: 6,
minWidth: 40, minWidth: 36,
alignItems: "center", alignItems: "center",
justifyContent: "center",
}, },
oddText: { oddText: {
fontSize: 11, fontSize: 10.5,
fontWeight: "600", fontWeight: "700",
opacity: 0.8, opacity: 0.9,
}, },
oddTextHighlight: { oddTextHighlight: {
color: "#FF9500", color: "#FF9500",
opacity: 1,
}, },
right: { right: {
flexDirection: "row", flexDirection: "row",
alignItems: "center", alignItems: "center",
gap: 10,
},
scoreBox: {
width: 44,
height: 56,
borderRadius: 10,
borderWidth: 1,
borderColor: "rgba(0,0,0,0.12)",
backgroundColor: "rgba(255,255,255,0.6)",
alignItems: "center",
justifyContent: "center",
gap: 6, gap: 6,
}, },
scoreBox: {
width: 36,
height: 54,
borderRadius: 8,
borderWidth: 1.5,
alignItems: "center",
justifyContent: "center",
},
scoreBoxText: { scoreBoxText: {
fontSize: 16, fontSize: 20,
fontWeight: "700", fontWeight: "900",
opacity: 0.9, },
scoreDivider: {
width: "60%",
height: 1,
backgroundColor: "rgba(0,0,0,0.06)",
marginVertical: 1,
}, },
scoreBoxPlaceholder: { scoreBoxPlaceholder: {
width: 44, width: 36,
height: 56, height: 54,
}, },
}); });