diff --git a/PROJECT_EVALUATION.md b/PROJECT_EVALUATION.md index db900cb..b8c891f 100644 --- a/PROJECT_EVALUATION.md +++ b/PROJECT_EVALUATION.md @@ -80,6 +80,7 @@ | 监控大屏(自定义仪表盘) | ✅ custom_dashboard.go CRUD | ✅ GrafanaDashboard 自定义 Tab + GrafanaPanelContent PromQL 渲染 | ✅ F4 done | | 链路追踪 | ✅ trace_proxy.go Jaeger/Tempo 代理 | ✅ TraceManager (587L) — traceApi 对接真实后端 + demo 数据兜底 | ✅ F5 done | | **中间件监控** | ✅ middleware_monitor.go 后端直连采集 Redis/MySQL | ✅ MiddlewareMonitor 完整管理页面 (CRUD + 测试 + 概览) | ✅ M15 done | +| **主机监控大屏** | ✅ serverApi 复用 | ✅ HostMonitorDashboard (Grafana 风格大屏 + CPU/内存 Top5 排行 + 统计卡片) | ✅ U13 done | ### 2.5 自动化运维 ✅ 完善 @@ -145,9 +146,9 @@ | 问题 | 数量 | |------|------| -| 前端 `set-state-in-effect`(潜在无限循环) | 7 处 | -| 前端 `react-hooks/purity`(render 调 Date.now) | 6 处 | -| 前端死代码(HostMonitorDashboard lazy 未挂载) | 1 处 | +| ~~前端死代码(HostMonitorDashboard lazy 未挂载)~~ → **U13 done: 已挂载为 `/host-dashboard` 路由 + 监控菜单「主机大屏」** | ~~1 处~~ ✅ done | +| ~~前端 `set-state-in-effect`(潜在无限循环)~~ → **U12 done: 0 处** | ~~7 处~~ ✅ done | +| ~~前端 `react-hooks/purity`(render 调 Date.now)~~ → **U12 done: 0 处** | ~~6 处~~ ✅ done | | 后端 `exec.Command` + `bash -c`(命令注入面) | 18 处(需审计用户输入路径) | ### 3.4 Mock API / 未对接后端 diff --git a/ROADMAP.md b/ROADMAP.md index 8f0ae77..7472f9f 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -475,6 +475,7 @@ services/api.ts (1324L) | U5 | Kubernetes 模块国际化 | P3 | **done** | | U12 | 工程质量回归修复(ESLint errors + React Hooks 关键规则) | P3 | **done** | | Q4+ | 后端错误处理治理扩展(Q5: RDP/API Token/AIOps 模块 `_ =` DB 写入) | P0 | **done** | +| U13 | 主机监控大屏挂载(HostMonitorDashboard 死代码复活) | P3 | **done** | --- @@ -555,3 +556,28 @@ pending → in_progress → done / blocked 1. 更新本文件状态 2. 更新 PROJECT_EVALUATION.md 对应行 3. git commit message 格式: `refactor: Q2 kubernetes.go 模块化拆分` + +--- + +## U13: 主机监控大屏挂载(HostMonitorDashboard 死代码复活)[done] + +**问题**: `frontend/src/components/monitor/dashboard/HostMonitorDashboard.tsx`(497 行)是一个完整的 Grafana 风格主机监控大屏组件(统计卡片 + CPU/内存 Top5 排行 + 可排序表格 + 分页 + 国际化),但**从未被任何路由或菜单挂载**——是死代码(PROJECT_EVALUATION.md 3.3 低优先级技术债之一)。早期项目评估中"监控告警 80%"也明确指出"缺大屏"。 + +**已完成 (2026-07-06)**: +- ✅ **路由挂载** — `App.tsx` 新增 lazy import + ``,主机大屏作为独立路由 `/host-dashboard` +- ✅ **侧边栏菜单** — `Sidebar.tsx` 监控告警菜单新增「主机大屏」子项(`menu.hostDashboard`,LayoutDashboard 图标,`agent:monitor` 权限),位于「资源监控」之后 +- ✅ **面包屑识别** — `Breadcrumb.tsx` 新增 `host-dashboard` 路由段映射 +- ✅ **i18n 翻译键** — zh-CN.json + en-US.json 新增 `menu.hostDashboard`(主机大屏 / Host Dashboard)+ `breadcrumb.hostDashboard` 两键,zh/en 对齐 7556 keys +- ✅ **复用已有翻译** — 组件内部 `monitor:hostDashboard.*` 23 个翻译键早已存在(被 AgentMonitor/MiddlewareMonitor/data-table 等复用),无需新增 + +**验收标准**: +- [x] `/host-dashboard` 路由可访问,HostMonitorDashboard 组件渲染 +- [x] 侧边栏「监控告警 → 主机大屏」菜单项可见,权限 `agent:monitor` 过滤 +- [x] 面包屑显示「主机大屏」 +- [x] `tsc -b` 零错误 +- [x] `npm run build` 零错误(✓ built in 17.50s) +- [x] ESLint errors=0(无新增) +- [x] zh/en 翻译键对齐(7556 = 7556) +- [x] 17/17 集成回归测试通过(零回归) +- [x] Docker 部署 healthy +- [x] PROJECT_EVALUATION.md 3.3 死代码项已清除 diff --git a/TDD_PLAN.md b/TDD_PLAN.md index 75f8f94..48f61bc 100644 --- a/TDD_PLAN.md +++ b/TDD_PLAN.md @@ -1088,3 +1088,66 @@ python3 ../tests/integration_test.py --host 127.0.0.1 --port 8080 - [x] U4: KubernetesClusterDetail 非注释 CJK = 0 - [x] U5: TopologyView 非注释 CJK = 0 - [x] U6: 17/17 集成回归测试通过 + +--- + +## P3-U13: 主机监控大屏挂载(HostMonitorDashboard 死代码复活) + +### 验证用例 + +```bash +# U1: 路由配置存在 +grep -c 'host-dashboard' /srv/aiops/frontend/src/App.tsx +# 期望: >= 2 (lazy import + Route) + +# U2: Sidebar 菜单项存在 +grep -c 'host-dashboard' /srv/aiops/frontend/src/components/layout/Sidebar.tsx +# 期望: >= 1 + +# U3: Breadcrumb 映射存在 +grep -c 'host-dashboard' /srv/aiops/frontend/src/components/layout/Breadcrumb.tsx +# 期望: >= 1 + +# U4: i18n 翻译键存在且对齐 +python3 -c " +import json +zh = json.load(open('/srv/aiops/frontend/src/locales/zh-CN.json', encoding='utf-8')) +en = json.load(open('/srv/aiops/frontend/src/locales/en-US.json', encoding='utf-8')) +assert zh['menu']['hostDashboard'] == '主机大屏' +assert en['menu']['hostDashboard'] == 'Host Dashboard' +assert zh['breadcrumb']['hostDashboard'] == '主机大屏' +assert en['breadcrumb']['hostDashboard'] == 'Host Dashboard' +print('✅ i18n keys aligned') +" + +# U5: TypeScript 编译零错误 +cd /srv/aiops/frontend && npx tsc -b 2>&1 | tail -3 +# 期望: 退出码 0 + +# U6: Vite 构建 +npm run build 2>&1 | tail -3 +# 期望: built in Ns + +# U7: ESLint 无新增 errors +npx eslint src/ --format json 2>/dev/null | python3 -c " +import json, sys +data = json.load(sys.stdin) +errors = sum(1 for r in data for m in r.get('messages', []) if m.get('severity') == 2) +assert errors == 0, f'{errors} errors' +print('✅ ESLint errors=0') +" + +# U8: 集成回归测试 +python3 /srv/aiops/tests/integration_test.py --host 127.0.0.1 --port 8080 | tail -3 +# 期望: 17/17 passed +``` + +### 通过标准 +- [x] U1: App.tsx 路由配置存在(lazy import + Route path="host-dashboard") +- [x] U2: Sidebar 监控菜单含「主机大屏」项 +- [x] U3: Breadcrumb 路由映射存在 +- [x] U4: zh/en 翻译键对齐(menu.hostDashboard + breadcrumb.hostDashboard) +- [x] U5: `tsc -b` 零错误 +- [x] U6: `npm run build` 零错误(✓ built in 17.50s) +- [x] U7: ESLint errors=0(无新增) +- [x] U8: 17/17 集成回归测试通过(零回归) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index c392693..4473948 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -63,6 +63,7 @@ const TraceManager = lazy(() => import('@/components/monitor/trace/TraceManager' const HostMonitor = lazy(() => import('@/pages/monitor/HostMonitor').then(m => ({ default: m.HostMonitor }))); const GrafanaDashboard = lazy(() => import('@/components/monitor/dashboard/GrafanaDashboard').then(m => ({ default: m.default }))); const MonitorCenter = lazy(() => import('@/pages/monitor/MonitorCenter').then(m => ({ default: m.MonitorCenter }))); +const HostMonitorDashboard = lazy(() => import('@/components/monitor/dashboard/HostMonitorDashboard')); const MetricsExplorer = lazy(() => import('@/pages/monitor/MetricsExplorer').then(m => ({ default: m.MetricsExplorer }))); const DatasourcePage = lazy(() => import('@/components/monitor/datasource/DatasourcePage').then(m => ({ default: m.default }))); const LogCenter = lazy(() => import('@/components/monitor/log-center/LogCenter')); @@ -186,6 +187,7 @@ function App() { } /> } /> } /> + } /> } /> } /> } /> diff --git a/frontend/src/components/layout/Breadcrumb.tsx b/frontend/src/components/layout/Breadcrumb.tsx index 7fa6845..7cdf438 100644 --- a/frontend/src/components/layout/Breadcrumb.tsx +++ b/frontend/src/components/layout/Breadcrumb.tsx @@ -50,6 +50,7 @@ const ROUTE_I18N_MAP: Record = { 'datasources': 'breadcrumb.datasources', 'dashboards': 'breadcrumb.dashboards', 'host-monitor': 'breadcrumb.hostMonitor', + 'host-dashboard': 'breadcrumb.hostDashboard', 'alerts': 'breadcrumb.alerts', 'approval': 'breadcrumb.approval', 'approval-resource': 'breadcrumb.approvalResource', diff --git a/frontend/src/components/layout/Sidebar.tsx b/frontend/src/components/layout/Sidebar.tsx index 0f9fe5e..152720e 100644 --- a/frontend/src/components/layout/Sidebar.tsx +++ b/frontend/src/components/layout/Sidebar.tsx @@ -115,6 +115,7 @@ const menuItems: MenuItem[] = [ children: [ { id: 'grafana', name: 'Dashboards', labelKey: 'menu.grafana', icon: Monitor, path: '/dashboards', permission: 'monitor:alert' }, { id: 'monitor-center', name: 'Resource Monitor', labelKey: 'menu.resourceMonitor', icon: Activity, path: '/monitor-center', permission: 'agent:monitor' }, + { id: 'host-dashboard', name: 'Host Dashboard', labelKey: 'menu.hostDashboard', icon: LayoutDashboard, path: '/host-dashboard', permission: 'agent:monitor' }, { id: 'trace', name: 'Tracing', labelKey: 'menu.trace', icon: GitBranch, path: '/trace', permission: 'monitor:alert' }, { id: 'alert-center', name: 'Alert Center', labelKey: 'menu.alertCenter', icon: Bell, path: '/alert-center', permission: 'monitor:alert' }, { id: 'datasources', name: 'Datasources', labelKey: 'menu.datasources', icon: Database, path: '/datasources', permission: 'monitor:alert' }, diff --git a/frontend/src/locales/en-US.json b/frontend/src/locales/en-US.json index 093b8e9..4dbdbac 100644 --- a/frontend/src/locales/en-US.json +++ b/frontend/src/locales/en-US.json @@ -563,6 +563,7 @@ "monitor": "Monitoring", "grafana": "Dashboards", "resourceMonitor": "Resource Monitor", + "hostDashboard": "Host Dashboard", "trace": "Tracing", "alertCenter": "Alert Center", "datasources": "Datasources", @@ -7995,6 +7996,7 @@ "datasources": "Data Sources", "dashboards": "Dashboards", "hostMonitor": "Host Monitor", + "hostDashboard": "Host Dashboard", "alerts": "Alerts", "approval": "Requests", "approvalResource": "Resource Request", diff --git a/frontend/src/locales/zh-CN.json b/frontend/src/locales/zh-CN.json index 8eeb825..d213573 100644 --- a/frontend/src/locales/zh-CN.json +++ b/frontend/src/locales/zh-CN.json @@ -563,6 +563,7 @@ "monitor": "监控中心", "grafana": "监控大屏", "resourceMonitor": "资源监控", + "hostDashboard": "主机大屏", "trace": "链路追踪", "alertCenter": "告警中心", "datasources": "数据源", @@ -7995,6 +7996,7 @@ "datasources": "数据源", "dashboards": "监控大屏", "hostMonitor": "主机监控", + "hostDashboard": "主机大屏", "alerts": "监控告警", "approval": "资源申请", "approvalResource": "资源申请",