import { ThemedText } from "@/components/themed-text"; import { IconSymbol } from "@/components/ui/icon-symbol"; import { getInitials, getLogoGradient } from "@/lib/avatar-utils"; import { MatchDetailData } from "@/types/api"; import { Image } from "expo-image"; import { LinearGradient } from "expo-linear-gradient"; import React, { useMemo, useState } from "react"; import { ScrollView, StyleSheet, Switch, TouchableOpacity, View } from "react-native"; interface BasketballStatsProps { data: MatchDetailData; isDark: boolean; } // 定义固定高度以保证左右对齐 const HEADER_HEIGHT = 40; const ROW_HEIGHT = 60; const LEFT_COLUMN_WIDTH = 150; const COLUMNS_BASIC = [ { key: "pts", label: "PTS", width: 50 }, { key: "reb", label: "REB", width: 50 }, { key: "ast", label: "AST", width: 50 }, ]; const COLUMNS_DETAILED = [ { key: "min", label: "MIN", width: 50 }, { key: "pts", label: "PTS", width: 50 }, { key: "reb", label: "REB", width: 50 }, { key: "ast", label: "AST", width: 50 }, { key: "blk", label: "BLK", width: 50 }, { key: "stl", label: "STL", width: 50 }, { key: "to", label: "TO", width: 50 }, { key: "pf", label: "PF", width: 50 }, ]; export function BasketballStats({ data, isDark }: BasketballStatsProps) { const { match } = data; const [activeTab, setActiveTab] = useState<"home" | "away">("home"); const [isDetailed, setIsDetailed] = useState(false); // 获取当前展示的球员列表 const currentPlayers = useMemo(() => { if (!match.players) return []; return activeTab === "home" ? match.players.home_team : match.players.away_team; }, [match.players, activeTab]); const columns = isDetailed ? COLUMNS_DETAILED : COLUMNS_BASIC; const getPlayerStat = (player: any, statKey: string): string => { const statMap: Record = { pts: player.player_points || "0", reb: player.player_total_rebounds || "0", ast: player.player_assists || "0", min: player.player_minutes || "0", blk: player.player_blocks || "0", stl: player.player_steals || "0", to: player.player_turnovers || "0", pf: player.player_personal_fouls || "0", }; const value = statMap[statKey] || "0"; return value === "-" || value === "" ? "0" : value; }; const bgColor = isDark ? "#1C1C1E" : "#FFF"; const borderColor = isDark ? "#2C2C2E" : "rgba(0,0,0,0.06)"; const textColor = isDark ? "#FFF" : "#000"; const secondaryText = isDark ? "#8E8E93" : "#6B7280"; // --- 渲染组件 --- // 1. 左上角:Player 表头 const renderLeftHeader = () => ( Player ); // 2. 左侧列:球员信息行 const renderLeftPlayerRow = (player: any) => { const playerName = player.player || ""; const playerPosition = player.player_position || ""; const gradient = getLogoGradient(playerName); const initials = getInitials(playerName); return ( {initials} {playerName} {playerPosition && ( {playerPosition} )} ); }; // 3. 右上角:数据表头 const renderRightHeader = () => ( {columns.map((col) => ( {col.label} ))} ); // 4. 右侧列:数据行 const renderRightDataRow = (player: any) => ( {columns.map((col) => ( {getPlayerStat(player, col.key)} ))} ); // 队名/Logo逻辑 const homeTeamName = match.eventHomeTeam || ""; const awayTeamName = match.eventAwayTeam || ""; const homeTeamLogo = match.homeTeamLogo || ""; const awayTeamLogo = match.awayTeamLogo || ""; const hasHomeLogo = homeTeamLogo && homeTeamLogo.trim() !== "" && !homeTeamLogo.includes("placehold"); const hasAwayLogo = awayTeamLogo && awayTeamLogo.trim() !== "" && !awayTeamLogo.includes("placehold"); const homeGradient = getLogoGradient(homeTeamName); const awayGradient = getLogoGradient(awayTeamName); const homeInitials = getInitials(homeTeamName); const awayInitials = getInitials(awayTeamName); return ( {/* 顶部控制栏 */} 统计外观 详细视图 {/* 队伍切换 Tab */} setActiveTab("home")} > {hasHomeLogo ? ( ) : ( {homeInitials} )} setActiveTab("away")} > {hasAwayLogo ? ( ) : ( {awayInitials} )} {/* 核心表格区域:Vertical ScrollView 包裹整个表格 */} {/* 左侧区域:固定不横向滚动 */} {/* Header */} {renderLeftHeader()} {/* Players List */} {currentPlayers?.map((player, index) => ( {renderLeftPlayerRow(player)} ))} {/* 右侧区域:整体横向滚动 */} {/* Header */} {renderRightHeader()} {/* Data List */} {currentPlayers?.map((player, index) => ( {renderRightDataRow(player)} ))} {/* Empty State */} {(!currentPlayers || currentPlayers.length === 0) && ( 暂无球员数据 )} ); } const styles = StyleSheet.create({ container: { flex: 1, paddingTop: 12, }, controlsHeader: { flexDirection: "row", justifyContent: "space-between", alignItems: "center", paddingHorizontal: 16, marginBottom: 12, }, controlTitle: { fontSize: 14, fontWeight: "600", }, controlSubtitle: { fontSize: 12, marginTop: 2, }, teamTabsContainer: { flexDirection: "row", marginHorizontal: 16, marginBottom: 12, borderRadius: 12, height: 44, borderWidth: 1, overflow: "hidden", }, teamTab: { flex: 1, justifyContent: "center", alignItems: "center", }, teamTabLogo: { width: 24, height: 24, }, teamTabLogoGradient: { width: 24, height: 24, borderRadius: 12, alignItems: "center", justifyContent: "center", }, teamTabLogoText: { fontSize: 10, fontWeight: "700", color: "rgba(255, 255, 255, 0.92)", }, tableContainer: { marginHorizontal: 16, marginBottom: 20, borderRadius: 16, borderWidth: 1, overflow: "hidden", // 确保圆角生效 }, // 左侧样式 headerCell: { flexDirection: "row", alignItems: "center", borderBottomWidth: StyleSheet.hairlineWidth, paddingHorizontal: 12, width: "100%", }, playerRow: { flexDirection: "row", alignItems: "center", borderBottomWidth: StyleSheet.hairlineWidth, paddingHorizontal: 8, width: "100%", }, // 右侧样式 dataHeaderRow: { flexDirection: "row", alignItems: "center", borderBottomWidth: StyleSheet.hairlineWidth, paddingHorizontal: 16, // 给右侧表头一些左右padding,美观 }, dataRow: { flexDirection: "row", alignItems: "center", borderBottomWidth: StyleSheet.hairlineWidth, paddingHorizontal: 16, }, // 通用文本 headerText: { fontSize: 12, fontWeight: "700", }, statText: { fontSize: 14, fontWeight: "500", }, // 球员头像与信息 avatarContainer: { marginRight: 8, }, avatarGradient: { width: 32, height: 32, borderRadius: 16, alignItems: "center", justifyContent: "center", }, avatarText: { fontSize: 12, fontWeight: "700", color: "rgba(255, 255, 255, 0.92)", }, playerInfo: { flex: 1, justifyContent: "center", }, playerName: { fontSize: 13, fontWeight: "600", marginBottom: 2, }, playerNumPos: { fontSize: 11, }, emptyState: { padding: 40, alignItems: "center", }, });