# admin-web 19 路由业务指纹矩阵

> 生成日期：2026-05-04 ／ 视角：系统运维（开发 + 运维操作 ETL 库 + AI 监控） ／ 用户：Neo + 运维成员
> 来源：`apps/admin-web/src/App.tsx`、`apps/admin-web/src/pages/*.tsx`、`apps/admin-web/src/api/*.ts`
> 后端 baseURL：`/api`（见 `apps/admin-web/src/api/client.ts`），路由挂载见 `apps/backend/app/main.py` L203-L246

---

## 一、菜单结构（7 一级 + 子菜单）

```
Sider（侧边栏）
├─ /dashboard            运行状态（首页）
├─ /etl-tasks            ETL 任务管理（5 子 Tab：config/queue/schedule/history/status）
├─ task-engine-group     小程序任务管理 ▼
│   ├─ /task-engine/trigger-jobs    定时任务
│   ├─ /task-engine/transfer-log    转移日志
│   ├─ /task-engine/pending-review  待审核任务
│   └─ /task-engine/config          参数管理
├─ /triggers             触发器管理（4 子 Tab：all/biz/ai/etl）
├─ ai-group              AI 管理 ▼
│   ├─ /ai/dashboard            总览
│   ├─ /ai/operations           手动操作
│   ├─ /ai/prewarm              预热进度
│   ├─ /triggers?tab=ai         触发器设置（跳到 TriggerManager AI Tab）
│   └─ /ai/trigger-jobs         调度历史
├─ /tenant-admins        租户管理员
├─ settings-group        系统设置 ▼
│   ├─ /settings/env-config         环境配置
│   ├─ /settings/runtime-context    业务运行上下文 / 沙箱
│   └─ /triggers?tab=biz            触发器配置（跳到 TriggerManager 业务 Tab）
└─ logs-group            日志调试 ▼
    ├─ /logs/dev-trace          DevTrace（全链路日志）
    ├─ /logs/ai-run-logs        AI 调用明细
    └─ /logs/db-viewer          数据库查看器
```

设计意图：

- 一级菜单按业务域聚合（运行状态 / ETL / 小程序任务引擎 / 触发器 / AI / 租户 / 设置 / 日志）。
- `?tab=` 参数使 AI 与系统设置共用 `/triggers` 一个页面，不同入口落到不同 Tab。
- 历史上是 11 个一级项（CHANGE 2026-07-14 Task 7.1 重组为 7 个），合并的页面（`TaskConfig`、`TaskManager`、`ETLStatus`、`AITriggers`）以子组件形式被新页面 import，未直接挂载路由。

---

## 二、菜单 → 路由 → 页面 → 后端 API 映射

