fix: 更新数据面板的驱动方式

This commit is contained in:
Daniel
2026-03-02 23:21:07 +08:00
parent ef60f18cb0
commit 92914e6522
22 changed files with 427 additions and 62 deletions

View File

@@ -15,7 +15,7 @@ export function connectSituationWebSocket(onData: Handler): () => void {
ws.onmessage = (e) => {
try {
const msg = JSON.parse(e.data)
if (msg.type === 'situation' && msg.data) handler?.(msg.data)
if (msg.type === 'situation') handler?.({ situation: msg.data, stats: msg.stats })
} catch (_) {}
}
ws.onclose = () => {

View File

@@ -1,6 +1,7 @@
import { useState, useEffect } from 'react'
import { StatCard } from './StatCard'
import { useSituationStore } from '@/store/situationStore'
import { useStatsStore } from '@/store/statsStore'
import { useReplaySituation } from '@/hooks/useReplaySituation'
import { usePlaybackStore } from '@/store/playbackStore'
import { Wifi, WifiOff, Clock, Share2, Heart, Eye, MessageSquare } from 'lucide-react'
@@ -23,10 +24,12 @@ export function HeaderPanel() {
const [now, setNow] = useState(() => new Date())
const [likes, setLikes] = useState(getStoredLikes)
const [liked, setLiked] = useState(false)
const [viewers, setViewers] = useState(0)
const [cumulative, setCumulative] = useState(0)
const [feedbackCount, setFeedbackCount] = useState(0)
const [shareCount, setShareCount] = useState(0)
const stats = useStatsStore((s) => s.stats)
const setStats = useStatsStore((s) => s.setStats)
const viewers = stats.viewers ?? 0
const cumulative = stats.cumulative ?? 0
const feedbackCount = stats.feedbackCount ?? 0
const shareCount = stats.shareCount ?? 0
const [feedbackOpen, setFeedbackOpen] = useState(false)
const [feedbackText, setFeedbackText] = useState('')
const [feedbackSending, setFeedbackSending] = useState(false)
@@ -41,13 +44,14 @@ export function HeaderPanel() {
try {
const res = await fetch('/api/visit', { method: 'POST' })
const data = await res.json()
if (data.viewers != null) setViewers(data.viewers)
if (data.cumulative != null) setCumulative(data.cumulative)
if (data.feedbackCount != null) setFeedbackCount(data.feedbackCount)
if (data.shareCount != null) setShareCount(data.shareCount)
setStats({
viewers: data.viewers,
cumulative: data.cumulative,
feedbackCount: data.feedbackCount,
shareCount: data.shareCount,
})
} catch {
setViewers((v) => (v > 0 ? v : 0))
setCumulative((c) => (c > 0 ? c : 0))
setStats({ viewers: 0, cumulative: 0 })
}
}
@@ -79,7 +83,7 @@ export function HeaderPanel() {
try {
const res = await fetch('/api/share', { method: 'POST' })
const data = await res.json()
if (data.shareCount != null) setShareCount(data.shareCount)
if (data.shareCount != null) setStats({ shareCount: data.shareCount })
} catch {}
}
}
@@ -102,7 +106,7 @@ export function HeaderPanel() {
if (data.ok) {
setFeedbackText('')
setFeedbackDone(true)
setFeedbackCount((c) => c + 1)
setStats({ feedbackCount: (feedbackCount ?? 0) + 1 })
setTimeout(() => {
setFeedbackOpen(false)
setFeedbackDone(false)

View File

@@ -3,6 +3,7 @@ import type { MilitarySituation } from '@/data/mockData'
import { INITIAL_MOCK_DATA } from '@/data/mockData'
import { fetchSituation } from '@/api/situation'
import { connectSituationWebSocket } from '@/api/websocket'
import { useStatsStore } from './statsStore'
interface SituationState {
situation: MilitarySituation
@@ -60,9 +61,11 @@ function pollSituation() {
export function startSituationWebSocket(): () => void {
useSituationStore.getState().setLastError(null)
disconnectWs = connectSituationWebSocket((data) => {
disconnectWs = connectSituationWebSocket((payload) => {
const { situation, stats } = payload as { situation?: MilitarySituation; stats?: { viewers?: number; cumulative?: number; feedbackCount?: number; shareCount?: number } }
useSituationStore.getState().setConnected(true)
useSituationStore.getState().setSituation(data as MilitarySituation)
if (situation) useSituationStore.getState().setSituation(situation)
if (stats) useStatsStore.getState().setStats(stats)
})
pollSituation()

18
src/store/statsStore.ts Normal file
View File

@@ -0,0 +1,18 @@
import { create } from 'zustand'
export interface Stats {
viewers?: number
cumulative?: number
feedbackCount?: number
shareCount?: number
}
interface StatsState {
stats: Stats
setStats: (stats: Stats) => void
}
export const useStatsStore = create<StatsState>((set) => ({
stats: {},
setStats: (stats) => set((s) => ({ stats: { ...s.stats, ...stats } })),
}))