feat(audit): F1+F2 告警静默规则标记完成 + 审计日志CSV导出实现

F1 告警静默规则 [done]:
- 后端 alert_silence.go: CRUD + Toggle (onetime/daily/weekly 三模式)
- 告警引擎 isSilenced 集成 (alert_engine.go)
- 前端 SilenceRuleTab + SilenceDialog
- 路由 /alerts/silences 已注册

F2 审计日志导出 [done]:
- 重写 ExportAuditLogs: 真正的 CSV 导出 (encoding/csv + UTF-8 BOM)
- 支持 module/action/username/startTime/endTime 筛选
- 导出限制 10000 条防溢出,自动记录审计日志
- JSON 格式向后兼容 (format=json)
- 前端 exportLogs 传递查询参数

同时包含累积的前期工作:
- 目录重构 internal/ -> controller/model/router (v0.55-v0.57)
- 后端分层架构 dto/repository/service/utils
- 审计模块全功能 (终端审计/操作审计/登录日志)
- asciicast v2 录制格式
- SFTP 文件浏览器
- StatStrip 紧凑统计条
- 在线会话自动刷新
- LiveMonitor WebSocket 诊断修复

验证: go build ✅ | npm run build ✅ | Docker 部署 ✅ | 10 回归端点 ✅ | CSV 导出 ✅ | 静默 CRUD ✅
This commit is contained in:
attacker committed 2026-06-25 20:16:30 +08:00
1 parent e57718998a
commit 77c234b060
314 files changed
+10050 -4065

No files matched your search

+16 -54
View File
@@ -2,10 +2,10 @@ import { useCallback, useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils';
import { Clock, Server, Cloud, Bell, DollarSign, ArrowRight} from 'lucide-react';
import { Clock, Server, ArrowRight } from 'lucide-react';
import { dashboardStatsApi, serverApi, kubernetesApi } from '@/services/api';
import { StatCard } from './DashboardStats';
import { CostOverviewCard, TopResourceUsageCard, ResourceUsageCard, computeMonthChange } from './DashboardCharts';
import { StatStrip } from '@/components/ui/stat-strip';
import { CostOverviewCard, TopResourceUsageCard, ResourceUsageCard } from './DashboardCharts';
import {
AlertMessagesCard,
CertificateExpiryCard,
@@ -98,7 +98,6 @@ export function Dashboard() {
const k8sStats = stats?.kubernetes_stats;
const alertStats = stats?.alert_stats;
const costStats = stats?.cost_stats;
const costChange = computeMonthChange(costStats?.month_trend);
return (
<div className="dg-page">
@@ -129,56 +128,19 @@ export function Dashboard() {
</div>
</div>
{/* Stats Grid with staggered animation */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<div className="animate-fade-in-delay-1">
<StatCard
title="服务器总数"
value={serverStats?.total ?? 0}
description={`${serverStats?.running ?? 0} 台运行中`}
icon={Server}
trend={Number(serverStats?.error ?? 0) > 0 ? 'down' : 'neutral'}
trendValue={Number(serverStats?.error ?? 0) > 0 ? `${serverStats?.error} 台异常` : '运行正常'}
color="blue"
onClick={() => navigate('/servers')}
/>
</div>
<div className="animate-fade-in-delay-2">
<StatCard
title="Kubernetes 集群"
value={k8sStats?.total ?? 0}
description={`${k8sStats?.healthy ?? 0} 个健康`}
icon={Cloud}
trend="neutral"
trendValue="稳定"
color="purple"
onClick={() => navigate('/kubernetes')}
/>
</div>
<div className="animate-fade-in-delay-3">
<StatCard
title="待处理告警"
value={alertStats?.firing ?? 0}
description={`${alertStats?.critical ?? 0} 个严重`}
icon={Bell}
trend={Number(alertStats?.today_count ?? 0) > 0 ? 'up' : 'down'}
trendValue={`本周 ${alertStats?.week_count ?? 0} 条`}
color="rose"
onClick={() => navigate('/alert-center')}
/>
</div>
<div className="animate-fade-in-delay-4">
<StatCard
title="本月云成本"
value={`¥${Number(costStats?.month_cost ?? 0).toLocaleString()}`}
description={costChange.label}
icon={DollarSign}
trend={costChange.direction}
trendValue={`${costChange.pct > 0 ? '+' : ''}${costChange.pct.toFixed(1)}%`}
color="orange"
onClick={() => navigate('/cloud-billing')}
/>
</div>
{/* Stats — compact strip */}
<div className="animate-fade-in-delay-1">
<StatStrip
items={[
{ label: '服务器', value: serverStats?.total ?? 0, color: 'blue' },
{ label: '运行中', value: serverStats?.running ?? 0, color: 'emerald' },
{ label: 'K8s 集群', value: k8sStats?.total ?? 0, color: 'purple' },
{ label: '健康集群', value: k8sStats?.healthy ?? 0, color: 'cyan' },
{ label: '告警', value: alertStats?.firing ?? 0, color: alertStats?.firing > 0 ? 'red' : 'muted' },
{ label: '严重', value: alertStats?.critical ?? 0, color: 'red' },
{ label: '本月成本', value: `¥${Number(costStats?.month_cost ?? 0).toLocaleString()}`, color: 'amber' },
]}
/>
</div>
{/* Resource Usage Chart */}