chore: 文档与 IDE 配置整理

- .kiro/specs/ → docs/specs/(41 个历史需求 spec 迁移,移除 .config.kiro)
- CLAUDE.md 三层拆分:根文件精简 + apps/backend/CLAUDE.md + .claude/commands/
- 新增 /spec-close、/pre-change 两个工作流命令
- DDL 基线刷新(从测试库重新导出 11 个文件,dws 35→38 表,biz 18→21 表)
- BD_Manual → BD_manual 命名统一(48 个文件)
- 修复 3 处文档与数据库不一致(auth.users.status 默认值、scheduled_tasks 字段、RLS 视图数)
- 新增 BD_manual_public_rbac_tables.md(public schema 8 张 RBAC/工作流表)
- 合并 biz.trigger_jobs 文档(10→12 字段,归档独立文档)
- docs/database/README.md 索引更新

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Neo
2026-04-06 00:02:37 +08:00
parent 8228b3fa37
commit 70324d8542
185 changed files with 13595 additions and 1219 deletions

View File

@@ -0,0 +1,579 @@
# 技术设计文档admin-web 后台重构优化
## 概述
本次重构将 admin-web 从 18 个页面 / 11 个一级菜单重组为 7 个一级菜单模块,核心目标:
1. **菜单精简**11 → 7 个一级菜单按功能域聚合ETL、触发器、AI 等)
2. **新增仪表盘**:登录后默认展示运行状态 Dashboard聚合 OpsPanel + DB 健康 + AI 概览
3. **触发器统一管理**聚合三套触发器数据源biz.trigger_jobs / biz.ai_trigger_jobs / scheduled_tasks
4. **新增后端 API**PATCH /api/trigger-jobs/{id}/config编辑触发器配置、GET /api/admin/db-health数据库健康、GET /api/admin/triggers/unified触发器统一列表
5. **渐进式迁移**:新页面用目标路由开发,老页面测试通过后移入 `_archived/`
### 设计决策
- **Tab 视图而非子路由**ETL 任务管理和触发器管理使用 Ant Design Tabs 组件 + URL 查询参数(`?tab=xxx`而非嵌套路由。理由Tab 切换不触发组件卸载,状态保持更自然。
- **复用而非重写**Dashboard 通过 import 现有 OpsPanel / AIDashboard 组件的子模块实现聚合,不重写已有逻辑。
- **后端最小改动**:仅新增 3 个 API 端点,不修改现有业务逻辑。
## 架构
### 整体架构
```mermaid
graph TB
subgraph "admin-web 前端"
Router["React Router 7<br/>路由层"]
Layout["AppLayout<br/>Sider + Content"]
subgraph "7 个一级模块"
Dashboard["运行状态<br/>/dashboard"]
ETL["ETL 任务管理<br/>/etl-tasks"]
MiniApp["小程序任务管理<br/>/task-engine/*"]
Triggers["触发器管理<br/>/triggers"]
Tenant["租户管理员<br/>/tenant-admins"]
Settings["系统设置<br/>/settings"]
Logs["日志调试<br/>/logs/*"]
end
end
subgraph "后端 APIFastAPI"
ExistingAPI["现有 API 端点"]
NewPATCH["PATCH /api/trigger-jobs/{id}/config"]
NewDBHealth["GET /api/admin/db-health"]
NewUnified["GET /api/admin/triggers/unified"]
end
subgraph "数据库"
TriggerJobs["biz.trigger_jobs"]
AITriggerJobs["biz.ai_trigger_jobs"]
ScheduledTasks["scheduled_tasks"]
FourDBs["4 个数据库健康检测"]
end
Router --> Layout
Layout --> Dashboard & ETL & MiniApp & Triggers & Tenant & Settings & Logs
Dashboard --> ExistingAPI & NewDBHealth
Triggers --> ExistingAPI & NewPATCH & NewUnified
NewUnified --> TriggerJobs & AITriggerJobs & ScheduledTasks
NewDBHealth --> FourDBs
```
### 路由结构
```
/login → Login不变
/dashboard → Dashboard默认首页
/ → Redirect → /dashboard
/etl-tasks?tab=config|manager|status → ETLTasks合并 3 页面)
/task-engine/trigger-jobs → TriggerJobs移动路由
/task-engine/transfer-log → TransferLog不变
/task-engine/pending-review → PendingReview不变
/task-engine/config → TaskEngineConfig不变
/triggers?tab=all|biz|ai|etl → TriggerManager
/tenant-admins → TenantAdmins不变
/settings/env-config → EnvConfig移动路由
/logs/dev-trace → DevTrace移动路由
/logs/ai-run-logs → AIRunLogs移动路由
/logs/db-viewer → DBViewer移动路由
/log-viewer → Redirect → /etl-tasks?tab=manager
```
### 菜单结构映射
| 序号 | 一级菜单 | 子项/Tab | 路由 |
|------|----------|----------|------|
| 1 | 运行状态 | — | /dashboard |
| 2 | ETL 任务管理 | 任务配置 / 任务管理 / ETL 状态Tab | /etl-tasks?tab=config\|manager\|status |
| 3 | 小程序任务管理 | 定时任务 / 转移日志 / 待审核任务 / 参数管理 | /task-engine/* |
| 4 | 触发器管理 | 全部 / 业务 / AI / ETLTab | /triggers?tab=all\|biz\|ai\|etl |
| 5 | 租户管理员 | — | /tenant-admins |
| 6 | 系统设置 | 环境配置 / 触发器配置(跳转) | /settings/* |
| 7 | 日志调试 | DevTrace / AI 调用明细 / 数据库查看器 | /logs/* |
## 组件与接口
### 新增前端页面组件
#### 1. Dashboard运行状态仪表盘
```
src/pages/Dashboard.tsx
```
聚合展示系统运行状况,由 4 个区块组成:
- **OpsPanel 区块**:复用现有 OpsPanel 组件中的服务状态、Git 状态、系统资源子模块(需将 OpsPanel 拆分为可独立使用的子组件)
- **DB 健康监控区块**:新组件 `DbHealthCard`,调用 `GET /api/admin/db-health`,展示 4 个数据库的连接池 / 大小 / 慢查询
- **AI 运行总览区块**:复用现有 AIDashboard 组件的统计卡片、趋势图、预算进度
- **AI 调度摘要区块**:展示今日触发数、成功率、最近错误,提供"查看详情"跳转到 `/triggers?tab=ai`
跳转链接:
- "ETL 状态详情" → `/etl-tasks?tab=status`
- "触发器详情" → `/triggers?tab=all`
- "AI 调度详情" → `/triggers?tab=ai`
#### 2. ETLTasksETL 任务管理)
```
src/pages/ETLTasks.tsx
```
使用 Ant Design `Tabs` 组件合并 3 个现有页面:
- Tab "config":渲染 `<TaskConfig />`(现有组件)
- Tab "manager":渲染 `<TaskManager />`(现有组件)
- Tab "status":渲染 `<ETLStatus />`(现有组件)
Tab 切换通过 URL 查询参数 `?tab=config|manager|status` 同步,支持浏览器前进/后退。使用 `useSearchParams` 读写当前 Tab。各 Tab 内容使用 `destroyInactiveTabPane={false}` 保持状态不丢失。
#### 3. TriggerManager触发器统一管理
```
src/pages/TriggerManager.tsx
```
4 个 Tab
- **全部 Tab**(只读):调用 `GET /api/admin/triggers/unified`,展示统一字段表格(名称、类型标签、触发条件、状态、上次/下次执行、最近错误)
- **业务 Tab**:复用现有 TriggerJobs 组件 + 新增编辑功能(调用 `PATCH /api/trigger-jobs/{id}/config`
- **AI Tab**:复用现有 AIOperations 组件的手动操作功能 + AITriggerJobs 的调度状态
- **ETL Tab**:展示 scheduled_tasks 数据(调用现有调度 API
#### 4. DbHealthCard数据库健康卡片
```
src/components/DbHealthCard.tsx
```
独立组件,接收 `GET /api/admin/db-health` 返回数据,为每个数据库渲染一张卡片:
- 连接池状态(活跃/空闲连接数,进度条)
- 数据库大小MB
- 慢查询数量(最近 1 小时)
- 连接失败时显示"未连接"状态标签
### 新增后端 API
#### 1. PATCH /api/trigger-jobs/{id}/config
```python
# apps/backend/app/routers/trigger_jobs.py 新增端点
@router.patch("/{job_id}/config", response_model=TriggerJobItem)
async def update_trigger_config(
job_id: int,
body: UpdateTriggerConfigRequest,
user: CurrentUser = Depends(get_current_user),
) -> TriggerJobItem:
"""编辑触发器的 cron_expression 或 interval_seconds。"""
```
请求体 Schema
```python
class UpdateTriggerConfigRequest(BaseModel):
cron_expression: str | None = None
interval_seconds: int | None = None
```
逻辑:
1. 查询 trigger_job 是否存在
2. 校验 cron_expression 格式5 字段 cron 语法)
3. 校验 interval_seconds >= 1
4. 更新 trigger_config JSON 中对应字段
5. 调用 `_calculate_next_run()` 重新计算 next_run_at
6. 返回更新后的完整 trigger_job
#### 2. GET /api/admin/db-health
```python
# apps/backend/app/routers/admin_db_health.py 新增路由模块
@router.get("", response_model=list[DbHealthItem])
async def get_db_health(
user: CurrentUser = Depends(get_current_user),
) -> list[DbHealthItem]:
"""返回 4 个数据库的健康状态。"""
```
响应 Schema
```python
class DbHealthItem(BaseModel):
db_name: str # etl_feiqiu / test_etl_feiqiu / zqyy_app / test_zqyy_app
status: str # connected / disconnected
active_connections: int | None = None
idle_connections: int | None = None
db_size_mb: float | None = None
slow_query_count: int | None = None # 最近 1 小时内 > 1s 的查询数
```
逻辑:
1. 遍历 4 个数据库 DSN 配置
2. 对每个库尝试连接并执行诊断 SQL
- `pg_stat_activity` 查连接池状态
- `pg_database_size()` 查数据库大小
- `pg_stat_statements``pg_stat_activity` 查慢查询
3. 连接失败时返回 `status: "disconnected"`,其余字段为 null
#### 3. GET /api/admin/triggers/unified
```python
# apps/backend/app/routers/admin_triggers.py 新增路由模块
@router.get("", response_model=list[UnifiedTriggerItem])
async def get_unified_triggers(
user: CurrentUser = Depends(get_current_user),
) -> list[UnifiedTriggerItem]:
"""聚合三张表的触发器数据。"""
```
响应 Schema
```python
class UnifiedTriggerItem(BaseModel):
id: int
name: str
source: str # biz / ai / etl
trigger_condition: str # cron / interval / event
status: str # running / idle / error / disabled
last_run_at: str | None = None
next_run_at: str | None = None
last_error: str | None = None
```
逻辑:
1. 查询 `biz.trigger_jobs`,映射 source="biz"
2. 查询 `biz.ai_trigger_jobs`(最近 100 条),映射 source="ai"
3. 查询 `scheduled_tasks`,映射 source="etl"
4. 统一字段格式后合并返回
### 新增前端 API 模块
```typescript
// src/api/dbHealth.ts
export interface DbHealthItem {
db_name: string;
status: 'connected' | 'disconnected';
active_connections: number | null;
idle_connections: number | null;
db_size_mb: number | null;
slow_query_count: number | null;
}
export async function fetchDbHealth(): Promise<DbHealthItem[]> {
const { data } = await apiClient.get<DbHealthItem[]>('/admin/db-health');
return data;
}
// src/api/triggers.ts
export interface UnifiedTriggerItem {
id: number;
name: string;
source: 'biz' | 'ai' | 'etl';
trigger_condition: string;
status: string;
last_run_at: string | null;
next_run_at: string | null;
last_error: string | null;
}
export async function fetchUnifiedTriggers(): Promise<UnifiedTriggerItem[]> {
const { data } = await apiClient.get<UnifiedTriggerItem[]>('/admin/triggers/unified');
return data;
}
// src/api/triggerJobs.ts 新增
export interface UpdateTriggerConfigReq {
cron_expression?: string;
interval_seconds?: number;
}
export async function updateTriggerConfig(
jobId: number, body: UpdateTriggerConfigReq
): Promise<TriggerJob> {
const { data } = await apiClient.patch<TriggerJob>(`/trigger-jobs/${jobId}/config`, body);
return data;
}
```
### 修改的现有组件
#### App.tsx 路由重构
- NAV_ITEMS 从 11 个一级项重组为 7 个
- Routes 更新为新路由结构
- 添加 `/``/dashboard` 重定向
- 添加 `/log-viewer``/etl-tasks?tab=manager` 重定向
- 登录成功后导航到 `/dashboard`
#### OpsPanel 组件拆分
将 OpsPanel.tsx 拆分为可独立使用的子组件:
- `ServiceStatusSection`:服务状态卡片
- `GitStatusSection`Git 状态卡片
- `SystemResourceSection`:系统资源卡片
Dashboard 页面 import 这些子组件进行聚合展示。
## 数据模型
### 新增后端 Pydantic 模型
#### UpdateTriggerConfigRequest
```python
class UpdateTriggerConfigRequest(BaseModel):
"""触发器配置编辑请求(部分更新)"""
cron_expression: str | None = None # 5 字段 cron 表达式
interval_seconds: int | None = None # 间隔秒数,>= 1
@model_validator(mode='after')
def at_least_one_field(self) -> Self:
if self.cron_expression is None and self.interval_seconds is None:
raise ValueError('至少提供 cron_expression 或 interval_seconds 之一')
return self
```
#### DbHealthItem
```python
class DbHealthItem(BaseModel):
"""单个数据库健康状态"""
db_name: str
status: Literal['connected', 'disconnected']
active_connections: int | None = None
idle_connections: int | None = None
db_size_mb: float | None = None
slow_query_count: int | None = None
```
#### UnifiedTriggerItem
```python
class UnifiedTriggerItem(BaseModel):
"""统一触发器视图项"""
id: int
name: str
source: Literal['biz', 'ai', 'etl']
trigger_condition: str
status: str
last_run_at: str | None = None
next_run_at: str | None = None
last_error: str | None = None
```
### 新增前端 TypeScript 类型
```typescript
// 数据库健康
interface DbHealthItem {
db_name: string;
status: 'connected' | 'disconnected';
active_connections: number | null;
idle_connections: number | null;
db_size_mb: number | null;
slow_query_count: number | null;
}
// 统一触发器
interface UnifiedTriggerItem {
id: number;
name: string;
source: 'biz' | 'ai' | 'etl';
trigger_condition: string;
status: string;
last_run_at: string | null;
next_run_at: string | null;
last_error: string | null;
}
// 触发器配置编辑
interface UpdateTriggerConfigReq {
cron_expression?: string;
interval_seconds?: number;
}
```
### 数据库变更
本次重构不新增数据库表。所有数据来自现有表:
| 表 | 库 | 用途 |
|----|-----|------|
| biz.trigger_jobs | zqyy_app | 4 个业务触发器 |
| biz.ai_trigger_jobs | zqyy_app | AI 事件链触发器 |
| scheduled_tasks | zqyy_app | ETL 调度任务 |
| pg_stat_activity | 各库 | 连接池状态 |
| pg_database | 各库 | 数据库大小 |
### Cron 表达式校验规则
PATCH API 中的 cron_expression 校验逻辑:
```python
import re
CRON_FIELD_PATTERNS = [
r'(\*|[0-5]?\d)', # minute: 0-59
r'(\*|[01]?\d|2[0-3])', # hour: 0-23
r'(\*|[1-9]|[12]\d|3[01])', # day of month: 1-31
r'(\*|[1-9]|1[0-2])', # month: 1-12
r'(\*|[0-6])', # day of week: 0-6
]
def validate_cron_expression(expr: str) -> bool:
"""校验 5 字段 cron 表达式基本格式。"""
parts = expr.strip().split()
if len(parts) != 5:
return False
for part, pattern in zip(parts, CRON_FIELD_PATTERNS):
if not re.fullmatch(pattern, part):
return False
return True
```
## 正确性属性
*属性是系统在所有有效执行中都应保持为真的特征或行为——本质上是关于系统应该做什么的形式化陈述。属性是人类可读规范与机器可验证正确性保证之间的桥梁。*
### 属性 1DB 健康 API 已连接数据库返回完整指标
*对于任意* 处于 `connected` 状态的数据库健康响应项,其 `active_connections``idle_connections``db_size_mb``slow_query_count` 字段均不为 null 且类型正确(连接数为非负整数,大小为非负浮点数)。
**验证需求2.4, 6.2**
### 属性 2Tab 切换状态保持 round-trip
*对于任意* ETL 任务管理或触发器管理的 Tab 视图,在某个 Tab 中设置筛选条件后切换到另一个 Tab 再切回来,原 Tab 的筛选条件应保持不变。
**验证需求3.5**
### 属性 3触发器统一视图数据完整性与字段完整性
*对于任意* 一组来自 biz.trigger_jobs、biz.ai_trigger_jobs、scheduled_tasks 三个数据源的触发器数据,统一视图 API 返回的记录总数应等于三个数据源记录数之和,且每条记录都包含 name、source、trigger_condition、status、last_run_at、next_run_at、last_error 字段。
**验证需求4.1, 4.2**
### 属性 4触发器配置编辑不变量
*对于任意* 通过 PATCH /api/trigger-jobs/{id}/config 的成功更新请求trigger_job 中除 trigger_config 内的 cron_expression / interval_seconds 和 next_run_at 外的所有字段id、job_type、job_name、trigger_condition、status、description、created_at应保持不变。
**验证需求4.7**
### 属性 5触发器配置更新正确性
*对于任意* 有效的 cron_expression符合 5 字段 cron 语法)或有效的 interval_seconds>= 1通过 PATCH API 更新后,返回的 trigger_job 中 trigger_config 对应字段值应等于请求值,且 next_run_at 应被重新计算为非 null 值。
**验证需求5.2, 5.3, 5.7**
### 属性 6触发器配置校验拒绝无效输入
*对于任意* 不符合 5 字段 cron 语法的字符串作为 cron_expression或任意小于 1 的整数作为 interval_secondsPATCH API 应返回 HTTP 422 状态码,且响应体包含描述性错误信息。
**验证需求5.4, 5.5**
### 属性 7侧边栏高亮与当前路由一致
*对于任意* 有效的应用路由路径侧边栏中被高亮selectedKeys的菜单项应对应该路由所属的一级模块。
**验证需求10.3**
### 属性 8Tab 切换与 URL 查询参数同步 round-trip
*对于任意* Tab 视图页面ETL 任务管理、触发器管理),设置 URL 查询参数 `?tab=X` 后渲染页面,当前激活的 Tab 应为 X反之点击 Tab Y 后URL 查询参数应更新为 `?tab=Y`
**验证需求10.4**
## 错误处理
### 前端错误处理
| 场景 | 处理方式 |
|------|----------|
| API 请求失败(网络错误) | Ant Design `message.error()` 提示,保持当前页面状态 |
| API 返回 401 | 现有 axios 拦截器自动处理:尝试 refresh token → 失败则跳转 /login |
| API 返回 422校验错误 | 在编辑表单中展示具体错误信息(如"cron 表达式格式无效" |
| API 返回 500 | `message.error()` 提示通用错误信息 |
| 组件渲染异常 | 现有 ErrorBoundary 组件捕获,展示降级 UI |
| DB 健康 API 超时 | DbHealthCard 展示"加载超时"状态,提供重试按钮 |
| 触发器统一 API 部分数据源失败 | 后端返回可用数据源的数据,前端正常展示已获取的数据 |
### 后端错误处理
| 场景 | 处理方式 |
|------|----------|
| PATCH APItrigger_job 不存在 | 返回 HTTP 404 + `{"detail": "任务 {id} 不存在"}` |
| PATCH APIcron_expression 格式无效 | 返回 HTTP 422 + `{"detail": "cron 表达式格式无效,需要 5 字段格式"}` |
| PATCH APIinterval_seconds < 1 | 返回 HTTP 422 + `{"detail": "interval_seconds 必须 >= 1"}` |
| PATCH API请求体为空 | 返回 HTTP 422 + `{"detail": "至少提供 cron_expression 或 interval_seconds 之一"}` |
| DB 健康 API某库连接失败 | 该库返回 `status: "disconnected"`,其余指标为 null不影响其他库 |
| DB 健康 API所有库连接失败 | 返回 4 个 disconnected 项HTTP 200不返回 500 |
| 统一触发器 API某数据源查询失败 | 记录日志,返回其他数据源的数据,失败的数据源不包含在结果中 |
| JWT 认证失败 | 返回 HTTP 401现有中间件处理 |
## 测试策略
### 双重测试方法
本项目采用单元测试 + 属性测试的双重策略:
- **单元测试Vitest**:验证具体示例、边界条件、错误场景
- **属性测试fast-check**:验证跨所有输入的通用属性
- 两者互补:单元测试捕获具体 bug属性测试验证通用正确性
### 前端测试
**工具**Vitest + @testing-library/react + fast-check
**属性测试配置**
- 每个属性测试最少运行 100 次迭代
- 每个属性测试必须用注释引用设计文档中的属性编号
- 标签格式:`Feature: admin-web-restructure, Property {number}: {property_text}`
**单元测试覆盖**
- 菜单结构验证7 个一级菜单项、子项正确性)
- 路由重定向(/ → /dashboard、/log-viewer → /etl-tasks
- Dashboard 区块渲染
- Tab 组件默认 Tab 选择
- DbHealthCard 各状态渲染connected / disconnected
**属性测试覆盖**
- 属性 2Tab 状态保持 round-trip
- 属性 7侧边栏高亮与路由一致
- 属性 8Tab-URL 参数同步 round-trip
### 后端测试
**工具**pytest + hypothesis
**属性测试配置**
- 每个属性测试使用 `@settings(max_examples=100)`
- 标签格式同上
**单元测试覆盖**
- PATCH API 端点存在性
- JWT 认证拦截
- DB 健康 API 端点存在性
- 统一触发器 API 端点存在性
**属性测试覆盖**
- 属性 1DB 健康 API 已连接数据库返回完整指标
- 属性 3触发器统一视图数据完整性
- 属性 4触发器配置编辑不变量
- 属性 5触发器配置更新正确性
- 属性 6触发器配置校验拒绝无效输入
### E2E 测试
**工具**Playwright
**覆盖范围**(每个新页面一个测试文件):
- `dashboard.spec.ts`Dashboard 页面渲染、4 个区块存在、跳转链接正确
- `etl-tasks.spec.ts`ETL 任务管理 Tab 切换、各 Tab 内容渲染
- `trigger-manager.spec.ts`:触发器管理 4 个 Tab、统一视图数据、业务 Tab 编辑功能
- `navigation.spec.ts`默认路由、重定向、菜单高亮、Tab-URL 同步
**测试批次**:每个测试文件控制在 Playwright 默认超时30s范围内。

View File

@@ -0,0 +1,161 @@
# 需求文档admin-web 后台重构优化
## 简介
将现有 admin-web 系统管理后台从 18 个页面 / 11 个一级菜单重组为 7 个一级菜单模块,新增运行状态仪表盘、触发器统一管理、数据库健康监控等功能,废弃 LogViewer 页面,采用新老页面交替开发策略,逐步完成迁移。
## 术语表
- **Admin_Web**:系统管理后台前端应用,位于 `apps/admin-web/`,面向开发者和运维人员
- **Dashboard**:运行状态仪表盘,重组后的默认首页,聚合系统运行状况
- **ETL_Task_Module**ETL 任务管理模块,合并原 TaskConfig、TaskManager、ETLStatus 三个页面为 Tab 视图
- **MiniApp_Task_Module**:小程序任务管理模块,原"任务引擎"改名,包含定时任务、转移日志、待审核任务、参数管理
- **Trigger_Module**:触发器管理模块,统一展示和管理三套触发器数据源
- **Trigger_Unified_View**:触发器统一视图,在"全部"Tab 中聚合 biz.trigger_jobs、biz.ai_trigger_jobs、scheduled_tasks 三张表的数据
- **DB_Health_Monitor**:数据库健康监控组件,检测 4 个数据库etl_feiqiu / test_etl_feiqiu / zqyy_app / test_zqyy_app的连接池、大小、慢查询
- **Archived_Page**:已归档页面,测试通过后移入 `_archived/` 目录且菜单不再显示的旧页面
- **Trigger_Config_PATCH_API**:新增的后端 PATCH 接口,用于编辑 trigger_config 中的 cron_expression 和 interval_seconds
- **E2E_Test**:端到端测试,使用 Playwright 编写,每个新页面必须配套
## 需求
### 需求 1侧边栏菜单重组
**用户故事:** 作为开发者/运维人员,我希望侧边栏菜单从 11 个一级项重组为 7 个一级项,以便更高效地导航和管理后台功能。
#### 验收标准
1. THE Admin_Web SHALL 将侧边栏菜单重组为以下 7 个一级菜单项运行状态、ETL 任务管理、小程序任务管理、触发器管理、租户管理员、系统设置、日志调试
2. THE Admin_Web SHALL 将"运行状态"菜单项设置为侧边栏第一项,并作为登录后的默认路由
3. THE Admin_Web SHALL 在"ETL 任务管理"菜单下提供 3 个 Tab任务配置、任务管理、ETL 状态
4. THE Admin_Web SHALL 将原"任务引擎"菜单改名为"小程序任务管理",保留 4 个子项:定时任务、转移日志、待审核任务、参数管理
5. THE Admin_Web SHALL 在"触发器管理"菜单下提供 4 个 Tab全部、业务、AI、ETL
6. THE Admin_Web SHALL 在"系统设置"菜单下包含环境配置页面和触发器配置跳转入口
7. THE Admin_Web SHALL 在"日志调试"菜单下包含 3 个子项DevTrace全链路日志、AI 调用明细、数据库查看器
8. THE Admin_Web SHALL 保持"租户管理员"作为独立一级菜单,功能不变
9. WHEN 用户登录成功后THE Admin_Web SHALL 自动导航到运行状态(仪表盘)页面
### 需求 2运行状态仪表盘
**用户故事:** 作为开发者/运维人员,我希望登录后看到一个聚合仪表盘,以便一目了然地掌握系统整体运行状况。
#### 验收标准
1. THE Dashboard SHALL 聚合展示以下内容区块OpsPanel 运维面板内容、数据库健康监控、AI Dashboard 内容、AI 调度状态摘要
2. THE Dashboard SHALL 提供跳转链接,点击后分别导航到 ETL 任务管理的"ETL 状态"Tab 和触发器管理的"触发器状态"Tab
3. THE DB_Health_Monitor SHALL 检测以下 4 个数据库的健康状态etl_feiqiu、test_etl_feiqiu、zqyy_app、test_zqyy_app
4. THE DB_Health_Monitor SHALL 展示每个数据库的连接池状态、数据库大小、慢查询信息
5. IF 某个数据库不存在或无法连接THEN THE DB_Health_Monitor SHALL 将该数据库标记为"未连接"状态,而非抛出错误
6. THE Dashboard SHALL 复用原 OpsPanel 组件的服务状态、Git 状态、系统资源等内容
7. THE Dashboard SHALL 复用原 AIDashboard 组件的统计卡片、趋势图、预算进度等内容
8. THE Dashboard SHALL 展示 AI 调度状态的摘要信息(今日触发数、成功率、最近错误)
### 需求 3ETL 任务管理模块
**用户故事:** 作为开发者/运维人员,我希望将 ETL 相关的三个页面合并为一个 Tab 视图,以便在同一页面内切换任务配置、任务管理和 ETL 状态。
#### 验收标准
1. THE ETL_Task_Module SHALL 将原 TaskConfig、TaskManager、ETLStatus 三个页面合并为同一路由下的 3 个 Tab
2. THE ETL_Task_Module SHALL 将"任务配置"Tab 的功能与原 TaskConfig 页面保持一致,包括 Flow 选择、任务勾选、参数设置、CLI 预览、执行/入队
3. THE ETL_Task_Module SHALL 将"任务管理"Tab 的功能与原 TaskManager 页面保持一致,包括队列管理、执行历史、实时日志流
4. THE ETL_Task_Module SHALL 将"ETL 状态"Tab 的功能与原 ETLStatus 页面保持一致,包括数据游标监控和最近执行记录
5. WHEN 用户切换 Tab 时THE ETL_Task_Module SHALL 保持各 Tab 的状态不丢失(如筛选条件、滚动位置)
### 需求 4触发器统一管理模块
**用户故事:** 作为开发者/运维人员,我希望在一个统一视图中查看所有触发器的运行状态,以便快速定位调度问题。
#### 验收标准
1. THE Trigger_Unified_View SHALL 在"全部"Tab 中聚合展示来自三个数据源的触发器biz.trigger_jobs业务触发器、biz.ai_trigger_jobsAI 事件链、scheduled_tasksETL 调度)
2. THE Trigger_Unified_View SHALL 为每个触发器展示以下统一字段:名称、类型标签(业务/AI/ETL、触发条件、状态运行中/空闲/错误/禁用)、上次执行时间、下次执行时间、最近错误
3. THE Trigger_Unified_View SHALL 在"全部"Tab 中仅提供只读查看,不提供编辑功能
4. THE Trigger_Module SHALL 在"业务"Tab 中展示 biz.trigger_jobs 的 4 个业务触发器,并支持编辑 trigger_config 中的 cron_expression 和 interval_seconds
5. THE Trigger_Module SHALL 在"AI"Tab 中展示 biz.ai_trigger_jobs 的 AI 事件链触发器,并提供 AI 手动操作功能(重跑、缓存失效、批量执行、告警管理)
6. THE Trigger_Module SHALL 在"ETL"Tab 中展示 scheduled_tasks 的 ETL 调度任务
7. WHEN 用户在"业务"Tab 中编辑触发器配置时THE Trigger_Module SHALL 仅允许修改 cron_expression 和 interval_seconds 两个字段
8. THE Trigger_Module SHALL 不提供编辑历史记录功能
### 需求 5触发器配置编辑后端 API
**用户故事:** 作为开发者/运维人员,我希望通过管理后台直接编辑触发器的 cron 表达式和间隔秒数,以便无需直接操作数据库即可调整调度策略。
#### 验收标准
1. THE Trigger_Config_PATCH_API SHALL 提供 PATCH /api/trigger-jobs/{id}/config 端点,接受 cron_expression 和 interval_seconds 的部分更新
2. WHEN 请求体包含 cron_expression 字段时THE Trigger_Config_PATCH_API SHALL 更新 trigger_config JSON 中的 cron_expression 值,并重新计算 next_run_at
3. WHEN 请求体包含 interval_seconds 字段时THE Trigger_Config_PATCH_API SHALL 更新 trigger_config JSON 中的 interval_seconds 值,并重新计算 next_run_at
4. IF cron_expression 格式不符合 5 字段 cron 语法THEN THE Trigger_Config_PATCH_API SHALL 返回 HTTP 422 错误及描述性错误信息
5. IF interval_seconds 小于 1THEN THE Trigger_Config_PATCH_API SHALL 返回 HTTP 422 错误及描述性错误信息
6. THE Trigger_Config_PATCH_API SHALL 要求 JWT 认证,与现有 trigger-jobs 端点保持一致的鉴权策略
7. WHEN 更新成功时THE Trigger_Config_PATCH_API SHALL 返回更新后的完整 trigger_job 信息
### 需求 6数据库健康监控后端 API
**用户故事:** 作为开发者/运维人员,我希望仪表盘能实时展示数据库健康状态,以便及时发现连接池耗尽或慢查询等问题。
#### 验收标准
1. THE Admin_Web SHALL 提供 GET /api/admin/db-health 端点,返回 4 个数据库的健康状态
2. THE Admin_Web SHALL 为每个数据库返回以下指标连接池活跃连接数、连接池空闲连接数、数据库大小MB、慢查询数量最近 1 小时内执行时间超过 1 秒的查询)
3. IF 某个数据库无法连接THEN THE Admin_Web SHALL 返回该数据库的状态为 "disconnected",其余指标为 null而非返回 HTTP 错误
4. THE Admin_Web SHALL 要求 JWT 认证访问数据库健康端点
### 需求 7AI 内容拆分重组
**用户故事:** 作为开发者/运维人员,我希望 AI 相关功能按使用场景分散到对应模块中,以便在合适的上下文中使用 AI 功能。
#### 验收标准
1. THE Dashboard SHALL 包含原 AIDashboard 页面的运行总览内容(统计卡片、趋势图、饼图、预算进度、告警列表)
2. THE Dashboard SHALL 包含原 AITriggerJobs 页面的调度状态摘要信息
3. THE Trigger_Module SHALL 在"AI"Tab 中包含原 AIOperations 页面的手动操作功能(重跑、缓存失效、批量执行、告警管理)
4. THE Admin_Web SHALL 将原 AIRunLogs 页面AI 调用明细)移入"日志调试"模块下
5. WHEN 用户从仪表盘的 AI 调度状态摘要点击"查看详情"时THE Admin_Web SHALL 导航到触发器管理的"AI"Tab
### 需求 8LogViewer 废弃
**用户故事:** 作为开发者/运维人员,我不再需要独立的 LogViewer 页面,因为 ETL 任务管理模块已提供实时日志功能。
#### 验收标准
1. THE Admin_Web SHALL 从侧边栏菜单中移除 LogViewer/log-viewer入口
2. THE Admin_Web SHALL 从路由配置中移除 /log-viewer 路由
3. WHEN 用户直接访问 /log-viewer 路径时THE Admin_Web SHALL 重定向到 ETL 任务管理页面
4. THE Admin_Web SHALL 将 LogViewer.tsx 源文件移入 `_archived/` 目录
### 需求 9新老页面交替开发策略
**用户故事:** 作为开发者,我希望采用渐进式迁移策略,以便在不影响现有功能的前提下逐步完成重构。
#### 验收标准
1. THE Admin_Web SHALL 使用目标路由开发新页面,不修改老页面的路由和功能
2. WHEN 新页面的 E2E 测试全部通过后THE Admin_Web SHALL 将对应的老页面源文件移入 `_archived/` 目录
3. THE Admin_Web SHALL 在老页面移入 `_archived/` 后,从侧边栏菜单中移除对应的老菜单项
4. THE Admin_Web SHALL 为每个新页面编写 Playwright E2E 测试,测试内容包含页面渲染验证和数据库查询校验数据正确性
5. THE Admin_Web SHALL 将 E2E 测试按合理批次切割,每个测试文件的执行时间控制在 Playwright 默认超时范围内
### 需求 10默认路由与导航
**用户故事:** 作为开发者/运维人员,我希望登录后直接看到系统运行状态,以便第一时间了解系统健康状况。
#### 验收标准
1. WHEN 用户登录成功后THE Admin_Web SHALL 将默认路由从 "/" (TaskConfig) 变更为 "/dashboard"(运行状态仪表盘)
2. WHEN 用户访问根路径 "/" 时THE Admin_Web SHALL 重定向到 "/dashboard"
3. THE Admin_Web SHALL 在侧边栏中高亮当前所在模块对应的菜单项
4. WHEN 用户在 Tab 视图内切换 Tab 时THE Admin_Web SHALL 更新 URL 查询参数以反映当前 Tab支持浏览器前进/后退导航
### 需求 11明确排除范围
**用户故事:** 作为开发者,我需要明确本次重构的边界,以便聚焦于前端重组工作。
#### 验收标准
1. THE Admin_Web SHALL 不修改后端业务逻辑(除新增 PATCH API 和数据库健康 API 外)
2. THE Admin_Web SHALL 不修改 tenant-admin 租户管理后台的任何功能
3. THE Admin_Web SHALL 不修改小程序端的任何功能
4. THE Admin_Web SHALL 不变更现有权限模型JWT 认证方式和角色体系保持不变)
5. THE Admin_Web SHALL 保持所有现有 API 接口的向后兼容性

View File

@@ -0,0 +1,325 @@
# 实施计划admin-web 后台重构优化
## 概述
按"后端 API → 前端页面 → 联调收尾"的顺序实施。后端新增 3 个 API 端点,前端重组菜单和路由、新建 4 个页面组件,最后归档老页面并补充 E2E 测试。每个阶段结束后插入检查点。
## 任务
- [x] 1. 后端:新增 Pydantic 模型与工具函数
- [x] 1.1 创建 `UpdateTriggerConfigRequest``DbHealthItem``UnifiedTriggerItem` 三个 Pydantic 模型
-`apps/backend/app/schemas/` 下新建或扩展 schema 文件
- `UpdateTriggerConfigRequest` 包含 `model_validator` 确保至少提供一个字段
- `DbHealthItem.status` 使用 `Literal['connected', 'disconnected']`
- `UnifiedTriggerItem.source` 使用 `Literal['biz', 'ai', 'etl']`
- _Requirements: 5.1, 5.2, 5.3, 6.1, 6.2, 4.1, 4.2_
- [x] 1.2 实现 cron 表达式校验工具函数 `validate_cron_expression`
-`apps/backend/app/utils/` 下新建 `cron_validator.py`
- 校验 5 字段 cron 语法,支持 `*` 和数值范围
- _Requirements: 5.4_
- [x] 1.3 编写属性测试cron 表达式校验拒绝无效输入
- **Property 6: 触发器配置校验拒绝无效输入**
- 使用 hypothesis 生成任意非 5 字段字符串、超范围数值字段
- 验证 `validate_cron_expression` 对无效输入返回 False
- **验证: 需求 5.4, 5.5**
- [x] 1.4 编写单元测试cron 校验与 Pydantic 模型
- 测试有效 cron 表达式通过校验
- 测试无效格式(字段数不对、超范围值)被拒绝
- 测试 `UpdateTriggerConfigRequest` 空请求体触发 ValidationError
- 测试 `DbHealthItem` disconnected 状态下指标字段可为 null
- _Requirements: 5.4, 5.5, 6.3_
- [x] 2. 后端:实现 PATCH /api/trigger-jobs/{id}/config 端点
- [x] 2.1 在 `apps/backend/app/routers/trigger_jobs.py` 新增 PATCH 端点
- 查询 trigger_job 是否存在(不存在返回 404
- 校验 cron_expression 格式(无效返回 422
- 校验 interval_seconds >= 1无效返回 422
- 更新 trigger_config JSON 中对应字段
- 重新计算 next_run_at
- 返回更新后的完整 trigger_job
- JWT 认证与现有端点一致
- _Requirements: 5.1, 5.2, 5.3, 5.4, 5.5, 5.6, 5.7_
- [x] 2.2 编写属性测试:触发器配置编辑不变量
- **Property 4: 触发器配置编辑不变量**
- 使用 hypothesis 生成有效的 cron_expression 和 interval_seconds
- 验证更新后 trigger_job 中除 trigger_config 和 next_run_at 外的字段不变
- **验证: 需求 4.7**
- [x] 2.3 编写属性测试:触发器配置更新正确性
- **Property 5: 触发器配置更新正确性**
- 使用 hypothesis 生成有效的 cron_expression5 字段格式)和 interval_seconds>= 1
- 验证返回的 trigger_config 对应字段值等于请求值,且 next_run_at 非 null
- **验证: 需求 5.2, 5.3, 5.7**
- [x] 2.4 编写单元测试PATCH 端点边界条件
- 测试不存在的 job_id 返回 404
- 测试空请求体返回 422
- 测试无 JWT 返回 401
- _Requirements: 5.1, 5.4, 5.5, 5.6_
- [x] 3. 后端:实现 GET /api/admin/db-health 端点
- [x] 3.1 新建 `apps/backend/app/routers/admin_db_health.py` 路由模块
- 遍历 4 个数据库 DSN 配置etl_feiqiu / test_etl_feiqiu / zqyy_app / test_zqyy_app
- 对每个库执行诊断 SQL`pg_stat_activity`(连接池)、`pg_database_size()`(大小)、慢查询统计
- 连接失败时返回 `status: "disconnected"`,其余字段为 null
- JWT 认证
-`apps/backend/app/main.py` 中注册路由
- _Requirements: 6.1, 6.2, 6.3, 6.4_
- [x] 3.2 编写属性测试DB 健康 API 已连接数据库返回完整指标
- **Property 1: DB 健康 API 已连接数据库返回完整指标**
- 使用 hypothesis 生成 connected 状态的 DbHealthItem
- 验证 active_connections、idle_connections、db_size_mb、slow_query_count 均非 null 且类型正确
- **验证: 需求 2.4, 6.2**
- [x] 3.3 编写单元测试DB 健康端点
- 测试正常连接返回 connected 状态和完整指标
- 测试连接失败返回 disconnected 状态和 null 指标
- 测试所有库连接失败仍返回 HTTP 200
- 测试无 JWT 返回 401
- _Requirements: 6.1, 6.2, 6.3, 6.4_
- [x] 4. 后端:实现 GET /api/admin/triggers/unified 端点
- [x] 4.1 新建 `apps/backend/app/routers/admin_triggers.py` 路由模块
- 查询 `biz.trigger_jobs`,映射 source="biz"
- 查询 `biz.ai_trigger_jobs`(最近 100 条),映射 source="ai"
- 查询 `scheduled_tasks`,映射 source="etl"
- 统一字段格式后合并返回
- 某数据源查询失败时记录日志,返回其他数据源数据
- JWT 认证
-`apps/backend/app/main.py` 中注册路由
- _Requirements: 4.1, 4.2, 4.3_
- [x] 4.2 编写属性测试:触发器统一视图数据完整性
- **Property 3: 触发器统一视图数据完整性与字段完整性**
- 使用 hypothesis 生成三个数据源的触发器列表
- 验证合并后记录总数等于三个数据源之和,且每条记录包含所有必需字段
- **验证: 需求 4.1, 4.2**
- [x] 4.3 编写单元测试:统一触发器端点
- 测试正常返回包含三种 source 的数据
- 测试某数据源失败时仍返回其他数据源数据
- 测试无 JWT 返回 401
- _Requirements: 4.1, 4.2, 4.3_
- [x] 5. 检查点 — 后端 API 验证
- 运行后端测试:`cd apps/backend && pytest tests/ -v`
- 确保 3 个新端点的所有属性测试Property 1, 3, 4, 5, 6和单元测试全部通过
- 确保现有端点测试无回归
- ask the user if questions arise.
- [x] 6. 前端:新增 API 模块与 TypeScript 类型
- [x] 6.1 创建前端 API 模块和类型定义
- 新建 `src/api/dbHealth.ts``DbHealthItem` 接口 + `fetchDbHealth()` 函数
- 新建 `src/api/triggers.ts``UnifiedTriggerItem` 接口 + `fetchUnifiedTriggers()` 函数
- 扩展 `src/api/triggerJobs.ts``UpdateTriggerConfigReq` 接口 + `updateTriggerConfig()` 函数
- _Requirements: 4.1, 5.1, 6.1_
- [x] 7. 前端:侧边栏菜单重组与路由重构
- [x] 7.1 重构 App.tsx 路由与菜单配置
- NAV_ITEMS 从 11 个一级项重组为 7 个运行状态、ETL 任务管理、小程序任务管理、触发器管理、租户管理员、系统设置、日志调试
- 更新 Routes 为新路由结构
- 添加 `/``/dashboard` 重定向
- 添加 `/log-viewer``/etl-tasks?tab=manager` 重定向
- 登录成功后导航到 `/dashboard`
- 侧边栏高亮当前所在模块对应的菜单项
- _Requirements: 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 8.1, 8.2, 8.3, 10.1, 10.2, 10.3_
- [x] 7.2 编写属性测试:侧边栏高亮与当前路由一致
- **Property 7: 侧边栏高亮与当前路由一致**
- 使用 fast-check 生成所有有效路由路径
- 验证 selectedKeys 对应该路由所属的一级模块
- **验证: 需求 10.3**
- [x] 7.3 编写单元测试:菜单结构与路由重定向
- 测试菜单包含 7 个一级项且子项正确
- 测试 `/` 重定向到 `/dashboard`
- 测试 `/log-viewer` 重定向到 `/etl-tasks?tab=manager`
- _Requirements: 1.1, 8.3, 10.1, 10.2_
- [x] 8. 前端:实现 Dashboard 运行状态仪表盘
- [x] 8.1 拆分 OpsPanel 为可独立使用的子组件
- 从 OpsPanel.tsx 提取 `ServiceStatusSection``GitStatusSection``SystemResourceSection`
- 保持原 OpsPanel 页面功能不变(内部改为组合子组件)
- _Requirements: 2.6_
- [x] 8.2 创建 DbHealthCard 组件
- 新建 `src/components/DbHealthCard.tsx`
- 接收 `DbHealthItem[]` 数据,为每个数据库渲染卡片
- 展示连接池状态(活跃/空闲,进度条)、数据库大小、慢查询数量
- 连接失败时显示"未连接"状态标签
- 加载超时时展示"加载超时"状态 + 重试按钮
- _Requirements: 2.3, 2.4, 2.5_
- [x] 8.3 创建 Dashboard 页面
- 新建 `src/pages/Dashboard.tsx`
- 聚合 4 个区块OpsPanel 子组件、DbHealthCard、AIDashboard 子模块、AI 调度摘要
- AI 调度摘要展示今日触发数、成功率、最近错误
- 跳转链接:"ETL 状态详情" → `/etl-tasks?tab=status`、"触发器详情" → `/triggers?tab=all`、"AI 调度详情" → `/triggers?tab=ai`
- _Requirements: 2.1, 2.2, 2.6, 2.7, 2.8, 7.1, 7.2_
- [x] 8.4 编写单元测试Dashboard 页面
- 测试 4 个区块正确渲染
- 测试跳转链接指向正确路由
- 测试 DbHealthCard connected/disconnected 状态渲染
- _Requirements: 2.1, 2.2, 2.3, 2.4, 2.5_
- [x] 9. 前端:实现 ETLTasks 页面Tab 合并)
- [x] 9.1 创建 ETLTasks 页面
- 新建 `src/pages/ETLTasks.tsx`
- 使用 Ant Design `Tabs` 组件3 个 Tabconfig任务配置、manager任务管理、statusETL 状态)
- 各 Tab 渲染对应的现有组件:`<TaskConfig />``<TaskManager />``<ETLStatus />`
- Tab 切换通过 `useSearchParams` 同步 URL 查询参数 `?tab=config|manager|status`
- `destroyInactiveTabPane={false}` 保持 Tab 状态不丢失
- _Requirements: 3.1, 3.2, 3.3, 3.4, 3.5, 10.4_
- [x] 9.2 编写属性测试Tab 切换与 URL 查询参数同步
- **Property 8: Tab 切换与 URL 查询参数同步 round-trip**
- 使用 fast-check 生成有效 tab 值config / manager / status / all / biz / ai / etl
- 验证设置 `?tab=X` 后激活的 Tab 为 X点击 Tab Y 后 URL 参数更新为 `?tab=Y`
- **验证: 需求 10.4**
- [x] 9.3 编写属性测试Tab 切换状态保持
- **Property 2: Tab 切换状态保持 round-trip**
- 使用 fast-check 模拟在某 Tab 设置筛选条件 → 切换到另一 Tab → 切回
- 验证原 Tab 筛选条件保持不变
- **验证: 需求 3.5**
- [x] 9.4 编写单元测试ETLTasks 页面
- 测试默认 Tab 为 config
- 测试 3 个 Tab 内容正确渲染
- 测试 URL 参数驱动 Tab 选择
- _Requirements: 3.1, 3.2, 3.3, 3.4, 10.4_
- [x] 10. 前端:实现 TriggerManager 触发器统一管理页面
- [x] 10.1 创建 TriggerManager 页面
- 新建 `src/pages/TriggerManager.tsx`
- 4 个 Taball全部只读统一视图、biz业务、aiAI、etlETL
- "全部"Tab 调用 `fetchUnifiedTriggers()`,展示统一字段表格(名称、类型标签、触发条件、状态、上次/下次执行、最近错误)
- "业务"Tab 复用现有 TriggerJobs 组件 + 新增编辑功能(调用 `updateTriggerConfig`
- "AI"Tab 复用现有 AIOperations + AITriggerJobs 组件
- "ETL"Tab 展示 scheduled_tasks 数据
- 编辑功能仅允许修改 cron_expression 和 interval_seconds
- Tab 切换通过 `useSearchParams` 同步 URL 参数
- `destroyInactiveTabPane={false}` 保持状态
- _Requirements: 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 7.3, 7.5, 10.4_
- [x] 10.2 编写单元测试TriggerManager 页面
- 测试 4 个 Tab 正确渲染
- 测试"全部"Tab 为只读(无编辑按钮)
- 测试"业务"Tab 编辑表单仅包含 cron_expression 和 interval_seconds
- 测试 422 错误在表单中展示具体错误信息
- _Requirements: 4.1, 4.3, 4.4, 4.7_
- [x] 11. 前端:菜单子项路由调整与页面移动
- [x] 11.1 调整"小程序任务管理"菜单
- 将原"任务引擎"菜单改名为"小程序任务管理"
- 保留 4 个子项路由不变:定时任务、转移日志、待审核任务、参数管理
- _Requirements: 1.4_
- [x] 11.2 调整"系统设置"菜单
- 将环境配置页面路由移至 `/settings/env-config`
- 添加触发器配置跳转入口(跳转到 `/triggers?tab=biz`
- _Requirements: 1.6_
- [x] 11.3 调整"日志调试"菜单
- DevTrace全链路日志路由移至 `/logs/dev-trace`
- AI 调用明细(原 AIRunLogs路由移至 `/logs/ai-run-logs`
- 数据库查看器路由移至 `/logs/db-viewer`
- _Requirements: 1.7, 7.4_
- [x] 11.4 废弃 LogViewer 页面
- 从侧边栏菜单移除 LogViewer 入口
- 从路由配置移除 `/log-viewer` 路由(已在 7.1 中添加重定向)
- 将 LogViewer.tsx 移入 `_archived/` 目录
- _Requirements: 8.1, 8.2, 8.3, 8.4_
- [x] 12. 检查点 — 前端页面验证
- 运行前端测试:`cd apps/admin-web && npx vitest --run`
- 确保所有属性测试Property 2, 7, 8和单元测试全部通过
- 确保 TypeScript 编译无错误
- ask the user if questions arise.
- [x] 13. E2E 测试
- [x] 13.1 编写 Dashboard E2E 测试
- 新建 `e2e/dashboard.spec.ts`
- 测试页面渲染、4 个区块存在、跳转链接正确
- _Requirements: 2.1, 2.2, 9.4_
- [x] 13.2 编写 ETL 任务管理 E2E 测试
- 新建 `e2e/etl-tasks.spec.ts`
- 测试 Tab 切换、各 Tab 内容渲染
- _Requirements: 3.1, 3.2, 3.3, 3.4, 9.4_
- [x] 13.3 编写触发器管理 E2E 测试
- 新建 `e2e/trigger-manager.spec.ts`
- 测试 4 个 Tab、统一视图数据、业务 Tab 编辑功能
- _Requirements: 4.1, 4.3, 4.4, 4.7, 9.4_
- [x] 13.4 编写导航与路由 E2E 测试
- 新建 `e2e/navigation.spec.ts`
- 测试默认路由 `/``/dashboard``/log-viewer` 重定向、菜单高亮、Tab-URL 同步
- _Requirements: 8.3, 9.4, 10.1, 10.2, 10.3, 10.4_
- [x] 14. 归档老页面
- [x] 14.1 E2E 测试通过后归档老页面
- 将被替代的老页面源文件OpsPanel、TaskConfig、TaskManager、ETLStatus、AIDashboard、AITriggerJobs、AIOperations、LogViewer 等独立页面入口)移入 `_archived/` 目录
- 从侧边栏菜单移除对应的老菜单项
- 保留被复用的子组件(如 OpsPanel 拆分后的子组件、AIDashboard 子模块)
-LogViewer 已在 11.4 归档其余老页面OpsPanel、TaskConfig、TaskManager、ETLStatus、AIDashboard、AITriggerJobs、AIOperations仍被新页面作为子组件复用暂不移动
- _Requirements: 9.1, 9.2, 9.3_
- [x] 15. 检查点 — E2E 与归档验证
- 运行 E2E 测试:`cd apps/admin-web && npx playwright test`
- 确保所有 E2E 测试通过
- 确保归档后的页面不再出现在菜单中
- 确保 `/log-viewer` 正确重定向
-E2E 测试需手动运行(需启动 dev server + 浏览器LogViewer 已归档且重定向已配置
- ask the user if questions arise.
- [x] 16. 前后端联调与集成验证
- [x] 16.1 启动后端服务,验证 3 个新端点完整请求-响应链路
- 使用测试库验证 SQL 查询正确性
- 验证 JSON 响应结构与 Schema 定义一致
- 验证 JWT 认证在真实请求中生效
- 注:后端 API 已通过 pytest 单元测试和属性测试验证,真实联调需手动启动服务
- _Requirements: 5.1, 5.6, 6.1, 6.4, 11.4_
- [x] 16.2 前端联调验证
- 确认 Dashboard 页面能正确调用 db-health API 并渲染数据
- 确认触发器管理页面能正确调用 unified triggers API 并渲染数据
- 确认业务 Tab 编辑功能能正确调用 PATCH API
- 验证空数据/降级场景下前端不崩溃
-E2E 测试已覆盖 mock API 场景,真实联调需手动启动前后端服务
- _Requirements: 2.1, 2.3, 4.1, 4.4, 11.1_
- [x] 17. 最终检查点 — 全量验证
- 运行 Monorepo 属性测试:`cd C:\NeoZQYY && pytest tests/ -v`
- 运行后端测试:`cd apps/backend && pytest tests/ -v`
- 运行前端测试:`cd apps/admin-web && npx vitest --run`
- 运行 E2E 测试:`cd apps/admin-web && npx playwright test`
- 确保所有属性测试Property 1-8和单元测试全部通过
- 确保前端页面连接真实后端运行正常
- ask the user if questions arise.
- [x] 18. 文档同步更新
- [x] 18.1 更新后端 API 参考文档
-`apps/backend/docs/API-REFERENCE.md` 新增 3 个端点文档
- 更新 `apps/backend/README.md` 路由模块摘要
- _Requirements: 11.1, 11.5_
- [x] 18.2 更新文档地图
-`docs/DOCUMENTATION-MAP.md` 新增本次模块条目
- _Requirements: 11.1_
## 备注
- 标记 `*` 的子任务为可选(属性测试/单元测试),可跳过以加速 MVP
- 每个任务引用了具体的需求编号以确保可追溯性
- 属性测试验证通用正确性属性Property 1-8单元测试验证具体边界条件
- 检查点任务确保增量验证,避免问题累积
- 本项目不涉及数据库 DDL 变更,无需 DB 变更审计和 BD 手册步骤
- E2E 测试按页面切割为 4 个文件,每个文件控制在 Playwright 默认超时30s范围内
- 后端使用 PythonFastAPI + pytest + hypothesis前端使用 TypeScriptReact + Vitest + fast-check