接入统计进度
This commit is contained in:
@@ -16,20 +16,38 @@ export function LiveScoreHeader({ match, topInset }: LiveScoreHeaderProps) {
|
|||||||
|
|
||||||
const parseMin = (t: string) => parseInt(t?.match(/(\d+)/)?.[1] || "0");
|
const parseMin = (t: string) => parseInt(t?.match(/(\d+)/)?.[1] || "0");
|
||||||
|
|
||||||
const [minutes, setMinutes] = React.useState(parseMin(match.event_time));
|
// 解析初始时间逻辑:(event_status 分钟 - event_time 分钟) : event_time 秒
|
||||||
const [seconds, setSeconds] = React.useState(0);
|
const getInitialTime = () => {
|
||||||
const lastServerMinRef = React.useRef(parseMin(match.event_time));
|
const statusIdx = parseInt(match.event_status) || 0;
|
||||||
|
const timeParts = match.event_time?.split(":") || [];
|
||||||
|
const tMin = parseInt(timeParts[0]) || 0;
|
||||||
|
const tSec = parseInt(timeParts[1]) || 0;
|
||||||
|
|
||||||
|
// 如果 event_status 是纯数字分钟数
|
||||||
|
if (!isNaN(statusIdx) && /^\d+$/.test(match.event_status)) {
|
||||||
|
return { min: Math.max(0, statusIdx - tMin), sec: tSec };
|
||||||
|
}
|
||||||
|
// 回退到解析 event_time 中的数字
|
||||||
|
return { min: tMin || parseMin(match.event_time), sec: tSec };
|
||||||
|
};
|
||||||
|
|
||||||
|
const initial = getInitialTime();
|
||||||
|
const [minutes, setMinutes] = React.useState(initial.min);
|
||||||
|
const [seconds, setSeconds] = React.useState(initial.sec);
|
||||||
|
const lastServerMatchRef = React.useRef(
|
||||||
|
`${match.event_status}-${match.event_time}`
|
||||||
|
);
|
||||||
|
|
||||||
// 服务器时间同步
|
// 服务器时间同步
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const serverMin = parseMin(match.event_time);
|
const currentKey = `${match.event_status}-${match.event_time}`;
|
||||||
// 只有当服务器分钟数变化时,才同步并重置秒数
|
if (currentKey !== lastServerMatchRef.current) {
|
||||||
if (serverMin !== lastServerMinRef.current) {
|
const updated = getInitialTime();
|
||||||
setMinutes(serverMin);
|
setMinutes(updated.min);
|
||||||
setSeconds(0);
|
setSeconds(updated.sec);
|
||||||
lastServerMinRef.current = serverMin;
|
lastServerMatchRef.current = currentKey;
|
||||||
}
|
}
|
||||||
}, [match.event_time]);
|
}, [match.event_time, match.event_status]);
|
||||||
|
|
||||||
// 本地秒级自增计时器
|
// 本地秒级自增计时器
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
@@ -114,13 +132,11 @@ export function LiveScoreHeader({ match, topInset }: LiveScoreHeaderProps) {
|
|||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={styles.timeInfoRow}>
|
<View style={styles.timeInfoRow}>
|
||||||
{match.event_status &&
|
{match.event_status && (
|
||||||
match.event_status.toLowerCase() !==
|
<ThemedText style={styles.statusLabel}>
|
||||||
displayTime?.toLowerCase().replace("'", "") && (
|
{match.event_status}
|
||||||
<ThemedText style={styles.statusLabel}>
|
</ThemedText>
|
||||||
{match.event_status}
|
)}
|
||||||
</ThemedText>
|
|
||||||
)}
|
|
||||||
<ThemedText style={styles.timeText}>{displayTime}</ThemedText>
|
<ThemedText style={styles.timeText}>{displayTime}</ThemedText>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,54 @@ export function StatsCard({ match, isDark }: StatsCardProps) {
|
|||||||
const [cardSwitch, setCardSwitch] = useState(true);
|
const [cardSwitch, setCardSwitch] = useState(true);
|
||||||
const [showInfo, setShowInfo] = useState(false);
|
const [showInfo, setShowInfo] = useState(false);
|
||||||
|
|
||||||
|
// 实时时间与进度计算
|
||||||
|
const getInitialMinutes = () => {
|
||||||
|
const statusIdx = parseInt(match.event_status) || 0;
|
||||||
|
const timeParts = match.event_time?.split(":") || [];
|
||||||
|
const tMin = parseInt(timeParts[0]) || 0;
|
||||||
|
const tSec = parseInt(timeParts[1]) || 0;
|
||||||
|
|
||||||
|
if (!isNaN(statusIdx) && /^\d+$/.test(match.event_status)) {
|
||||||
|
return { min: Math.max(0, statusIdx - tMin), sec: tSec };
|
||||||
|
}
|
||||||
|
return { min: tMin, sec: tSec };
|
||||||
|
};
|
||||||
|
|
||||||
|
const initial = getInitialMinutes();
|
||||||
|
const [minutes, setMinutes] = useState(initial.min);
|
||||||
|
const [seconds, setSeconds] = useState(initial.sec);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
const updated = getInitialMinutes();
|
||||||
|
setMinutes(updated.min);
|
||||||
|
setSeconds(updated.sec);
|
||||||
|
}, [match.event_time, match.event_status]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
const statusStr = match.event_status?.toLowerCase() || "";
|
||||||
|
const isLive =
|
||||||
|
String(match.event_live) === "1" ||
|
||||||
|
statusStr.includes("live") ||
|
||||||
|
(parseInt(statusStr) > 0 && parseInt(statusStr) < 120);
|
||||||
|
|
||||||
|
if (!isLive || statusStr.includes("ht")) return;
|
||||||
|
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
setSeconds((s) => {
|
||||||
|
if (s >= 59) {
|
||||||
|
setMinutes((m) => m + 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return s + 1;
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
return () => clearInterval(interval);
|
||||||
|
}, [match.event_key, match.event_live, match.event_status]);
|
||||||
|
|
||||||
|
const displayTime = `${minutes}:${seconds.toString().padStart(2, "0")}`;
|
||||||
|
const totalSeconds = minutes * 60 + seconds;
|
||||||
|
const progressPercent = Math.min(100, (totalSeconds / (90 * 60)) * 100);
|
||||||
|
|
||||||
// 从 statistics 中提取数据
|
// 从 statistics 中提取数据
|
||||||
const stats = match.statistics || [];
|
const stats = match.statistics || [];
|
||||||
const getStatValue = (type: string) => {
|
const getStatValue = (type: string) => {
|
||||||
@@ -194,12 +242,23 @@ export function StatsCard({ match, isDark }: StatsCardProps) {
|
|||||||
|
|
||||||
{/* Time Progress Slider */}
|
{/* Time Progress Slider */}
|
||||||
<View style={styles.sliderContainer}>
|
<View style={styles.sliderContainer}>
|
||||||
<ThemedText style={styles.currentTime}>46:53</ThemedText>
|
<ThemedText style={styles.currentTime}>{displayTime}</ThemedText>
|
||||||
<View style={styles.trackContainer}>
|
<View style={styles.trackContainer}>
|
||||||
<View style={[styles.track, isDark && { backgroundColor: "#333" }]} />
|
<View style={[styles.track, isDark && { backgroundColor: "#333" }]} />
|
||||||
<View style={[styles.filledTrack, { width: "55%" }]} />
|
<View
|
||||||
|
style={[styles.filledTrack, { width: `${progressPercent}%` }]}
|
||||||
|
/>
|
||||||
<View style={[styles.thumb, { left: "0%" }]} />
|
<View style={[styles.thumb, { left: "0%" }]} />
|
||||||
<View style={[styles.thumb, { left: "55%" }]} />
|
<View
|
||||||
|
style={[
|
||||||
|
styles.thumb,
|
||||||
|
{
|
||||||
|
left: `${progressPercent}%`,
|
||||||
|
backgroundColor: "#FFAB00",
|
||||||
|
borderColor: "#FFF",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
styles.thumb,
|
styles.thumb,
|
||||||
|
|||||||
Reference in New Issue
Block a user