refactor(quality): Q19 前端巨型组件拆分 — GrafanaDashboard 624L→78L (-87%), 提取 grafana-dashboard/ 5 个独立文件 (types + datasource-toolbar + BatchDeployDialog + AgentTab + ExternalDatasourceTab), DRY 合并 Zabbix/Prometheus Tab 为通用 ExternalDatasourceTab (render-prop 模式), 移除文件级 eslint-disable + 类型安全升级 (any→具体接口), 零逻辑变更, ESLint errors=0/warnings=65/any=0, tsc -b=0, npm build✓, 17/17 测试通过

This commit is contained in:
attacker committed 2026-07-08 09:45:39 +08:00
1 parent 69447e4d66
commit 42340edce2
8 files changed
+1018 -576

No files matched your search

+42
View File
@@ -490,6 +490,48 @@ services/api.ts (1324L)
| Q16 | 前端巨型组件拆分(RdpDialog 642L→442L,提取 types + rdpp-utils + RdpDialogHeader) | P0 | **done** |
| Q17 | 前端巨型组件拆分(DeploymentEditService 627L→394L,提取 types + ServiceCreateForm + IngressCreateForm + ServiceListItem + IngressListItem) | P0 | **done** |
| Q18 | 前端巨型组件拆分(TraceManager 605L→331L,提取 types + trace-helpers + SpanTreeNode + TraceDetailDialog + SpanDetailDialog,修复 SpanTreeNode 内联定义反模式) | P0 | **done** |
| Q19 | 前端巨型组件拆分(GrafanaDashboard 624L→78L,提取 types + datasource-toolbar + BatchDeployDialog + AgentTab + ExternalDatasourceTab,DRY 合并 Zabbix/Prometheus Tab,移除文件级 eslint-disable,类型安全升级 any→具体接口) | P0 | **done** |
---
## Q19: 前端巨型组件拆分 — GrafanaDashboard [done]
**问题**: `GrafanaDashboard.tsx`(624 行)是 Q18 拆分后项目最大的核心业务组件之一(排除 UI 库 sidebar/data-table),包含监控大屏页面的全部逻辑:Tab 配置、Agent 主机监控表格(状态管理 + 排序 + 分页 + 选择 + 批量部署/卸载 + Agent 安装向导)、批量部署对话框(模式切换 + 主机列表 + 凭据输入 + 警告确认)、数据源工具栏、Zabbix Tab、Prometheus Tab(两者逻辑近乎重复)、以及主组件编排。文件顶部有 `eslint-disable @typescript-eslint/no-explicit-any`,多处 `any` 类型。单文件过大导致维护困难。
**已完成 (2026-07-08)**:
将类型/常量、数据源工具栏、批量部署对话框、Agent Tab、外部数据源通用 Tab 提取为 `grafana-dashboard/` 子目录下的独立文件:
| 新文件 | 行数 | 职责 |
|--------|------|------|
| `types.ts` | 60 | AgentHost/SortField/MonitorDatasource/BatchCreds/WizardServer/TabId 接口 + DEFAULT_BATCH_CREDS 常量 |
| `datasource-toolbar.tsx` | 49 | normalizeDatasourceList(后端响应归一化+排序)+ DatasourceToolbar 组件(数据源下拉+刷新) |
| `BatchDeployDialog.tsx` | 273 | 批量部署 Agent 对话框(安装/升级模式切换 + 主机列表表格 + 凭据输入 + 警告确认 + 我已知悉勾选),12 个 props 的受控组件 |
| `AgentTab.tsx` | 486 | Agent 主机监控 Tab(状态管理 + fetch + 排序/分页/选择 + 批量卸载 + 安装向卫集成 + BatchDeployDialog 集成 + 主机表格渲染) |
| `ExternalDatasourceTab.tsx` | 78 | 外部数据源通用 Tab(fetcher + loading + empty + children render-prop),DRY 合并 Zabbix/Prometheus 两个近乎重复的组件 |
主文件 `GrafanaDashboard.tsx` 从 **624 行降至 78 行**(-87%),仅保留:getTabs 配置、ZabbixTab/PrometheusTab 薄包装(用 ExternalDatasourceTab + render-prop)、GrafanaDashboard 主组件编排(PageShell + 全屏切换 + Tab 分发)。
**关键改进**:
- **DRY 合并**: 原 ZabbixTab 和 PrometheusTab 各 30 行,逻辑近乎完全重复(仅 API/标签/渲染组件不同)。合并为 ExternalDatasourceTab 通用组件 + render-prop 模式,消除重复代码。
- **类型安全升级**: 移除文件顶部的 `/* eslint-disable @typescript-eslint/no-explicit-any */`。`wizardServer: any` → `WizardServer | null`;`ds: any` → `MonitorDatasource | null`;`catch (e: any)` → `catch (e)` + `e instanceof Error` 类型守卫;排序函数 `let va: any` → `string | number`。全局 ESLint any 保持 **0**。
- **命名规范化**: 数据源工具栏 prop `activeId` → `activeID`(避免与 HTML `id` 混淆),`normalizeDatasourceList` 参数 `r: any` → `r: unknown` + 类型断言。
**提取原则**: types 为纯数据/类型(零 React 依赖);datasource-toolbar 为共享工具+组件(被 ExternalDatasourceTab 和主文件引用);BatchDeployDialog 为受控展示组件(接收 12 个 props,零独立状态);AgentTab 为自包含业务组件(内部管理全部 Agent 监控状态 + 集成 AgentWizard + BatchDeployDialog);ExternalDatasourceTab 为通用容器组件(fetcher render-prop 模式)。零逻辑变更。
**验收标准**:
- [x] GrafanaDashboard.tsx 从 624 行降至 **78 行**(-87%)
- [x] 5 个提取的文件全部 < 490 行(最大 AgentTab 486 行,聚焦单一职责)
- [x] `tsc -b` 零错误
- [x] `npm run build` 零错误(✓ built in 17.56s)
- [x] ESLint errors 保持 **0**(grafana-dashboard/ 目录零 errors,仅 1 个 react-refresh 架构性 warning)
- [x] ESLint warnings 从 64 增至 **65**(+1 datasource-toolbar react-refresh/only-export-components,符合既有模式)
- [x] 全局 ESLint any 保持 **0**(移除文件级 eslint-disable)
- [x] `go build` 零错误
- [x] 17/17 集成回归测试通过(零回归)
- [x] Docker 部署 healthy,前端页面正常加载(HTTP 200)
- [x] 监控大屏页功能不变(Agent/Zabbix/Prometheus 三 Tab + 主机表格 + 排序/分页/选择 + 批量部署/卸载 + 安装向导全部正常)
- [x] DRY 合并 ZabbixTab/PrometheusTab 为 ExternalDatasourceTab 通用组件
---