| 一级菜单 | 子菜单 | 路由 | 页面文件 | 主要后端 API（前缀 `/api`） | 设计目的 |
|---|---|---|---|---|---|
| —（登录） | — | `/login` | `Login.tsx` | `POST /auth/login`（authStore） | JWT 登录，成功跳 `/dashboard` |
| 运行状态 | — | `/dashboard` | `Dashboard.tsx` | `GET /ops/system`、`GET /ops/services`、`GET /ops/git`、`GET /admin/db-health`、`GET /admin/ai/trigger-jobs` | 登录后默认首页：服务器资源 + 服务/Git 状态 + DB 健康 + AI 总览 + AI 调度摘要 |
| ETL 任务管理 | — | `/etl-tasks` | `ETLTasks.tsx`（包 5 Tab） | （见各 Tab） | 合并 ETL 五大场景为 Tab：发起 / 队列 / 调度 / 历史 / 状态 |
| ↳ config | — | `/etl-tasks?tab=config` | `TaskConfig.tsx`（被 ETLTasks 引用） | `GET /tasks`、`POST /tasks/validate`、`POST /execution/queue`、`POST /execution/run`、`POST /schedules`、`GET /tasks/flows` | Flow 选择 + 处理模式 + 时间窗口 + 提交 / 直跑 / 创建调度 |
| ↳ queue | — | `/etl-tasks?tab=queue` | `TaskManager.tsx::QueueTab` | `GET /execution/queue`、`DELETE /execution/queue/:id`、`POST /execution/:id/cancel`、WS `/ws/logs/:id` | 当前队列 + WebSocket 实时日志 |
| ↳ schedule | — | `/etl-tasks?tab=schedule` | `components/ScheduleTab.tsx` | `GET/POST/PUT/DELETE /schedules`、`PATCH /schedules/:id/toggle`、`POST /schedules/:id/run` | 调度任务 CRUD + 启停 + 立即执行 |
| ↳ history | — | `/etl-tasks?tab=history` | `TaskManager.tsx::HistoryTab` | `GET /execution/history`、`POST /execution/:id/rerun`、`POST /execution/cleanup-output` | 执行历史 + 重跑 + 清理输出 |
| ↳ status | — | `/etl-tasks?tab=status` | `ETLStatus.tsx`（被 ETLTasks 引用） | `GET /etl-status/cursors`、`GET /etl-status/recent-runs` | 任务游标 + 最近执行（success/failed/running 统计） |
| 小程序任务管理 | 定时任务 | `/task-engine/trigger-jobs` | `TriggerJobs.tsx` | `GET /trigger-jobs`、`POST /trigger-jobs/:id/run`、`DELETE /admin/task-engine/clear-all-tasks` | `biz.trigger_jobs` 列表 + 手动执行 + 清空助教任务（高危） |
| ↳ | 转移日志 | `/task-engine/transfer-log` | `TransferLog.tsx` | `GET /admin/task-engine/transfer-log` | P18 客户转移日志（门店/时间/助教筛选 + guard_checks 标签） |
| ↳ | 待审核任务 | `/task-engine/pending-review` | `PendingReview.tsx` | `GET /admin/task-engine/pending-review`、`POST .../:id/reassign`、`POST .../:id/close`、`GET .../transfer-log/:memberId/history` | 待审核任务列表 + 重新分配 + 关闭 + 客户历史抽屉 |
| ↳ | 参数管理 | `/task-engine/config` | `TaskEngineConfig.tsx` | `GET /admin/task-engine/config`、`PUT /admin/task-engine/config/:id`、`POST /admin/task-engine/config`、`DELETE /admin/task-engine/config/:id` | `biz.cfg_task_generator_params` 全局/门店覆盖参数 + 权重卡片编辑 |
| 触发器管理 | — | `/triggers` | `TriggerManager.tsx`（包 4 Tab） | （见各 Tab） | 聚合 biz / ai / etl 三类触发器为统一管理入口 |
| ↳ all | — | `/triggers?tab=all` | `TriggerManager.tsx::AllTriggersTab` | `GET /admin/triggers/unified` | 跨源只读统一视图 |
| ↳ biz | — | `/triggers?tab=biz` | `TriggerManager.tsx::BizTriggersTab` | `GET /trigger-jobs`、`PATCH /trigger-jobs/:id/config` | 业务触发器列表 + 编辑 cron / 间隔秒数 |
| ↳ ai | — | `/triggers?tab=ai` | `TriggerManager.tsx::AITriggersTab`（包 `AITriggers` + `AIOperations` + `AITriggerJobs`） | `GET /admin/ai/triggers`、`PATCH /admin/ai/triggers/:id`、`POST /admin/ai/trigger-event`、`POST /admin/ai/trigger-jobs/:id/retry`、`POST /admin/ai/cache/invalidate`、`POST /admin/ai/run/:appType`、`POST /admin/ai/batch-run`、`POST /admin/ai/batch-run/confirm`、`GET/POST /admin/ai/alerts/:id/(ack\|ignore)` | AI 触发器启停 + 编辑 cron + AI 手动操作 + 调度历史 |
| ↳ etl | — | `/triggers?tab=etl` | `TriggerManager.tsx::ETLTriggersTab` | `GET /schedules` | `meta.scheduled_tasks` 调度任务只读列表 |
| AI 管理 | 总览 | `/ai/dashboard` | `AIDashboard.tsx` | `GET /admin/ai/dashboard` | 4 卡 + 7 天趋势 + App 占比 + 预算进度 + App 健康 + 最近告警 |
| ↳ | 手动操作 | `/ai/operations` | `AIOperations.tsx` | `POST /admin/ai/trigger-jobs/:id/retry`、`POST /admin/ai/cache/invalidate`、`POST /admin/ai/batch-run(/confirm)`、`POST /admin/ai/run/:appType`、`POST /admin/ai/trigger-event`、`GET /admin/ai/alerts`、`POST /admin/ai/alerts/:id/(ack\|ignore)` | 重跑 / 缓存失效 / 按需重跑 / 批量执行 / 告警管理 / 越过去重 |
| ↳ | 预热进度 | `/ai/prewarm` | `AIPrewarm.tsx` | `GET /admin/ai/prewarm/progress`、`POST /admin/ai/run/:appType`（app2_finance / app2a_finance_area）、`POST /admin/ai/trigger-event` | app2_finance 72 组合（8 时间 × 9 区域）覆盖率 + 一键补缺 + 单组合重跑 |
| ↳ | 触发器设置 | `/triggers?tab=ai` | （跳转 TriggerManager） | （同 ai Tab） | 入口跳转，不渲染独立页面 |
| ↳ | 调度历史 | `/ai/trigger-jobs` | `AITriggerJobs.tsx` | `GET /admin/ai/trigger-jobs`、`GET /admin/ai/trigger-jobs/:id`、`POST /admin/ai/trigger-jobs/:id/retry` | 事件链调度记录 + 详情 + 重跑（含今日去重统计） |
| 租户管理员 | — | `/tenant-admins` | `TenantAdmins/index.tsx` | `GET/POST/PATCH/DELETE /admin/tenant-admins`、`POST /admin/tenant-admins/:id/reset-password`、`GET /admin/registry/tenants`、`GET .../sites`、`PATCH .../sites/:id/code`、`GET .../sites/:id/code-history`、`POST/DELETE .../sites` | 租户管理员 CRUD + 简写 ID 管理 + 门店建删 |
| 系统设置 | 环境配置 | `/settings/env-config` | `EnvConfig.tsx` | `GET /env-config`、`PUT /env-config`、`GET /env-config/export` | `.env` 键值对编辑 + 导出（敏感值脱敏） |
| ↳ | 业务运行上下文 / 沙箱 | `/settings/runtime-context` | `RuntimeContext.tsx` | `GET /admin/runtime-context/sites`、`PATCH /admin/runtime-context` | 多门店 live/sandbox 切换 + 历史日期固定 + 触发器自动暂停 |
| ↳ | 触发器配置 | `/triggers?tab=biz` | （跳转 TriggerManager） | （同 biz Tab） | 入口跳转 |
| 日志调试 | DevTrace | `/logs/dev-trace` | `DevTrace.tsx` | `GET /admin/dev-trace/(dates\|requests\|coverage\|settings)`、`GET /admin/dev-trace/request/:id`、`POST /admin/dev-trace/cleanup`、`POST /admin/dev-trace/coverage/scan`、`PUT /admin/dev-trace/settings` | 全链路 trace 请求列表 + span 树 + 覆盖率扫描 + 清理 |
| ↳ | AI 调用明细 | `/logs/ai-run-logs` | `AIRunLogs.tsx` | `GET /admin/ai/run-logs`、`GET /admin/ai/run-logs/:id` | AI 单次调用 prompt / response / error 详情 |
| ↳ | 数据库查看器 | `/logs/db-viewer` | `DBViewer.tsx` | `GET /db/schemas`、`GET /db/schemas/:s/tables`、`GET /db/tables/:s/:t/columns`、`POST /db/query` | Schema/Table 树 + 只读 SQL 执行 |

