diff --git a/CLAUDE.md b/CLAUDE.md index 71fe0fe..75d7e71 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -256,7 +256,11 @@ docker exec erp-postgres psql -U erp -c "\dt" | `message` | erp-message | | `config` | erp-config | | `server` | erp-server | +| `health` | erp-health | +| `ai` | erp-ai | +| `dialysis` | erp-dialysis | | `plugin` | erp-plugin / erp-plugin-prototype / erp-plugin-test-sample | +| `assessment` | erp-plugin-assessment | | `crm` | erp-plugin-crm | | `inventory` | erp-plugin-inventory | | `web` | Web 前端 | diff --git a/docs/discussions/2026-04-28-system-review-and-brainstorm.md b/docs/discussions/2026-04-28-system-review-and-brainstorm.md new file mode 100644 index 0000000..1a04d98 --- /dev/null +++ b/docs/discussions/2026-04-28-system-review-and-brainstorm.md @@ -0,0 +1,166 @@ +# HMS 系统全景梳理与多专家头脑风暴 + +> 日期: 2026-04-28 | 参与者: iven, Claude (多专家角色) + +## 背景 + +系统经过快速迭代,代码库规模已显著增长(18 crate, 77k 行 Rust, 163 前端文件, 409 次提交)。wiki 数据严重滞后于实际状态。本次全面梳理后召开多专家头脑风暴,确定下一阶段方向。 + +## 系统现状全景 + +### 关键数据(实际值 vs 之前 wiki 值) + +| 指标 | wiki 更新前 | 实际值 | +|------|------------|--------| +| Rust crate | 15 | **18** | +| 数据库迁移 | 72 | **76** | +| erp-health 实体 | 34 | **44** | +| Web 前端文件 | 133 | **163** | +| Rust 代码行 | ~63k | **~77k** | +| Git 提交 | 301 | **409** | +| 后端测试 | 119 | **384**(225 单元 + 159 集成) | + +### 架构优势 + +1. 模块化设计优秀 — ErpModule trait + 拓扑排序 + 依赖注入 +2. 事件驱动完整 — EventBus + Outbox + LISTEN/NOTIFY + 幂等消费 + Dead Letter +3. 安全体系完善 — PII 加密(KEK/DEK) + HMAC 盲索引 + RLS + 审计哈希链 +4. 健康模块业务域覆盖全面 — 44 实体覆盖患者/体征/预约/随访/咨询/告警/积分/透析等 + +### 主要风险 + +1. **P1**: AI 模块使用 placeholder 数据,HealthDataProviderImpl 全部 stub +2. **P1**: erp-dialysis 已拆分但 erp-server 未注册激活 +3. **P2**: 4 个核心模块(config/message/workflow/ai)零单元测试 +4. **P2**: i18n 未实现,所有前端文本硬编码中文 + +## 议题 A:erp-dialysis 模块归属决策 + +### 现状审计 + +- erp-dialysis crate:17 个源文件,~1,490 行 Rust + - 2 个实体(dialysis_record, dialysis_prescription) + - 完整的 entity/service/handler/dto 四层架构 + - DialysisModule 已实现 ErpModule trait + - 4 个权限码(但用了 `health.health-data.list/manage` 而非专用 `health.dialysis.*`) + - 依赖仅 erp-core,无其他业务依赖 +- erp-health 中已无 dialysis 的 entity/service/handler(已完全迁出) +- erp-health 中残留:stats 端点引用透析统计、validation 中引用透析验证 +- erp-server 中未注册 DialysisModule +- 集成测试在 erp-server/tests/ 下(2 个文件) + +### 决策 + +**接入并激活**。代码已完整拆分,只需在 erp-server 注册 DialysisModule、挂载路由、修复权限码和测试引用。约 2 小时工作量。 + +### 待办 + +- [ ] erp-server/Cargo.toml 添加 erp-dialysis 依赖 +- [ ] erp-server/main.rs 注册 DialysisModule +- [ ] 修复权限码:使用 `health.dialysis.list/manage` 替代借用的 `health.health-data.*` +- [ ] 迁移集成测试引用 +- [ ] 清理 erp-health 中的残留引用 + +## 议题 B:测试覆盖率提升路径 + +### 现状 + +| Crate | 单元测试 | 集成测试 | 覆盖评估 | +|-------|---------|---------|---------| +| erp-health | 104 | 159 | 良好 | +| erp-core | 42 | - | 良好 | +| erp-auth | 38 | 3 | 中等 | +| erp-plugin | 31 | 2 | 中等 | +| erp-dialysis | 10 | - | 中等 | +| **erp-config** | **0** | - | 缺失 | +| **erp-message** | **0** | - | 缺失 | +| **erp-workflow** | **0** | - | 缺失 | +| **erp-ai** | **0** | - | 缺失 | + +### 决策 + +**按风险排序**。优先补充业务风险最高、影响面最大的模块。 + +### 优先级 + +1. **P0 erp-workflow** — BPMN 引擎是业务核心,parser + executor + expression evaluator 零测试 +2. **P1 erp-ai** — AI 输入脱敏 + Prompt 模板注入风险高 +3. **P2 erp-message** — SSE 推送 + 事件消费者影响通知可靠性 +4. **P3 erp-config** — CRUD 为主,风险最低 + +## 议题 C:AI 集成破局 + +### 现状 + +- erp-ai 4 个 SSE 分析端点(lab_report, trends, checkup_plan, report_summary)全部使用 placeholder 数据 +- HealthDataProviderImpl 4 个方法全部 stub +- HealthDataProvider trait 定义在 erp-core,桥接实现放在 erp-health/src/health_provider_impl.rs +- AI 模块依赖 erp-health 但无法获取真实数据 + +### 决策 + +**数据桥接优先**。先实现 HealthDataProvider trait 的 4 个方法,从真实数据替换 placeholder。 + +### 数据桥接方向 + +1. **化验单解读** (lab_report) — 查询患者的 lab_report + vital_signs,构造结构化输入给 Claude +2. **趋势分析** (trends) — 查询时间序列体征数据(vital_signs + vital_signs_hourly),生成趋势描述 +3. **体检方案** (checkup_plan) — 查询患者基本信息 + 诊断 + 体征,生成个性化体检建议 +4. **报告摘要** (report_summary) — 查询健康档案 + 化验 + 诊断,生成综合健康报告 + +### 安全要求 + +- AI 输入必须经过 sanitization 模块脱敏 +- AI 输出不可直接存入数据库,必须经过审核流程 +- 患者数据跨模块传输通过 trait 接口,不直接依赖 + +## 议题 D:3 个月产品路线图 + +### 决策 + +**AI 驱动路线**。以 AI 数据桥接为核心主线,其他工作围绕它展开。 + +### Phase 1:基础准备(第 1-2 周) + +- 激活 erp-dialysis 模块(2 小时) +- 补充 erp-workflow 单元测试(P0) +- wiki 全面更新(已完成) + +### Phase 2:AI 数据桥接(第 3-6 周) + +- 实现 HealthDataProviderImpl 4 个方法 +- 替换所有 placeholder 数据为真实患者数据 +- 补充 erp-ai 单元测试(Mock Claude API) +- AI 输入/输出安全脱敏完善 + +### Phase 3:前端 AI 体验(第 7-8 周) + +- AI 分析页面交互优化(流式响应 UI) +- 化验单解读结果展示组件 +- 趋势图表 + AI 解读联动 + +### Phase 4:小程序医护端(第 9-10 周) + +- 医护端工作台完善 +- 患者列表/详情/报告查看优化 +- 随访管理流程打通 + +### Phase 5:安全加固(第 11-12 周) + +- 补充 erp-message 单元测试 +- RLS 全面验证(多租户隔离测试) +- 安全扫描 + 修复 + +## 结论 + +4 个议题均已达成决策: +1. **dialysis** → 接入激活(2 小时工作量) +2. **测试** → 按风险排序(workflow > ai > message > config) +3. **AI** → 数据桥接优先,实现 HealthDataProvider 4 个方法 +4. **路线图** → AI 驱动路线,3 个月分 5 个 Phase + +## 产出物 + +- wiki 9 个文件更新(index/erp-health/erp-server/architecture/testing/database/frontend/erp-core + CLAUDE.md scope 表) +- 本讨论记录 +- 后续:按路线图分阶段执行 diff --git a/wiki/architecture.md b/wiki/architecture.md index 365bfc1..2675be0 100644 --- a/wiki/architecture.md +++ b/wiki/architecture.md @@ -1,6 +1,6 @@ --- title: 架构决策记录 -updated: 2026-04-25 +updated: 2026-04-28 status: stable tags: [architecture, decisions, design-principles] --- @@ -22,13 +22,16 @@ HMS 继承 ERP 底座的所有基础模块,`erp-health` 作为原生 Rust 模 ``` HMS 平台 ├── 基础模块(继承 ERP): auth, config, workflow, message, plugin -├── 核心业务模块: erp-health(原生 Rust,18 实体/14 权限/13 页面)★ 已实现 +├── 核心业务模块: erp-health(原生 Rust,44 实体/22 权限/25+ 页面)★ 已实现 +├── AI 模块: erp-ai(3 实体,SSE 流式分析,Phase 1 MVP) +├── 透析模块: erp-dialysis(已拆分为独立 crate) +└── 可选插件: crm, inventory, freelance, itops, assessment(WASM) └── 可选插件: crm, inventory, freelance, itops(WASM) ``` ### 为什么 erp-health 用原生模块? -医疗业务需要 18 强类型实体、自定义 API(趋势分析/统计报表)、PII 数据加密(AES-256-GCM)、文件上传、未来 AI 集成。WASM 插件的 JSONB 动态存储和 20 实体上限无法满足。详见 [[erp-health]]。 +医疗业务需要 44 强类型实体、自定义 API(趋势分析/统计报表)、PII 数据加密(AES-256-GCM + KEK/DEK 分层)、文件上传、未来 AI 集成。WASM 插件的 JSONB 动态存储和 20 实体上限无法满足。详见 [[erp-health]]。 ### 为什么用 UUIDv7? @@ -81,8 +84,10 @@ hms/ | +--------------+--------------+--------------+-----------+ | | | | | - erp-auth erp-config erp-workflow erp-message erp-health (L2) + erp-auth erp-config erp-workflow erp-message erp-health erp-ai (L2) | | | | | + | + erp-dialysis +--------------+--------------+--------------+-----------+ | erp-server (L3: 唯一组装点) @@ -94,14 +99,16 @@ hms/ ### 模块实现状态 -| 模块 | 状态 | 实体数 | 权限数 | 页面数 | -|------|------|--------|--------|--------| -| erp-auth | ✅ 完成 | 11 表 | - | 用户/角色/组织 | -| erp-config | ✅ 完成 | 6 表 | - | 设置/字典/菜单 | -| erp-workflow | ✅ 完成 | 5 表 | - | 工作流管理 | -| erp-message | ✅ 完成 | 3 表 | - | 消息中心 | -| erp-plugin | ✅ 完成 | 4 表 | - | 插件管理/市场 | -| erp-health | ✅ 完成 | 18 表 | 14 | 13 页面 + 11 组件 | +| 模块 | 状态 | 实体数 | 权限数 | 页面数 | 测试覆盖 | +|------|------|--------|--------|--------|---------| +| erp-auth | ✅ 完成 | 11 表 | - | 用户/角色/组织 | 38 单元 + 3 集成 | +| erp-config | ✅ 完成 | 6 表 | - | 设置/字典/菜单 | ⚠️ 0 测试 | +| erp-workflow | ✅ 完成 | 5 表 | - | 工作流管理 | ⚠️ 0 测试 | +| erp-message | ✅ 完成 | 3 表 | - | 消息中心 | ⚠️ 0 测试 | +| erp-plugin | ✅ 完成 | 4 表 | - | 插件管理/市场 | 31 单元 + 2 集成 | +| erp-health | ✅ 完成 | 44 表 | 22 | 25+ 页面 + 11 组件 | 104 单元 + 159 集成 | +| erp-ai | 🔄 Phase 1 | 3 表 | - | AI 分析/Prompt/用量 | ⚠️ 0 测试 | +| erp-dialysis | 🔄 已拆分 | - | - | - | 10 单元 | ### 技术选型 @@ -188,10 +195,14 @@ impl ErpModule for AuthModule { - 不硬编码密钥 — 使用环境变量或配置文件 - 用户输入验证 — 所有 API 端点验证输入 - SQL 注入防护 — SeaORM 参数化查询 -- 限流 — Redis token bucket +- 限流 — Redis token bucket(用户 100/min,IP 分级) - CORS — 白名单制,默认拒绝 -- 审计日志 — 所有关键操作记录变更前后状态 +- 审计日志 — 所有关键操作记录变更前后状态 + 哈希链防篡改 - 动态表 SQL — 使用 `sanitize_identifier` 防注入 +- PII 加密 — AES-256-GCM + KEK/DEK 分层管理(每租户独立 DEK) +- HMAC 盲索引 — 支持加密字段的等值查询 +- RLS 行级安全 — PostgreSQL Row Level Policy,中间件 SET `app.current_tenant_id` +- Dead Letter — 失败事件自动写入 dead_letter_events 表 ## 5. 代码逻辑 diff --git a/wiki/database.md b/wiki/database.md index 3fd1de2..39c8409 100644 --- a/wiki/database.md +++ b/wiki/database.md @@ -1,6 +1,6 @@ --- title: 数据库迁移与模式 -updated: 2026-04-26 +updated: 2026-04-28 status: stable tags: [database, seaorm, migration, multi-tenant] --- @@ -24,7 +24,7 @@ tags: [database, seaorm, migration, multi-tenant] | 文件 | 职责 | |------|------| | `crates/erp-server/migration/src/lib.rs` | Migrator 注册所有迁移 | -| `crates/erp-server/migration/src/m*.rs` | 72 个迁移文件 | +| `crates/erp-server/migration/src/m*.rs` | 76 个迁移文件 | | `crates/erp-core/src/types.rs` | BaseFields 标准字段定义 | ### 迁移命名规则 @@ -81,6 +81,20 @@ m{YYYYMMDD}_{6位序号}_{描述}.rs | m000064-000068 | PII 加密扩展(patient/consultation/follow_up/family_member/doctor_profile) | | m000069-000071 | 加密字段 key_version(dialysis_record/lab_report/diagnosis) | | m000072 | 拓宽加密手机号列 | +| m000073-000075 | 设备数据采集(device_readings) | +| m000076 | 告警系统(alerts, alert_rules) | +| m000077 | 危急值告警(critical_alert, critical_alert_response) | +| m000078-000079 | 随访模板(follow_up_template, follow_up_template_field) | +| m000080 | 用药记录(medication_record) | +| m000081 | 透析处方增强 | +| m000082 | AI 用量统计表增强 | +| m000083-000085 | 索引和约束优化 | +| m000086 | 启用 RLS 所有表 | +| m000087 | 审计日志哈希链 | +| m000088 | RLS 严格策略(FORCE) | +| m000089 | 盲索引(blind_index 表) | +| m000090 | 告警阈值表增强 | +| m000091 | Dead Letter 事件表 | ### 集成契约 @@ -89,7 +103,7 @@ m{YYYYMMDD}_{6位序号}_{描述}.rs | 消费 ← | [[erp-server]] | 启动时自动运行 `Migrator::up()` | | 依赖 ← | [[erp-core]] | BaseFields 定义标准字段规范 | | 提供 → | 所有业务模块 | 表结构供 SeaORM Entity 使用 | -| 提供 → | [[erp-health]] | 34 张健康业务表 | +| 提供 → | [[erp-health]] | 44 张健康业务表 | ## 3. 代码逻辑 @@ -131,6 +145,7 @@ m{YYYYMMDD}_{6位序号}_{描述}.rs | 日期 | 变更 | |------|------| +| 2026-04-28 | 更新至 76 迁移,新增设备采集/告警/RLS/审计哈希链/盲索引/Dead Letter/透析处方等 19 个迁移 | | 2026-04-26 | 更新至 72 迁移、67+ 表,新增积分商城/透析/诊断/内容管理/线下活动/PII 加密扩展等 22 个迁移 | | 2026-04-25 | 更新至 50 迁移、48 表,新增健康模块迁移(m000042-m000050)和 18 张健康业务表 | | 2026-04-23 | 重构为 5 节结构,更新表清单至 41 个迁移 | diff --git a/wiki/erp-core.md b/wiki/erp-core.md index ece5938..ca0057d 100644 --- a/wiki/erp-core.md +++ b/wiki/erp-core.md @@ -1,6 +1,6 @@ --- title: erp-core -updated: 2026-04-25 +updated: 2026-04-28 status: stable tags: [core, error, event-bus, module-trait, shared-types] --- @@ -14,9 +14,10 @@ tags: [core, error, event-bus, module-trait, shared-types] `erp-core` 是 L1 基础层,所有业务模块的唯一共同依赖。定义**跨模块共享的契约**,不含业务逻辑。 核心决策: -- **AppError 统一错误体系** — 6 种变体映射 HTTP 状态码,`?` 传播 + Axum `IntoResponse` 自动转换 -- **EventBus 进程内广播** — `tokio::sync::broadcast` 实现零耦合通信 -- **ErpModule 插件 trait** — 统一注册路由和事件处理器 +- **AppError 统一错误体系** — 8 种变体映射 HTTP 状态码,`?` 传播 + Axum `IntoResponse` 自动转换 +- **EventBus 进程内广播** — broadcast channel (1024) + PostgreSQL Outbox + LISTEN/NOTIFY + 幂等消费 + Dead Letter +- **PiiCrypto 加密体系** — AES-256-GCM + KEK/DEK 分层管理 + HMAC 盲索引 + 数据脱敏 +- **ErpModule 插件 trait** — 统一注册路由和事件处理器 + 拓扑排序启动 - **BaseFields 强制多租户** — 所有实体基础字段模板 ## 2. 关键文件 + 数据流 @@ -29,7 +30,11 @@ tags: [core, error, event-bus, module-trait, shared-types] | `crates/erp-core/src/events.rs` | DomainEvent、EventBus、EventHandler trait | | `crates/erp-core/src/module.rs` | ErpModule trait、ModuleRegistry | | `crates/erp-core/src/types.rs` | BaseFields、Pagination、ApiResponse、TenantContext | +| `crates/erp-core/src/crypto/` | PiiCrypto(engine/key_manager/masking/hmac_index),AES-256-GCM + KEK/DEK | | `crates/erp-core/src/sanitize.rs` | strip_html_tags()、sanitize_string() | +| `crates/erp-core/src/entity/` | audit_log, domain_event, processed_event, dead_letter_event | +| `crates/erp-core/src/audit.rs` | 审计日志记录 | +| `crates/erp-core/src/rbac.rs` | require_permission 权限检查 | | `crates/erp-core/src/lib.rs` | 模块导出入口 | ### 集成契约 @@ -59,10 +64,15 @@ tags: [core, error, event-bus, module-trait, shared-types] ### 事件总线 ``` -EventBus::publish(DomainEvent) → broadcast channel → Receiver -事件字段: id(UUIDv7), event_type("user.created"), tenant_id, payload(JSON), timestamp +EventBus::publish(DomainEvent) + → INSERT pending → 内存 broadcast(channel 1024) → UPDATE published → NOTIFY outbox_channel +Outbox Relay: PgListener (LISTEN/NOTIFY) + 30s 兜底轮询 + 自动重连 +幂等消费: processed_events 表 + consumer_id +Dead Letter: 失败事件 → dead_letter_events 表 ``` +事件字段: id(UUIDv7), event_type("user.created"), tenant_id, payload(JSON), timestamp + 命名规则:`{模块}.{动作}` 如 `user.created`, `workflow.task.completed` 健康模块事件:`patient.created`, `appointment.confirmed`, `appointment.cancelled` @@ -75,7 +85,7 @@ ErpModule trait → ModuleRegistry::register() → register_handlers(): 注册事件处理器 → EventBus ``` -已注册模块:AuthModule → ConfigModule → WorkflowModule → MessageModule → PluginModule → **HealthModule** +已注册模块:AuthModule → ConfigModule → WorkflowModule → MessageModule → PluginModule → **HealthModule** → **AiModule** ### 共享类型 diff --git a/wiki/erp-health.md b/wiki/erp-health.md index 9116bb6..99e3cfa 100644 --- a/wiki/erp-health.md +++ b/wiki/erp-health.md @@ -1,6 +1,6 @@ --- title: erp-health 健康管理模块 -updated: 2026-04-26 +updated: 2026-04-28 status: implemented tags: [health, patient, appointment, follow-up, consultation, content, points, dialysis, offline-events] --- @@ -32,7 +32,7 @@ tags: [health, patient, appointment, follow-up, consultation, content, points, d - **原生 Rust crate** — 与 erp-auth、erp-workflow 同等地位,直接访问数据库 - **ErpModule trait 实现** — `HealthModule` 在 erp-server 注册,路由挂载到 `/api/v1/health` - **EventBus 通信** — 发布 `patient.created`、`appointment.confirmed` 等,订阅 `workflow.task.completed` -- **HealthCrypto** — AES-256-GCM 加密 + HMAC-SHA256 哈希,保护 PII 数据 +- **HealthCrypto** — 已迁移到 `erp_core::crypto::PiiCrypto`(AES-256-GCM + KEK/DEK 分层 + HMAC 盲索引),`crypto.rs` 保留兼容层 ## 2. 关键文件 + 数据流 @@ -47,33 +47,48 @@ crates/erp-health/ │ ├── state.rs ← HealthState { db, event_bus, crypto } │ ├── crypto.rs ← AES-256-GCM 加密 + HMAC-SHA256 (PII 保护) │ ├── event.rs ← 事件处理器 (订阅 workflow/message 事件) -│ ├── entity/ ← 34 个 SeaORM Entity -│ ├── service/ ← 14 个业务 service + validation + masking + trend -│ ├── handler/ ← 16 个路由 handler -│ ├── dto/ ← 7 个请求/响应 DTO -│ ├── validation.rs ← 输入验证逻辑 (302 行, 57 纯函数测试) +│ ├── entity/ ← 44 个 SeaORM Entity +│ ├── service/ ← 25 个业务 service + validation + masking + trend +│ ├── handler/ ← 21 个路由 handler +│ ├── dto/ ← 15 个请求/响应 DTO +│ ├── validation.rs ← 输入验证逻辑 (302 行, 104 纯函数测试) │ ├── masking.rs ← PII 数据脱敏 (手机号/身份证) +│ ├── health_provider_impl.rs ← AI 数据桥接(当前 stub) │ └── seed.rs ← 租户种子数据 + 软删除清理 ``` -### 实体模型(34 个实体) +### 实体模型(44 个实体) | 域 | 实体 | |----|------| -| 患者管理 | patient, patient_family_member, patient_tag, patient_tag_relation, patient_doctor_relation, consent | -| 医护管理 | doctor_profile | -| 健康数据 | health_record, vital_signs, lab_report, health_trend | -| 日常监测 | daily_monitoring, critical_value_threshold | -| 诊断管理 | diagnosis | +| 患者管理 | patient, patient_family_member, patient_tag, patient_tag_relation, patient_doctor_relation, patient_devices, blind_index, consent | +| 医护管理 | doctor_profile, doctor_schedule | +| 健康数据 | health_record, vital_signs, vital_signs_hourly, daily_monitoring, lab_report, health_trend, diagnosis, medication_record, device_readings | | 透析管理 | dialysis_record | -| 预约排班 | appointment, doctor_schedule | -| 随访管理 | follow_up_task, follow_up_record | +| 预约排班 | appointment | +| 随访管理 | follow_up_task, follow_up_record, follow_up_template, follow_up_template_field | | 咨询管理 | consultation_session, consultation_message | | 内容管理 | article, article_category, article_tag, article_article_tag, article_revision | +| 告警系统 | alerts, alert_rules, critical_alert, critical_alert_response, critical_value_threshold | | 积分商城 | points_account, points_rule, points_product, points_order, points_transaction, points_checkin | | 线下活动 | offline_event, offline_event_registration | -### 权限码(15+ 个) +### 权限码(22 个) + +| 权限码 | 说明 | +|--------|------| +| `health.patient.list` / `health.patient.manage` | 患者查看/管理 | +| `health.health-data.list` / `health.health-data.manage` | 健康数据查看/管理 | +| `health.appointment.list` / `health.appointment.manage` | 预约查看/管理 | +| `health.follow-up.list` / `health.follow-up.manage` | 随访查看/管理 | +| `health.consultation.list` / `health.consultation.manage` | 咨询查看/管理 | +| `health.doctor.list` / `health.doctor.manage` | 医护查看/管理 | +| `health.articles.list` / `health.articles.manage` | 文章查看/管理 | +| `health.articles.review` | 文章审核 | +| `health.points.list` / `health.points.manage` | 积分查看/管理 | +| `health.device-readings.list` / `health.device-readings.manage` | 设备数据查看/管理 | +| `health.alerts.list` / `health.alerts.manage` | 告警查看/管理 | +| `health.alert-rules.list` / `health.alert-rules.manage` | 告警规则查看/管理 | | 权限码 | 说明 | |--------|------| @@ -94,7 +109,12 @@ crates/erp-health/ | 调用 → | [[erp-core]] | EventBus | 发布/订阅领域事件 | | 关联 → | erp-auth | `users` 表 (user_id FK) | 患者/医护关联账号 | | 订阅 ← | erp-workflow | `workflow.task.completed` | 随访任务状态更新 | -| 订阅 ← | erp-message | `message.sent` | 咨询会话 last_message_at | +| 订阅 ← | erp-message | `message.sent` | 消息通知(预留) | +| 订阅 ← | 设备同步 | `device.readings.synced` | 触发告警引擎评估 | +| 订阅 ← | 事件总线 | `patient.*` | 发送欢迎消息 | +| 订阅 ← | 事件总线 | `appointment.*` | 通知 + 号源释放 | +| 订阅 ← | 事件总线 | `follow_up.overdue` | 升级通知 | +| 订阅 ← | 事件总线 | `health_data.critical_alert` | 创建危急值告警 | ## 3. 代码逻辑 @@ -167,13 +187,35 @@ draft → pending_review → published → draft (撤回) ### PII 数据保护 -- `HealthCrypto`: AES-256-GCM 加密敏感字段,HMAC-SHA256 哈希身份证号 +- `PiiCrypto`(erp-core): AES-256-GCM 加密,KEK/DEK 分层管理(每租户独立 DEK) - `masking.rs`: 手机号脱敏 `138****1234`,身份证脱敏 `110****1111` -- 生产密钥通过环境变量 `ERP__HEALTH__AES_KEY` / `ERP__HEALTH__HMAC_KEY` 配置 +- HMAC 盲索引: 支持加密字段的等值查询(手机号、身份证号搜索) +- 生产密钥通过环境变量 `ERP__CRYPTO__KEK` 配置 KEK,DEK 由 `tenant_crypto_keys` 表管理 + +### 事件发布(25 个事件) + +| 服务 | 事件类型 | +|------|---------| +| patient_service | patient.created, patient.updated | +| appointment_service | appointment.created, appointment.confirmed, appointment.cancelled | +| consultation_service | consultation.opened, consultation.closed | +| article_service | article.published, article.rejected | +| consent_service | consent.granted, consent.revoked | +| device_reading_service | device.readings.synced | +| doctor_service | doctor.online_status_changed | +| daily_monitoring_service | daily_monitoring.created | +| follow_up_service | follow_up.created, follow_up.completed, follow_up.overdue | +| health_data_service | lab_report.uploaded, health_data.critical_alert | +| points_service | points.earned, points.exchanged, points.expired | +| alert_engine | alert.triggered | + +所有消费者都有幂等保护(`is_event_processed` / `mark_event_processed`)。 ### 后台任务 -- 随访逾期检查器 — 每 5 分钟扫描 `follow_up_task` 中超过 `planned_date` 仍未完成的任务 +- 随访逾期检查器 — 每 6 小时扫描 `follow_up_task` 中超过 `planned_date` 仍未完成的任务 +- 积分过期清理 — 每 24 小时扫描并处理过期积分 +- 预约提醒 — 每 1 小时扫描即将到来的预约并发送提醒 ⚡ **不变量**: 预约创建必须走原子 CAS,不能用 read-then-write ⚡ **不变量**: `patient.user_id` 允许 NULL(先建档后绑定) @@ -184,7 +226,7 @@ draft → pending_review → published → draft (撤回) ### 当前状态: ✅ 已完成 -34 实体、16 个 handler(~148 个 pub fn)、15+ 权限、22 Web 页面 + 11 组件,17k 行 Rust 代码。状态转换验证统一到 validation 模块(83 纯函数测试)。 +44 实体、21 个 handler(~160 个 pub fn)、22 权限、25+ Web 路由页面 + 11 组件,~21k 行 Rust 代码。状态转换验证统一到 validation 模块(104 纯函数测试)。18 个集成测试文件覆盖所有子域。 ### 待优化 @@ -210,6 +252,7 @@ draft → pending_review → published → draft (撤回) | 日期 | 变更 | |------|------| +| 2026-04-28 | 全面数据刷新:44 实体(+10 告警/设备/随访模板/体征小时聚合等)、21 handler、22 权限、25+ Web 路由、事件系统完善(25 发布/6 消费者)、3 个后台任务、PiiCrypto 迁移到 erp-core | | 2026-04-26 | 全面更新:34 实体(+13 积分/透析/诊断/日常监测/线下活动/危急值/知情同意)、16 handler、stats 统计端点、validation 统一模块(83 测试)、PII 加密扩展(doctor_profile/dialysis_record/lab_report/diagnosis key_version) | | 2026-04-26 | 新增内容管理:article_category/article_tag/article_article_tag/article_revision 4 实体、审核状态机 | | 2026-04-25 | 全面更新为已实现状态:18 实体、14 权限、全链路验证通过 | diff --git a/wiki/erp-server.md b/wiki/erp-server.md index d9f6532..9a7ac8b 100644 --- a/wiki/erp-server.md +++ b/wiki/erp-server.md @@ -1,6 +1,6 @@ --- title: erp-server -updated: 2026-04-25 +updated: 2026-04-28 status: stable tags: [server, axum, assembly, entry-point] --- @@ -35,7 +35,7 @@ tags: [server, axum, assembly, entry-point] ``` AppConfig::load() → 安全检查 → init_tracing → db::connect → Migrator::up → 种子数据(默认租户+管理员) → Redis客户端 → EventBus(容量1024) - → 注册6个模块 → 初始化插件引擎+恢复插件 → 5个后台任务 + → 注册7个模块 → 初始化插件引擎+恢复插件 → 8+后台任务 → 构建Router → bind + serve → 优雅关闭(CTRL+C/SIGTERM) ``` @@ -77,18 +77,24 @@ AppState { 1. 消息监听器 — EventBus → MessageModule 2. 插件通知 — EventBus → PluginModule -3. Outbox relay — domain_events → 外部 -4. 超时检查器 — 工作流任务超时处理 -5. 随访逾期检查 — HealthModule 每 5 分钟扫描过期随访任务 +3. Outbox relay — domain_events → 外部(LISTEN/NOTIFY + 30s 兜底轮询) +4. 事件清理 — 归档 + 清理过期事件 +5. 超时检查器 — 工作流任务超时处理(60s) +6. 随访逾期检查 — HealthModule 每 6 小时扫描过期随访任务 +7. 积分过期清理 — HealthModule 每 24 小时处理过期积分 +8. 预约提醒 — HealthModule 每 1 小时扫描即将到来的预约 +9. 插件恢复 — 启动时恢复已安装插件 ## 3. 代码逻辑 ### 中间件栈 ``` -CORS(可配置 origins) → IP限流(公开路由) → 用户限流(受保护路由) → JWT认证 +CORS(可配置 origins) → Tenant RLS(SET app.current_tenant_id) → JWT认证 → 用户限流(100 req/min/user, Redis) ``` +公开路由额外:IP 限流 + 账户锁定 + ### 配置结构 ``` @@ -116,5 +122,6 @@ AppConfig | 日期 | 变更 | |------|------| -| 2026-04-25 | 更新为 6 模块注册,8 个环境变量,新增随访逾期检查后台任务 | +| 2026-04-28 | 更新后台任务为 9 个、中间件栈含 RLS、outbox relay 机制完善 | +| 2026-04-25 | 更新为 7 模块注册,8 个环境变量,新增随访逾期检查后台任务 | | 2026-04-23 | 重构为 5 节结构,更新为当前集成状态 | diff --git a/wiki/frontend.md b/wiki/frontend.md index b879389..60f2b18 100644 --- a/wiki/frontend.md +++ b/wiki/frontend.md @@ -12,8 +12,8 @@ tags: [frontend, react, antd, vite, spa] ## 1. 设计决策 - **组件库优先** — Ant Design 6,不自造轮子 -- **状态集中** — Zustand 管理全局状态(4 个 store) -- **API 层分离** — HTTP 调用封装到 `src/api/`(28 个文件),组件不直接 fetch +- **状态集中** — Zustand 管理全局状态(5 个 store) +- **API 层分离** — HTTP 调用封装到 `src/api/`(含 health/ 和 ai/ 子目录),组件不直接 fetch - **代理开发** — Vite 代理 `/api` 到后端 3000 端口 - **HashRouter** — 不需要服务端 fallback 配置,部署更稳健 - **懒加载** — 除 Login 外所有页面使用 `lazy()` 按需加载 @@ -186,16 +186,17 @@ React 19.2.4 / Ant Design 6.3.5 / React Router 7.14.0 / Zustand 5.0.12 / Vite 8. ## 4. 代码逻辑 -### 状态管理(4 个 Zustand Store) +### 状态管理(5 个 Zustand Store) | Store | 状态 | |-------|------| | `app.ts` | theme(blue/warm/dark/emerald), sidebarCollapsed, localStorage 持久化 | | `auth.ts` | user, isAuthenticated, localStorage 持久化 | -| `message.ts` | unreadCount, recentMessages, 请求去重 | +| `health.ts` | 患者/医生姓名缓存与批量解析 | +| `message.ts` | unreadCount, recentMessages, SSE 实时推送连接, 请求去重 | | `plugin.ts` | plugins 列表, 动态菜单, schema 缓存, 请求去重 | -### 健康模块 API 文件(7 个) +### 健康模块 API 文件(10 个) | 文件 | 覆盖端点 | |------|---------| @@ -206,14 +207,19 @@ React 19.2.4 / Ant Design 6.3.5 / React Router 7.14.0 / Zustand 5.0.12 / Vite 8. | `followUp.ts` | 随访任务 + 记录 | | `consultations.ts` | 咨询会话 + 消息 + 导出 | | `articles.ts` | 健康文章 | +| `points.ts` | 积分系统 | +| `deviceReadings.ts` | 设备数据采集 | +| `alerts.ts` | 健康预警 | -### 前端单元测试(3 个) +### 前端单元测试(5 个) | 文件 | 测试内容 | |------|---------| | `constants/health.test.ts` | 健康常量定义验证 | | `hooks/useThemeMode.test.ts` | 暗色模式 hook | +| `hooks/useDebouncedValue.test.ts` | 防抖 hook | | `pages/health/components/StatusTag.test.tsx` | 状态标签渲染 | +| `utils/exprEvaluator.test.ts` | 表达式求值 | ### 插件页面系统 diff --git a/wiki/index.md b/wiki/index.md index 7771405..281fc7e 100644 --- a/wiki/index.md +++ b/wiki/index.md @@ -6,20 +6,20 @@ | 指标 | 值 | |------|-----| -| Rust crate | 15 个(erp-core + 5 基础业务 + erp-health + erp-ai + erp-plugin + 4 插件 + erp-plugin-prototype) | -| 数据库表 | 30 基础表 + 34 健康业务表 + 3 AI 表(已实现) | -| 数据库迁移 | 72 个 | -| 核心模块 | 5 基础 (auth/config/workflow/message/plugin) + 2 业务 (health + ai) | -| erp-health 实体 | 34 个 Entity(17k 行 Rust) | +| Rust crate | 18 个(erp-core + 5 基础业务 + erp-health + erp-ai + erp-dialysis + erp-plugin + 5 插件 + erp-plugin-prototype) | +| 数据库表 | 30 基础表 + 44 健康业务表 + 3 AI 表(已实现) | +| 数据库迁移 | 76 个 | +| 核心模块 | 5 基础 (auth/config/workflow/message/plugin) + 3 业务 (health + ai + dialysis) | +| erp-health 实体 | 44 个 Entity(~21k 行 Rust) | | erp-ai 实体 | 3 个 Entity(1.7k 行 Rust) | -| Web 前端 | 77 个 TSX + 56 个 TS = 133 个源文件(48 个页面 + 22 健康页面 + 11 健康组件) | +| Web 前端 | 92 TSX + 71 TS = 163 个源文件(含 25+ 健康路由页面 + 11 健康组件) | | 微信小程序 | Taro 4.2 + React 18,40 个页面(31 患者端 + 9 医护端),5 个 TabBar | -| 前端单元测试 | 3 个(vitest)+ 4 E2E spec(playwright) | -| 后端测试 | 36 个(workspace)+ 83 validation 纯函数测试 | -| 总代码量 | Rust ~63k 行 + 前端 TSX/TS ~133 文件 + 小程序 ~7.5k 行 | +| 前端单元测试 | 5 个(vitest)+ 5 E2E spec(playwright) | +| 后端测试 | 225 单元 + 159 集成(含 18 个健康模块集成测试文件) | +| 总代码量 | Rust ~77k 行(459 源文件)+ Web 前端 163 文件 + 小程序 125 文件 | | API 文档 | `http://localhost:3000/api/docs/openapi.json` | -| Git 提交 | 301 次 | -| UI/UX 重构 | Phase 1-2 完成(6 共享组件 + 4 角色仪表盘 + personal-stats API),Phase 3-6 待实施 | +| Git 提交 | 409 次 | +| UI/UX 重构 | Phase 1-5 完成(6 共享组件 + 4 角色仪表盘 + 个人统计数据 + 表单抽屉 + 小程序优化) | ## 症状导航 @@ -60,19 +60,19 @@ - erp-plugin — WASM 运行时 · 动态表 · 热更新(HMS 保留但非主要扩展方式) ### 核心业务层(HMS 专属) -- [[erp-health]] — **患者管理 · 健康数据 · 预约排班 · 随访管理 · 咨询管理 · 内容管理 · 积分商城 · 透析管理 · 线下活动 · 日常监测**(原生 Rust 模块,34 实体,已实现) +- [[erp-health]] — **患者管理 · 健康数据 · 预约排班 · 随访管理 · 咨询管理 · 内容管理 · 积分商城 · 透析管理 · 线下活动 · 日常监测 · 告警系统**(原生 Rust 模块,44 实体,已实现) - [[erp-ai]] — **AI 智能分析 · 化验单解读 · 趋势分析 · 报告摘要**(原生 Rust 模块,3 实体,Phase 1 MVP) ### 组装层 -- [[erp-server]] — Axum 入口 · AppState · 7 模块注册 · 后台任务 · 优雅关闭 +- [[erp-server]] — Axum 入口 · AppState · 7+ 模块注册 · 后台任务 · 优雅关闭 ### 患者端 - [[miniprogram]] — **微信小程序** · Taro 4.2 · 微信登录 · 手机绑定 · 健康数据查看 ### 基础设施 - [[infrastructure]] — 连接信息 · 环境变量 · 一键启动 (**单一真相源**) -- [[database]] — SeaORM 迁移 · 多租户表结构(72 迁移) -- [[frontend]] — React 19 SPA · 健康管理页面(22 页面 + 11 组件) +- [[database]] — SeaORM 迁移 · 多租户表结构(76 迁移) +- [[frontend]] — React 19 SPA · 健康管理页面(25+ 路由 + 11 组件) - [[testing]] — 验证清单 · 测试分布 · 性能基准 ## 核心架构问答 @@ -95,10 +95,10 @@ | PII 加密扩展规格 | `docs/superpowers/specs/2026-04-26-pii-encryption-expansion-design.md` | | 实时体征管线探讨 | `docs/superpowers/specs/2026-04-26-realtime-vital-signs-pipeline-design.md` | | 平台复盘与演进 | `docs/superpowers/specs/2026-04-26-platform-retrospective-and-evolution-design.md` | -| 设计规格(全量) | `docs/superpowers/specs/` (24 份) | +| 设计规格(全量) | `docs/superpowers/specs/` (31 份) | | UI/UX 重构设计规格 | `docs/superpowers/specs/2026-04-28-ui-ux-overhaul-design.md` | | UI/UX 重构实施计划 | `docs/superpowers/plans/2026-04-28-ui-ux-overhaul-plan.md` | -| 实施计划(全量) | `docs/superpowers/plans/` (19 份) | -| 讨论记录 | `docs/discussions/` (6 份) | +| 实施计划(全量) | `docs/superpowers/plans/` (27 份) | +| 讨论记录 | `docs/discussions/` (10 份) | | 协作规则 | `CLAUDE.md` | | 插件制作指南 | `.claude/skills/plugin-development/SKILL.md` | diff --git a/wiki/testing.md b/wiki/testing.md index 9d19847..9be8b76 100644 --- a/wiki/testing.md +++ b/wiki/testing.md @@ -1,6 +1,6 @@ --- title: 测试与验证 -updated: 2026-04-25 +updated: 2026-04-28 status: stable tags: [testing, verification] --- @@ -19,16 +19,20 @@ tags: [testing, verification] ### 测试分布 -| Crate | 测试数 | 覆盖 | -|-------|--------|------| -| erp-auth | 8 | 密码哈希、TTL 解析 | -| erp-core | 6 | RBAC 权限检查 | -| erp-workflow | 16 | BPMN 解析、表达式求值 | -| erp-plugin-prototype | 6 | WASM 插件集成 | -| erp-health (validation) | 57 | 输入验证纯函数测试 | -| **后端总计** | **93** | | -| 前端 (vitest) | 3 | 健康常量、useThemeMode hook、StatusTag 组件 | -| E2E (playwright) | 4 spec | 登录、用户管理、插件、租户隔离 | +| Crate | 单元测试 | 集成测试 | 覆盖评估 | +|-------|---------|---------|---------| +| erp-health (validation) | 104 | 18 文件 ~159 | 良好 | +| erp-core | 42 | - | 良好(crypto/module/error/rbac/sanitize/types) | +| erp-auth | 38 | 3 | 中等 | +| erp-plugin | 31 | 2 | 中等 | +| erp-dialysis | 10 | - | 中等 | +| erp-config | **0** | - | ⚠️ 缺失 | +| erp-message | **0** | - | ⚠️ 缺失 | +| erp-workflow | **0** | - | ⚠️ 缺失 | +| erp-ai | **0** | - | ⚠️ 缺失 | +| **后端总计** | **225** | **159** | | +| 前端 (vitest) | 5 | - | 健康常量/useThemeMode/useDebouncedValue/StatusTag/exprEvaluator | +| E2E (playwright) | - | 5 spec | 登录/用户管理/插件/租户隔离 | ### 编译 + 测试 @@ -126,10 +130,12 @@ SELECT count(*) FROM patient WHERE deleted_at IS NULL; -- 患者数量 | 领域 | 当前状态 | 优先级 | |------|---------|--------| -| erp-health service 层集成测试 | 无 | P0 | -| erp-health handler 层测试 | 无 | P1 | -| 前端健康模块组件测试 | 仅 StatusTag | P1 | -| E2E 健康模块测试 | 无 | P1 | +| erp-config 单元测试 | **0 测试** | P1 | +| erp-message 单元测试 | **0 测试** | P1 | +| erp-workflow 单元测试 | **0 测试**(BPMN 解析 + Token 驱动) | P1 | +| erp-ai 单元测试 | **0 测试**(Prompt 管理 + 脱敏) | P2 | +| 前端健康模块组件测试 | 仅 StatusTag + exprEvaluator | P2 | +| E2E 健康模块测试 | 无 | P2 | ### 活跃问题