feat(monitor): U13 主机监控大屏挂载 — HostMonitorDashboard 死代码复活为 /host-dashboard 路由 + 监控菜单

- App.tsx: 新增 HostMonitorDashboard lazy import + Route path=host-dashboard
- Sidebar.tsx: 监控告警菜单新增「主机大屏」子项 (menu.hostDashboard, agent:monitor 权限)
- Breadcrumb.tsx: 新增 host-dashboard 路由段映射
- i18n: zh-CN/en-US 新增 menu.hostDashboard + breadcrumb.hostDashboard (主机大屏/Host Dashboard), 7556 keys 对齐
- 复用已有 monitor:hostDashboard.* 23 翻译键 (AgentMonitor/MiddlewareMonitor/data-table 共享)
- ROADMAP.md: 新增 U13 模块记录 + 状态追踪表
- PROJECT_EVALUATION.md: 清除 3.3 死代码技术债 + U12 过时数字 + 监控模块补充主机大屏
- TDD_PLAN.md: 新增 P3-U13 验证用例和通过标准

验证: tsc -b=0, npm build✓(17.50s), ESLint errors=0, 17/17 集成回归通过, Docker healthy
This commit is contained in:
attacker committed 2026-07-06 09:34:39 +08:00
1 parent cd30af5bd6
commit e19c27707f
8 files changed
+101 -3

No files matched your search

