Files
Neo-ZQYY/.kiro/specs/admin-web-console/tasks.md

293 lines
14 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.
# 实现计划Web 管理后台admin-web-console
## 概述
将现有 PySide6 桌面 GUI 替换为 BS 架构的 Web 管理后台。后端在 `apps/backend/` 上扩展 FastAPI API前端在 `apps/admin-web/` 下使用 React + Vite + Ant Design 构建。实现按"后端基础设施 → 核心 API → 前端骨架 → 功能模块逐个对接"的顺序推进。
## 任务
- [x] 1. 后端基础设施搭建
- [x] 1.1 创建数据库迁移脚本,在 `zqyy_app` 库中创建 4 张新表admin_users、task_queue、task_execution_log、scheduled_tasks所有表包含 site_id 字段
- 迁移脚本放在 `db/zqyy_app/migrations/`,日期前缀命名
- 包含索引创建site_id 相关的复合索引)
- 包含种子数据:插入一个默认管理员账号
- _Requirements: 1.1, 4.1, 5.1_
- [x] 1.2 实现 JWT 认证模块(`apps/backend/app/auth/`
- `jwt.py`JWT 令牌生成access_token + refresh_token、验证、解码payload 包含 user_id 和 site_id
- `dependencies.py`FastAPI 依赖注入函数 `get_current_user`,从 JWT 提取用户信息和 site_id
- 新增依赖:`python-jose[cryptography]``passlib[bcrypt]``apps/backend/pyproject.toml`
- _Requirements: 1.1, 1.2, 1.3, 1.4_
- [x] 1.3 实现认证路由(`apps/backend/app/routers/auth.py`
- `POST /api/auth/login`:验证用户名密码,返回 JWT 令牌对
- `POST /api/auth/refresh`:用刷新令牌换取新的访问令牌
- Pydantic schemas`LoginRequest``TokenResponse`
- _Requirements: 1.1, 1.2, 1.4_
- [x] 1.4 编写认证模块属性测试
- **Property 2: 无效凭据始终被拒绝**
- **Property 3: 有效 JWT 令牌授权访问**
- **Validates: Requirements 1.2, 1.3**
- [x] 1.5 扩展 `apps/backend/app/database.py`,新增 ETL 数据库只读连接函数
- `get_etl_readonly_connection(site_id)`:连接 ETL 数据库,设置 `SET LOCAL app.current_site_id`
- 配置项从 .env 读取 ETL 数据库连接参数
- _Requirements: 7.4, 7.5_
- [x] 1.6 在 `apps/backend/app/main.py` 中注册所有路由和中间件,配置 CORS 允许前端开发服务器访问
- _Requirements: 10.2_
- [x] 2. 检查点 — 确保认证模块测试通过
- 确保所有测试通过,如有问题请向用户确认。
- [x] 3. 任务配置与执行 API
- [x] 3.1 迁移 CLIBuilder 到后端(`apps/backend/app/services/cli_builder.py`
-`gui/utils/cli_builder.py` 迁移核心逻辑
- 适配新的 TaskConfigSchema自动注入 `--store-id` 参数
- 支持 7 种 Flow 和 4 种处理模式
- _Requirements: 2.6_
- [x] 3.2 实现任务注册表 API`apps/backend/app/routers/tasks.py`
- `GET /api/tasks/registry`:返回按业务域分组的任务列表
- `GET /api/tasks/dwd-tables`:返回按业务域分组的 DWD 表定义
- `GET /api/tasks/flows`:返回 7 种 Flow 定义和 4 种处理模式定义
- `POST /api/tasks/validate`:验证 TaskConfig 并返回生成的 CLI 命令预览
- Pydantic schemas 在 `apps/backend/app/schemas/tasks.py`
- _Requirements: 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 11.1, 11.2_
- [x] 3.3 编写 TaskConfig 属性测试
- **Property 1: TaskConfig 序列化往返一致性**
- **Property 6: 时间窗口验证**
- **Property 7: TaskConfig 到 CLI 命令转换完整性**
- **Validates: Requirements 2.3, 2.5, 2.6, 11.1, 11.2, 11.3**
- [x] 3.4 实现 TaskExecutor 服务(`apps/backend/app/services/task_executor.py`
- 使用 `asyncio.create_subprocess_exec` 启动 ETL_CLI 子进程
- 逐行读取 stdout/stderr存储到内存缓冲区并广播到 WebSocket
- 记录退出码、执行时长到 task_execution_log 表
- 支持取消(发送 SIGTERM
- _Requirements: 3.1, 3.2, 3.3, 3.4, 3.5_
- [x] 3.5 实现 TaskQueue 服务(`apps/backend/app/services/task_queue.py`
- `enqueue(config, site_id)`:入队,自动分配 position
- `dequeue(site_id)`:取出 position 最小的 pending 任务
- `reorder(task_id, new_position, site_id)`:调整顺序
- `delete(task_id, site_id)`:删除 pending 任务
- `process_loop()`:后台协程,自动取出并执行
- _Requirements: 4.1, 4.2, 4.3, 4.4_
- [x] 3.6 实现执行与队列路由(`apps/backend/app/routers/execution.py`
- `POST /api/execution/run`:直接执行任务
- `GET /api/execution/queue`:获取当前队列(按 site_id 过滤)
- `POST /api/execution/queue`:添加到队列
- `PUT /api/execution/queue/reorder`:重排
- `DELETE /api/execution/queue/{id}`:删除
- `POST /api/execution/{id}/cancel`:取消
- `GET /api/execution/history`:执行历史(按 site_id 过滤limit 参数)
- `GET /api/execution/{id}/logs`:获取历史日志
- _Requirements: 3.1, 3.5, 4.1, 4.2, 4.3, 4.4, 4.5_
- [x] 3.7 编写队列属性测试
- **Property 8: 队列 CRUD 不变量**
- **Property 9: 队列出队顺序**
- **Property 10: 队列重排一致性**
- **Property 11: 执行历史排序与限制**
- **Validates: Requirements 4.1, 4.2, 4.3, 4.4, 4.5, 8.2**
- [x] 4. 检查点 — 确保任务配置与执行 API 测试通过
- 确保所有测试通过,如有问题请向用户确认。
- [x] 5. 调度与辅助 API
- [x] 5.1 实现 Scheduler 服务(`apps/backend/app/services/scheduler.py`
- `check_and_enqueue()`:查询 enabled=true 且 next_run_at <= now 的调度任务,将其 TaskConfig 入队
- `start()`:启动后台 asyncio 循环,每 30 秒检查一次
- 在 FastAPI lifespan 中启动/停止
- _Requirements: 5.2_
- [x] 5.2 实现调度路由(`apps/backend/app/routers/schedules.py`
- `GET /api/schedules`:列表(按 site_id 过滤)
- `POST /api/schedules`:创建
- `PUT /api/schedules/{id}`:更新
- `DELETE /api/schedules/{id}`:删除
- `PATCH /api/schedules/{id}/toggle`:启用/禁用
- Pydantic schemas 在 `apps/backend/app/schemas/schedules.py`
- _Requirements: 5.1, 5.3, 5.4, 5.5, 5.6_
- [x] 5.3 编写调度属性测试
- **Property 12: 调度任务 CRUD 往返**
- **Property 13: 到期调度任务自动入队**
- **Property 14: 调度任务启用/禁用状态**
- **Validates: Requirements 5.1, 5.2, 5.3, 5.4**
- [x] 5.4 实现环境配置路由(`apps/backend/app/routers/env_config.py`
- `GET /api/env-config`:读取 .env敏感值掩码
- `PUT /api/env-config`:验证并写入 .env
- `GET /api/env-config/export`:导出去敏感值的配置文件
- 敏感键列表PASSWORD、TOKEN、SECRET、DSN
- _Requirements: 6.1, 6.2, 6.3, 6.4_
- [x] 5.5 编写环境配置属性测试
- **Property 15: .env 解析与敏感值掩码**
- **Property 16: .env 写入往返一致性**
- **Validates: Requirements 6.1, 6.2, 6.3**
- [x] 5.6 实现数据库查看器路由(`apps/backend/app/routers/db_viewer.py`
- `GET /api/db/schemas`:返回 Schema 列表
- `GET /api/db/schemas/{name}/tables`:返回表列表和行数
- `GET /api/db/tables/{schema}/{table}/columns`:返回列定义
- `POST /api/db/query`:只读 SQL 执行写操作拦截、1000 行限制、30 秒超时)
- 使用 `get_etl_readonly_connection(site_id)` 确保 RLS 隔离
- _Requirements: 7.1, 7.2, 7.3, 7.4, 7.5, 7.6_
- [x] 5.7 编写数据库查看器属性测试
- **Property 17: SQL 写操作拦截**
- **Property 18: SQL 查询结果行数限制**
- **Validates: Requirements 7.4, 7.5**
- [x] 5.8 实现 ETL 状态路由(`apps/backend/app/routers/etl_status.py`
- `GET /api/etl-status/cursors`:查询 etl_admin.etl_cursor 表,返回各任务游标
- `GET /api/etl-status/recent-runs`:查询 task_execution_log 表,返回最近 50 条记录
- _Requirements: 8.1, 8.2, 8.3_
- [x] 5.9 实现 WebSocket 日志推送(`apps/backend/app/ws/logs.py`
- `WS /ws/logs/{execution_id}`:实时推送任务执行日志
- TaskExecutor 执行时广播日志行到已连接的 WebSocket 客户端
- _Requirements: 9.1, 9.4_
- [x] 6. 检查点 — 确保所有后端 API 测试通过
- 确保所有测试通过,如有问题请向用户确认。
- [x] 7. 前端项目初始化
- [x] 7.1 在 `apps/admin-web/` 下初始化 React + Vite + TypeScript 项目
- `pnpm create vite . --template react-ts`
- 安装核心依赖:`antd``@ant-design/icons``react-router-dom``axios``zustand`
- 配置 `vite.config.ts`API 代理到后端 `http://localhost:8000`
- 配置中文 localeantd ConfigProvider
- _Requirements: 10.1, 10.2_
- [x] 7.2 实现 API 客户端(`src/api/client.ts`
- 创建 axios 实例baseURL 指向 `/api`
- 请求拦截器:自动附加 JWT Authorization header
- 响应拦截器401 时尝试刷新令牌,刷新失败跳转登录页
- _Requirements: 1.3, 1.4, 1.5_
- [x] 7.3 实现认证状态管理(`src/store/authStore.ts`)和登录页(`src/pages/Login.tsx`
- Zustand store存储 token、user info、site_id
- 登录页Ant Design Form用户名 + 密码
- 登录成功后存储令牌到 localStorage 并跳转首页
- _Requirements: 1.1, 1.2_
- [x] 7.4 实现主布局(`src/App.tsx`)和路由配置
- Ant Design LayoutSider侧边栏导航+ Content + Footer状态栏
- react-router-dom6 个功能页面路由 + 登录页路由
- 路由守卫:未登录重定向到登录页
- 侧边栏导航项任务配置、任务管理、环境配置、数据库、ETL 状态、日志
- _Requirements: 10.1, 10.2, 10.3_
- [x] 8. 前端功能页面 — 任务配置
- [x] 8.1 实现任务配置页面(`src/pages/TaskConfig.tsx`
- Flow 选择器Radio Group7 种 Flow选择后动态显示/隐藏任务区域
- 处理模式选择器3 种模式 + 校验附加选项
- 时间窗口配置回溯模式lookback_hours + overlap_seconds/ 自定义模式DatePicker
- 窗口切分选项:不切分 / 按天1/10/30
- 高级选项折叠面板dry-run、force-full 等 Checkbox
- _Requirements: 2.2, 2.3, 2.5_
- [x] 8.2 实现 TaskSelector 组件(`src/components/TaskSelector.tsx`
-`/api/tasks/registry` 获取任务列表
- 按业务域分组展示Collapse + Checkbox Group
- 根据当前 Flow 包含的层过滤可见任务
- 全选/反选功能
- _Requirements: 2.1, 2.2_
- [x] 8.3 实现 DwdTableSelector 组件(`src/components/DwdTableSelector.tsx`
-`/api/tasks/dwd-tables` 获取 DWD 表定义
- 按业务域分组展示Collapse + Checkbox Group
- 仅在 Flow 包含 DWD 层时显示
- _Requirements: 2.4_
- [x] 8.4 实现任务提交和 CLI 命令预览
- 提交前调用 `/api/tasks/validate` 预览生成的 CLI 命令
- 提交到队列(`/api/execution/queue`)或直接执行(`/api/execution/run`
- 提交成功后跳转到任务管理页面
- _Requirements: 2.6, 3.1, 4.1_
- [x] 8.5 编写 Flow 层级过滤前端单元测试
- **Property 21: Flow 层级与任务兼容性**
- 使用 Vitest 测试过滤逻辑函数
- **Validates: Requirements 2.2**
- [x] 9. 前端功能页面 — 任务管理
- [x] 9.1 实现任务管理页面(`src/pages/TaskManager.tsx`
- Ant Design Tabs队列 + 调度 + 历史
- 队列 TabTable 展示当前队列,支持拖拽排序、删除、取消
- 历史 TabTable 展示执行历史,点击行查看详情和日志
- _Requirements: 4.1, 4.2, 4.3, 4.4, 4.5_
- [x] 9.2 实现调度管理 Tab
- 调度任务列表 Table名称、调度描述、启用状态 Switch、下次执行时间、执行次数
- 创建/编辑调度任务 Modal任务选择 + 调度配置(类型、间隔、时间等)
- 删除确认
- _Requirements: 5.1, 5.3, 5.4, 5.5, 5.6_
- [x] 9.3 实现状态栏任务执行指示
- 在 Layout Footer 或 Sider 底部显示当前执行状态
- 轮询 `/api/execution/queue` 检查是否有 running 状态的任务
- 有任务执行时显示 Spin 动画和任务名称
- _Requirements: 10.3, 10.4_
- [x] 10. 前端功能页面 — 辅助模块
- [x] 10.1 实现环境配置页面(`src/pages/EnvConfig.tsx`
- 键值对编辑表格Ant Design Tableeditable cells
- 敏感值显示为 `****`,编辑时可输入新值
- 保存按钮调用 `PUT /api/env-config`
- 导出按钮调用 `GET /api/env-config/export` 下载文件
- _Requirements: 6.1, 6.2, 6.3, 6.4_
- [x] 10.2 实现数据库查看器页面(`src/pages/DBViewer.tsx`
- 左侧 TreeSchema → Table 层级浏览
- 右侧上方SQL 编辑器Ant Design Input.TextArea 或集成 CodeMirror
- 右侧下方:查询结果 Table
- 选择表时自动展示列定义
- 执行查询按钮,结果分页展示
- _Requirements: 7.1, 7.2, 7.3, 7.4_
- [x] 10.3 实现 ETL 状态页面(`src/pages/ETLStatus.tsx`
- 游标状态 Table任务编码、最后抓取时间、记录数
- 最近执行记录 Table任务名称、状态 Tag、开始时间、执行时长
- 刷新按钮
- _Requirements: 8.1, 8.2, 8.3_
- [x] 10.4 实现日志查看器页面(`src/pages/LogViewer.tsx`)和 LogStream 组件
- WebSocket 连接 `/ws/logs/{execution_id}`,实时追加日志行
- 日志过滤输入框:按关键词过滤显示
- 自动滚动到底部,可手动暂停滚动
- 历史日志:从 `/api/execution/{id}/logs` 加载
- _Requirements: 9.1, 9.2, 9.3, 9.4_
- [x] 10.5 编写日志过滤前端单元测试
- **Property 19: 日志过滤正确性**
- 使用 Vitest 测试过滤函数
- **Validates: Requirements 9.2**
- [x] 11. 门店隔离集成验证
- [x] 11.1 编写门店隔离属性测试
- **Property 20: 门店隔离 — 队列和调度数据不跨站泄露**
- 使用 pytest + hypothesis 生成随机 site_id 对,验证数据隔离
- **Validates: Requirements 1.3**
- [x] 11.2 编写任务注册表分组属性测试
- **Property 4: 任务注册表按业务域正确分组**
- **Validates: Requirements 2.1**
- [x] 12. 最终检查点 — 确保所有测试通过 ✅
- 后端 302 passed / 0 failed前端 33 passed / 0 failed全部通过。
## 说明
- 标记 `*` 的子任务为可选测试任务,可跳过以加速 MVP
- 每个任务引用了具体的需求编号,确保可追溯
- 检查点用于阶段性验证,确保增量正确
- 属性测试验证通用正确性属性,单元测试覆盖具体示例和边界条件