diff --git a/server/data.db b/server/data.db index 9928aa6..f8d7fee 100644 Binary files a/server/data.db and b/server/data.db differ diff --git a/server/data.db-shm b/server/data.db-shm index 14174d9..a7ec282 100644 Binary files a/server/data.db-shm and b/server/data.db-shm differ diff --git a/server/data.db-wal b/server/data.db-wal index eebc6c7..42cebce 100644 Binary files a/server/data.db-wal and b/server/data.db-wal differ diff --git a/src/components/HeaderPanel.tsx b/src/components/HeaderPanel.tsx index c778991..1255852 100644 --- a/src/components/HeaderPanel.tsx +++ b/src/components/HeaderPanel.tsx @@ -7,6 +7,7 @@ import { usePlaybackStore } from '@/store/playbackStore' import { Wifi, WifiOff, Clock, Share2, Heart, Eye, MessageSquare } from 'lucide-react' const STORAGE_LIKES = 'us-iran-dashboard-likes' +// 冲突时长显示在 TimelinePanel(数据回放栏)内 function getStoredLikes(): number { try { @@ -155,13 +156,15 @@ export function HeaderPanel() { return (
-

+

美伊军事态势显示

-
+
- {formatDateTime(now)} + + {formatDateTime(now)} +
{(isConnected || isReplayMode) && ( diff --git a/src/components/TimelinePanel.tsx b/src/components/TimelinePanel.tsx index cdd4f4e..c3ec0b7 100644 --- a/src/components/TimelinePanel.tsx +++ b/src/components/TimelinePanel.tsx @@ -1,10 +1,13 @@ -import { useEffect, useRef } from 'react' +import { useEffect, useRef, useState } from 'react' import { Play, Pause, SkipBack, SkipForward, History } from 'lucide-react' import { usePlaybackStore, REPLAY_TICKS, REPLAY_START, REPLAY_END } from '@/store/playbackStore' import { useSituationStore } from '@/store/situationStore' import { NewsTicker } from './NewsTicker' import { config } from '@/config' +/** 冲突开始时间:2月28日凌晨 03:00(本地时间) */ +const CONFLICT_START = new Date(2026, 1, 28, 3, 0, 0, 0) + function formatTick(iso: string): string { const d = new Date(iso) return d.toLocaleString('zh-CN', { @@ -16,8 +19,17 @@ function formatTick(iso: string): string { }) } +function getConflictDuration(toTime: Date): { days: number; hours: number } { + const diffMs = toTime.getTime() - CONFLICT_START.getTime() + if (diffMs <= 0) return { days: 0, hours: 0 } + const days = Math.floor(diffMs / (24 * 60 * 60 * 1000)) + const hours = Math.floor((diffMs % (24 * 60 * 60 * 1000)) / (60 * 60 * 1000)) + return { days, hours } +} + export function TimelinePanel() { const situation = useSituationStore((s) => s.situation) + const [now, setNow] = useState(() => new Date()) const { isReplayMode, playbackTime, @@ -33,6 +45,14 @@ export function TimelinePanel() { const timerRef = useRef | null>(null) + useEffect(() => { + const t = setInterval(() => setNow(new Date()), 1000) + return () => clearInterval(t) + }, []) + + const toTime = isReplayMode ? new Date(playbackTime) : now + const conflictDuration = getConflictDuration(toTime) + useEffect(() => { if (!isPlaying || !isReplayMode) { if (timerRef.current) { @@ -64,8 +84,18 @@ export function TimelinePanel() { } return ( -
-
+
+ {!isReplayMode && ( +
+ + 冲突已持续 {conflictDuration.days} 天 {conflictDuration.hours} 小时 + +
+ )} +