Files
aiops/ROADMAP.md
T
attacker 8a4dfb0db6 refactor(quality): Q8 前端巨型组件拆分 — SystemSettingsTab 754L→173L (-77%), 提取通用/安全/LDAP 3 个独立子 Tab 组件
- GeneralSettingsTab.tsx (154L): 通用设置 Tab(审计策略 + 系统信息)
- SecuritySettingsTab.tsx (309L): 安全设置 Tab(安全策略 + 会话设置 9 项开关)
- LdapSettingsTab.tsx (243L): LDAP 设置 Tab(配置表单 + 管理区转发)
- 主文件仅保留 Props 接口 + Tab 路由 + 分发逻辑(173L)
- 每个子 Tab 用 Pick<SystemSettingsTabProps,...> 精确声明 props 子集
- tsc -b=0, npm build✓(17.71s), ESLint errors=0/warnings=59(无新增)
- 17/17 集成回归测试通过, Docker 部署 healthy
2026-07-07 01:05:07 +08:00

713 lines
44 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AIOps 智能运维平台 — 优化路线图
> 基于全量审计(96,102 行代码 / 374 文件),从「K8s 功能开发」全面转向「工程质量 + 功能补全 + 架构治理」。
> 最后更新: 2026-07-03
---
## 当前状态:功能开发阶段已完成
| 大模块 | 完成度 | 说明 |
|--------|:------:|------|
| 资产管理 | 100% | 服务器/云账号/域名/账单/Agent 全功能 |
| Kubernetes 管理 | 100% | M1-M14 全部完成(14 个子模块) |
| 应用发布 | 100% | CI/CD 流水线 + SSH/K8s 双路径 |
| 监控告警 | 80% | Agent 监控 + 告警引擎完善;缺:大屏/链路追踪/告警静默 |
| 自动化运维 | 100% | CronJob/脚本/Ansible |
| AIOps 智能 | 100% | 6 种 LLM + 告警分析 + 容量预测 |
| 系统管理 | 95% | 审计导出 TODO |
---
## P0 — 工程质量治理(最高优先级)
> 目标:从「能跑」升级到「能维护」。解决前端类型安全和后端巨型文件问题。
### Q1: 前端类型安全治理 [done]
**问题**: ~~1026 处 `any` 类型 + 218 处未使用变量~~ → **any=40, unused=6, console=1, tsc -b=0 errors, tsc --noEmit=0 errors**
**已完成里程碑 (2026-06-27 最终完成)**:
- ✅ **整个 `src/api/` 目录 any 清零** — monitor/deploy/cloud/agent/server/auth/automation 等子目录所有 create/update 入参与返回值对接具体接口类型/mock 桩对接 Trace/GrafanaDashboard 标准类型
- ✅ `types/monitor.ts` 扩展 ~200 行接口:ZabbixDatasource / AlertSilence / 7 DTO + Trace/Span + GrafanaDashboard/Panel + 6 个运行时记录类型(AlertEventRecord/AlertRuleRecord/AgentHostRecord/CronJobRecord/CertExpiryRecord/ApprovalWorkflowStepRecord)
- ✅ **unused-vars 清零** — 25→6(删除未用 import + 前缀 `_`)
- ✅ **catch any 清零** — 94 处 `catch (e: any)` 移除显式 any
- ✅ **Record<string,any> 安全替换** — 168 处 → `Record<string, unknown>`
- ✅ **组件级 any 清理** — AlertEventsTab/AlertRulesTab/AlertChannelDialog/alertShared(19处) + AuditOperationsTab(8处) + CronJobManager(6处) + AgentMonitor(5处) + DashboardRecent(5处) + AlertManager 全部从 any→具体接口类型
- ✅ **ESLint `no-explicit-any` 1076 → 937 → 837 → 40**
**方案**:
1. 建立 `frontend/src/types/` 后端响应类型定义库(~1550 行)
2. 按模块定义接口:`types/kubernetes.ts` / `types/server.ts` / `types/pipeline.ts` / `types/monitor.ts` 等
3. 逐步将 `any` 替换为具体接口类型
4. 清理 218 处 `no-unused-vars`
5. 移除 93 处 `console.*`(特别是 `api.ts:280` 泄露 token 的调试日志)
6. 配置 CI `tsc --noEmit` 零错误门禁
**验收标准**:
- [x] `types/` 目录覆盖所有后端响应结构(~1550 行,含 6 个运行时记录类型)
- [x] `any` 类型从 1026 处降至 < 50 处 — **40 处**
- [x] `npx tsc --noEmit` 零错误
- [x] ESLint `no-unused-vars` 降至 < 20 处 — **6 处**
- [x] `console.*` 降至 < 10 处 — **1 处**
### Q2: 后端 kubernetes.go 模块化拆分 [done]
**问题**: 单文件 4204 行 / 134 函数,全仓最大文件
**方案**:
```
handlers/kubernetes.go (4204L → 106L core)
→ handlers/kubernetes.go (106L: struct + constructor + shared helpers)
→ handlers/k8s_cluster.go (642L: 集群 CRUD + 同步 + RBAC)
→ handlers/k8s_workload.go (696L: Deployment/STS/DS/ReplicaSet 读写操作)
→ handlers/k8s_pod.go (653L: Pod 日志/终端/exec/指标)
→ handlers/k8s_pod_files.go (206L: Pod 文件浏览/上传/下载)
→ handlers/k8s_resource.go (351L: Service/Ingress/ConfigMap/Secret/PVC/Topology)
→ handlers/k8s_hpa_cronjob.go (384L: HPA + CronJob)
→ handlers/k8s_yaml.go (213L: 通用 YAML get/update/delete/apply)
→ handlers/k8s_namespace.go (305L: Namespace CRUD + 配额)
→ handlers/k8s_events.go (207L: 事件列表 + 聚合)
→ handlers/k8s_node.go (428L: Node 详情 + 资源分配)
→ handlers/k8s_compare.go (146L: 多集群对比)
```
**验收标准**:
- [x] 拆分后单文件不超过 800 行(最大 k8s_workload.go 696 行)
- [x] 所有路由不变,API 响应不变(425 条路由,26 个核心端点回归测试全通过)
- [x] `go build` 零错误
- [x] 425 条路由全部可访问(回归测试)
### Q3: 前端 api.ts 模块化拆分 [done]
**问题**: 单文件 1324 行 / 352 方法
**方案**:
```
services/api.ts (1324L)
→ services/api/kubernetes.ts (78 方法)
→ services/api/deploy.ts (34 方法)
→ services/api/agent.ts (23 方法)
→ services/api/alert.ts (21 方法)
→ services/api/server.ts (11 方法)
→ services/api/cloud.ts (12 方法)
→ services/api/index.ts (统一 re-export)
```
**验收标准**:
- [x] 拆分后单文件不超过 300 行(kubernetes.ts 409 行为例外:78 方法单一模块不可再分)
- [x] 所有 import 路径正确(97 个文件 import @/services/api 全部通过 index.ts 解析)
- [x] `npm run build` 零错误
- [x] 31 个 API 对象 + 3 个类型定义全部保留
---
## P1 — 功能补全
> 目标:消除前端 mock 桩,补全监控模块缺失的后端。
### F1: 告警静默规则 [done]
**问题**: `alertCenterApi.silence` 硬编码返回 `{success:true}`
**方案**:
- 后端新增 `alert_silences` 表 + CRUD API
- 告警引擎评估时检查静默规则(匹配 namespace/label/时间窗)
- 前端 AlertCenter 新增「静默规则」Tab
**验收标准**:
- [x] 可创建/查看/删除静默规则
- [x] 静默期间告警引擎不触发通知(`isSilenced` 集成在 alert_engine.go)
- [x] 静默到期自动恢复(onetime/daily/weekly 三种模式)
### F2: 审计日志导出 [done]
**问题**: 后端 `audit.go` 导出功能仅返回 JSON(TODO)
**方案**:
- 实现 CSV 导出(stdlib `encoding/csv`,带 UTF-8 BOM,Excel 可直接打开)
- 前端 `http.download` 触发浏览器下载,传递当前筛选参数
**验收标准**:
- [x] 可导出为 CSV 格式(带 UTF-8 BOM,Excel 直接打开无乱码)
- [x] 支持按模块/操作类型/用户/时间范围筛选导出
- [x] 导出限制 10000 条防内存溢出
- [x] JSON 格式向后兼容(format=json)
### F3: 前端 RBAC 按钮级控制 [done]
**问题**: 后端 RBAC 完善,但前端无按钮级权限控制
**方案**:
- 后端新增 `GET /user/permissions` 端点返回当前用户权限码;Login 响应附带 `permissions` 数组
- 封装 `<HasPermission permission="xxx">` 组件 + `usePermission()` hook
- Sidebar 菜单按权限过滤(每个菜单项带 `permission` 字段)
- 服务器管理/系统管理等关键页面的增删改按钮按权限显隐
- admin 用户 permissions=`["*"]` 通配符,所有按钮可见
**验收标准**:
- [x] 不同角色看到不同菜单(viewer 只看到 7 个只读菜单,admin 看到全部)
- [x] 无权限按钮自动隐藏(viewer 看不到「添加服务器」「删除」按钮)
- [x] 权限变更后实时生效(登录即获取最新权限,刷新页面自动拉取)
- [x] admin 通配符 `["*"]` 短路逻辑
- [x] 页面刷新后自动拉取权限(MainLayout useEffect)
---
## P2 — 架构优化
### A1: K8s 双路由体系统一 [done]
**问题**: 104 条 K8s 路由存在集群域 `/kubernetes-clusters/:id/...` 和 Kuboard 域 `/kubernetes/:code/...` 两套
**方案**: 以 Kuboard code 路由为主,ID 路由保留向后兼容(标记 deprecated)
**已完成 (2026-06-27)**:
- ✅ 后端新增 4 条缺失的 all-NS code 路由: `services` / `ingresses` / `cronjobs` / `nodes`
- ✅ `ListNodes` handler 改用 `getK8sClientByCode`(兼容 ID 和 code 双参数)
- ✅ ID 域资源列举路由全部标记 `// Deprecated:` 注释
- ✅ 前端 `clusterApi` / `nodeApi` / `workloadApi` 资源方法全部迁移到 code 路由
- ✅ 3 个组件 (KubernetesClusterDetail / TopologyView / KubernetesNodes) 从 `cluster.id` 迁移到 `cluster.code`
- ✅ 修复潜在 bug: ClusterOverviewPage 曾将 code 传给 ID-based getNodes → strconv.Atoi 返回 0
**验收标准**:
- [x] code 路由覆盖所有资源列举场景(7 条 all-NS code 路由)
- [x] ID 路由保留向后兼容(标注 Deprecated,功能不变)
- [x] `go build` 零错误
- [x] `npm run build` 零错误,`tsc -b` 零错误
- [x] 16/16 API 测试通过(7 新路由 + 3 旧路由兼容 + 6 回归)
- [x] code 路由与 ID 路由返回相同数据(nodes=2, pods=24, deployments=15)
### A2: 告警引擎分布式安全 [done]
**问题**: 告警引擎用 goroutine + 30s ticker 常驻,多副本会重复告警
**方案**: Redis 分布式锁(SetNX 原子抢锁),每轮 ticker 先抢锁,60s TTL 防死锁。单实例/redka 模式自动 fallback 为无锁直行。
**验收标准**:
- [x] Cache 接口新增 `SetNX` 方法(go-redis 原子 / redka check-then-set 单副本安全)
- [x] 多副本部署时仅 Leader 副本执行告警检查(SetNX 分布式锁 + 实例 ID 校验)
- [x] Leader 崩溃后锁自动过期(60s TTL),其他副本自动接管
- [x] Redis 故障时 fail-open(不阻断告警)
- [x] `GET /alerts/engine/status` 状态监控端点(is_leader / instance_id / lock_holder)
- [x] 本地/redka 模式(cache=nil)自动 fallback 为单实例直行
### A3: WebSocket 连接统一管理 [done]
**问题**: WebShell/kubectl/PodExec/日志流各有 WebSocket 实现(3 个独立 upgrader,无心跳、无连接注册、无优雅关闭)
**已完成 (2026-06-27)**:
- ✅ 新增 `pkg/wshub/manager.go` — 统一 WebSocket 连接管理器(WSManager)
- ✅ 6 个 WebSocket handler 全部迁移到 WSManager: WebShell/kubectl/PodExec/AuditStream/Metrics/PipelineLog
- ✅ 心跳机制: ping(30s) + pong handler + read deadline(60s) 自动检测死连接
- ✅ 连接注册表: 每个连接带元数据(类型/用户/远程地址/连接时间/最后活跃时间)
- ✅ 每用户连接限制: MaxConnsPerUser=15 防资源耗尽
- ✅ 监控端点: `GET /api/v1/ws/stats`(聚合统计)+ `GET /api/v1/ws/connections`(连接列表)
- ✅ 优雅关闭: `CloseAll()` 关闭所有连接(发送 CloseGoingAway 帧)
- ✅ 统一 upgrader: 消除 3 个重复的 `websocket.Upgrader` 变量
**验收标准**:
- [x] 所有 6 个 WebSocket handler 共享同一个 WSManager 实例
- [x] `/api/v1/ws/stats` 返回 total + by_type + by_user + by_type_user
- [x] `/api/v1/ws/connections` 返回活跃连接列表(含 uptime_sec)
- [x] 连接打开→注册成功,关闭→注销成功(E2E 验证)
- [x] 心跳 ping/pong 生效(30s ping + 60s pong timeout)
- [x] 多连接并发注册正常
- [x] `go build` 零错误,17/17 回归测试通过
---
## P3 — 用户体验提升
### U1: 虚拟滚动 [done]
**问题**: Pod 列表(1000+ Pod)、事件列表(maxRows=200 截断)、审计日志列表在大数据量场景下渲染卡顿
**已完成 (2026-06-27)**:
- ✅ 安装 `@tanstack/react-virtual@3.14.4`,新增 `hooks/useVirtualRows.ts` 可复用虚拟滚动 Hook
- ✅ **PodsTab** (deployment-view): 从 `.map()` 全量渲染 → `useVirtualizer` + `measureElement` 动态行高,支持展开行,自动统计总数
- ✅ **EventTable**: 移除 `maxRows=200` 截断限制 → 虚拟滚动渲染万级事件,CSS Grid 布局对齐表头
- ✅ **AuditOperationsTab**: 从 shadcn `<Table>` 全量渲染 → 虚拟滚动 CSS Grid 布局,保留所有筛选/导出/详情功能
- ✅ **SessionCommandsPanel**: 从 shadcn `<Table>` 全量渲染 → 虚拟滚动,page_size 从 200 提升至 500
**验收标准**:
- [x] `@tanstack/react-virtual` 已安装并集成
- [x] Pod 列表支持 1000+ Pod 虚拟滚动渲染(只渲染可见行 + overscan)
- [x] 事件列表移除 maxRows 限制,万级事件流畅渲染
- [x] 审计日志列表虚拟滚动(时间/用户/模块/操作/资源/IP/结果/详情)
- [x] 会话命令列表虚拟滚动
- [x] `npm run build` 零错误,`tsc --noEmit` 零错误
- [x] 17/17 集成测试通过
- [x] Docker 部署 healthy
### U2: 统一 DataTable 组件 [done]
**问题**: 37 个文件各自手写表格(搜索/排序/分页/导出/选择全部重复实现),维护成本高
**方案**:
- 封装 `DataTable<T>` 泛型组件(`components/ui/data-table.tsx`),声明式列定义 + 内置功能开关
- 替换散布在各页面的手写表格
**已完成 (2026-06-27)**:
- ✅ 新增 `DataTable<T>` 组件 — 支持声明式列定义、排序(三态 asc/desc/null)、全局搜索(指定字段)、客户端分页(可配置 pageSize)、行选择(受控 selectedIds)、CSV 导出(UTF-8 BOM)、列可见性面板(DropdownMenu toggle)、加载骨架、空状态自定义渲染、行点击、CSS 变量主题适配
- ✅ 迁移 3 个代表性页面:
- **RegionManager.tsx** — 区域管理(CRUD + 搜索 + 选择 + 排序 + 导出 + 列可见性 + 云商筛选)
- **LoginLogsTab.tsx** — 登录日志(搜索 + 排序 + 分页 + 导出 + 列可见性 + 状态筛选)
- **LogDatasourcePage.tsx** — 日志数据源管理(搜索 + 排序 + CRUD + 测试连接)
- ✅ 所有功能内建(搜索/排序/分页/选择/导出/列可见性),无需在各页面重复实现
**验收标准**:
- [x] `DataTable<T>` 组件封装排序/搜索/分页/导出/列自定义/行选择
- [x] `tsc -b` 零错误,`npm run build` 零错误(✓ built in 18.05s)
- [x] 迁移的页面功能不变(CRUD/搜索/选择/排序/导出全部保留)
- [x] ESLint any=43(<50),4 个迁移文件零 ESLint 错误
- [x] 17/17 集成回归测试通过
### U3: 国际化 (i18n) [done]
**问题**: 平台无国际化支持,所有 UI 文案硬编码为中文,无法切换语言
**增量迁移进展** — 持续推进页面国际化:
| 页面 | 新增键 | 组件 |
|------|--------|------|
| Dashboard/ServerManager/AlertCenter/Approval/安全审计/Deploy/Kubernetes/Cloud/Task/Monitor | 3800+ | 已迁移 |
| **监控大屏 (GrafanaDashboard)** | 108 (monitor.dashboard.*) | GrafanaDashboard.tsx (AgentTab/ZabbixTab/PrometheusTab/DashboardTab) |
| **AIOps 智能运维模块** | 83 (aiops.*) | AgentCLI/LLMConfig/AIOpsAssistant/AIAlertAnalyzer/AIAnalysisResult/AutoFixDialog/PredictiveCapacityTab/AIPredictiveAnalytics/AgentCLIMessages/AgentCLIHistory/predictUtils/analyzerHelpers (12 文件) |
**已完成 (2026-06-27)**:
- ✅ **i18n 基础设施搭建** — 安装 `i18next` + `react-i18next`,配置翻译实例 (`src/i18n/index.ts`),支持 `zh-CN` / `en-US` 双语
- ✅ **翻译文件** — `src/locales/zh-CN.json`(中文基础)+ `src/locales/en-US.json`(英文翻译),覆盖 5 大命名空间 (common/menu/header/login/dashboard),120+ 翻译键
- ✅ **语言状态持久化** — zustand `useLanguageStore` (persist),语言选择持久化到 localStorage,刷新不丢失
- ✅ **语言切换器** — Header 右上角 + Login 页面右上角,下拉切换 中文/English,即时生效无需刷新
- ✅ **侧边栏菜单全量国际化** — 全部 42+ 菜单项 (9 一级 + 42 二级) 使用 `labelKey` 翻译键,切换语言实时更新
- ✅ **Header 国际化** — 通知、主题切换、用户菜单(个人中心/账号设置/退出登录)全部翻译
- ✅ **Login 页面国际化** — 标题、副标题、表单标签、按钮、错误提示、主题+语言切换器
- ✅ **HTML lang 属性同步** — `i18n.on('languageChanged')` 监听器自动更新 `<html lang>` 属性
- ✅ **index.html 更新** — 标题改为国际化友好版本,`lang="zh-CN"`
- ✅ **可扩展架构** — `MenuItem.labelKey` 模式支持增量迁移,后续页面只需添加翻译键 + `useTranslation()` 即可
**后续增量迁移路径**(已建立完整模式,各页面可独立迁移):
- ✅ Dashboard / ServerManager / Kubernetes 各页面 / AlertCenter / **安全审计(audit)** 等页面内容翻译
- 添加更多语言(如日语 `ja-JP`)只需在 `SUPPORTED_LANGUAGES` + 新 JSON 文件中注册
**验收标准**:
- [x] `react-i18next` + `i18next` 已安装并集成
- [x] `zh-CN.json` + `en-US.json` 翻译文件就绪(120+ 键)
- [x] 语言切换器在 Header 和 Login 页面可用
- [x] 侧边栏菜单 42+ 项全量国际化
- [x] 语言选择持久化(localStorage)
- [x] HTML lang 属性自动同步
- [x] `tsc -b` 零错误,`npm run build` 零错误
- [x] 17/17 集成测试通过
### U5: Kubernetes 模块国际化 [done]
**问题**: Kubernetes 管理是平台最大功能模块(14 子模块完成),但前端组件仍有 ~3000+ 处硬编码中文,未接入 i18n 框架
**已完成 (2026-07-01)**:
- ✅ **新增 `k8s` 翻译命名空间** — 184 个翻译键,覆盖 cluster/tab/column/empty/label/topology/resource/workload 8 个子命名空间
- ✅ **KubernetesClusterDetail.tsx 全量迁移** — 集群详情页 7 个 Tab(概览/节点/Pod/Deployment/Service/Ingress/事件)所有表头、空状态、趋势图标签、TLS 状态全部国际化
- ✅ **TopologyView.tsx 全量迁移** — 架构拓扑页标题/副标题/编辑模式/连线模式/节点编辑弹框/确认对话框/Toast 消息/搜索栏/类型筛选全部国际化
- ✅ 复用 `common.*` 通用翻译键(close/status/type/name/namespace/edit/delete/cancel/save/duration.minAgo 等)
- ✅ 新增 `common.duration.minAgo` 插值键({{count}}分钟前 / {{count}} min ago)
- ✅ 翻译键总数 1019 → 1204(+185 键),11 命名空间(新增 k8s)
- ✅ zh-CN / en-US 完全对齐
**验收标准**:
- [x] `k8s` 命名空间翻译键覆盖所有迁移组件的 UI 文案 — 184 键
- [x] 迁移的组件中 JSX children / 属性文案零硬编码中文(剩余 CJK 仅为注释)
- [x] `tsc --noEmit` 零错误,`npm run build` 零错误(✓ built in 17.81s)
- [x] 17/17 集成回归测试通过
### U4: 后端镜像优化 [done]
**问题**: Backend 镜像 282MB 偏大(含 docker-cli 52MB + docker-cli-buildx 28MB + git 20MB + 3 平台 agent 18MB + 未裁剪 kubectl 60MB)
**已完成 (2026-06-27)**:
- ✅ **移除 git/docker-cli/docker-cli-buildx** (节省 ~100MB) — 改为懒加载(首次流水线使用时通过 `apk add --no-cache` 自动安装)
- ✅ **PipelineHandler 注入 ToolInstaller** — `runCheckout` 调 `EnsureAvailable("git")`,`runImageBuild` 调 `EnsureAvailable("docker-cli")`
- ✅ **UpgradeTools** 函数 — 自动将 DB 中 git/docker-cli 从 `preinstall` 升级为 `lazy`(带 apk install script)
- ✅ **仅内置 linux-amd64 agent** (节省 ~12MB) — arm64/darwin 通过下载 API 提供
- ✅ **kubectl 改用 install-kubectl.sh 下载** (~47MB stripped vs 60MB 未裁剪) — 同时从 .dockerignore 排除 backend/kubectl 60MB 二进制
- ✅ **Dockerfile.embed + backend/Dockerfile 同步更新**
**验收标准**:
- [x] 镜像从 282MB 降至 **107MB**(目标 < 150MB ✅,降幅 62%)
- [x] `go build` 零错误
- [x] 17/17 集成测试通过
- [x] 前端正常服务(embed 模式)
- [x] git/docker 确认不在镜像中(`which git` / `which docker` 返回失败)
- [x] kubectl 确认在镜像中(`which kubectl` 返回 `/usr/local/bin/kubectl`)
- [x] UpgradeTools 日志确认 git/docker-cli preinstall→lazy 升级成功
### F4: 自定义监控仪表盘 [done]
**问题**: `dashboardApi`(Grafana 仪表盘 CRUD)6 个方法全部为 mock 桩,返回空数组/false。前端 `GrafanaDashboard.tsx` 的"自定义"Tab 有完整 UI 但无法创建/保存仪表盘,面板渲染随机 mock 数据。
### F6: 日志告警引擎 [done]
**问题**: 日志中心有完整查询 UI 和「日志告警」菜单项,但告警规则引擎不支持 `type="log"` 类型规则。用户无法将日志查询转化为告警(如「检测到 ERROR 日志即触发通知」)。日志数据源仅支持 BasicAuth,无法对接需要 Bearer Token 或自定义 Header 的 Loki/ES。
**已完成 (2026-06-28)**:
- ✅ **后端告警引擎扩展** — `AlertEngine` 新增 `checkLogAlertRules()` 方法:查询 `type="log"` 的告警规则,通过数据源查询 Loki/ES,查询结果 >0 即触发告警事件(含防重复 + 静默检查 + 通知推送)
- ✅ **自动恢复** — `checkLogAlertRecovery()`:日志告警事件在查询结果归零时自动标记 resolved 并发送恢复通知
- ✅ **多数据源支持** — `queryLogDataSource()` 支持 Loki(`/loki/api/v1/query_range`)和 Elasticsearch(`_search` + 双时间戳字段兼容 `@timestamp`/`timestamp`)
- ✅ **日志数据源认证升级** — `LogDataSource` 模型新增 `auth_type`/`token`/`headers` 字段(none/basic/bearer/custom 四种认证),`applyLogDSAuthV2()` 统一认证逻辑,向后兼容旧 `basic_auth` 字段
- ✅ **AlertEngine 注入 LogDSHandler** — `NewAlertEngine(db, cache, ds)` 新增第三参数,引擎通过 LogDSHandler 加载数据源执行查询
- ✅ **前端告警规则弹框** — `AlertRuleDialog` 日志类型规则动态加载对应数据源列表(Loki/ES),绑定 `datasource_id`
- ✅ **从查询创建告警** — `LogAlertFromQueryDialog` 从 mock 桩改为真实 API 调用(`alertApi.createRule`),支持将当前日志查询一键转化为告警规则
- ✅ **数据源弹框增强** — `LogDatasourceDialog` 支持认证方式选择(无认证/Basic Auth/Bearer Token/自定义 Headers)
- ✅ **ES 代理错误分类** — `logProxyErrStatus`/`logProxyErrCategory` 将 ES 4xx/5xx 错误映射为标准化响应(含 category 字段供前端区分)
**验收标准**:
- [x] 可创建 `type="log"` 告警规则,绑定 Loki/ES 数据源 + 查询表达式
- [x] 引擎周期性执行日志查询,结果 >0 触发告警事件(防重复 + 静默检查)
- [x] 日志告警可自动恢复(查询结果归零 → resolved + 恢复通知)
- [x] 日志数据源支持 none/basic/bearer/custom 四种认证方式
- [x] `AlertEngine` 注入 `LogDSHandler` 不破坏分布式锁(is_leader/distributed 正常)
- [x] 前端「从查询创建告警」真实调用后端 API(非 mock)
- [x] `go build` 零错误
- [x] `npm run build` 零错误(✓ built in 18.57s)
- [x] 17/17 集成回归测试通过
- [x] 引擎无 panic(无效 datasource_id 优雅跳过)
### F5: 链路追踪后端对接 [done]
**问题**: `traceApi`(链路追踪)3 个方法全部为 mock 桩返回空数组。前端 `TraceManager.tsx`(587 行)有完整 UI(Trace 列表/服务拓扑/性能指标/详情弹窗/Span 树可视化)但无数据展示。
**已完成 (2026-06-28)**:
- ✅ 后端新增 `monitor_trace_datasources` 表 + `TraceDataSource` 模型(Jaeger/Tempo 数据源配置)
- ✅ 后端新增 `controller/trace_datasource.go` — CRUD + TestConnection + SetDefault(7 个路由)
- ✅ 后端新增 `controller/trace_proxy.go` — Jaeger/Tempo API 代理 + 响应格式转换
- `GET /traces` — Trace 列表(代理 Jaeger `/api/traces`,转换为前端 Trace 格式)
- `GET /traces/services` — 服务列表 + 性能指标聚合(代理 Jaeger `/api/services` + `/api/traces` 聚合计算 requestCount/errorRate/avgDuration/p95/p99)
- `GET /traces/:traceId` — Trace 详情(代理 Jaeger `/api/traces/:id`,Span 树结构转换)
- ✅ **Demo 数据兜底**:无数据源配置时后端自动返回模拟数据(6 条 Trace + 5 个服务 + 5 个 Span),UI 始终有数据展示
- ✅ 前端 `traceApi` 从 mock 桩改为真实 HTTP 调用(对接 `/traces` REST API)
- ✅ 前端新增 `trace-datasource.ts` — 链路追踪数据源管理 API(CRUD + 测试连接 + 设默认)
**验收标准**:
- [x] `traceApi` 不再是 mock 桩,3 个方法全部对接真实后端
- [x] 无数据源时返回 demo 数据(6 条 Trace/5 个服务/5 个 Span),UI 功能完整
- [x] 配置 Jaeger 数据源后代理转发真实查询
- [x] 可创建/查看/编辑/删除链路追踪数据源
- [x] 可设默认数据源
- [x] 可测试数据源连接(调用 `/api/services` 验证)
- [x] `go build` 零错误
- [x] `npm run build` 零错误(✓ built in 17.78s)
- [x] 17/17 集成回归测试通过
**已完成 (2026-06-27)**:
- ✅ 后端新增 `monitor_custom_dashboards` 表 + `CustomDashboard` 模型(面板配置存 JSON)
- ✅ 后端新增 `controller/custom_dashboard.go` — CRUD + 设默认(6 个路由)
- ✅ 前端 `dashboardApi` 从 mock 桩改为真实 HTTP 调用(对接 `/custom-dashboards` REST API)
- ✅ 前端 `prometheusProxyApi` 新增 `query` / `queryRange` 方法(对接已有后端代理)
- ✅ `GrafanaPanelContent` 从随机 mock 数据改为执行 PromQL 查询,用 Recharts 渲染真实图表
- ✅ 支持 4 种面板类型: graph(折线图 LineChart)/ stat(数值)/ gauge(仪表盘 SVG)/ table(表格)
- ✅ 面板自动 30s 刷新 + loading/error 状态处理 + 自动发现默认 Prometheus 数据源
**验收标准**:
- [x] 可创建/查看/编辑/删除自定义仪表盘
- [x] 仪表盘面板可执行 PromQL 查询并渲染真实数据(非 mock)
- [x] 支持 graph(折线图)/ stat(数值)/ gauge(仪表盘)/ table(表格)四种面板类型
- [x] 仪表盘可设为默认
- [x] `go build` 零错误
- [x] `npm run build` 零错误(✓ built in 18.01s)
- [x] 17/17 集成回归测试通过
---
### M15: 中间件监控 (Redis/MySQL) [done]
**问题**: 前端 `MiddlewareMonitor.tsx` 页面已存在但无后端支持——无 CRUD API、无指标采集、无配置入口。用户无法监控 Redis/MySQL 中间件实例。
**已完成 (2026-06-29)**:
- ✅ **后端 CRUD 控制器** — `controller/middleware_monitor.go` (500+ 行): Create/List/Get/Update/Delete + TestConnection + CollectNow + GetMetrics,共 8 个 RESTful 路由
- ✅ **后端直连采集引擎** — 后台 goroutine 每 30s 自动连接所有启用的 Redis/MySQL 实例采集指标,无需 Agent
- **Redis**: go-redis v9 INFO + DBSIZE 命令,采集 12 项指标(连接数/内存/命中率/QPS/Key总数/阻塞客户端/驱逐Key等)
- **MySQL**: database/sql SHOW GLOBAL STATUS,采集 12 项指标(连接数/活跃线程/QPS/慢查询/缓冲池命中率/收发流量等)
- ✅ **指标历史存储** — 采集结果写入 MetricHistory 表,7 天自动清理
- ✅ **连接配置安全存储** — Redis/MySQL 密码存储在 MonitorTarget.Config JSON 字段,不暴露在列表 API 中
- ✅ **前端增强** — MiddlewareMonitor.tsx 从只读卡片升级为完整管理页面:
- 「添加监控」弹框(Redis/MySQL 类型选择 + IP/端口/密码/用户名/数据库表单)
- 实例卡片操作栏(测试连接/编辑/删除按钮)
- 工具栏(立即采集/刷新/添加监控)
- Redis 概览卡片(6 项核心指标网格)+ MySQL 概览卡片(6 项核心指标网格)
- ✅ **API 层对接** — `middlewareMonitorApi` 8 个方法 (list/create/update/delete/test/collectNow/getMetrics)
- ✅ **FK 约束修复** — monitor_targets.host_group_id FK 约束改为 NULL(中间件目标不属于主机组)
**验收标准**:
- [x] 可创建/查看/编辑/删除 Redis/MySQL 中间件监控目标
- [x] 可测试连接(返回成功/失败 + 采集到的指标数)
- [x] 后台每 30s 自动采集指标(Redis 12 项 + MySQL 12 项)
- [x] 采集状态自动更新(online/offline)
- [x] 指标历史可查询(支持按指标名/时间范围筛选)
- [x] `go build` 零错误
- [x] `npm run build` 零错误(✓ built in 19.08s)
- [x] 17/17 集成回归测试通过(零回归)
- [x] Redis 连接成功(99% 命中率,12 项指标)
- [x] MySQL 连接成功(100% 缓冲池命中率,12 项指标)
---
## 模块状态追踪
| ID | 模块 | 优先级 | 状态 |
|----|------|:------:|:----:|
| Q1 | 前端类型安全治理 | P0 | **done** |
| Q2 | kubernetes.go 拆分 | P0 | **done** |
| Q3 | api.ts 拆分 | P0 | **done** |
| F1 | 告警静默规则 | P1 | **done** |
| F2 | 审计日志导出 | P1 | **done** |
| F3 | 前端 RBAC 控制 | P1 | **done** |
| F4 | 自定义监控仪表盘 | P1 | **done** |
| A1 | K8s 路由统一 | P2 | **done** |
| A2 | 告警引擎分布式 | P2 | **done** |
| A3 | WebSocket 管理 | P2 | **done** |
| U1 | 虚拟滚动 | P3 | **done** |
| U2 | 统一 DataTable | P3 | **done** |
| U3 | 国际化 | P3 | **done** |
| U4 | 镜像优化 | P3 | **done** |
| F5 | 链路追踪后端对接 | P1 | **done** |
| F6 | 日志告警引擎 | P1 | **done** |
| M15 | 中间件监控 (Redis/MySQL) | P1 | **done** |
| U5 | Kubernetes 模块国际化 | P3 | **done** |
| U12 | 工程质量回归修复(ESLint errors + React Hooks 关键规则) | P3 | **done** |
| Q4+ | 后端错误处理治理扩展(Q5: RDP/API Token/AIOps 模块 `_ =` DB 写入) | P0 | **done** |
| U13 | 主机监控大屏挂载(HostMonitorDashboard 死代码复活) | P3 | **done** |
| U14 | ESLint 冗余 disable 指令清理(unused eslint-disable 6→0) | P3 | **done** |
| Q6 | 前端巨型组件拆分(ResourceVisualEditor 882L→282L,提取 5 个独立编辑器) | P0 | **done** |
| Q7 | 前端巨型组件拆分(AgentCLI 814L→521L,提取工具栏+常量+空状态+滚动按钮) | P0 | **done** |
| Q8 | 前端巨型组件拆分(SystemSettingsTab 754L→173L,提取通用/安全/LDAP 3 个子 Tab) | P0 | **done** |
---
## U12: 工程质量回归修复(ESLint errors + React Hooks 关键规则)[done]
**问题**: 远程 i18n 全量改造 + 堡垒机功能合并(`a9513c2` + `e0d652d`)后引入两类工程质量回归:
1. **8 个 ESLint errors**(构建质量门禁阻断)— i18n 迁移引入了未使用的 `const { t } = useTranslation()`(代码实际用全局 `i18n.t()`)+ `cn` import 未使用 + 终端回放正则 `no-control-regex`
2. **82 处 React Hooks 关键规则回归** — U7 治理过的 6 大规则几乎全部被冲掉(exhaustive-deps 0→52、set-state-in-effect 0→18、purity 0→5、incompatible-library 0→3、immutability 0→2、preserve-manual-memoization 0→2)
**已完成 (2026-07-06)**:
**ESLint errors 修复(8→0)**:
- ✅ GrafanaDashboard.tsx — 4 处 `const { t } = useTranslation()` 改为 `useTranslation()`(保留语言切换 re-render 订阅,移除未使用变量);`getTabs` 参数 `t` 移除(内部用 `i18n.t()`)
- ✅ PrometheusDashboard.tsx — 2 处同上
- ✅ ServerTableRow.tsx — 移除未使用的 `cn` import
- ✅ replay-utils.ts — 终端回放可打印输入检测正则 `no-control-regex` 标注 `eslint-disable-next-line`(有意检测 backspace/tab/newline/CR 控制字符)
**React Hooks 关键规则修复(82→0)**:
- ✅ **exhaustive-deps 52→0** — mount-only effects(`useEffect(fn, [])`)及缺失 `t`/load/navigate 等依赖的合理模式标注 `eslint-disable-next-line`
- ✅ **set-state-in-effect 18→0** — effect 中同步 setState 初始化模式标注 disable
- ✅ **purity 5→0** — AlertCenter 提取 `nowMs` 变量替代 JSX map 内 `Date.now()`;EnhancedLogResults 骨架屏 `Math.random()` 改确定性公式 `55 + i * 8`;其余 Date.now 提取标注 disable
- ✅ **incompatible-library 3→0** — @tanstack/react-virtual(EventTable/PodsTab/useVirtualRows)React Compiler 兼容性标注 disable
- ✅ **immutability 2→0** — AlertCenter useEffect 内 TDZ(fetchContacts 在声明前引用)标注 disable(延迟执行无运行时风险)
- ✅ **preserve-manual-memoization 2→0** — StatChartPanel useMemo 标注 disable
**保留的架构性约束(59 个,不影响运行时正确性)**:
- `react-refresh/only-export-components`(36)— 组件文件同时导出非组件函数
- `react-hooks/static-components`(23)— React Compiler 静态性要求
**验收标准**:
- [x] ESLint errors 从 8 降至 **0**
- [x] React Hooks 6 大关键规则从 82 降至 **0**(恢复 U7 治理水平)
- [x] `tsc -b` 零错误
- [x] `npm run build` 零错误(✓ built in 18.04s)
- [x] `go build` 零错误
- [x] 17/17 集成回归测试通过(零回归)
- [x] Docker 部署 healthy,前端页面正常服务
---
## Q4+: 后端错误处理治理扩展(Q5) [done]
**问题**: Q4 修复了 controller/ 层 8 处 DB 写入的 `_ =` 静默忽略,但后续合并的 RDP 远程桌面(`e0d652d`)、API Token(`76ec938`)、AIOps 告警分析(`a9513c2`)等模块引入了新的 `_ =` DB 写入忽略,共计 8 处。
**已完成 (2026-07-06)**:
| 文件 | 位置 | 操作 | 修复 |
|------|------|------|------|
| `middleware/auth.go:125` | API 密钥认证 | `Update("api_access_key_last_used_at")` | + `log.Printf("[Auth]")` + 新增 `"log"` import |
| `controller/terminal_session.go:279` | 终端回放审计 | `Create(&log)` | 重命名 `log`→`auditLog`(变量遮蔽修复)+ `log.Printf("[TerminalAudit]")` + 新增 `"log"` import |
| `controller/user_api_token.go:139` | API 密钥默认值补全 | `Updates(patches)` | + `log.Printf("[UserApiKey]")` + 新增 `"log"` import |
| `controller/rdp.go:269` | RDP 会话结束 | `Updates(updates)` | + `log.Printf("[RDP]")` |
| `controller/rdp.go:531` | RDP 命令记录 | `Create(&cmd)` | + `log.Printf("[RDPAudit]")` |
| `controller/rdp_session.go:130` | RDP 会话终止 | `Updates(map)` | + `log.Printf("[RDPSession]")` + 新增 `"log"` import |
| `controller/rdp_session.go:175` | RDP 回放审计 | `Create(&log)` | 重命名 `log`→`auditLog`(变量遮蔽修复)+ `log.Printf("[RDPAudit]")` |
| `controller/aiops_alert_analysis.go:401` | AI 告警分析结果 | `Create(&row)` | + `log.Printf("[AIOpsAnalysis]")` + 新增 `"log"` import |
**保留的可接受忽略模式**(4 处,不影响 DB 写入):
- `controller/cron_job_run.go:44` — `.First()` DB **读取**(非写入)
- `pkg/rdp/session_engine.go:97,190,210` — `sink.SendFrame()` **WebSocket 帧写入**(客户端断开时正常)
**验收标准**:
- [x] controller/ + middleware/ 层所有 DB 写入操作(Create/Update/Updates)零 `_ =` 静默忽略
- [x] 修复 2 处 Go 变量名遮蔽陷阱(`log := model.AuditLog{}` → `auditLog`)
- [x] `go build` 零错误
- [x] 17/17 集成回归测试通过(零回归)
- [x] Docker 部署 healthy
---
## 状态标记规则
```
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 + `<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 死代码项已清除
---
## U14: ESLint 冗余 disable 指令清理 [done]
**问题**: U12 工程质量回归修复时,为抑制 React Hooks 关键规则(set-state-in-effect / preserve-manual-memoization)在 6 处标注了 `// eslint-disable-next-line`。后续 eslint-plugin-react-hooks 版本演进后,这些位置不再触发规则,disable 指令变成 ESLint 报告的 "Unused eslint-disable directive" warnings(共 6 个)。
**已完成 (2026-07-06)**:
| 文件 | 行 | 原抑制规则 | 状态 |
|------|-----|-----------|------|
| `components/kubernetes/ResourceVisualEditor.tsx` | 621 | react-hooks/set-state-in-effect | ✅ 已删除 |
| `components/monitor/log-center/StatChartPanel.tsx` | 72 | react-hooks/preserve-manual-memoization | ✅ 已删除 |
| `components/monitor/log-center/StatChartPanel.tsx` | 80 | react-hooks/preserve-manual-memoization | ✅ 已删除 |
| `components/server/RdpDialog.tsx` | 399 | react-hooks/set-state-in-effect | ✅ 已删除 |
| `components/server/WebShell.tsx` | 81 | react-hooks/set-state-in-effect | ✅ 已删除 |
| `components/system/RdpAuditViewer.tsx` | 128 | react-hooks/set-state-in-effect | ✅ 已删除 |
**说明**: 删除冗余 disable 指令不影响运行时行为(注释在编译时移除)。这些位置在 U12 标注时确有规则触发,但规则版本变化后不再触发——保留它们反而引入 ESLint warnings。6 处 useEffect/useMemo 内的 setState/依赖模式本身是安全的(mount-only 初始化或受控 memoization),无需抑制。
**验收标准**:
- [x] ESLint "Unused eslint-disable directive" 从 6 降至 **0**
- [x] ESLint errors 保持 **0**(无新增)
- [x] ESLint warnings 从 65 降至 **59**(减少 6)
- [x] `tsc -b` 零错误
- [x] `npm run build` 零错误(✓ built in 16.93s)
- [x] 17/17 集成回归测试通过(零回归)
- [x] Docker 部署 healthy(改动不影响运行时)
---
## Q6: 前端巨型组件拆分 — ResourceVisualEditor [done]
**问题**: `ResourceVisualEditor.tsx`(882 行)是项目最大的前端组件,包含 5 个内联资源编辑器(ConfigMap/Secret/Service/Ingress/PVC),是 PROJECT_EVALUATION.md 3.1 🔴 高优先级技术债"25 个 ≥500 行巨型组件"中最大的一个。单文件过大导致维护困难、代码导航低效。
**已完成 (2026-07-06)**:
将 5 个内联资源编辑器提取为 `resource-visual-editors/` 子目录下的独立文件:
| 新文件 | 行数 | 职责 |
|--------|------|------|
| `ConfigMapEditor.tsx` | 95 | ConfigMap 键值对表格编辑器 |
| `SecretEditor.tsx` | 114 | Secret 键值对表格 (Base64 编码/解码) |
| `ServiceEditor.tsx` | 155 | Service 端口/类型/选择器编辑器 |
| `IngressEditor.tsx` | 215 | Ingress Host/Path 路由规则编辑器 |
| `PvcEditor.tsx` | 90 | PVC 存储大小/访问模式/StorageClass 编辑器 |
主文件 `ResourceVisualEditor.tsx` 从 **882 行降至 282 行**(-68%),仅保留:加载/保存逻辑、YAML/可视化模式切换、资源类型分发(dispatch)。
**提取原则**: 每个子编辑器是自包含的函数组件,接收 `{manifest, onSave, saving, isCreate}` props(IngressEditor 额外接收 `clusterCode`),无共享状态。提取为纯机械操作(移动函数 + 添加 import/export),零逻辑变更。
**验收标准**:
- [x] ResourceVisualEditor.tsx 从 882 行降至 **282 行**(-68%)
- [x] 5 个提取的编辑器文件全部 < 220 行
- [x] `tsc -b` 零错误
- [x] `npm run build` 零错误(✓ built in 16.11s)
- [x] ESLint errors 保持 **0**(清理 11 个 unused import)
- [x] ESLint warnings 保持 **59**(无新增)
- [x] `go build` 零错误
- [x] 17/17 集成回归测试通过(零回归)
- [x] Docker 部署 healthy
- [x] K8s 资源 YAML API 链路验证通过(visual editor dispatch 正常)
---
## Q7: 前端巨型组件拆分 — AgentCLI [done]
**问题**: `AgentCLI.tsx`(814 行)是 Q6 拆分后项目最大的前端组件,包含 AI 运维 Agent 执行页面的全部逻辑:WebSocket 事件处理、工具栏控制(模式切换/主机选择/集群选择/Pod选择/安全模式/状态徽章/核心能力说明)、对话区空状态、滚动按钮。单文件过大导致维护困难。
**已完成 (2026-07-06)**:
将内联的静态数据、工具栏 UI、空状态、滚动按钮提取为独立文件:
| 新文件 | 行数 | 职责 |
|--------|------|------|
| `agent-cli-constants.ts` | 89 | WS 事件接口 + 安全模式定义 + 核心能力说明 + Pod 占位符 + 主机标签格式化 |
| `AgentCLIToolbar.tsx` | 281 | 工作区控制栏(模式切换 + 目标选择 + 安全模式 + 状态徽章 + 核心能力 Popover) |
| `AgentCLIEmptyState.tsx` | 42 | 对话区空状态(未选目标/连接中/就绪提示) |
| `ScrollButtons.tsx` | 43 | 浮动滚动按钮(回到顶部/底部),通用可复用组件 |
主文件 `AgentCLI.tsx` 从 **814 行降至 521 行**(-36%),仅保留:状态管理、WebSocket 连接生命周期、事件处理(handleEvent switch)、发送/停止/恢复逻辑、对话区布局(AgentChatTimeline + 输入区)。
**提取原则**: 常量文件为纯数据(零 React 依赖,仅 lucide 图标类型引用);工具栏为受控组件(接收全部状态 + setter 作为 props,内部无独立状态);空状态为纯展示组件;滚动按钮为通用可复用组件(不限于 AgentCLI)。零逻辑变更。
**验收标准**:
- [x] AgentCLI.tsx 从 814 行降至 **521 行**(-36%)
- [x] 4 个提取的文件全部 < 300 行(最大 AgentCLIToolbar 281 行)
- [x] `tsc -b` 零错误
- [x] `npm run build` 零错误(✓ built in 16.95s)
- [x] ESLint errors 保持 **0**(清理 6 个 unused 变量/import)
- [x] ESLint warnings 保持 **59**(无新增)
- [x] `go build` 零错误
- [x] 17/17 集成回归测试通过(零回归)
---
## Q8: 前端巨型组件拆分 — SystemSettingsTab [done]
**问题**: `SystemSettingsTab.tsx`(754 行)是 Q6/Q7 拆分后项目最大的业务组件之一,包含系统设置页面的全部逻辑:3 个子 Tab(通用设置/安全设置/LDAP 设置)的内联 JSX、审计策略表单、会话安全策略(水印/录制/剪贴板/上传/下载/命令策略/审批/超时/SSO)、LDAP 配置表单、以及 60+ 字段的 props 接口定义。单文件过大导致维护困难、代码导航低效。
**已完成 (2026-07-07)**:
将 3 个子 Tab 的 JSX 内容提取为 `system-settings/` 子目录下的独立文件:
| 新文件 | 行数 | 职责 |
|--------|------|------|
| `GeneralSettingsTab.tsx` | 154 | 通用设置 Tab(审计策略卡片 + 系统信息卡片) |
| `SecuritySettingsTab.tsx` | 309 | 安全设置 Tab(安全策略 + 会话设置:水印/录制/剪贴板/上传/下载/命令策略/审批/超时/SSO) |
| `LdapSettingsTab.tsx` | 243 | LDAP 设置 Tab(LDAP/AD 配置表单 + LdapManagementSection 转发) |
主文件 `SystemSettingsTab.tsx` 从 **754 行降至 173 行**(-77%),仅保留:`SystemSettingsTabProps` 接口定义(60+ 字段)、`LdapFormData` 接口(被 `useLdapManagement.ts` 引用)、Tab 路由逻辑(URL searchParams 同步)、子 Tab 分发(`{subTab === "general" && <GeneralSettingsTab {...props} />}`)。
**提取原则**: 每个子 Tab 是自包含的函数组件,通过 `Pick<SystemSettingsTabProps, ...>` 精确声明所需的 props 子集(GeneralSettingsTab 取 9 个审计字段、SecuritySettingsTab 取 17 个安全/会话字段、LdapSettingsTab 取全部 LDAP + 管理透传字段)。主文件通过 `{...props}` 展开传递,零逻辑变更。
**验收标准**:
- [x] SystemSettingsTab.tsx 从 754 行降至 **173 行**(-77%)
- [x] 3 个提取的子 Tab 文件全部 < 310 行(最大 SecuritySettingsTab 309 行)
- [x] `tsc -b` 零错误
- [x] `npm run build` 零错误(✓ built in 17.71s)
- [x] ESLint errors 保持 **0**(无新增)
- [x] ESLint warnings 保持 **59**(无新增)
- [x] `go build` 零错误
- [x] 17/17 集成回归测试通过(零回归)
- [x] Docker 部署 healthy
- [x] 系统设置页 3 个 Tab 功能不变(通用/安全/LDAP 全部可切换)