// v1的时候就连统计信息也5秒获取一次,不妥,所以改成逻辑触发刷新 import React, { useState, useEffect, useCallback } from 'react'; import { makeStyles, tokens, Card, CardHeader, Text, Spinner, Badge, Button, useToastController, Toast, ToastTitle, } from '@fluentui/react-components'; import { CheckmarkCircle20Filled, DismissCircle20Filled, ArrowClockwise20Regular } from '@fluentui/react-icons'; import { useLayout } from '../context/LayoutContext'; import { testApiStatus, getStatics } from '../api'; import type { StaticsData } from '../api'; const useStyles = makeStyles({ container: { display: 'flex', flexDirection: 'column', gap: tokens.spacingVerticalS, width: '100%', }, card: { width: '100%', }, statusContainer: { padding: `${tokens.spacingVerticalS} ${tokens.spacingHorizontalM}`, paddingBottom: tokens.spacingVerticalM, }, statusText: { display: 'flex', alignItems: 'center', gap: tokens.spacingHorizontalSNudge, }, online: { color: tokens.colorStatusSuccessForeground1, fontSize: tokens.fontSizeBase200, }, offline: { color: tokens.colorStatusDangerForeground1, fontSize: tokens.fontSizeBase200, }, statsContainer: { padding: `${tokens.spacingVerticalS} ${tokens.spacingHorizontalM}`, paddingBottom: tokens.spacingVerticalM, display: 'flex', flexDirection: 'column', gap: '4px', }, statRow: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', }, refreshButton: { minWidth: 'auto', padding: '2px', }, labelText: { fontSize: tokens.fontSizeBase200, }, headerText: { fontSize: tokens.fontSizeBase300, fontWeight: tokens.fontWeightSemibold, } }); const StatusDisplay: React.FC = () => { const styles = useStyles(); const { toasterId, refreshTrigger } = useLayout(); const { dispatchToast } = useToastController(toasterId); const [isApiOnline, setIsApiOnline] = useState(null); const [statics, setStatics] = useState(null); const [isTestLoading, setIsTestLoading] = useState(true); const [isStaticsLoading, setIsStaticsLoading] = useState(true); const checkStatus = useCallback(async () => { const online = await testApiStatus(); setIsApiOnline(online); setIsTestLoading(false); }, []); const refreshStatics = useCallback(async (isManual: boolean = false) => { setIsStaticsLoading(true); try { const data = await getStatics(); setStatics(data); if (isManual) { dispatchToast( 统计数据已刷新 , { intent: 'success' } ); } } catch (error) { console.error('Failed to refresh statics:', error); setStatics(null); // 失败时重置数据 } finally { setIsStaticsLoading(false); } }, [dispatchToast]); useEffect(() => { // 初始加载 checkStatus(); refreshStatics(false); // 每 10 秒测试一次后端 API 状态 const testInterval = setInterval(checkStatus, 10000); return () => { clearInterval(testInterval); }; }, [checkStatus, refreshStatics]); // Listen for global refresh trigger useEffect(() => { if (refreshTrigger > 0) { refreshStatics(false); } }, [refreshTrigger, refreshStatics]); return (
系统状态} />
{isTestLoading && isApiOnline === null ? ( ) : (
{isApiOnline ? ( <> 在线 ) : ( <> 离线 )}
)}
统计数据} action={
); }; export default StatusDisplay;