+4 -3
View File
@@ -80,6 +80,7 @@
| 监控大屏(自定义仪表盘) | ✅ custom_dashboard.go CRUD | ✅ GrafanaDashboard 自定义 Tab + GrafanaPanelContent PromQL 渲染 | ✅ F4 done | | 监控大屏(自定义仪表盘) | ✅ custom_dashboard.go CRUD | ✅ GrafanaDashboard 自定义 Tab + GrafanaPanelContent PromQL 渲染 | ✅ F4 done |
| 链路追踪 | ✅ trace_proxy.go Jaeger/Tempo 代理 | ✅ TraceManager (587L) — traceApi 对接真实后端 + demo 数据兜底 | ✅ F5 done | | 链路追踪 | ✅ trace_proxy.go Jaeger/Tempo 代理 | ✅ TraceManager (587L) — traceApi 对接真实后端 + demo 数据兜底 | ✅ F5 done |
| **中间件监控** | ✅ middleware_monitor.go 后端直连采集 Redis/MySQL | ✅ MiddlewareMonitor 完整管理页面 (CRUD + 测试 + 概览) | ✅ M15 done | | **中间件监控** | ✅ middleware_monitor.go 后端直连采集 Redis/MySQL | ✅ MiddlewareMonitor 完整管理页面 (CRUD + 测试 + 概览) | ✅ M15 done |
| **主机监控大屏** | ✅ serverApi 复用 | ✅ HostMonitorDashboard (Grafana 风格大屏 + CPU/内存 Top5 排行 + 统计卡片) | ✅ U13 done |
### 2.5 自动化运维 ✅ 完善 ### 2.5 自动化运维 ✅ 完善
@@ -145,9 +146,9 @@
| 问题 | 数量 | | 问题 | 数量 |
|------|------| |------|------|
| 前端 `set-state-in-effect`(潜在无限循环) | 7 处 | | ~~前端死代码(HostMonitorDashboard lazy 未挂载)~~ → **U13 done: 已挂载为 `/host-dashboard` 路由 + 监控菜单「主机大屏」** | ~~1 处~~ ✅ done |
| 前端 `react-hooks/purity`(render 调 Date.now) | 6 处 | | ~~前端 `set-state-in-effect`(潜在无限循环)~~ → **U12 done: 0 处** | ~~7 处~~ ✅ done |
| 前端死代码(HostMonitorDashboard lazy 未挂载) | 1 处 | | ~~前端 `react-hooks/purity`(render 调 Date.now)~~ → **U12 done: 0 处** | ~~6 处~~ ✅ done |
| 后端 `exec.Command` + `bash -c`(命令注入面) | 18 处(需审计用户输入路径) | | 后端 `exec.Command` + `bash -c`(命令注入面) | 18 处(需审计用户输入路径) |
### 3.4 Mock API / 未对接后端 ### 3.4 Mock API / 未对接后端
+26
View File
@@ -475,6 +475,7 @@ services/api.ts (1324L)
| U5 | Kubernetes 模块国际化 | P3 | **done** | | U5 | Kubernetes 模块国际化 | P3 | **done** |
| U12 | 工程质量回归修复(ESLint errors + React Hooks 关键规则) | P3 | **done** | | U12 | 工程质量回归修复(ESLint errors + React Hooks 关键规则) | P3 | **done** |
| Q4+ | 后端错误处理治理扩展(Q5: RDP/API Token/AIOps 模块 `_ =` DB 写入) | P0 | **done** | | Q4+ | 后端错误处理治理扩展(Q5: RDP/API Token/AIOps 模块 `_ =` DB 写入) | P0 | **done** |
| U13 | 主机监控大屏挂载(HostMonitorDashboard 死代码复活) | P3 | **done** |
--- ---
@@ -555,3 +556,28 @@ pending → in_progress → done / blocked
1. 更新本文件状态 1. 更新本文件状态
2. 更新 PROJECT_EVALUATION.md 对应行 2. 更新 PROJECT_EVALUATION.md 对应行
3. git commit message 格式: `refactor: Q2 kubernetes.go 模块化拆分` 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 + `<Route path="host-dashboard">`,主机大屏作为独立路由 `/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 死代码项已清除
+63
View File
@@ -1088,3 +1088,66 @@ python3 ../tests/integration_test.py --host 127.0.0.1 --port 8080
- [x] U4: KubernetesClusterDetail 非注释 CJK = 0 - [x] U4: KubernetesClusterDetail 非注释 CJK = 0
- [x] U5: TopologyView 非注释 CJK = 0 - [x] U5: TopologyView 非注释 CJK = 0
- [x] U6: 17/17 集成回归测试通过 - [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 集成回归测试通过(零回归)
+2
View File
@@ -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 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 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 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 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 DatasourcePage = lazy(() => import('@/components/monitor/datasource/DatasourcePage').then(m => ({ default: m.default })));
const LogCenter = lazy(() => import('@/components/monitor/log-center/LogCenter')); const LogCenter = lazy(() => import('@/components/monitor/log-center/LogCenter'));
@@ -186,6 +187,7 @@ function App() {
<Route path="alerts" element={<LazyPage><AlertManager /></LazyPage>} /> <Route path="alerts" element={<LazyPage><AlertManager /></LazyPage>} />
<Route path="alert-center" element={<LazyPage><AlertCenter /></LazyPage>} /> <Route path="alert-center" element={<LazyPage><AlertCenter /></LazyPage>} />
<Route path="monitor-center" element={<LazyPage><MonitorCenter /></LazyPage>} /> <Route path="monitor-center" element={<LazyPage><MonitorCenter /></LazyPage>} />
<Route path="host-dashboard" element={<LazyPage><HostMonitorDashboard /></LazyPage>} />
<Route path="log-center" element={<Navigate to="/log-center/loki" replace />} /> <Route path="log-center" element={<Navigate to="/log-center/loki" replace />} />
<Route path="log-center/:section" element={<LazyPage><LogCenter /></LazyPage>} /> <Route path="log-center/:section" element={<LazyPage><LogCenter /></LazyPage>} />
<Route path="logs" element={<Navigate to="/log-center/loki" replace />} /> <Route path="logs" element={<Navigate to="/log-center/loki" replace />} />
@@ -50,6 +50,7 @@ const ROUTE_I18N_MAP: Record<string, string> = {
'datasources': 'breadcrumb.datasources', 'datasources': 'breadcrumb.datasources',
'dashboards': 'breadcrumb.dashboards', 'dashboards': 'breadcrumb.dashboards',
'host-monitor': 'breadcrumb.hostMonitor', 'host-monitor': 'breadcrumb.hostMonitor',
'host-dashboard': 'breadcrumb.hostDashboard',
'alerts': 'breadcrumb.alerts', 'alerts': 'breadcrumb.alerts',
'approval': 'breadcrumb.approval', 'approval': 'breadcrumb.approval',
'approval-resource': 'breadcrumb.approvalResource', 'approval-resource': 'breadcrumb.approvalResource',
@@ -115,6 +115,7 @@ const menuItems: MenuItem[] = [
children: [ children: [
{ id: 'grafana', name: 'Dashboards', labelKey: 'menu.grafana', icon: Monitor, path: '/dashboards', permission: 'monitor:alert' }, { 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: '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: '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: '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' }, { id: 'datasources', name: 'Datasources', labelKey: 'menu.datasources', icon: Database, path: '/datasources', permission: 'monitor:alert' },
+2
View File
@@ -563,6 +563,7 @@
"monitor": "Monitoring", "monitor": "Monitoring",
"grafana": "Dashboards", "grafana": "Dashboards",
"resourceMonitor": "Resource Monitor", "resourceMonitor": "Resource Monitor",
"hostDashboard": "Host Dashboard",
"trace": "Tracing", "trace": "Tracing",
"alertCenter": "Alert Center", "alertCenter": "Alert Center",
"datasources": "Datasources", "datasources": "Datasources",
@@ -7995,6 +7996,7 @@
"datasources": "Data Sources", "datasources": "Data Sources",
"dashboards": "Dashboards", "dashboards": "Dashboards",
"hostMonitor": "Host Monitor", "hostMonitor": "Host Monitor",
"hostDashboard": "Host Dashboard",
"alerts": "Alerts", "alerts": "Alerts",
"approval": "Requests", "approval": "Requests",
"approvalResource": "Resource Request", "approvalResource": "Resource Request",
+2
View File
@@ -563,6 +563,7 @@
"monitor": "监控中心", "monitor": "监控中心",
"grafana": "监控大屏", "grafana": "监控大屏",
"resourceMonitor": "资源监控", "resourceMonitor": "资源监控",
"hostDashboard": "主机大屏",
"trace": "链路追踪", "trace": "链路追踪",
"alertCenter": "告警中心", "alertCenter": "告警中心",
"datasources": "数据源", "datasources": "数据源",
@@ -7995,6 +7996,7 @@
"datasources": "数据源", "datasources": "数据源",
"dashboards": "监控大屏", "dashboards": "监控大屏",
"hostMonitor": "主机监控", "hostMonitor": "主机监控",
"hostDashboard": "主机大屏",
"alerts": "监控告警", "alerts": "监控告警",
"approval": "资源申请", "approval": "资源申请",
"approvalResource": "资源申请", "approvalResource": "资源申请",