Files
hms/CLAUDE.md
iven 75cd305996
Some checks failed
CI / security-audit (push) Has been cancelled
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
docs(wiki): 全景梳理 — 更新 9 个 wiki + CLAUDE.md scope + 头脑风暴记录
基于 3 个并行探索代理的全面扫描结果,更新 wiki 数据至实际状态:
- index.md: 18 crate / 76 迁移 / 44 实体 / 77k 行 / 409 提交
- erp-health.md: 44 实体 / 21 handler / 22 权限 / 25 事件 / 6 消费者
- erp-server.md: 9 后台任务 / RLS 中间件栈
- architecture.md: 新增 erp-ai/dialysis 到依赖图 / 测试覆盖表
- testing.md: 225 单元 + 159 集成 / 4 模块零测试警告
- database.md: 76 迁移 / RLS+哈希链+盲索引+Dead Letter
- erp-core.md: PiiCrypto 加密体系 / EventBus 完整描述
- frontend.md: 163 文件 / 5 store / 10 API 文件
- CLAUDE.md: 新增 health/ai/dialysis/assessment scope

头脑风暴 4 个议题决策:
- dialysis: 接入激活
- 测试: 按风险排序(workflow > ai > message > config)
- AI: 数据桥接优先
- 路线图: AI 驱动 3 个月 5 Phase
2026-04-28 14:53:04 +08:00

