import React, { useState, useEffect } from 'react'; import { Activity, Clock, Folders, CheckCircle2, Loader2 } from 'lucide-react'; import { progressWS, type ProgressMessage } from '../lib/websocket'; import { cn } from '../lib/utils'; interface QueueTask { id: string; name: string; progress: number; status: string; } export function Dashboard() { const [tasks, setTasks] = useState([ { id: '1', name: 'City_Driving_Dataset_004.mp4', progress: 85, status: '正在截取帧 (30fps)' }, { id: '2', name: 'Pedestrian_Night_Vision_02.mkv', progress: 32, status: '正在截取帧 (60fps)' }, { id: '3', name: 'Drone_Mapping_Sector_7.avi', progress: 0, status: '队列排队等待中' }, ]); const [isConnected, setIsConnected] = useState(false); const [activityLog, setActivityLog] = useState>([ { time: '10 分钟前', message: '语义归档完成 54 帧', project: 'Highway_Data' }, { time: '25 分钟前', message: '项目解析开始', project: 'City_Driving_Dataset_004' }, { time: '1 小时前', message: '模板库更新: Cityscapes_v2', project: '系统' }, { time: '2 小时前', message: 'AI 推理完成 12 个实例', project: 'Nav_Cam_Left' }, ]); useEffect(() => { progressWS.connect(); const unsubscribe = progressWS.onProgress((data: ProgressMessage) => { setIsConnected(progressWS.isConnected()); if (data.type === 'progress' && data.taskId && data.filename) { setTasks((prev) => { const exists = prev.find((t) => t.id === data.taskId); if (exists) { return prev.map((t) => t.id === data.taskId ? { ...t, progress: data.progress ?? t.progress, status: data.status ?? t.status } : t ); } return [ ...prev, { id: data.taskId!, name: data.filename!, progress: data.progress ?? 0, status: data.status ?? '处理中', }, ]; }); } if (data.type === 'complete' && data.taskId) { setTasks((prev) => prev.map((t) => t.id === data.taskId ? { ...t, progress: 100, status: '已完成' } : t ) ); setActivityLog((prev) => [ { time: '刚刚', message: `解析完成: ${data.filename || data.taskId}`, project: '系统' }, ...prev.slice(0, 9), ]); } if (data.type === 'error' && data.taskId) { setTasks((prev) => prev.map((t) => t.id === data.taskId ? { ...t, status: `错误: ${data.message || '未知错误'}` } : t ) ); } if (data.type === 'status') { setActivityLog((prev) => [ { time: '刚刚', message: data.message || '状态更新', project: '系统' }, ...prev.slice(0, 9), ]); } }); const checkConnection = setInterval(() => { setIsConnected(progressWS.isConnected()); }, 5000); return () => { unsubscribe(); clearInterval(checkConnection); progressWS.disconnect(); }; }, []); const stats = [ { label: '运行中项目', value: '14', icon: Folders, color: 'text-blue-400', bg: 'bg-blue-400/10' }, { label: '排队处理任务', value: tasks.length.toString(), icon: Clock, color: 'text-orange-400', bg: 'bg-orange-400/10' }, { label: '已归档批次', value: '128', icon: CheckCircle2, color: 'text-emerald-400', bg: 'bg-emerald-400/10' }, { label: '系统负载', value: '78%', icon: Activity, color: 'text-cyan-400', bg: 'bg-cyan-400/10' }, ]; return (

系统整体概况

{isConnected ? 'WebSocket 已连接' : 'WebSocket 断开'}

系统全局数据吞吐状态与所有接入项目进度实时洞察驾驶舱。

{stats.map((stat, i) => { const Icon = stat.icon; return (
{stat.value}
{stat.label}
); })}

解析队列 (FFmpeg 挂起任务)

{tasks.map((task) => (
{task.name} {task.progress}%
{task.status === '已完成' ? ( ) : task.status.includes('错误') ? ( ) : ( )} {task.status}
))} {tasks.length === 0 && (
当前无处理任务
)}

近期实时流转记录

{activityLog.map((log, i) => (
{log.time}
{log.message}
归属项目: {log.project}
))}
); }