---

## 三、19 页指纹卡

> 实际可路由页面共 19 个：`Login` + 18 个登录后页面（其中 `/triggers?tab=biz`、`/triggers?tab=ai` 是 `/triggers` 的查询参数入口，菜单暴露但共用 1 个 `TriggerManager.tsx`）。

### 3.1 `/login`

- **设计目的**：JWT 用户名+密码登录，仅渐变色卡片。
- **关键操作**：填写用户名 / 密码 → 「登录」按钮。
- **后端 API**：`POST /api/auth/login`（通过 `useAuthStore.login`）；JWT aud=`admin`。
- **数据来源**：`auth.admin_users`（admin/super_admin/site_admin 共表，aud 区分）。
- **必现字段**：渐变色背景、`NeoZQYY` 标题、用户名输入、密码输入、登录按钮。
- **典型用例**：进入后台首屏。
- **测试校核重点**：错误返回应展示 `detail` 文案；成功后 `navigate("/dashboard")`。

---

### 3.2 `/dashboard`（运行状态，首页）

- **设计目的**：登录后默认首页，聚合服务器、服务、Git、DB、AI 状态在一屏。
- **关键操作**：刷新（轮询 15s）、跳转「ETL 状态详情」、「触发器详情」、「AI 调度详情」、启停服务、`git pull`、同步依赖。
- **后端 API**：`GET /api/ops/system`、`/services`、`/git`；`POST /api/ops/services/:env/(start|stop|restart)`、`POST /api/ops/git/:env/(pull|sync-deps)`；`GET /api/admin/db-health`；`GET /api/admin/ai/trigger-jobs`；内嵌 `AIDashboard` 调 `GET /api/admin/ai/dashboard`。
- **数据来源**：服务器实时（`psutil`）+ Git CLI + 业务库 `biz.ai_run_logs` / `biz.trigger_jobs` + 测试库连接探活。
- **必现字段**：CPU/内存/磁盘三组进度条、4 个环境（prod/test/etl/dev）状态、Git branch + last_commit、DB 健康行、AI 调用量/成功率/Token/延迟、AI 调度摘要（今日触发数/成功率/最近错误）。
- **典型用例**：每天进入后台第一眼看的总览；判断「服务是否在线」「ETL 是否卡住」「AI 是否预算耗尽」。
- **最近变更**：CHANGE 2026-07-25（Task 8.1）OpsPanel 拆出 3 个 Section 组件被本页复用；Task 8.x 增加 AI 调度摘要。
- **测试校核重点**：`AIDashboard` 在本页是嵌入子组件，不应有独立顶部 Title；DB 健康超时 10s 回落 timeout 状态；AI 调度摘要的「今日」基于 `created_at.startsWith(YYYY-MM-DD)`，跨时区注意。

