feat(health): 添加 erp-health 健康管理模块骨架
新建 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 知识库、设计规格文档。
This commit is contained in:
@@ -1,66 +1,110 @@
|
||||
---
|
||||
title: erp-server
|
||||
updated: 2026-04-23
|
||||
status: stable
|
||||
tags: [server, axum, assembly, entry-point]
|
||||
---
|
||||
|
||||
# erp-server
|
||||
|
||||
## 设计思想
|
||||
> 从 [[index]] 导航。关联: [[erp-core]] [[infrastructure]] [[database]] [[frontend]]
|
||||
|
||||
`erp-server` 是 L3 层——**唯一的组装点**。它不包含业务逻辑,只负责把所有业务模块组装成可运行的服务。
|
||||
## 1. 设计决策
|
||||
|
||||
核心决策:
|
||||
- **配置优先** — 使用 `config` crate 从 TOML 文件 + 环境变量加载,`ERP__` 前缀覆盖(如 `ERP__DATABASE__URL`)
|
||||
- **启动序列严格有序** — 配置 → 日志 → 数据库 → 迁移 → Redis → 路由 → 监听,每步失败即终止
|
||||
- **单一入口** — 所有模块通过 `ModuleRegistry` 注册,server 本身不直接 import 业务模块的类型
|
||||
- **唯一组装点** — 不含业务逻辑,只负责把所有模块组装成可运行服务
|
||||
- **配置优先** — `config` crate 从 TOML + 环境变量加载,`ERP__` 前缀覆盖
|
||||
- **严格启动序列** — 每步失败即终止,不做部分启动
|
||||
- **安全检查** — 拒绝默认 JWT 密钥 / 数据库 URL
|
||||
|
||||
## 代码逻辑
|
||||
## 2. 关键文件 + 数据流
|
||||
|
||||
### 启动流程 (`main.rs`)
|
||||
```
|
||||
1. AppConfig::load() ← config/default.toml + 环境变量
|
||||
2. init_tracing(level) ← JSON 格式日志
|
||||
3. db::connect(&db_config) ← SeaORM 连接池 (max=20, min=5)
|
||||
4. Migrator::up(&db_conn) ← 运行所有待执行迁移
|
||||
5. redis::Client::open(url) ← Redis 客户端(当前未使用)
|
||||
6. Router::new() ← 当前仅有 404 fallback
|
||||
7. bind(host, port).serve() ← 启动 HTTP 服务
|
||||
```
|
||||
|
||||
### 配置结构
|
||||
```
|
||||
AppConfig
|
||||
├── server: ServerConfig { host: "0.0.0.0", port: 3000 }
|
||||
├── database: DatabaseConfig { url, max_connections: 20, min_connections: 5 }
|
||||
├── redis: RedisConfig { url: "redis://localhost:6379" }
|
||||
├── jwt: JwtConfig { secret, access_token_ttl, refresh_token_ttl }
|
||||
└── log: LogConfig { level: "info" }
|
||||
```
|
||||
|
||||
### 当前状态
|
||||
- 数据库连接池正常工作
|
||||
- 迁移自动执行
|
||||
- **没有注册任何路由** — 仅返回 404
|
||||
- **没有使用 ModuleRegistry** — 未集成业务模块
|
||||
- Redis 客户端已创建但未执行任何命令
|
||||
- 缺少 CORS、压缩、请求追踪中间件
|
||||
|
||||
## 关联模块
|
||||
|
||||
- **[[erp-core]]** — 提供 AppError、ErpModule trait、ModuleRegistry
|
||||
- **[[database]]** — 迁移文件通过 `erp-server-migration` crate 引用
|
||||
- **[[infrastructure]]** — Docker 提供 PostgreSQL 和 Redis 服务
|
||||
- **[[frontend]]** — Vite 代理 `/api` 请求到 server 的 3000 端口
|
||||
|
||||
## 关键文件
|
||||
### 核心文件
|
||||
|
||||
| 文件 | 职责 |
|
||||
|------|------|
|
||||
| `crates/erp-server/src/main.rs` | 服务启动入口 |
|
||||
| `crates/erp-server/src/state.rs` | AppState 定义 |
|
||||
| `crates/erp-server/src/config.rs` | 5 个配置 struct + 加载逻辑 |
|
||||
| `crates/erp-server/src/db.rs` | SeaORM 连接池配置 |
|
||||
| `crates/erp-server/config/default.toml` | 默认配置值 |
|
||||
| `crates/erp-server/Cargo.toml` | 依赖声明 |
|
||||
| `crates/erp-server/config/default.toml` | 默认配置(密钥为占位符) |
|
||||
|
||||
## 待完成 (Phase 1 剩余)
|
||||
### 启动流程
|
||||
|
||||
1. 实例化 `ModuleRegistry` 并注册模块
|
||||
2. 添加 CORS 中间件(tower-http)
|
||||
3. 添加请求追踪中间件
|
||||
4. 将 Redis 连接注入 AppState
|
||||
5. 健康检查端点 (`/api/v1/health`)
|
||||
```
|
||||
AppConfig::load() → 安全检查 → init_tracing → db::connect → Migrator::up
|
||||
→ 种子数据(默认租户+管理员) → Redis客户端 → EventBus(容量1024)
|
||||
→ 注册5个模块 → 初始化插件引擎+恢复插件 → 4个后台任务
|
||||
→ 构建Router → bind + serve → 优雅关闭(CTRL+C/SIGTERM)
|
||||
```
|
||||
|
||||
### 注册的 5 个模块
|
||||
|
||||
AuthModule → ConfigModule → WorkflowModule → MessageModule → PluginModule
|
||||
|
||||
### AppState
|
||||
|
||||
```
|
||||
AppState {
|
||||
db: DatabaseConnection,
|
||||
config: AppConfig,
|
||||
event_bus: EventBus,
|
||||
module_registry: ModuleRegistry,
|
||||
redis: redis::Client,
|
||||
default_tenant_id: Uuid,
|
||||
plugin_engine: PluginEngine,
|
||||
plugin_entity_cache: moka::Cache (1000容量, 5分钟TTL),
|
||||
}
|
||||
```
|
||||
|
||||
### 集成契约
|
||||
|
||||
| 方向 | 模块 | 接口 | 触发时机 |
|
||||
|------|------|------|---------|
|
||||
| 组装 → | erp-auth | `AuthModule` | 启动时注册 |
|
||||
| 组装 → | erp-config | `ConfigModule` | 启动时注册 |
|
||||
| 组装 → | erp-workflow | `WorkflowModule` | 启动时注册 |
|
||||
| 组装 → | erp-message | `MessageModule` | 启动时注册 |
|
||||
| 组装 → | erp-plugin | `PluginModule` | 启动时注册 |
|
||||
| 依赖 ← | [[erp-core]] | ErpModule trait, EventBus | 所有模块 |
|
||||
| 依赖 ← | [[infrastructure]] | PostgreSQL, Redis | 连接 |
|
||||
|
||||
### 后台任务
|
||||
|
||||
1. 消息监听器 — EventBus → MessageModule
|
||||
2. 插件通知 — EventBus → PluginModule
|
||||
3. Outbox relay — domain_events → 外部
|
||||
4. 超时检查器 — 工作流任务超时处理
|
||||
|
||||
## 3. 代码逻辑
|
||||
|
||||
### 中间件栈
|
||||
|
||||
```
|
||||
CORS(可配置 origins) → IP限流(公开路由) → 用户限流(受保护路由) → JWT认证
|
||||
```
|
||||
|
||||
### 配置结构
|
||||
|
||||
```
|
||||
AppConfig
|
||||
├── server: { host: "0.0.0.0", port: 3000 }
|
||||
├── database: { url, max_connections: 20, min_connections: 5 }
|
||||
├── redis: { url }
|
||||
├── jwt: { secret, access_token_ttl: 15min, refresh_token_ttl: 7d }
|
||||
└── log: { level: "info" }
|
||||
```
|
||||
|
||||
⚡ **不变量**: 4 个环境变量在 default.toml 中都是 `__MUST_SET_VIA_ENV__` 占位符,必须通过环境变量设置
|
||||
|
||||
⚡ **不变量**: 启动顺序不可变更 — 数据库必须先于迁移,迁移必须先于模块注册
|
||||
|
||||
## 4. 活跃问题 + 陷阱
|
||||
|
||||
⚠️ 后端必须从 `crates/erp-server/` 目录启动(或通过环境变量覆盖所有配置)
|
||||
⚠️ 种子数据自动创建默认租户和管理员,重复启动幂等
|
||||
|
||||
## 5. 变更记录
|
||||
|
||||
| 日期 | 变更 |
|
||||
|------|------|
|
||||
| 2026-04-23 | 重构为 5 节结构,更新为当前集成状态 |
|
||||
|
||||
Reference in New Issue
Block a user