331 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.
@wiki/index.md
整个项目对话都使用中文进行,包括文档、代码注释、事件名称等。
# HMS 健康管理平台 — 协作与实现规则
> **Health Management System (HMS)** — 面向体检中心/医疗机构的综合健康管理平台。从 ERP 底座分叉独立,继承身份权限/工作流/消息/配置等基础能力,`erp-health` 原生模块承载医疗业务。
> **当前阶段: erp-health 模块开发。** 设计规格已确认,开始实施。
## 1. 项目定位
### 1.1 这是什么
一个 **健康管理 + ERP 基础设施** 架构的医疗 SaaS 平台:
- **医疗核心** — 患者管理、健康数据、预约排班、随访管理、咨询管理(原生 Rust 模块 erp-health
- **基础底座** — 身份权限、工作流引擎、消息中心、系统配置(继承自 ERP
- **多租户 + 私有化** — 默认 SaaS 共享数据库隔离,支持独立 schema 私有部署
- **Web 优先** — 浏览器 SPA 是 PC 管理后台主力,小程序(患者端/医护端)独立开发
### 1.2 决策原则
**任何改动都要问:这对健康管理平台的医疗业务和可扩展性有帮助吗?**
- ✅ 完善模块接口和 trait 定义 → 最高优先
- ✅ 确保多租户隔离的正确性 → 最高优先
- ✅ 按计划推进 Phase 交付物 → 高优先
- ✅ 清晰的模块边界和事件契约 → 高优先
- ❌ 跳过 Phase 顺序提前实现远期功能 → 禁止
- ❌ 在模块间创建直接耦合 → 永远不做
- ❌ 硬编码租户 ID 或绕过多租户中间件 → 永远不做
- ❌ 过度设计未来才需要的能力 → 永远不做
### 1.3 架构铁律
| 约束 | 原因 |
|------|------|
| 模块间只通过事件总线和 trait 通信 | 保证模块可独立拆分为微服务 |
| 所有数据表必须含 `tenant_id` | 多租户是核心能力,不可事后补 |
| 使用 UUID v7 作为主键 | 时间排序 + 唯一性,分布式友好 |
| 软删除,不硬删除 | ERP 数据不可丢失,审计追溯需要 |
| 所有 API 使用 `/api/v1/` 前缀 | 版本化是 SaaS 产品的基本要求 |
---
## 2. 工作风格
### 2.1 按计划推进
- **严格按 Phase 顺序执行** — Phase 2 依赖 Phase 1 的基础设施
- **每个 Task 完成后立即提交** — 不积压,保持可追溯
- **先测试后实现** — TDD 流程:写失败测试 → 实现 → 通过 → 提交
### 2.2 分步编写文档(强制)
编写计划、设计文档、实施报告等长文档时,**必须分步编写**,禁止一次性输出全文:
1. **先写大纲** — 确认文档结构和章节划分
2. **逐章编写** — 每次只写 1-2 个章节,写完确认后继续下一章
3. **最终整合** — 所有章节完成后合并为完整文档
**原因:** 上下文过长会导致输出截断或卡死。分步编写保证每步都能完整输出,且用户可以中途调整方向。
**适用范围:** 超过 200 行的文档、实施计划、设计规格、技术报告等。简短的 bugfix 说明、单页 wiki 更新不受此限制。
### 2.3 讨论记录
每次发散式讨论brainstorming、方案探索、需求梳理、技术选型等**必须建立独立文档**
- **存放位置:** `docs/discussions/YYYY-MM-DD-{主题简称}.md`
- **文档格式:**
```markdown
# {讨论主题}
> 日期: YYYY-MM-DD | 参与者: ...
## 背景
为什么会有这次讨论
## 讨论要点
- 要点 1
- 要点 2
## 结论 / 待定
达成的共识或遗留问题
```
- **时机:** 讨论结束后立即创建,不要积压。如果讨论横跨多个主题,拆分为多份文档。
- **用途:** 作为后续实施的输入和决策追溯的依据,避免"之前讨论过但忘了结论"。
### 2.4 模块化思维
开发任何功能时先问:
1. **它属于哪个模块?** — 不确定就放到 `erp-core` 共享层
2. **它的接口是什么?** — 先定义 trait再实现
3. **它需要发什么事件?** — 跨模块通知必须走事件总线
4. **其他模块怎么发现它?** — 通过 `ErpModule` trait 注册
### 2.5 闭环工作法(强制)
每次改动**必须**按顺序完成以下步骤,不允许跳过:
0. **阅读 Wiki强制起点** — 收到任何任务后,**先读 wiki 再动手**
- 读取 `wiki/index.md` 了解项目全貌和当前进度
- 根据任务涉及的范围,读取相关 wiki 页面(`wiki/infrastructure.md`、`wiki/testing.md`、`wiki/wasm-plugin.md` 等)
- wiki 中包含实际的环境配置(数据库连接、端口、登录凭据、启动方式),不看 wiki 就无法正确验证
- **违反此步骤 = 盲目工作,浪费时间去猜环境配置,产出不可信**
1. **现状确认(强制)** — 动手之前,先检查代码里已经有什么:
- 用 Grep/Glob/Read 工具搜索相关文件,确认哪些能力已存在
- 明确列出"已有"和"缺失",不允许凭印象断言缺失
- 如果不确定现有实现状态,停下来问用户,不要编造
- 违反此步骤 = 所有后续工作可能脱离实际,白费力气
2. **理解需求** — 确认改动的目标模块和影响范围
3. **最小实现** — 只改必要的代码,保持模块边界
4. **验证通过** — 必须全部通过才可继续:
- `cargo check` — 编译无错误
- `cargo test --workspace` — 所有测试通过(有相关测试时)
- 功能验证 — 启动后端 + 前端服务,在浏览器中实际操作验证改动生效(涉及 API 或 UI 时)
- `pnpm build` — 前端生产构建通过(涉及前端时)
5. **提交** — 验证通过后按 §5 规范提交
6. **文档同步** — 更新相关文档(如果涉及架构、接口、模块变化)
7. **推送到仓库** — 提交后立即 `git push`,确保远程仓库同步
**铁律:**
- **步骤 0 阅读 Wiki 是绝对起点** — 不读 wiki 就开干 = 连环境配置都不知道,所有验证步骤都是空谈。
- **步骤 1 现状确认是强制起点** — 不检查就开干 = 脱离实际,所有产出不可信。
- **步骤 4 功能验证必须实际操作** — 只看编译通过不算验证,必须启动服务、在浏览器中确认功能正常。
- **步骤 7 推送是强制环节**,不推送就等于没完成。不允许"等一下再推"。
---
## 3. 实现规则
### 3.1 错误处理
- **跨 crate 边界**:使用 `thiserror` 定义类型化错误,转换为 `AppError`
- **crate 内部**:可以使用 `anyhow`,但**永远不**跨越 crate 边界
- **数据库错误**:通过 `From<sea_orm::DbErr>` 自动转换为 `AppError`
- **验证错误**:包含字段级详情,方便 UI 渲染
### 3.2 数据库操作
- 所有 SeaORM Entity 必须包含:`id`, `tenant_id`, `created_at`, `updated_at`, `created_by`, `updated_by`, `deleted_at`, `version`
- 查询时**始终**带 `tenant_id` 过滤(中间件自动注入)
- 更新时检查 `version` 字段实现乐观锁
- 删除使用软删除(设置 `deleted_at`
### 3.3 API 设计
- 所有端点使用 `/api/v1/` 前缀
- 响应统一使用 `ApiResponse<T>` 包装
- 分页使用 `Pagination` + `PaginatedResponse<T>`
- utoipa 自动生成 OpenAPI 文档
- 租户 ID 从 JWT 中间件注入,**不在** API 路径中传递(管理员接口除外)
### 3.4 事件总线
- 模块间通信**只能**通过 `EventBus`
- 事件必须持久化到 `domain_events` 表outbox 模式)
- 事件处理失败记录到 dead-letter 存储
- 事件类型命名:`{模块}.{动作}` 如 `user.created`, `workflow.task.completed`
- **铁律:每个事件必须有至少一个消费者,否则功能不算完成。** 新增事件发布时必须同步实现消费者和对应测试。详见 `docs/discussions/2026-04-28-architecture-retrospective.md` §4。
### 3.5 Rust 代码规范
```rust
// 命名snake_case (函数/变量), PascalCase (类型/trait), SCREAMING_SNAKE (常量)
// 模块公开接口通过 lib.rs 统一导出
// 每个 public 函数和 trait 必须有文档注释
// 异步函数返回 Result 时使用 AppResult<T> 类型别名
// 数据库操作使用 SeaORM 的 Entity + Model + Relation 模式
```
### 3.6 TypeScript / React 代码规范
```typescript
// 避免 any优先 unknown + 类型守卫
// 函数组件 + hooks
// 复杂状态收敛到 Zustand store
// API 调用封装到独立的 service 层,不在组件中直接 fetch
// 使用 Ant Design 组件,不自行实现已有组件
// 国际化文案使用 i18n key不硬编码中文
```
---
## 4. 测试与验证
### 4.1 测试要求
| 测试类型 | 覆盖目标 | 工具 |
|----------|---------|------|
| 单元测试 | 每个 service 函数 | `#[cfg(test)]` + `tokio::test` |
| 集成测试 | API 端点 → 数据库 | Testcontainers + 真实 PostgreSQL |
| 多租户测试 | 数据隔离验证 | 独立测试 crate |
| E2E 测试 | 前端关键流程 | Playwright |
| 插件测试 | 动态表 CRUD + 租户隔离 | Testcontainers |
### 4.2 验证命令
```bash
# Rust 编译检查
cargo check
# Rust 全量测试
cargo test --workspace
# 后端服务启动
cd crates/erp-server && cargo run
# Docker 环境
cd docker && docker compose up -d
# 桌面端开发
cd apps/desktop && pnpm tauri dev
# 数据库迁移检查
docker exec erp-postgres psql -U erp -c "\dt"
```
### 4.3 Phase 完成标准
每个 Phase 完成时必须满足:
- [ ] `cargo check` 全 workspace 通过
- [ ] `cargo test` 全部通过
- [ ] PostgreSQL 服务正常运行,迁移自动执行
- [ ] 所有迁移可正/反向执行
- [ ] API 端点可通过 Swagger UI 测试
- [ ] 桌面端可正常启动并展示对应 UI
- [ ] 所有代码已提交
---
## 5. 提交规范
```
<type>(<scope>): <description>
```
**类型:**
- `feat` — 新功能
- `fix` — 修复问题
- `refactor` — 重构
- `docs` — 文档更新
- `test` — 测试相关
- `chore` — 杂项(构建、配置等)
- `perf` — 性能优化
**Scope 对应 crate 或模块名:**
| scope | 范围 |
|-------|------|
| `core` | erp-core |
| `auth` | erp-auth |
| `workflow` | erp-workflow |
| `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 前端 |
| `ui` | React 组件 |
| `db` | 数据库迁移 |
| `docker` | Docker 配置 |
**示例:**
```
feat(auth): 添加用户管理 CRUD
feat(core): 实现事件总线和模块注册
fix(server): 修复数据库连接池配置
refactor(auth): 拆分 RBAC 和 ABAC 权限模型
chore(docker): 添加 PostgreSQL 健康检查
```
---
## 6. 反模式警告
- ❌ **不要**不看 wiki 就开干 — wiki 包含环境配置、数据库连接、启动方式、已知问题,不看就做等于盲猜,浪费时间且产出不可信
- ❌ **不要**在业务 crate 之间创建直接依赖 — 只通过事件和 trait 通信
- ❌ **不要**跳过多租户中间件 — 所有数据操作必须带 `tenant_id` 过滤
- ❌ **不要**硬编码配置值 — 使用 config.toml + 环境变量
- ❌ **不要**跳过迁移直接建表 — 所有 schema 变更通过 SeaORM Migration
- ❌ **不要**在前端组件中直接调用 HTTP — 封装到 service 层
- ❌ **不要**使用 `anyhow` 跨越 crate 边界 — 内部可用,对外必须转 `AppError`
- ❌ **不要**假设只有单租户 — 从第一天就按多租户设计
- ❌ **不要**提前实现远期功能 — 严格按 Phase 计划推进
- ❌ **不要**忽略 `version` 字段 — 所有更新操作必须检查乐观锁
- ❌ **不要**在动态表 SQL 中拼接用户输入 — 使用 `sanitize_identifier` 防注入
- ❌ **不要**在插件 crate 中直接依赖 erp-auth — 权限注册用 raw SQL保持模块边界
- ❌ **不要**在 plugin.toml 中使用与实体名不一致的权限码 — `permissions[].code` 前缀必须与 `schema.entities[].name` 完全一致(如实体 `customer_tag` → 权限码 `customer_tag.list`/`customer_tag.manage`,不能写成 `tag.manage`),否则页面 403
- ❌ **不要**漏掉实体的 `.list` 权限 — 每个实体必须同时声明 `.list` 和 `.manage`,缺少 `.list` 导致列表页 403
- ❌ **不要**跳过验证直接提交 — 编译/测试/功能验证必须全部通过
- ❌ **不要**提交后忘记推送 — 不推送等于没完成,远程仓库必须同步
- ❌ **不要**忘记更新文档 — 涉及架构、接口、模块变化时必须同步更新相关文档
- ❌ **不要**一次性输出长文档 — 超过 200 行的文档必须分步编写(先大纲 → 逐章 → 整合),否则会因上下文过长卡死
- ❌ **不要**忽略讨论记录 — 每次发散式讨论结束后必须建立文档到 `docs/discussions/`,不要口头确认后就忘
### 场景化指令
- 当遇到**新增模块** → 实现 `ErpModule` trait在 `erp-server` 注册
- 当遇到**跨模块通信** → 定义事件类型,通过 `EventBus` 发布/订阅
- 当遇到**数据查询** → 确保包含 `tenant_id` 过滤,检查软删除条件
- 当遇到**新增 API** → 添加 utoipa 注解,确保 OpenAPI 文档同步
- 当遇到**新增表** → 创建 SeaORM migration + Entity包含所有标准字段
- 当遇到**新增页面** → 使用 Ant Design 组件i18n key 引用文案
- 当遇到**新增业务模块插件** → 参考 `wiki/wasm-plugin.md` 的插件制作完整流程和 `.claude/skills/plugin-development/SKILL.md`,创建 cdylib crate + 实现 Guest trait + 编译为 WASM Component。**权限码必须与实体名一致(每个实体声明 `.list` + `.manage`**
---
## 7. 详细参考wiki
以下内容已从本文件迁移到 wiki需要时查阅
| 主题 | wiki 页面 |
|------|----------|
| 目录结构、crate 依赖、技术栈 | `wiki/architecture.md` §2 |
| 模块开发规范、ErpModule trait、迁移规范 | `wiki/architecture.md` §3 |
| 安全注意事项(认证/多租户/通用) | `wiki/architecture.md` §4 |
| UI 布局规范 | `wiki/frontend.md` §2 |
| 常用命令Rust/前端/数据库/WASM | `wiki/infrastructure.md` §3 |
| 设计文档索引 | `wiki/index.md` |
| 开发进度、模块状态 | `wiki/index.md` 关键数字 |
| 环境配置、连接信息、登录凭据 | `wiki/infrastructure.md` §2 |