---

### 3.3 `/etl-tasks`（ETL 任务管理，5 Tab）

- **设计目的**：把 ETL 全生命周期（发起 → 队列 → 调度 → 历史 → 状态）合并为单页 5 Tab，URL 参数 `?tab=` 同步。
- **关键操作**：切换 Tab、Tab 内复用各原页面操作。
- **后端 API**：见 §二映射表（`/tasks/*`、`/execution/*`、`/schedules*`、`/etl-status/*`，WS `/ws/logs/:id`）。
- **数据来源**：ETL 库（`meta.scheduled_tasks`、`meta.execution_log`）+ 任务调度后端内存队列。
- **必现字段**：5 Tab 标题图标（发起 / 队列 / 调度 / 历史 / 状态），`destroyInactiveTabPane={false}` 切回不刷新。
- **典型用例**：运维新发起一次 ETL（config）→ 看队列 → 历史回看 → 状态确认游标推进。
- **最近变更**：CHANGE 2026-07-14 Task 9.1 合并 4 页为 Tab；CHANGE 2026-03-25 拆出原 TaskManager 内部子 Tab。
- **测试校核重点**：`?tab=xxx` 非法值回落 `config`；切 Tab 不丢失子 Tab 状态。

---

### 3.4 `/task-engine/trigger-jobs`（小程序定时任务）

- **设计目的**：管理 `biz.trigger_jobs` 中所有定时任务（cron / interval / event），支持手动执行。
- **关键操作**：刷新、手动执行（Popconfirm）、清空所有助教任务（高危 danger 按钮）。
- **后端 API**：`GET /api/trigger-jobs`、`POST /api/trigger-jobs/:id/run`、`DELETE /api/admin/task-engine/clear-all-tasks`。
- **数据来源**：`biz.trigger_jobs` + `biz.coach_tasks`（清空目标）。
- **必现字段**：任务名称（描述+job_name）、触发方式 Tag、触发配置 code、状态、上次/下次执行、最近错误、操作列。
- **典型用例**：测试重置任务表 + 强制运行某 cron。
- **测试校核重点**：清空所有任务的 `Popconfirm` 含 description，danger 按钮置 loading；status≠enabled 的执行按钮 disabled。

---

### 3.5 `/task-engine/transfer-log`（客户转移日志）

- **设计目的**：P18 助教任务引擎产生的 `biz.coach_task_transfer_log` 分页只读视图。
- **关键操作**：刷新、按门店/日期范围/助教 ID 筛选、翻页。
- **后端 API**：`GET /api/admin/task-engine/transfer-log`（分页 + 筛选）。
- **数据来源**：`biz.coach_task_transfer_log`（含 `guard_checks` JSON 三项检查）。
- **必现字段**：转移时间、门店、客户、原助教、新助教、转移原因（中文映射）、转移得分、保护检查 Tag（success/error 图标）。
- **典型用例**：审计某客户为何被转走、检查 guard 是否触发。

---

### 3.6 `/task-engine/pending-review`（待审核任务）

