diff --git a/frontend/src/components/monitor/alert-center/AlertCenter.tsx b/frontend/src/components/monitor/alert-center/AlertCenter.tsx index e54a71d..46c21d1 100644 --- a/frontend/src/components/monitor/alert-center/AlertCenter.tsx +++ b/frontend/src/components/monitor/alert-center/AlertCenter.tsx @@ -29,8 +29,10 @@ import { ContactGroupDialog } from './ContactGroupDialog'; import SilenceRuleTab from './SilenceRuleTab'; import type { Contact, ContactGroup } from './alert-center-helpers'; import type { JsonData } from '@/types/common'; +import { useTranslation } from 'react-i18next'; const AlertCenter: React.FC = () => { + const { t } = useTranslation(); const _confirm = useConfirm(); const [searchQuery, setSearchQuery] = useState(''); const [severityFilter, setSeverityFilter] = useState('all'); @@ -97,18 +99,18 @@ const AlertCenter: React.FC = () => { const handleAcknowledge = async (id: string) => { try { await ackMutation.mutateAsync(id); - toast.success('告警已确认'); + toast.success(t('alert.acknowledged')); } catch { - toast.error('操作失败'); + toast.error(t('alert.operationFailed')); } }; const handleResolve = async (id: string) => { try { await resolveMutation.mutateAsync(id); - toast.success('告警已解决'); + toast.success(t('alert.resolvedToast')); } catch { - toast.error('操作失败'); + toast.error(t('alert.operationFailed')); } }; @@ -123,7 +125,7 @@ const AlertCenter: React.FC = () => { const endTime = new Date(now.getTime() + hours * 3600_000); await alertCenterApi.createSilence({ name: `静默: ${alert?.title || id} (${duration})`, - description: `从告警列表快速静默 — ${alert?.source || ''}`, + description: `${t('alert.silenceDesc')} — ${alert?.source || ''}`, silence_type: 'onetime', start_time: now.toISOString(), end_time: endTime.toISOString(), @@ -132,16 +134,16 @@ const AlertCenter: React.FC = () => { setSilenceOpen(false); refetchAlerts(); } catch { - toast.error('操作失败'); + toast.error(t('alert.operationFailed')); } }; const toggleRule = async (ruleId: string, enabled: boolean) => { try { await toggleAgentRuleMutation.mutateAsync({ id: Number(ruleId), enabled }); - toast.success('规则状态已更新'); + toast.success(t('alert.ruleUpdated')); } catch { - toast.error('更新失败'); + toast.error(t('alert.updateFailed')); } }; @@ -151,23 +153,23 @@ const AlertCenter: React.FC = () => { const handleQuickSetup = async () => { const ok = await _confirm({ - title: '一键报警', - description: '为 Agent 在线主机创建 CPU(>80%)/内存(>80%)/磁盘(>90%)/TIME_WAIT(>15000)/CLOSE_WAIT(>200)/进程检测 6 条告警规则。', - confirmText: '确认创建', + title: t('alert.quickSetup'), + description: t('alert.quickSetupDesc'), + confirmText: t('alert.quickSetupConfirm'), }); if (!ok) return; try { const res = await quickSetupMutation.mutateAsync('ecs'); - toast.success(typeof res === 'string' ? res : ((res as { message?: string })?.message || '默认告警规则创建成功')); + toast.success(typeof res === 'string' ? res : ((res as { message?: string })?.message || t('alert.quickSetupSuccess'))); } catch { - toast.error('创建失败,请检查 Agent 主机是否在线'); + toast.error(t('alert.quickSetupFailed')); } }; const handleDeleteRule = async (rule: AlertRule) => { - const ok = await _confirm({ title: '删除规则', description: `确定删除规则「${rule.name}」?`, confirmText: '删除', variant: 'destructive' }); + const ok = await _confirm({ title: t('alert.deleteRule'), description: `${rule.name}`, confirmText: t('common.delete'), variant: 'destructive' }); if (!ok) return; - try { await deleteAgentRuleMutation.mutateAsync(Number(rule.id)); toast.success('已删除'); } catch { toast.error('删除失败'); } + try { await deleteAgentRuleMutation.mutateAsync(Number(rule.id)); toast.success(t('alert.deleted')); } catch { toast.error(t('alert.deleteFailed')); } }; const handleFilterChange = (type: 'severity' | 'status', value: string) => { @@ -181,20 +183,20 @@ const AlertCenter: React.FC = () => { {/* 统计 — 紧凑条 */} 0 ? 'red' : 'muted' }, - { label: '严重', value: stats.critical, color: 'red' }, - { label: '警告', value: stats.warning, color: 'amber' }, - { label: '已解决', value: stats.resolved, color: 'emerald' }, + { label: t('alert.stat.firing'), value: stats.firing, color: stats.firing > 0 ? 'red' : 'muted' }, + { label: t('alert.stat.critical'), value: stats.critical, color: 'red' }, + { label: t('alert.stat.warning'), value: stats.warning, color: 'amber' }, + { label: t('alert.stat.resolved'), value: stats.resolved, color: 'emerald' }, ]} /> - 告警列表 - 告警规则 - 静默规则 - 报警联系人 - 报警联系组 + {t('alert.tab.alerts')} + {t('alert.tab.rules')} + {t('alert.tab.silences')} + {t('alert.tab.contacts')} + {t('alert.tab.groups')} {/* 告警列表 Tab */} @@ -204,7 +206,7 @@ const AlertCenter: React.FC = () => {
setSearchQuery(e.target.value)} className="pl-8 h-8 text-xs" @@ -212,31 +214,31 @@ const AlertCenter: React.FC = () => {
- 共 {total} 条 + {t('alert.totalItems', { count: total })}
@@ -248,19 +250,19 @@ const AlertCenter: React.FC = () => { - - - - - - + + + + + + {loading ? ( - + ) : alerts.length === 0 ? ( - + ) : ( alerts.filter(alert => { // 客户端也保留关键词搜索过滤 @@ -288,8 +290,8 @@ const AlertCenter: React.FC = () => {
告警信息级别状态来源持续操作{t('alert.table.alertInfo')}{t('alert.table.severity')}{t('alert.table.status')}{t('alert.table.source')}{t('alert.table.duration')}{t('alert.table.actions')}
加载中...
{t('alert.loading')}
暂无告警
{t('alert.noAlerts')}
{alert.status === 'resolved' && alert.resolvedAt - ? `${Math.floor((new Date(alert.resolvedAt).getTime() - new Date(alert.startedAt).getTime()) / 60000)}分` - : `${Math.floor((Date.now() - new Date(alert.startedAt).getTime()) / 60000)}分`} + ? t('alert.minutesShort', { count: Math.floor((new Date(alert.resolvedAt).getTime() - new Date(alert.startedAt).getTime()) / 60000) }) + : t('alert.minutesShort', { count: Math.floor((Date.now() - new Date(alert.startedAt).getTime()) / 60000) })}
@@ -324,11 +326,11 @@ const AlertCenter: React.FC = () => { {/* 分页控件 */} {totalPages > 1 && (
- 第 {page}/{totalPages} 页,共 {total} 条 + {t('alert.pageInfo', { page, totalPages, total })}
{Array.from({ length: Math.min(totalPages, 5) }, (_, i) => { const start = Math.max(1, Math.min(page - 2, totalPages - 4)); @@ -344,7 +346,7 @@ const AlertCenter: React.FC = () => { })}
@@ -358,11 +360,11 @@ const AlertCenter: React.FC = () => {
{(() => { let chs: string[] = []; @@ -414,8 +416,8 @@ const AlertCenter: React.FC = () => { })()}
- - + + toggleRule(String(rule.id), checked)} @@ -437,7 +439,7 @@ const AlertCenter: React.FC = () => { {/* 报警联系人 Tab */}
-

报警联系人

+

{t('alert.contactsTitle')}

@@ -522,7 +524,7 @@ const AlertCenter: React.FC = () => {
{g.group_name} - {cids.length} 人 + {t('alert.peopleCount', { count: cids.length })}
@@ -539,10 +541,10 @@ const AlertCenter: React.FC = () => { diff --git a/frontend/src/locales/en-US.json b/frontend/src/locales/en-US.json index da50450..2ee9d0f 100644 --- a/frontend/src/locales/en-US.json +++ b/frontend/src/locales/en-US.json @@ -317,5 +317,77 @@ "status": "Status", "tags": "Tags" } + }, + "alert": { + "stat": { + "firing": "Firing", + "critical": "Critical", + "warning": "Warning", + "resolved": "Resolved" + }, + "tab": { + "alerts": "Alerts", + "rules": "Alert Rules", + "silences": "Silence Rules", + "contacts": "Contacts", + "groups": "Contact Groups" + }, + "searchPlaceholder": "Search alerts...", + "allSeverity": "All Severity", + "allStatus": "All Status", + "severity": { + "critical": "Critical", + "warning": "Warning", + "info": "Info" + }, + "status": { + "firing": "Firing", + "acknowledged": "Acknowledged", + "resolved": "Resolved" + }, + "table": { + "alertInfo": "Alert Info", + "severity": "Severity", + "status": "Status", + "source": "Source", + "duration": "Duration", + "actions": "Actions" + }, + "loading": "Loading...", + "noAlerts": "No alerts", + "totalItems": "{{count}} total", + "acknowledged": "Alert acknowledged", + "resolvedToast": "Alert resolved", + "operationFailed": "Operation failed", + "ruleUpdated": "Rule status updated", + "updateFailed": "Update failed", + "deleted": "Deleted", + "deleteFailed": "Delete failed", + "deleteRule": "Delete Rule", + "deleteContact": "Delete Contact", + "deleteGroup": "Delete Group", + "quickSetup": "Quick Setup", + "quickSetupDesc": "Create 6 alert rules for online Agent hosts: CPU(>80%)/Memory(>80%)/Disk(>90%)/TIME_WAIT(>15000)/CLOSE_WAIT(>200)/Process detection.", + "quickSetupConfirm": "Confirm Create", + "quickSetupCreating": "Creating…", + "quickSetupSuccess": "Default alert rules created successfully", + "quickSetupFailed": "Creation failed, check if Agent hosts are online", + "silenceDesc": "Quick silence from alert list", + "enabled": "Enabled", + "disabled": "Disabled", + "pageInfo": "Page {{page}}/{{totalPages}}, {{total}} total", + "addRule": "Add Rule", + "noRules": "No alert rules", + "noRulesHint": "Click 'Add Rule' or 'Quick Setup' to create", + "durationSeconds": "{{count}}s duration", + "contactsTitle": "Contacts", + "peopleCount": "{{count}} people", + "addContact": "Add Contact", + "addGroup": "Add Group", + "noContacts": "No contacts yet, click 'Add Contact' to create", + "noGroups": "No contact groups yet, click 'Add Group' to create", + "minutesShort": "{{count}}m", + "prevPage": "Previous", + "nextPage": "Next" } } diff --git a/frontend/src/locales/zh-CN.json b/frontend/src/locales/zh-CN.json index 8dd7272..e85a68b 100644 --- a/frontend/src/locales/zh-CN.json +++ b/frontend/src/locales/zh-CN.json @@ -317,5 +317,77 @@ "status": "状态", "tags": "标签" } + }, + "alert": { + "stat": { + "firing": "触发中", + "critical": "严重", + "warning": "警告", + "resolved": "已解决" + }, + "tab": { + "alerts": "告警列表", + "rules": "告警规则", + "silences": "静默规则", + "contacts": "报警联系人", + "groups": "报警联系组" + }, + "searchPlaceholder": "搜索告警...", + "allSeverity": "全部级别", + "allStatus": "全部状态", + "severity": { + "critical": "严重", + "warning": "警告", + "info": "信息" + }, + "status": { + "firing": "触发中", + "acknowledged": "已确认", + "resolved": "已解决" + }, + "table": { + "alertInfo": "告警信息", + "severity": "级别", + "status": "状态", + "source": "来源", + "duration": "持续", + "actions": "操作" + }, + "loading": "加载中...", + "noAlerts": "暂无告警", + "totalItems": "共 {{count}} 条", + "acknowledged": "告警已确认", + "resolvedToast": "告警已解决", + "operationFailed": "操作失败", + "ruleUpdated": "规则状态已更新", + "updateFailed": "更新失败", + "deleted": "已删除", + "deleteFailed": "删除失败", + "deleteRule": "删除规则", + "deleteContact": "删除联系人", + "deleteGroup": "删除联系组", + "quickSetup": "一键报警", + "quickSetupDesc": "为 Agent 在线主机创建 CPU(>80%)/内存(>80%)/磁盘(>90%)/TIME_WAIT(>15000)/CLOSE_WAIT(>200)/进程检测 6 条告警规则。", + "quickSetupConfirm": "确认创建", + "quickSetupCreating": "创建中…", + "quickSetupSuccess": "默认告警规则创建成功", + "quickSetupFailed": "创建失败,请检查 Agent 主机是否在线", + "silenceDesc": "从告警列表快速静默", + "enabled": "已启用", + "disabled": "已禁用", + "pageInfo": "第 {{page}}/{{totalPages}} 页,共 {{total}} 条", + "addRule": "添加规则", + "noRules": "暂无告警规则", + "noRulesHint": "点击「添加规则」或「一键报警」快速创建", + "durationSeconds": "持续 {{count}}秒", + "contactsTitle": "报警联系人", + "peopleCount": "{{count}} 人", + "addContact": "添加联系人", + "addGroup": "添加联系组", + "noContacts": "暂无报警联系人,点击「添加联系人」创建", + "noGroups": "暂无报警联系组,点击「添加联系组」创建", + "minutesShort": "{{count}}分", + "prevPage": "上一页", + "nextPage": "下一页" } }