diff --git a/app/match-detail/[id].tsx b/app/match-detail/[id].tsx
index 59ceec9..65a2cbc 100644
--- a/app/match-detail/[id].tsx
+++ b/app/match-detail/[id].tsx
@@ -1,15 +1,16 @@
+import { BasketballScoreTable } from "@/components/match-detail/basketball/basketball-score-table";
+import { FootballScoreTable } from "@/components/match-detail/football/football-score-table";
import { LeagueInfo } from "@/components/match-detail/league-info";
import { MatchInfoCard } from "@/components/match-detail/match-info-card";
import { MatchTabs } from "@/components/match-detail/match-tabs";
import { ScoreHeader } from "@/components/match-detail/score-header";
-import { ScoreTable } from "@/components/match-detail/score-table";
import { ThemedText } from "@/components/themed-text";
import { ThemedView } from "@/components/themed-view";
import { Colors } from "@/constants/theme";
import { useTheme } from "@/context/ThemeContext";
import { fetchMatchDetail } from "@/lib/api";
import { MatchDetailData } from "@/types/api";
-import { Stack, useLocalSearchParams, useRouter } from "expo-router";
+import { useLocalSearchParams, useRouter } from "expo-router";
import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import {
@@ -40,6 +41,30 @@ export default function MatchDetailScreen() {
}
}, [id]);
+ // 当数据加载完成且 sportId 变化时,检查并重置 activeTab
+ useEffect(() => {
+ if (data?.match?.sportId) {
+ const sportId = data.match.sportId;
+ let validTabs: string[] = [];
+
+ if (sportId === 1) {
+ // 足球
+ validTabs = ["info", "stats", "odds", "h2h", "chat"];
+ } else if (sportId === 2) {
+ // 篮球
+ validTabs = ["info", "h2h", "chat"];
+ } else {
+ // 默认
+ validTabs = ["info", "h2h", "chat"];
+ }
+
+ // 如果当前 activeTab 不在有效标签列表中,重置为第一个
+ if (!validTabs.includes(activeTab)) {
+ setActiveTab(validTabs[0]);
+ }
+ }
+ }, [data?.match?.sportId]);
+
const loadMatchDetail = async () => {
try {
setLoading(true);
@@ -73,13 +98,51 @@ export default function MatchDetailScreen() {
}
const renderTabContent = () => {
+ const sportId = data?.match?.sportId || 1;
+
switch (activeTab) {
case "info":
+ // 根据 sportId 显示不同的详情组件
+ if (sportId === 1) {
+ // 足球:显示 FootballScoreTable (半场/全场) 和 MatchInfoCard
+ return (
+ <>
+
+
+ >
+ );
+ } else if (sportId === 2) {
+ // 篮球:显示 BasketballScoreTable (4节) 和 MatchInfoCard
+ return (
+ <>
+
+
+ >
+ );
+ } else {
+ // 默认使用足球组件
+ return (
+ <>
+
+
+ >
+ );
+ }
+ case "stats":
return (
- <>
-
-
- >
+
+
+ {t("detail.empty_stats")}
+
+
+ );
+ case "odds":
+ return (
+
+
+ {t("detail.empty_odds")}
+
+
);
case "h2h":
return (
@@ -115,6 +178,7 @@ export default function MatchDetailScreen() {
activeTab={activeTab}
onTabChange={setActiveTab}
isDark={isDark}
+ sportId={data.match.sportId}
/>
{renderTabContent()}
diff --git a/components/match-detail/score-table.tsx b/components/match-detail/basketball/basketball-score-table.tsx
similarity index 71%
rename from components/match-detail/score-table.tsx
rename to components/match-detail/basketball/basketball-score-table.tsx
index fc3801c..48fa7a4 100644
--- a/components/match-detail/score-table.tsx
+++ b/components/match-detail/basketball/basketball-score-table.tsx
@@ -4,45 +4,55 @@ import React from "react";
import { useTranslation } from "react-i18next";
import { Image, StyleSheet, View } from "react-native";
-interface ScoreTableProps {
+interface BasketballScoreTableProps {
data: MatchDetailData;
isDark: boolean;
}
-export function ScoreTable({ data, isDark }: ScoreTableProps) {
+export function BasketballScoreTable({ data, isDark }: BasketballScoreTableProps) {
const { t } = useTranslation();
const { match } = data;
const bgColor = isDark ? "#1C1C1E" : "#FFF";
const headerTextColor = isDark ? "#666" : "#999";
- // Mock quarters for demo purposes as seen in screenshot
- // In real app, these would come from the API (e.g. match.eventQuarter or specific fields)
+ // 解析比分 - 篮球通常是 4 节
+ const parseScore = (scoreString: string) => {
+ if (!scoreString || scoreString === "-") return [0, 0, 0, 0, 0];
+ // 假设格式可能是 "25-20,30-28,22-25,28-26" 或类似
+ // 这里简化处理,实际需要根据 API 返回格式解析
+ return [0, 0, 0, 0, 0]; // total, q1, q2, q3, q4
+ };
+
+ const homeScores = parseScore(match.eventFinalResult || "-");
+ const awayScores = parseScore(match.eventFinalResult || "-");
+
const headers = [
t("detail.score_table.team"),
t("detail.score_table.total"),
- "1",
- "2",
- "3",
- "4",
+ "Q1",
+ "Q2",
+ "Q3",
+ "Q4",
];
+
const rows = [
{
logo: match.homeTeamLogo,
name: match.eventHomeTeam,
- total: 0,
- q1: 0,
- q2: 0,
- q3: 0,
- q4: 0,
+ total: homeScores[0],
+ q1: homeScores[1],
+ q2: homeScores[2],
+ q3: homeScores[3],
+ q4: homeScores[4],
},
{
logo: match.awayTeamLogo,
name: match.eventAwayTeam,
- total: 0,
- q1: 0,
- q2: 0,
- q3: 0,
- q4: 0,
+ total: awayScores[0],
+ q1: awayScores[1],
+ q2: awayScores[2],
+ q3: awayScores[3],
+ q4: awayScores[4],
},
];
@@ -70,6 +80,9 @@ export function ScoreTable({ data, isDark }: ScoreTableProps) {
+
+ {row.name}
+
{row.total}
{row.q1}
@@ -87,7 +100,6 @@ const styles = StyleSheet.create({
margin: 16,
borderRadius: 12,
padding: 16,
- // Shadow
elevation: 2,
shadowColor: "#000",
shadowOffset: { width: 0, height: 2 },
@@ -117,12 +129,18 @@ const styles = StyleSheet.create({
flex: 3,
flexDirection: "row",
alignItems: "center",
+ gap: 8,
},
teamLogo: {
width: 24,
height: 24,
resizeMode: "contain",
},
+ teamName: {
+ flex: 1,
+ fontSize: 14,
+ fontWeight: "500",
+ },
cellText: {
flex: 1,
textAlign: "center",
diff --git a/components/match-detail/football/football-score-table.tsx b/components/match-detail/football/football-score-table.tsx
new file mode 100644
index 0000000..e64f8a0
--- /dev/null
+++ b/components/match-detail/football/football-score-table.tsx
@@ -0,0 +1,141 @@
+import { ThemedText } from "@/components/themed-text";
+import { MatchDetailData } from "@/types/api";
+import React from "react";
+import { useTranslation } from "react-i18next";
+import { Image, StyleSheet, View } from "react-native";
+
+interface FootballScoreTableProps {
+ data: MatchDetailData;
+ isDark: boolean;
+}
+
+// 解析足球比分字符串,例如 "2-1" 或 "1-0"
+function parseFootballScore(scoreString: string): number[] {
+ if (!scoreString || scoreString === "-") return [0, 0];
+ const parts = scoreString.split("-");
+ if (parts.length === 2) {
+ return [parseInt(parts[0]) || 0, parseInt(parts[1]) || 0];
+ }
+ return [0, 0];
+}
+
+export function FootballScoreTable({ data, isDark }: FootballScoreTableProps) {
+ const { t } = useTranslation();
+ const { match } = data;
+ const bgColor = isDark ? "#1C1C1E" : "#FFF";
+ const headerTextColor = isDark ? "#666" : "#999";
+
+ // 解析足球比分
+ const finalScore = parseFootballScore(match.eventFinalResult || "-");
+ const halftimeScore = parseFootballScore(match.eventHalftimeResult || "-");
+
+ const headers = [
+ t("detail.score_table.team"),
+ t("detail.score_table.total"),
+ t("detail.score_table.halftime"),
+ ];
+
+ const rows = [
+ {
+ logo: match.homeTeamLogo,
+ name: match.eventHomeTeam,
+ total: finalScore[0],
+ halftime: halftimeScore[0],
+ },
+ {
+ logo: match.awayTeamLogo,
+ name: match.eventAwayTeam,
+ total: finalScore[1],
+ halftime: halftimeScore[1],
+ },
+ ];
+
+ return (
+
+
+ {headers.map((h, i) => (
+
+ {h}
+
+ ))}
+
+
+ {rows.map((row, idx) => (
+
+
+
+
+ {row.name}
+
+
+ {row.total}
+ {row.halftime}
+
+ ))}
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ margin: 16,
+ borderRadius: 12,
+ padding: 16,
+ elevation: 2,
+ shadowColor: "#000",
+ shadowOffset: { width: 0, height: 2 },
+ shadowOpacity: 0.1,
+ shadowRadius: 4,
+ },
+ header: {
+ flexDirection: "row",
+ paddingBottom: 12,
+ borderBottomWidth: StyleSheet.hairlineWidth,
+ borderBottomColor: "rgba(150,150,150,0.2)",
+ },
+ headerText: {
+ fontSize: 12,
+ fontWeight: "500",
+ },
+ row: {
+ flexDirection: "row",
+ alignItems: "center",
+ paddingVertical: 12,
+ },
+ rowBorder: {
+ borderBottomWidth: StyleSheet.hairlineWidth,
+ borderBottomColor: "rgba(150,150,150,0.1)",
+ },
+ teamCell: {
+ flex: 3,
+ flexDirection: "row",
+ alignItems: "center",
+ gap: 8,
+ },
+ teamLogo: {
+ width: 24,
+ height: 24,
+ resizeMode: "contain",
+ },
+ teamName: {
+ flex: 1,
+ fontSize: 14,
+ fontWeight: "500",
+ },
+ cellText: {
+ flex: 1,
+ textAlign: "center",
+ fontSize: 14,
+ fontWeight: "500",
+ },
+});
diff --git a/components/match-detail/match-tabs.tsx b/components/match-detail/match-tabs.tsx
index eb37553..412829c 100644
--- a/components/match-detail/match-tabs.tsx
+++ b/components/match-detail/match-tabs.tsx
@@ -7,17 +7,41 @@ interface MatchTabsProps {
activeTab: string;
onTabChange: (tab: string) => void;
isDark: boolean;
+ sportId: number;
}
-export function MatchTabs({ activeTab, onTabChange, isDark }: MatchTabsProps) {
+export function MatchTabs({ activeTab, onTabChange, isDark, sportId }: MatchTabsProps) {
const { t } = useTranslation();
const containerBg = isDark ? "#121212" : "#F8F8F8";
- const tabs = [
- { id: "info", label: t("detail.tabs.info") },
- { id: "h2h", label: t("detail.tabs.h2h") },
- { id: "chat", label: t("detail.tabs.chat") },
- ];
+ // 根据 sportId 动态生成标签
+ const getTabs = () => {
+ if (sportId === 1) {
+ // 足球: 详情、统计数据、赔率、交锋往绩、聊天
+ return [
+ { id: "info", label: t("detail.tabs.info") },
+ { id: "stats", label: t("detail.tabs.stats") },
+ { id: "odds", label: t("detail.tabs.odds") },
+ { id: "h2h", label: t("detail.tabs.h2h") },
+ { id: "chat", label: t("detail.tabs.chat") },
+ ];
+ } else if (sportId === 2) {
+ // 篮球: 详情、交锋往绩、聊天
+ return [
+ { id: "info", label: t("detail.tabs.info") },
+ { id: "h2h", label: t("detail.tabs.h2h") },
+ { id: "chat", label: t("detail.tabs.chat") },
+ ];
+ }
+ // 默认: 详情、交锋往绩、聊天
+ return [
+ { id: "info", label: t("detail.tabs.info") },
+ { id: "h2h", label: t("detail.tabs.h2h") },
+ { id: "chat", label: t("detail.tabs.chat") },
+ ];
+ };
+
+ const tabs = getTabs();
return (
diff --git a/i18n/locales/en.json b/i18n/locales/en.json
index 0ded263..00819f6 100644
--- a/i18n/locales/en.json
+++ b/i18n/locales/en.json
@@ -37,6 +37,8 @@
"not_found": "Match data not found",
"tabs": {
"info": "Details",
+ "stats": "Statistics",
+ "odds": "Odds",
"h2h": "H2H",
"chat": "Chat"
},
@@ -50,9 +52,12 @@
},
"score_table": {
"team": "Team",
- "total": "Total"
+ "total": "Full Time",
+ "halftime": "Half Time"
},
"halftime": "Half: {{score}}",
+ "empty_stats": "No statistics data",
+ "empty_odds": "No odds data",
"empty_h2h": "No H2H data",
"empty_chat": "Chat is not available"
},
diff --git a/i18n/locales/zh.json b/i18n/locales/zh.json
index a7b2a68..ca26b6d 100644
--- a/i18n/locales/zh.json
+++ b/i18n/locales/zh.json
@@ -37,6 +37,8 @@
"not_found": "未找到比赛数据",
"tabs": {
"info": "详情",
+ "stats": "统计数据",
+ "odds": "赔率",
"h2h": "交锋往绩",
"chat": "聊天"
},
@@ -50,9 +52,12 @@
},
"score_table": {
"team": "球队",
- "total": "Total"
+ "total": "全场",
+ "halftime": "半场"
},
"halftime": "半场: {{score}}",
+ "empty_stats": "暂无统计数据",
+ "empty_odds": "暂无赔率数据",
"empty_h2h": "暂无交锋数据",
"empty_chat": "聊天功能暂未开启"
},