- **设计目的**：展示 `status='pending_review'` 的助教任务，超管可重分配 / 关闭。
- **关键操作**：刷新、按门店筛选、重新分配（输入新助教 ID）、关闭（输入原因）、查看转移历史抽屉。
- **后端 API**：`GET /api/admin/task-engine/pending-review`、`POST .../:id/reassign`、`POST .../:id/close`、`GET .../transfer-log/:memberId/history`。
- **数据来源**：`biz.coach_tasks`（status=pending_review） + `coach_task_transfer_log`。
- **必现字段**：任务类型 Tag、转移次数、优先级得分、操作列（仅 super_admin 可见）。
- **测试校核重点**：`super_admin` 角色才显示重新分配/关闭按钮。

---

### 3.7 `/task-engine/config`（任务引擎参数管理）

- **设计目的**：`biz.cfg_task_generator_params` 全局默认 + 门店覆盖参数；权重 `w_rs/w_ms/w_ml` 卡片整体编辑（联合校验）。
- **关键操作**：行内编辑、新增（弹窗）、删除、权重卡片提交。
- **后端 API**：`GET /api/admin/task-engine/config`、`PUT .../:id`、`POST .../`、`DELETE .../:id`。
- **数据来源**：`biz.cfg_task_generator_params`。
- **必现字段**：参数中文标签（13 个映射）、当前值、归属（全局 / 门店#xxx）、更新时间。
- **测试校核重点**：3 个权重必须同步提交；非超管只读。

---

### 3.8 `/triggers`（触发器统一管理，4 Tab）

- **设计目的**：聚合 biz / ai / etl 三类触发器为单页 4 Tab，统一只读视图 + 编辑能力。
- **关键操作**：切 Tab、`all` 只读统一表、`biz` 编辑 cron/interval、`ai` 复用 AITriggers + AIOperations + AITriggerJobs、`etl` 只读 scheduled_tasks。
- **后端 API**：`GET /api/admin/triggers/unified`、`GET /api/trigger-jobs`、`PATCH /api/trigger-jobs/:id/config`、`GET /api/schedules`、（AI Tab 详见 3.12）。
- **数据来源**：`biz.trigger_jobs` + `meta.scheduled_tasks` + `biz.ai_run_logs`（健康）。
- **必现字段**：4 Tab 图标（全部 / 业务 / AI / ETL），「最近错误」单独一列。
- **最近变更**：CHANGE 2026-07-15 Task 10.1 创建。
- **测试校核重点**：`?tab=biz` / `?tab=ai` 直达正确 Tab；biz Tab 编辑校验 `cron_expression` 或 `interval_seconds` 至少一个；ai Tab 内三个组件按 `Space direction="vertical" size="large"` 纵向排列。
- **功能交集**：`AITriggers.tsx`（孤儿）功能已被 `BizTriggersTab` 编辑能力 + `AITriggersTab` 嵌入完整覆盖。

---

### 3.9 `/ai/dashboard`（AI 总览）

- **设计目的**：AI 8 个 App 的整体健康监控。
- **关键操作**：选门店、切日期范围（今日 / 近 3/7/10 天 / 自定义 RangePicker）、刷新。
- **后端 API**：`GET /api/admin/ai/dashboard`（参数 `site_id`、`range_days` 或 `date_from/date_to`）。
- **数据来源**：`biz.ai_run_logs` + `biz.ai_alerts` + `biz.ai_token_budget`。
- **必现字段**：4 统计卡（调用 / 成功率 / Token / 平均延迟）、7 天趋势、App 占比、预算进度（日/月）、App 健康、最近告警表。
- **测试校核重点**：`/dashboard` 嵌入本页时不应渲染重复顶部；range_days=0 时启用 RangePicker。

---

### 3.10 `/ai/operations`（AI 手动操作）

- **设计目的**：5 卡操作面板：重跑 / 缓存失效 / 按需重跑 / 批量执行 / 告警管理 / 越过去重事件。
- **关键操作**：输入 trigger_job_id 重跑；按 app_type+member 失效缓存；按 app+member+site 重跑某 App；批量执行（预估→确认两步）；ack/ignore 告警；触发事件链。
- **后端 API**：`POST /api/admin/ai/trigger-jobs/:id/retry`、`POST .../cache/invalidate`、`POST .../run/:appType`、`POST .../batch-run`、`POST .../batch-run/confirm`、`POST .../trigger-event`、`GET .../alerts`、`POST .../alerts/:id/(ack|ignore)`。
- **数据来源**：`biz.ai_run_logs` + `biz.trigger_jobs` + `biz.ai_chat_cache` + `biz.ai_alerts`。
- **必现字段**：site_id 默认 `2790685415443269`（朗朗台球）、6 个 App 类型选项（不含 app2 系列，预热单独走 `/ai/prewarm`）。
- **测试校核重点**：批量执行需先 estimate 拿 `batch_id` 再 confirm；缓存失效返回 `affected_count`。

