feat: add monitoring alert read state
This commit is contained in:
@@ -151,7 +151,7 @@ function severityTag(severity: InfrastructureAlert['severity']) {
|
||||
return <Tag tone="info">提示</Tag>;
|
||||
}
|
||||
|
||||
const alertColumns: Array<TableColumn<InfrastructureAlert>> = [
|
||||
function makeAlertColumns(onMarkRead: (alert: InfrastructureAlert) => void, readingFingerprint: string): Array<TableColumn<InfrastructureAlert>> { return [
|
||||
{ key: 'severity', title: '级别', width: '82px', render: (record) => severityTag(record.severity) },
|
||||
{
|
||||
key: 'alert', title: '告警', width: '280px', render: (record) => (
|
||||
@@ -162,7 +162,12 @@ const alertColumns: Array<TableColumn<InfrastructureAlert>> = [
|
||||
{ key: 'value', title: '当前值 / 阈值', width: '150px', render: (record) => `${record.currentValue || '—'} / ${record.threshold || '—'}` },
|
||||
{ key: 'startedAt', title: '开始时间', width: '150px', render: (record) => formatTime(record.startedAt) },
|
||||
{ key: 'duration', title: '持续时间', width: '120px', render: (record) => formatDuration(record.startedAt) },
|
||||
];
|
||||
{
|
||||
key: 'actions', title: '操作', width: '112px', render: (record) => record.acknowledged
|
||||
? <Tag tone="neutral">已读</Tag>
|
||||
: <Button disabled={readingFingerprint === record.fingerprint} icon={<CheckCircle2 size={14} />} onClick={() => onMarkRead(record)} size="sm" variant="ghost">{readingFingerprint === record.fingerprint ? '处理中' : '标记已读'}</Button>,
|
||||
},
|
||||
]; }
|
||||
|
||||
export function AdminSystemMonitoringPage() {
|
||||
const [range, setRange] = useState<InfrastructureMonitoringRange>('24h');
|
||||
@@ -174,6 +179,8 @@ export function AdminSystemMonitoringPage() {
|
||||
const [showSettings, setShowSettings] = useState(false);
|
||||
const [settingsError, setSettingsError] = useState('');
|
||||
const [savingSettings, setSavingSettings] = useState(false);
|
||||
const [readingFingerprint, setReadingFingerprint] = useState('');
|
||||
const [readError, setReadError] = useState('');
|
||||
const requestSequence = useRef(0);
|
||||
const pendingRequests = useRef(0);
|
||||
|
||||
@@ -226,6 +233,25 @@ export function AdminSystemMonitoringPage() {
|
||||
}
|
||||
}, [draftThresholds, loadData, settings]);
|
||||
|
||||
const markAlertRead = useCallback(async (alert: InfrastructureAlert) => {
|
||||
setReadingFingerprint(alert.fingerprint);
|
||||
setReadError('');
|
||||
try {
|
||||
const result = await adminApi.markInfrastructureAlertRead(alert.fingerprint, alert.startedAt);
|
||||
setOverview((current) => current ? {
|
||||
...current,
|
||||
alerts: current.alerts.map((item) => item.fingerprint === result.fingerprint && Date.parse(item.startedAt) === Date.parse(result.activeAt)
|
||||
? { ...item, acknowledged: true, acknowledgedAt: result.acknowledgedAt }
|
||||
: item),
|
||||
} : current);
|
||||
window.dispatchEvent(new Event('cmpp-infrastructure-alert-count-refresh'));
|
||||
} catch (reason) {
|
||||
setReadError(reason instanceof Error ? reason.message : '活动告警标记已读失败');
|
||||
} finally {
|
||||
setReadingFingerprint('');
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
void loadData(true);
|
||||
void loadSettings();
|
||||
@@ -263,6 +289,7 @@ export function AdminSystemMonitoringPage() {
|
||||
const metrics = overview?.metrics;
|
||||
const serviceHealthy = overview?.summary.serviceHealthy ?? 0;
|
||||
const serviceTotal = overview?.summary.serviceTotal ?? 6;
|
||||
const alertColumns = useMemo(() => makeAlertColumns((alert) => { void markAlertRead(alert); }, readingFingerprint), [markAlertRead, readingFingerprint]);
|
||||
|
||||
return (
|
||||
<section className="page-stack admin-system-monitoring-page">
|
||||
@@ -364,6 +391,7 @@ export function AdminSystemMonitoringPage() {
|
||||
|
||||
<section className="surface system-monitoring-alerts" id="active-alerts">
|
||||
<header><div><AlertTriangle size={18} /><strong>活动告警</strong><Tag tone={overview?.summary.activeAlerts ? 'warning' : 'success'}>{overview?.summary.activeAlerts ?? 0}</Tag></div><span><Clock3 size={14} /> 刷新于 {formatTime(overview?.collectedAt ?? null)}</span></header>
|
||||
{readError ? <div className="system-monitoring-unavailable" role="alert"><AlertTriangle size={18} /><div><strong>标记已读失败</strong><span>{readError}</span></div></div> : null}
|
||||
<Table columns={alertColumns} data={overview?.alerts ?? []} emptyText={overview?.available ? '当前没有活动告警' : '监控不可用,无法读取活动告警'} pagination={false} rowKey="fingerprint" />
|
||||
</section>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user