docs: 5 份实施计划 — 性能/安全/事件/前端/可观测性
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled

对应 5 份设计规格,共 75 个 Task:

1. 性能优化 (12 Task) — 批量INSERT/N+1内联name/合并COUNT/按需重绘/chunk拆分
2. 安全纵深防御 (8 Task) — RLS/行级数据范围/Redis session_key/审计哈希链
3. 事件驱动架构 (10 Task) — 11个缺失事件补发/LISTEN+NOTIFY/schema版本化
4. 前端工程化 (10 Task) — hook统一/组件拆分/Bundle优化
5. 可观测性运维 (10 Task) — 深度健康检查/Prometheus/OTel/生产Docker/告警
This commit is contained in:
iven
2026-04-27 08:00:50 +08:00
parent 215fb35e0e
commit b410fa9f78
5 changed files with 809 additions and 0 deletions

View File

@@ -0,0 +1,124 @@
# 性能优化实施计划
> 设计规格: `docs/superpowers/specs/2026-04-26-performance-optimization-design.md`
> 日期: 2026-04-26 | 状态: draft | 总周期: 3 周
---
## Phase 1: 后端批量插入优化Week 1, P0
### Task 1: device_reading_service batch_insert_readings 改为 SeaORM insert_many
**涉及文件**: `crates/erp-health/src/service/device_reading_service.rs`
**步骤**: 将 `batch_insert_readings()` 中 for 循环逐条 `model.insert(db).await` 替换为构建 `Vec<ActiveModel>` 后调用 `insert_many()` + `on_conflict(columns([...]).do_nothing())`。补充 50 条模拟数据的批量插入测试。
**验收**: `cargo test -p erp-health device_reading` 通过500 条插入延迟 < 100ms。
### Task 2: device_reading_service upsert_hourly_aggregates 批量化
**涉及文件**: `crates/erp-health/src/service/device_reading_service.rs`
**步骤**: 批量查出已存在的聚合记录(按 patient_id + device_type + hour分为"新增"和"更新"两组,分别 `insert_many` 和批量 `update`,事务包装。补充同一小时多次 upsert 的聚合精度测试。
**验收**: 聚合值avg/min/max精度与优化前一致`cargo test` 通过。
---
## Phase 2: 前端 N+1 根治Week 2, P0
### Task 3: 后端 appointment_service list 返回 patient_name/doctor_name
**涉及文件**: `crates/erp-health/src/service/appointment_service.rs`, `dto/mod.rs`, `handler/mod.rs`
**步骤**: 列表 DTO 增加 `patient_name/doctor_name` 字段service 查询中 `find_also_related` 或子查询关联 users 表获取 display_namehandler 层映射到响应 DTO。保持 Option 类型向后兼容。
**验收**: `GET /api/v1/health/appointments` 每条记录含 name 字段。
### Task 4: 后端 consultation_service / follow_up_service 同样内联 name
**涉及文件**: `consultation_service.rs`, `follow_up_service.rs`, `dto/mod.rs`
**步骤**: consultation list 添加 patient_name/doctor_namefollow_up list 添加 patient_name复用 Task 3 的 JOIN 模式。
**验收**: 两个列表 API 响应均含 name 字段;`cargo test` 通过。
### Task 5: 前端 AppointmentList 移除 nameCache改用内联字段
**涉及文件**: `apps/web/src/pages/health/AppointmentList.tsx`
**步骤**: 移除 `nameCache` useState 及逐条请求 name 的 useEffect表格列直接使用后端返回的 `patient_name/doctor_name`,消除 fetchData 对 nameCache 的依赖。
**验收**: Network 面板仅 1 个列表 API 请求;首屏 < 500ms20 条记录)。
### Task 6: 前端 ConsultationList / FollowUpTaskList 同样改造
**涉及文件**: `ConsultationList.tsx`, `FollowUpTaskList.tsx`
**步骤**: 两个页面移除 nameCache使用内联 name 字段。验证无 N+1 请求。
**验收**: 两个页面 Network 面板无 N+1 请求;`pnpm build` 通过。
---
## Phase 3: 后端查询优化Week 3, P1
### Task 7: stats_service 合并多次 COUNT 为 GROUP BY
**涉及文件**: `crates/erp-health/src/service/stats_service.rs`
**步骤**: 6 个统计函数从多次 COUNT 合并为 `SELECT status, COUNT(*) GROUP BY status` + 应用层 HashMap 聚合。`compute_avg_field` 用宏生成静态 SQL 常量替代 `format!` 拼接。编写对比测试确认 GROUP BY 与多次 COUNT 结果一致。
**验收**: `get_follow_up_statistics` 查询次数从 4 降为 1`compute_avg_field` 不再 format! 拼接。
### Task 8: patient_service get_health_summary 用 tokio::join! 并行化
**涉及文件**: `crates/erp-health/src/service/patient_service.rs`
**步骤**: `get_health_summary()` 中 4 次 `.await` 改为 `tokio::join!` 并行执行,各查询错误独立处理(未找到返回 None
**验收**: 并行化后返回数据与串行一致;`cargo test` 通过。
### Task 9: alert_engine 预加载规则批量评估
**涉及文件**: `crates/erp-health/src/service/alert_engine.rs`
**步骤**: 批量查询患者最近 cooldown 期间所有 alerts 构建 `HashSet<rule_id>`,按 device_type 批量查最新 hourly 记录后在内存匹配规则条件。重构为:批量加载 -> 内存过滤 -> 批量生成告警。
**验收**: 10 条规则评估查询次数从 ~20 降为 2-3`cargo test` 通过。
---
## Phase 4: 前端渲染优化Week 3, P2
### Task 10: PluginCRUDPage columns useMemo + 拆分子组件
**涉及文件**: `apps/web/src/pages/PluginCRUDPage.tsx`
**步骤**: `columns` 包裹 `useMemo(() => [...], [schema])`,搜索栏/分页/表格拆为独立子组件。
**验收**: 输入搜索时 columns 不重建;`pnpm build` 通过。
### Task 11: PluginGraphPage 按需重绘
**涉及文件**: `apps/web/src/pages/PluginGraphPage.tsx`
**步骤**: 移除持续 requestAnimationFrame 循环,改为数据变更 useEffect 触发单次重绘 + ResizeObserver 监听容器变化。
**验收**: 静态页面时 CPU 占用 < 1%`pnpm build` 通过。
### Task 12: vite.config.ts manualChunks 拆分 heavy deps
**涉及文件**: `apps/web/vite.config.ts`
**步骤**: `manualChunks` 配置 `vendor-charts`(@ant-design/charts) / `vendor-flow`(@xyflow/react) / `vendor-editor`(@wangeditor/editor),对应路由改用 `React.lazy` 动态加载。
**验收**: 主 bundle gzip 体积降低 200KB+;图表/流程图/编辑器按需加载。
---
## 执行原则
1. **每 Task 完成后立即提交** — 不积压,保持可追溯
2. **Phase 1-2 为 P0** — 批量插入和 N+1 根治直接影响生产性能
3. **cargo test + pnpm build 必须通过** — 每个 Task 完成后验证