---

### 3.11 `/ai/prewarm`（AI 预热进度）

- **设计目的**：监控 app2_finance / app2a_finance_area 的 8 时间 × 9 区域 = 72 组合覆盖率（注意：area=all 走 app2_finance 8 组合，其余 8 区域走 app2a_finance_area 64 组合）。
- **关键操作**：选门店、刷新、一键批量补缺（串行 POST）、触发全量预热（dws_completed 事件）、单组合重跑。
- **后端 API**：`GET /api/admin/ai/prewarm/progress`、`POST /api/admin/ai/run/(app2_finance|app2a_finance_area)`、`POST /api/admin/ai/trigger-event`。
- **数据来源**：`biz.ai_chat_cache`（统计已生成的 target_id × time_dimension × area 组合）。
- **必现字段**：环形进度条、缺失 missing 表（按区域分组）、单组合「重跑」按钮、批量补缺 Modal 进度。
- **最近变更**：CHANGE 2026-04-23 新增 app2a_finance_area 区域版（64 组合）。
- **测试校核重点**：`areaToAppType('all')` → `app2_finance`；其他 → `app2a_finance_area`。

---

### 3.12 `/ai/trigger-jobs`（AI 调度历史）

- **设计目的**：AI 事件链（consumption / dws_completed / note_created / task_assigned）的调度记录。
- **关键操作**：筛选 event_type / status / site_id / 日期范围、查看详情 Modal、Popconfirm 重跑、刷新。
- **后端 API**：`GET /api/admin/ai/trigger-jobs`、`GET .../:id`、`POST .../:id/retry`。
- **数据来源**：`biz.trigger_jobs`（job_type=ai_*）+ 关联 `biz.ai_run_logs`。
- **必现字段**：今日去重跳过数（`today_skipped_duplicates`）顶部统计、状态 Tag、事件类型、执行链 `app_chain`、耗时（finished_at - started_at）。

---

### 3.13 `/tenant-admins`（租户管理员）

- **设计目的**：管理员 CRUD（auth.tenant_admins，aud=tenant-admin），含 2 步创建（基本信息 → 简写 ID）。
- **关键操作**：搜索、切换显示已禁用、新增（2 步骤 Steps）、编辑、重置密码、软删除、简写 ID 管理弹窗。
- **后端 API**：`GET/POST/PATCH/DELETE /api/admin/tenant-admins`、`POST .../:id/reset-password`；`GET /api/admin/registry/tenants`、`GET .../sites`、`PATCH .../sites/:id/code`、`GET .../sites/:id/code-history`、`POST/DELETE .../sites`。
- **数据来源**：`auth.tenant_admins` + `core.tenants` + `core.sites`（FDW）。
- **必现字段**：用户名、显示名、租户名、管理类型 Tag、`managedSiteIds`、状态、最后登录、5 个操作按钮（编辑/重置密码/简写ID/启停/删除）。
- **后端响应**：CamelModel 已序列化为 camelCase（`displayName`、`managedSiteIds` 等）。
- **测试校核重点**：Step1 基本信息提交后才能进入 Step2；删除走软删除（`isActive=false`）；简写 ID 编辑同步写入 `core.site_codes_history`。

---

### 3.14 `/settings/env-config`（环境配置）

- **设计目的**：编辑根 `.env`（敏感值 `****` 脱敏，导出去敏感）。
- **关键操作**：行内编辑、批量保存（dirtyMap 暂存）、刷新、导出 `env-config.txt`。
- **后端 API**：`GET /api/env-config`、`PUT /api/env-config`、`GET /api/env-config/export`（blob 下载）。
- **数据来源**：根 `.env` 文件。
- **必现字段**：键 / 值（敏感为 ****）/ 是否敏感 Tag / 编辑按钮、顶部 dirty Badge 计数。
- **测试校核重点**：敏感值留空提交不修改；导出文件名从 `Content-Disposition` 提取，回退 `env-config.txt`。

---

### 3.15 `/settings/runtime-context`（业务运行上下文 / 沙箱）

