import { useState, useEffect, useCallback } from 'react'; import { Alert, Badge, List, Button, Space, Typography, Spin } from 'antd'; import { CheckOutlined } from '@ant-design/icons'; import { listAlerts, dismissInsight } from '../../api/copilot'; import type { CopilotInsight } from '../../api/copilot'; const severityConfig: Record = { critical: { type: 'error', label: '危急' }, warning: { type: 'warning', label: '警告' }, info: { type: 'processing', label: '提示' }, }; export function CopilotAlert() { const [alerts, setAlerts] = useState([]); const [loading, setLoading] = useState(false); const [dismissing, setDismissing] = useState(null); const fetchAlerts = useCallback(async () => { setLoading(true); try { const res = await listAlerts({ page_size: 50 }); const payload = (res.data as { data?: CopilotInsight[] }).data ?? []; setAlerts(payload); } catch { // 静默 } finally { setLoading(false); } }, []); useEffect(() => { fetchAlerts(); const timer = setInterval(fetchAlerts, 30_000); return () => clearInterval(timer); }, [fetchAlerts]); const handleDismiss = async (id: string) => { setDismissing(id); try { await dismissInsight(id); setAlerts((prev) => prev.filter((a) => a.id !== id)); } finally { setDismissing(null); } }; if (!alerts.length && !loading) return null; const criticalCount = alerts.filter((a) => a.severity === 'critical').length; return (
{criticalCount > 0 && ( )} {loading && alerts.length === 0 ? ( ) : ( { const config = severityConfig[item.severity] ?? severityConfig.info; return ( } loading={dismissing === item.id} onClick={() => handleDismiss(item.id)} > 已知悉 , ]} > {item.title} } description={ item.content?.suggestion ? ( {item.content.suggestion as string} ) : undefined } /> ); }} /> )}
); }