新建 erp-health 原生 Rust crate,覆盖设计规格中定义的 5 大业务域: - 16 个 SeaORM Entity(患者/家属/标签/医生/健康档案/体征/化验单/预约/排班/随访/咨询等) - 16 表数据库迁移(含索引、外键、默认值、可回滚) - 40+ API 路由骨架(患者管理/健康数据/预约排班/随访/咨询/医生管理) - 12 个权限声明(health.patient/health-data/appointment/follow-up/consultation/doctor 各 .list/.manage) - DTO / Service / Handler / Event 四层架构,Service 使用 todo!() 占位 - erp-server 集成:模块注册 + AppState FromRef 桥接 + 路由挂载 同步更新 CLAUDE.md 项目进度、wiki 知识库、设计规格文档。
3.7 KiB
title, updated, status, tags
| title | updated | status | tags | |||
|---|---|---|---|---|---|---|
| 架构决策记录 | 2026-04-23 | stable |
|
架构决策记录
从 index 导航。关联: erp-core erp-server database wasm-plugin erp-health
1. 设计决策
模块化单体 + 渐进式拆分
模块间零直接依赖,跨模块通信通过事件总线和 trait 接口。ErpModule trait 天然支持未来按模块拆分为微服务。
HMS 架构:原生模块 + 插件并存
HMS 继承 ERP 底座的所有基础模块,erp-health 作为原生 Rust 模块承载医疗业务。WASM 插件系统保留但非 HMS 主要扩展方式。
HMS 平台
├── 基础模块(继承 ERP): auth, config, workflow, message, plugin
├── 核心业务模块: erp-health(原生 Rust)★
└── 可选插件: crm, inventory, freelance, itops(WASM)
为什么 erp-health 用原生模块?
医疗业务需要 16+ 强类型实体、自定义 API(趋势分析/统计报表)、文件上传、未来 AI 集成。WASM 插件的 JSONB 动态存储和 20 实体上限无法满足。详见 erp-health。
为什么用 UUIDv7?
时间排序 + UUID 唯一性 + 接近自增 ID 的索引性能。多租户 SaaS 下不同租户数据不会因 ID 冲突互相影响。
为什么 tenant_id 不在 API 路径中?
从 JWT 提取,中间件注入 TenantContext。防止:手动改 URL 越权 / API 暴露租户信息 / 忘记检查权限。管理员接口例外。
为什么错误类型跨 crate 用 thiserror?
anyhow 无类型信息,无法精确映射 HTTP 状态码。thiserror → AppError → 400/401/403/404/409/500。
2. 关键文件 + 数据流
模块依赖图
erp-core (L1)
|
+--------------+--------------+--------------+-----------+
| | | | |
erp-auth erp-config erp-workflow erp-message erp-health (L2)
| | | | |
+--------------+--------------+--------------+-----------+
|
erp-server (L3: 唯一组装点)
|
erp-plugin (WASM 插件运行时)
禁止: L2 间直接依赖 / L1 依赖业务模块 / 绕过事件总线
技术选型
| 选择 | 理由 |
|---|---|
| Axum 0.8 | Tokio 团队维护,tower 生态,类型安全路由 |
| SeaORM 1.1 | 异步、类型安全、迁移工具完善 |
| PostgreSQL 18 | 企业级,JSON 支持,扩展丰富 |
| Redis 7 | 缓存 + 限流 token bucket |
| React 19 + Ant Design 6 | 企业后台 UI 标配 |
| Zustand 5 | 极简状态管理 |
| Wasmtime 43 | WASM 沙箱,Component Model,Fuel 限制 |
集成契约
| 方向 | 模块 | 触发时机 |
|---|---|---|
| 定义 → | erp-core | 所有模块的 trait 和类型 |
| 组装 ← | erp-server | 模块注册和启动 |
| 扩展 ← | wasm-plugin | 插件通过 Host Bridge 桥接 |
3. 代码逻辑
⚡ 不变量: 模块间只通过 EventBus 和 trait 通信,无直接依赖
⚡ 不变量: 所有数据表必须含 tenant_id,查询自动过滤
⚡ 不变量: UUID v7 作为主键
⚡ 不变量: 软删除,不硬删除
⚡ 不变量: 所有 API 使用 /api/v1/ 前缀
4. 活跃问题 + 陷阱
⚠️ 当前共享数据库 + tenant_id 过滤,未来可扩展为 Schema 隔离或数据库隔离 ⚠️ EventBus 内存 broadcast 需 outbox 持久化保障(已通过后台任务实现)
5. 变更记录
| 日期 | 变更 |
|---|---|
| 2026-04-23 | 重构为 5 节结构,删除 erp-common 引用,精简技术选型表 |