- **设计目的**：超管按门店切换 live ↔ sandbox（指定历史日期），切换会按 site_id 暂停/恢复 `biz.trigger_jobs`。
- **关键操作**：刷新列表、切到 sandbox（选历史日期 + reset_sandbox 开关 + 备注原因）、切回 live、查看切换步骤 Modal。
- **后端 API**：`GET /api/admin/runtime-context/sites`、`PATCH /api/admin/runtime-context`。
- **数据来源**：`meta.runtime_context` + `biz.trigger_jobs`（暂停/恢复影响）。
- **必现字段**：门店列表（site_id / site_code / mode Tag / sandbox_date / ai_mode）、切换 Drawer/Modal、步骤展示（success/skipped/warning/failed 颜色）。
- **测试校核重点**：仅 `super_admin` 可加载列表；sandbox_date 必填且 ≤ 今日；切换返回的 steps 全部展示。

---

### 3.16 `/logs/dev-trace`（DevTrace 全链路日志）

- **设计目的**：HTTP / SSE / WS / Job 全链路 span 树查看 + 覆盖率扫描 + 设置管理 + 手动清理。
- **关键操作**：选日期、按 trace_type / method / status_code / 关键字筛选、点行看 span 树、覆盖率扫描、设置 Drawer（开关 + 保留天数 + 清理）。
- **后端 API**：`GET /api/admin/dev-trace/(dates|requests|coverage|settings)`、`GET .../request/:id`、`PUT .../settings`、`POST .../cleanup`、`POST .../coverage/scan`。
- **数据来源**：本地 trace 日志文件（按日期分文件）。
- **必现字段**：覆盖率状态栏、25 种 span_type 颜色映射、左侧请求列表 + 右侧 span 树。
- **测试校核重点**：覆盖率 scan 是 POST，结果异步刷新；`cleanupLogs` 返回 `deleted_dates` + `deleted_files`。

---

### 3.17 `/logs/ai-run-logs`（AI 调用明细）

- **设计目的**：AI 单次调用的 prompt / response / error 详情查看。
- **关键操作**：筛选 app_type / status / trigger_type / site_id / 日期范围、点行打开 Drawer。
- **后端 API**：`GET /api/admin/ai/run-logs`、`GET .../:id`。
- **数据来源**：`biz.ai_run_logs`。
- **必现字段**：app_type、trigger_type、member_id、tokens_used、latency_ms、状态 Tag、Drawer 内 prompt/response/error 全文。

---

### 3.18 `/logs/db-viewer`（数据库查看器）

- **设计目的**：业务库只读 SQL 查询界面。
- **关键操作**：左侧 Tree 异步加载 schema → table、点表加载列定义、写 SQL → 执行（仅 SELECT）。
- **后端 API**：`GET /api/db/schemas`、`GET /api/db/schemas/:s/tables`、`GET /api/db/tables/:s/:t/columns`、`POST /api/db/query`。
- **数据来源**：业务库 `zqyy_app`（含 FDW 映射的 ETL `app.v_*`）。
- **必现字段**：左 Tree（schema 图标 + table 行数）、右上 SQL 编辑器、右下 列定义 / 查询结果切换。
- **测试校核重点**：后端只允许 `SELECT`；`encodeURIComponent` 处理 schema/table 名。

---

## 四、跨页共性约定

1. **认证守卫**：`PrivateRoute` 检查 `useAuthStore.isAuthenticated`，未登录跳 `/login`。Login 之外所有路由都包在 `AppLayout` 下。
2. **响应包装**：后端 `ResponseWrapperMiddleware` 把 2xx 响应包为 `{code:0, data:...}`，`apiClient` 拦截器统一解包，使页面代码直接拿 `data`。
3. **JWT 双认证**：admin-web 用 aud=`admin` token；本后台不应出现 miniapp / tenant-admin token（其它两个前端项目独立）。
4. **401 自动刷新**：`apiClient` 拦截器单飞刷新 + 队列重放，刷新失败清 token 跳 `/login`。
5. **重定向**：`/` → `/dashboard`；`/log-viewer`（已废弃）→ `/etl-tasks?tab=queue`。
6. **业务日**：`useBusinessDayStore.init()` 启动时拉营业日配置（用于 ETL 时间窗口）。
7. **底部状态栏**：每 5s 轮询 `/api/execution/queue`，展示 running 任务（flow + 前 3 个 task）。
8. **侧边栏**：`/triggers?tab=biz` 与 `/triggers?tab=ai` 是带 search 的特殊菜单 key，`getSelectedKeys` 根据 `pathname + search` 精确匹配。
9. **WebSocket**：仅 `TaskManager.QueueTab` 使用 `/ws/logs/:id` 实时日志（无独立 store）；后台 AI WS 由 `ai_ws_router` 提供，但 admin-web 暂未消费。
10. **响应格式**：多数 API 返回原始数组或对象；分页接口统一返回 `{ items, total, page, page_size }`（AI 系列再附加业务字段如 `today_skipped_duplicates`）。
11. **角色控制**：`super_admin` 才看到「业务运行上下文」「待审核任务的重分配/关闭」「参数管理的写入」按钮，前端通过 `useAuthStore.user.roles` 判断。

