import { useEffect, useState } from 'react' import { Card, Row, Col, Statistic, Typography, Button, Tag, Spin, Space } from 'antd' import { DatabaseOutlined, BarChartOutlined, AlertOutlined, WifiOutlined, DisconnectOutlined, ReloadOutlined, } from '@ant-design/icons' import { useAuthStore } from '../../stores/auth' import AppLayout from '../../components/AppLayout/AppLayout' const { Title, Text } = Typography interface Stats { total_datasources: number active_datasources: number tasks_today: number success_rate: number last_updated: string alerts: { critical: number warning: number info: number } } function Dashboard() { const { token, clearAuth } = useAuthStore() const [stats, setStats] = useState(null) const [loading, setLoading] = useState(true) const [wsConnected, setWsConnected] = useState(false) const [error, setError] = useState(null) useEffect(() => { if (!token) return const fetchStats = async () => { try { setLoading(true) const res = await fetch('/api/v1/dashboard/stats', { headers: { Authorization: `Bearer ${token}` }, }) if (res.status === 401) { clearAuth() window.location.href = '/' return } const data = await res.json() setStats(data) setError(null) } catch (err) { setError('获取数据失败') console.error(err) } finally { setLoading(false) } } fetchStats() }, [token, clearAuth]) useEffect(() => { if (!token) return let ws: WebSocket | null = null let reconnectTimer: ReturnType | null = null const connectWs = () => { try { ws = new WebSocket(`ws://localhost:8000/ws?token=${token}`) ws.onopen = () => { setWsConnected(true) ws?.send(JSON.stringify({ type: 'subscribe', data: { channels: ['dashboard'] } })) } ws.onmessage = (event) => { try { const msg = JSON.parse(event.data) if (msg.type === 'data_frame' && msg.channel === 'dashboard') { setStats(msg.payload?.stats as Stats) } } catch (e) { console.error('Parse WS message error:', e) } } ws.onclose = () => { setWsConnected(false) reconnectTimer = setTimeout(connectWs, 3000) } ws.onerror = () => { setWsConnected(false) } } catch (e) { console.error('WS connect error:', e) } } connectWs() return () => { ws?.close() if (reconnectTimer) clearTimeout(reconnectTimer) } }, [token]) const handleRetry = () => { window.location.reload() } if (loading && !stats) { return (
) } return (
仪表盘 系统总览与实时态势
{wsConnected ? ( } color="success">实时连接 ) : ( } color="default">离线 )}
{error && ( {error} )} } /> } /> } /> } /> } /> {stats?.last_updated && (
最后更新: {new Date(stats.last_updated).toLocaleString('zh-CN')} {wsConnected && 实时同步中}
)}
) } export default Dashboard