Files
hms/wiki/erp-server.md
iven 40b5141832
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
docs: 全面更新 wiki 文档至当前实现状态
9 个 wiki 页面全部更新:
- index: 关键数字更新(15 crate/48 表/50 迁移/6 模块)
- erp-health: 从"规划中"更新为"已实现"(18 实体/14 权限)
- erp-server: 6 模块注册/8 环境变量/5 后台任务
- database: 50 迁移/48 表/健康模块迁移(m000042-m000050)
- frontend: 10 健康路由/12 共享组件/7 健康 API/3 单元测试
- miniprogram: 20 页面/10 服务/9 组件
- testing: 93 后端测试+3 前端测试/全链路验证结果
- erp-core: 新增 erp-health 集成契约
- architecture: 6 模块实现状态表/预约 CAS/PII 加密
2026-04-25 11:57:20 +08:00

120 lines
4.1 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.
---
title: erp-server
updated: 2026-04-25
status: stable
tags: [server, axum, assembly, entry-point]
---
# erp-server
> 从 [[index]] 导航。关联: [[erp-core]] [[infrastructure]] [[database]] [[frontend]]
## 1. 设计决策
- **唯一组装点** — 不含业务逻辑,只负责把所有模块组装成可运行服务
- **配置优先** — `config` crate 从 TOML + 环境变量加载,`ERP__` 前缀覆盖
- **严格启动序列** — 每步失败即终止,不做部分启动
- **安全检查** — 拒绝默认 JWT 密钥 / 数据库 URL / 加密密钥
## 2. 关键文件 + 数据流
### 核心文件
| 文件 | 职责 |
|------|------|
| `crates/erp-server/src/main.rs` | 服务启动入口639 行) |
| `crates/erp-server/src/state.rs` | AppState 定义117 行) |
| `crates/erp-server/src/config.rs` | 配置 struct + 加载逻辑87 行) |
| `crates/erp-server/src/db.rs` | SeaORM 连接池配置 |
| `crates/erp-server/src/outbox.rs` | Domain event outbox 处理器 |
| `crates/erp-server/src/middleware/rate_limit.rs` | IP/用户限流176 行) |
| `crates/erp-server/config/default.toml` | 默认配置(密钥为占位符) |
### 启动流程
```
AppConfig::load() → 安全检查 → init_tracing → db::connect → Migrator::up
→ 种子数据(默认租户+管理员) → Redis客户端 → EventBus(容量1024)
→ 注册6个模块 → 初始化插件引擎+恢复插件 → 5个后台任务
→ 构建Router → bind + serve → 优雅关闭(CTRL+C/SIGTERM)
```
### 注册的 6 个模块
AuthModule → ConfigModule → WorkflowModule → MessageModule → PluginModule → **HealthModule**
### 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),
// HealthModule 状态通过 FromRef 提取
}
```
### 集成契约
| 方向 | 模块 | 接口 | 触发时机 |
|------|------|------|---------|
| 组装 → | erp-auth | `AuthModule` | 启动时注册 |
| 组装 → | erp-config | `ConfigModule` | 启动时注册 |
| 组装 → | erp-workflow | `WorkflowModule` | 启动时注册 |
| 组装 → | erp-message | `MessageModule` | 启动时注册 |
| 组装 → | erp-plugin | `PluginModule` | 启动时注册 |
| 组装 → | [[erp-health]] | `HealthModule` | 启动时注册 |
| 依赖 ← | [[erp-core]] | ErpModule trait, EventBus | 所有模块 |
| 依赖 ← | [[infrastructure]] | PostgreSQL, Redis | 连接 |
### 后台任务
1. 消息监听器 — EventBus → MessageModule
2. 插件通知 — EventBus → PluginModule
3. Outbox relay — domain_events → 外部
4. 超时检查器 — 工作流任务超时处理
5. 随访逾期检查 — HealthModule 每 5 分钟扫描过期随访任务
## 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 }
├── auth: { super_admin_password }
├── wechat: { appid, secret }
├── health: { aes_key, hmac_key }
└── log: { level: "info" }
```
**不变量**: 8 个环境变量在 default.toml 中都是 `__MUST_SET_VIA_ENV__` 占位符必须通过环境变量设置database.url, jwt.secret, redis.url, auth.super_admin_password, wechat.appid, wechat.secret, health.aes_key, health.hmac_key
**不变量**: 启动顺序不可变更 — 数据库必须先于迁移,迁移必须先于模块注册
## 4. 活跃问题 + 陷阱
⚠️ 后端必须从 `crates/erp-server/` 目录启动(或通过环境变量覆盖所有配置)
⚠️ 种子数据自动创建默认租户和管理员,重复启动幂等
## 5. 变更记录
| 日期 | 变更 |
|------|------|
| 2026-04-25 | 更新为 6 模块注册8 个环境变量,新增随访逾期检查后台任务 |
| 2026-04-23 | 重构为 5 节结构,更新为当前集成状态 |