---

## 五、文档冲突待确认清单

> 以下与 NS1 / NS4 PRD、API-REFERENCE 或代码现状发现不一致或需澄清的点，待 Neo 确认。

1. **NS1 vs 代码**：NS1 主要描述 `/api/xcx/*` 小程序接口，未覆盖 `/api/admin/*`；admin-web 的全部 API 当前以 `apps/backend/app/routers/admin_*.py` 与 `app/routers/*.py` 实际实现为准，缺少独立 PRD。`待 Neo 确认`：是否需要补一份 `NS-admin-web-backend-api.md`？
2. **NS4 / NS4.1 vs admin-web**：NS4 / NS4.1 是 tenant-admin 重设计，与 admin-web 视角无直接冲突。但 `auth.tenant_admins` 表与 `/admin/tenant-admins` 路由都在 admin-web 出现（管理租户管理员），两者职责边界文档化建议明确：admin-web 操作租户管理员账号本身，tenant-admin 管理「门店运营」。`待 Neo 确认`。
3. **AI 触发器双 API**：`/api/admin/ai/triggers`（adminAI.ts）与 `/api/trigger-jobs`（triggerJobs.ts）操作的是同一张 `biz.trigger_jobs` 表，前者带 job_type 过滤、后者全量。`AITriggers.tsx` 用前者编辑 cron/desc，`BizTriggersTab` 用后者编辑 cron_expression/interval_seconds。`待 Neo 确认`：两套 API 是否合并？或明文区分使用边界。
4. **预热进度 vs API 文档**：`AIPrewarm` 注释写「app2_finance 72 组合」，实际是 `area=all` 走 8 组合 + 8 区域走 64 组合 = 72；NS3 / API-REFERENCE 是否同步说明这个二分？`待 Neo 确认`。
5. **事件类型枚举**：`AIOperations.EVENT_TYPE_OPTIONS`（4 项）、`AIPrewarm` triggerEvent (`dws_completed`)、`AITriggerJobs` 不限制；NS3 是否有完整 event_type 枚举表？`待 Neo 确认`。
6. **DBViewer 的安全边界**：`POST /db/query` 后端是否仅允许 SELECT？前端无校验，依赖后端 sqlparse 或类似拦截。`待 Neo 确认`。
7. **`clearAllTasks`（清空 coach_tasks）危险操作**：`TriggerJobs` 顶部的 danger 按钮调 `DELETE /api/admin/task-engine/clear-all-tasks`，注释写「测试用」。`待 Neo 确认`：是否仅在 `mode=sandbox` 才允许？现状无运行模式守卫。
8. **侧边栏 `?tab=` 入口**：「AI 管理 → 触发器设置」与「系统设置 → 触发器配置」都跳到 `/triggers?tab=ai|biz`，菜单上是两个 entry 但页面只有一个 TriggerManager；UX 是否符合预期？`待 Neo 确认`。
9. **Login 接口路径**：前端 `useAuthStore.login` 调 `/api/auth/login`（main.py 通过 `auth.router` 注册），未在本调研中读取 `auth.py` 路径常量，但 401 刷新拦截器引用了 `/auth/refresh`。`待 Neo 确认`：路径前缀是否含 `/admin`？
10. **`ai-group` 「触发器设置」展开问题**：`getDefaultOpenKeys` 注释里写 「无法判断 tab，交由路由侧 searchParams 处理默认展开」，当前从 ai 子菜单跳到 `/triggers?tab=ai` 时不会自动展开 ai-group。`待 Neo 确认`：是否需要修正 selectedKeys 逻辑使两个 group 都高亮？

---

> 文档篇幅控制：约 280 行（不含本提示）。本文为快速核对参考，详细业务规则以各页面 `.tsx` 顶部注释 + 后端 router 实现为准。
