# admin-web 孤儿页面处置建议
> 生成日期:2026-05-04 / 范围:6 个 `.tsx`(5 个被列为孤儿 + 1 个已确认在用)
> 用户列出的清单经源码核对后修正:`AITriggers.tsx`、`ETLStatus.tsx`、`TaskConfig.tsx`、`TaskManager.tsx` 4 个并非孤儿,而是被新页面以子组件方式 import;只有 `OpsPanel.tsx` 是真正孤儿。
> 来源:`apps/admin-web/src/App.tsx`、`apps/admin-web/src/pages/ETLTasks.tsx`、`apps/admin-web/src/pages/TriggerManager.tsx`、`apps/admin-web/src/pages/Dashboard.tsx`,以及对 `import` 语句的全量 grep。
---
## 一、清单(实际状态)
| 页面 | 路由 | 状态 | App.tsx 是否 import | 实际是否被引用 | 建议 |
|---|---|---|---|---|---|
| `AITriggers.tsx` | 无 | 已挂载(子组件) | 否 | 是(`TriggerManager.tsx` L40 import;嵌入 `AITriggersTab`) | **保留** |
| `ETLStatus.tsx` | 无 | 已挂载(子组件) | 否 | 是(`ETLTasks.tsx` L25 import;作为 `status` Tab) | **保留** |
| `OpsPanel.tsx` | 无 | 真孤儿 | 否 | 否(grep 无任何 import;功能由 `Dashboard.tsx` 直接组合 ops/* Section 实现) | **归档到 `_archived/`,待 Neo 确认后删除** |
| `TaskConfig.tsx` | 无 | 已挂载(子组件) | 否 | 是(`ETLTasks.tsx` L22 import;作为 `config` Tab) | **保留** |
| `TaskManager.tsx` | 无 | 已挂载(子组件,仅命名导出) | 否 | 是(`ETLTasks.tsx` L23 `import { QueueTab, HistoryTab }`) | **保留**;可考虑后续重构为 `tabs/QueueTab.tsx` + `tabs/HistoryTab.tsx` |
| —(参考样例) | — | — | — | — | — |
> 注:`TenantAdmins/index.tsx` 以目录导出,不在本盘点范围。`_archived/LogViewer.tsx` 已规范归档。
---
## 二、逐个分析
### 2.1 `AITriggers.tsx`
- **代码内容**(顶部注释 + 关键能力):
- 「AI 触发器设置页面。管理 `biz.trigger_jobs` 表中 `job_type='ai_*'` 的所有触发器」
- 列表 + 启停 Switch + 编辑 cron 表达式 / 描述(仅 cron 类型可编辑 cron)。
- 调用 `listTriggers()`、`updateTrigger()`(即 `GET/PATCH /api/admin/ai/triggers/:id`)。
- **业务功能**:AI 触发器 CRUD(不含创建/删除)。
- **是否被替代**:未被替代,**而是被嵌入复用**。`TriggerManager.tsx` L40 显式 `import AITriggers from './AITriggers'`,并在 `AITriggersTab` 子组件里以 `` + `` + `` 的纵向组合展示。
- **建议**:**保留**。
- **删除影响**:会破坏 `/triggers?tab=ai` 入口的 AI 触发器编辑能力,且 `AITriggers` 调的是 `/api/admin/ai/triggers`(不同于 `BizTriggersTab` 用的 `/trigger-jobs`),两个 API 在后端实际由不同 router 提供,不能简单替代。
---
### 2.2 `ETLStatus.tsx`
- **代码内容**:游标状态 Table(`task_code` / `last_start` / `last_end`)+ 最近执行记录 Table(`task_codes` / 状态 / `started_at` / `duration_ms`)+ 顶部 success/failed/running 计数 Statistic。
- **业务功能**:ETL 调度任务的健康监控(游标推进 + 最近执行)。
- **是否被替代**:未替代,**被嵌入为 `/etl-tasks?tab=status` Tab**。`ETLTasks.tsx` L25 `import ETLStatus from './ETLStatus'`,L99 `children: `。
- **建议**:**保留**。
- **删除影响**:会让 `/etl-tasks?tab=status` 渲染失败(编译报错)。
---
### 2.3 `OpsPanel.tsx`(**真孤儿**)
- **代码内容**:组合 `SystemResourceSection` + `ServiceStatusSection` + `GitStatusSection` 三个 ops 子组件,调 `fetchSystemInfo / fetchServicesStatus / fetchGitInfo / startService / stopService / restartService / gitPull / syncDeps` 8 个 API。
- **业务功能**:服务器资源 + 服务启停 + Git 状态(与 `/dashboard` 上半部分完全重叠)。
- **是否被替代**:**是**。`Dashboard.tsx` 在 CHANGE 2026-07-25 / Task 8.1 之后直接内联 ops/* 三个 Section 组件 + 同样的 8 个 API 调用(含 `Modal.info` 显示 git pull 输出),等价复刻了 OpsPanel 的全部行为;并在其上叠加 DB 健康 + AI 总览 + AI 调度摘要。
- **建议**:**移到 `apps/admin-web/src/pages/_archived/OpsPanel.tsx`,待 Neo 确认后删除**。不直接删除是因为:
1. CHANGE 注释(2026-07-25 Task 8.1)有保留它作为「单页可见的运维子页」备份的潜在价值。
2. 测试文件 `apps/admin-web/src/__tests__/dashboard.test.tsx` 涉及 OpsPanel 相关命名,需先确认是否引用 `OpsPanel` 类型/常量后再清理。
- **删除影响**:grep 全量无任何 `from.*OpsPanel` 或 `import.*OpsPanel`(仅页面自身的注释和 `components/ops/*` 子组件出现)。`__tests__/dashboard.test.tsx` 中的 OpsPanel 字符串需复核(可能是断言文案,不影响)。
- **建议命令**(**示例,待 Neo 批准后再执行;本子代理不实际操作**):
```bash
git mv apps/admin-web/src/pages/OpsPanel.tsx apps/admin-web/src/pages/_archived/OpsPanel.tsx
```
---
### 2.4 `TaskConfig.tsx`
- **代码内容**(顶部注释):「ETL 任务配置页面。提供 Flow 选择、处理模式、时间窗口、高级选项等配置区域,以及连接器/Store 选择、任务选择、DWD 表选择、CLI 命令预览和任务提交功能」。包含丰富的 fallback Flow 字典 + `validateTaskConfig` + `submitToQueue` / `executeDirectly` / `createSchedule`。
- **业务功能**:ETL 任务发起(最复杂的页面之一)。
- **是否被替代**:未替代,**被嵌入为 `/etl-tasks?tab=config` Tab**(默认 Tab)。`ETLTasks.tsx` L22 `import TaskConfig from './TaskConfig'`,L59 `children: `。
- **建议**:**保留**。
- **删除影响**:`/etl-tasks?tab=config`(默认 Tab)渲染失败;这是用户进入 `/etl-tasks` 的首屏。
---
### 2.5 `TaskManager.tsx`
- **代码内容**:3 Tab 容器(队列 / 调度 / 历史),但 `ETLTasks.tsx` 只复用其中 2 个 **命名导出**:`export const QueueTab` / `export const HistoryTab`。WebSocket 实时日志在 `QueueTab`。
- **业务功能**:ETL 任务队列与历史。
- **是否被替代**:未替代,**子组件被新页面以命名 import 复用**。`ETLTasks.tsx` L23 `import { QueueTab, HistoryTab } from './TaskManager'`。但 `TaskManager` 默认导出(如果有)和「调度」Tab 内部逻辑(`ScheduleTab` 现已提到 `components/ScheduleTab.tsx` 顶层)已不再使用。
- **建议**:**保留**当前文件,但建议后续轻量重构(**非本次任务范围**):
1. 把 `QueueTab` / `HistoryTab` 拆到独立文件 `pages/etl-tasks/QueueTab.tsx` / `HistoryTab.tsx`;
2. 删除 `TaskManager.tsx` 的 default export(如有)和容器 Tabs 逻辑,因为已被 `ETLTasks.tsx` 取代。
- **删除影响**:直接删除会让 `ETLTasks.tsx` 的 queue / history Tab 渲染失败。
---
## 三、批量执行建议
仅对 **真孤儿 `OpsPanel.tsx`** 给出动作清单。其余 4 个文件**禁止删除或归档**(会破坏在用功能)。
### 3.1 推荐方案 A(保守,**默认推荐**)
```bash
# 仅归档 OpsPanel,保留可恢复路径
git mv apps/admin-web/src/pages/OpsPanel.tsx apps/admin-web/src/pages/_archived/OpsPanel.tsx
```
- 优点:可恢复;遵循 `_archived/` 归档惯例(同 `LogViewer.tsx` 在 `_archived/` 的处理);触发 `pre_read_archived_block.py` hook 阻断后续意外读取。
- 风险:`__tests__/dashboard.test.tsx` 内若有跨文件 import(grep 显示无 import 但有字符串匹配),需测试运行验证。
### 3.2 方案 B(激进,仅在 Neo 明确批准时使用)
```bash
git rm apps/admin-web/src/pages/OpsPanel.tsx
```
- 风险:丢失备份;如果 Dashboard 内联化未来回滚,需从 git 历史恢复。
### 3.3 不在本次任务执行的「后续重构」建议
- `TaskManager.tsx` 拆分为 `pages/etl-tasks/QueueTab.tsx` / `HistoryTab.tsx`,删除容器代码(仅在确认 `default export` 未被外部使用后)。
- `AITriggers.tsx` / `ETLStatus.tsx` / `TaskConfig.tsx` 的命名规范化建议:移动到 `pages/etl-tasks/` 与 `pages/triggers/` 子目录,使「孤儿假象」从源头消除。
---
## 四、对路由 / 测试 / 后续 Wave 的影响
1. **路由**:仅归档 `OpsPanel.tsx` 不改变任何已注册路由(App.tsx 未 import);19 个路由全部保留可达。
2. **构建**:归档后 `pnpm build` 应仍然通过(因无 import 引用);执行前建议在本机跑一次 `pnpm tsc --noEmit` 与 `pnpm build` 验证。
3. **测试**:
- `apps/admin-web/src/__tests__/dashboard.test.tsx` 对 OpsPanel 字符串的引用需 grep 复核:若仅是断言文案 `「OpsPanel」`,可不动;若 `import` 了 `OpsPanel`,需先调整测试。
4. **Wave 2/3 测试场景**:
- Wave 2「ETL 全流程走查」覆盖 `/etl-tasks` 5 Tab,**禁止删除 TaskConfig / TaskManager / ETLStatus**。
- Wave 2「触发器统一管理」覆盖 `/triggers` 4 Tab,**禁止删除 AITriggers**。
- Wave 3「运维首页」仅依赖 `Dashboard.tsx` 与 `components/ops/*`,与 OpsPanel 归档/删除无关。
---
## 五、修正用户原任务描述
用户原任务描述「6 个孤儿/已挂载页面(5 孤儿 + 1 已挂载)」与源码不符。修正:
- **真正孤儿**:1 个(`OpsPanel.tsx`)。
- **已挂载(路由)**:0 个(这 5 个文件均未直接挂载路由)。
- **已挂载(子组件复用)**:4 个(`AITriggers.tsx`、`ETLStatus.tsx`、`TaskConfig.tsx`、`TaskManager.tsx`)。
最终建议汇总:**1 归档(OpsPanel)+ 4 保留(其余)+ 0 直接删除**;待 Neo 确认是否升级到「方案 B 删除」或同时启动 TaskManager 重构。
---
> 文档篇幅约 200 行。本子代理仅产出建议,**未对任何源码执行修改**。