fix: 更新数据面板的驱动方式
This commit is contained in:
@@ -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 = () => {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
18
src/store/statsStore.ts
Normal 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 } })),
|
||||
}))
|
||||
Reference in New Issue
Block a user