- wiki/index.md: 更新关键数字、三端架构图、启动命令、症状导航 - wiki/architecture.md: 补充三端架构、来源追溯、活跃问题更新 - wiki/admin-web.md: 新建管理端文档 — 结构/API代理/功能映射/品牌定制清单 - CLAUDE.md: 补充 apps/web 目录、管理端场景化指令、三端启动命令
154 lines
6.1 KiB
Markdown
154 lines
6.1 KiB
Markdown
---
|
||
title: 架构决策
|
||
updated: 2026-06-02
|
||
status: active
|
||
tags: [architecture, base, multi-tenant, security, three-tier]
|
||
---
|
||
|
||
# 架构决策
|
||
|
||
> 从 [[index]] 导航。关联: [[data-layer]] [[erp-diary]] [[frontend]]
|
||
|
||
## 1. 设计决策
|
||
|
||
### Q: 为什么从 HMS 剥离而不是 fork?
|
||
|
||
独立 `base.git` 仓库(https://git.stableeasy.com/iven/base.git)作为通用 ERP 基座,多个项目可独立克隆后添加业务模块。fork 会将两个项目的 git 历史绑定,无法独立演进。
|
||
|
||
### Q: 为什么用 Feature Flag 组装模块?
|
||
|
||
`cargo build --features diary` 按需引入暖记模块。基座 crate(auth/config/message/workflow/plugin)不需要 diary 功能时零开销。
|
||
|
||
### Q: 为什么选 Flutter 而不是原生?
|
||
|
||
Android + iOS 跨平台首发。CustomPainter + Listener 手写性能满足 <16ms 目标,一套代码双端覆盖。
|
||
|
||
### Q: 为什么选 BLoC 不是 Provider/Riverpod?
|
||
|
||
编辑器、日历、同步引擎等复杂交互需要 Event/State 显式建模。BLoC 的单向数据流在复杂场景下比 Provider 更可控。
|
||
|
||
### 基座剥离 — 7 个耦合点
|
||
|
||
从 HMS 剥离到 base.git 时遇到的耦合及解决方案:
|
||
|
||
| 耦合点 | 问题 | 解决 |
|
||
|--------|------|------|
|
||
| main.rs 业务初始化 | 硬编码 health 模块注册 | 改为 Feature Flag 动态注册 |
|
||
| AppState 业务字段 | 嵌入 HealthState 等 | 改为 trait object / AnyMap |
|
||
| 迁移文件混合 | 基座 + 业务迁移在同一目录 | 按 prefix 分类,业务迁移独立 |
|
||
| 路由注册 | 业务路由写死在基座 | Module trait 的 routes() 方法 |
|
||
| 事件定义 | 业务事件在基座 crate | 各模块自定义 event.rs |
|
||
| 权限 seed | 业务权限码在基座迁移 | 各模块自带 seed 迁移 |
|
||
| Cargo.toml | 业务依赖在 workspace 根 | 各业务 crate 独立管理 |
|
||
|
||
## 2. 关键文件 + 数据流
|
||
|
||
### 仓库拓扑
|
||
|
||
```
|
||
HMS (G:\hms) [只读]
|
||
└─复制→ base.git (https://git.stableeasy.com/iven/base.git)
|
||
└─克隆→ nj.git (暖记 = 基座 + erp-diary + Flutter + 管理端)
|
||
```
|
||
|
||
### 三端架构
|
||
|
||
```
|
||
nj/
|
||
├── crates/ # 后端 (Rust Axum, :3000)
|
||
│ ├── erp-server/ # 入口 + diary feature flag
|
||
│ └── erp-diary/ # 暖记业务模块
|
||
├── apps/
|
||
│ └── web/ # 管理端 (React + Ant Design, :5174)
|
||
│ └── vite.config.ts # proxy /api → :3000
|
||
├── app/ # 学生端 (Flutter, :8080)
|
||
│ └── lib/features/ # 16 功能模块
|
||
├── scripts/dev.sh # 统一启动脚本 (自动清理端口)
|
||
└── config/default.toml # 环境配置 (CORS=*)
|
||
```
|
||
|
||
### 来源追溯
|
||
|
||
| 组件 | 来源 | 说明 |
|
||
|------|------|------|
|
||
| crates/erp-* (基座 6 个) | base.git | 零开发 |
|
||
| crates/erp-diary | 新增 | ~5100 行 Rust |
|
||
| apps/web/ | HMS apps/web/ | React 管理面板复用 |
|
||
| app/ (Flutter) | 新增 | ~19500 行 Dart |
|
||
| scripts/dev.sh | 新增 | 三端统一启动 |
|
||
|
||
### Cargo Workspace
|
||
|
||
```
|
||
nj/crates/
|
||
├── erp-core/ # 基座 — 模块系统/事件/加密/错误
|
||
├── erp-auth/ # 基座 — JWT/RBAC/用户/角色
|
||
├── erp-config/ # 基座 — 字典/菜单/设置
|
||
├── erp-message/ # 基座 — 消息/通知/SSE
|
||
├── erp-workflow/ # 基座 — BPMN 工作流
|
||
├── erp-plugin/ # 基座 — WASM 插件运行时
|
||
├── erp-server/ # Axum 入口 + 迁移 + 路由组装
|
||
└── erp-diary/ # 暖记业务模块 (~5,500 行新增)
|
||
```
|
||
|
||
### 集成契约
|
||
|
||
| 方向 | 模块 | 接口 | 触发时机 |
|
||
|------|------|------|---------|
|
||
| 被调用 ← | erp-server | `DiaryModule::new()` | 启动时 feature=diary |
|
||
| 调用 → | erp-core | `EventBus` | diary.created 等事件 |
|
||
| 调用 → | erp-auth | `require_permission()` | handler 层权限守卫 |
|
||
| 提供 → | erp-server | `routes()` + `entities()` | Axum 路由注册 |
|
||
|
||
## 3. 代码逻辑
|
||
|
||
### 不变量
|
||
|
||
⚡ **G:\hms 只读** — 绝不修改 HMS 源码,所有操作在 nj 仓库进行
|
||
|
||
⚡ **业务 crate 间无直接依赖** — erp-diary 不 import erp-health,只通过 EventBus 通信
|
||
|
||
⚡ **所有查询带 tenant_id** — 多租户中间件自动注入,API 路径不含 tenant_id
|
||
|
||
⚡ **软删除不硬删** — 所有 delete 操作设置 deleted_at,不做 DELETE FROM
|
||
|
||
⚡ **version 乐观锁** — 所有 Entity 的 version 字段用于同步冲突检测
|
||
|
||
### 多租户隔离策略
|
||
|
||
中间件从 JWT 提取 tenant_id → 注入请求扩展 → handler/service 层自动过滤。API 路径不含 tenant_id(`/api/v1/diary/...` 而非 `/{tenant}/diary/...`)。
|
||
|
||
### PIPL 合规
|
||
|
||
- 未满 14 岁必须家长授权
|
||
- 最小必要数据(昵称 + 年级,无需真实姓名)
|
||
- AES-256-GCM 加密 + TLS 传输
|
||
- 30 天内注销删除所有关联数据
|
||
- 班级码:6 位混合码,5 次错误锁定 30 分钟
|
||
|
||
## 4. 活跃问题 + 陷阱
|
||
|
||
| 问题 | 级别 | 状态 | 说明 |
|
||
|------|------|------|------|
|
||
| 管理端品牌仍是 HMS | HIGH | 待做 | 标题/Logo/颜色需替换为暖记品牌 |
|
||
| 管理端缺少暖记专用页面 | HIGH | 待做 | 班级管理/日记审核/贴纸管理等页面待添加 |
|
||
| Docker 部署未验证 | HIGH | 待做 | docker/ 配置完善但 Dockerfile 不存在 |
|
||
| 上下文窗口耗尽 | MEDIUM | 已缓解 | CLAUDE.md §8 会话交接机制 |
|
||
| Windows Defender 锁定 exe | MEDIUM | 需手动 | 排除 target/ 目录 |
|
||
| erp-plugin 超大文件 | LOW | 待重构 | manifest.rs 1809行 + data_service.rs 1907行 |
|
||
| Dashboard 部分数据加载失败 | LOW | 待做 | 统计 API 需适配暖记数据模型 |
|
||
|
||
### 历史教训
|
||
|
||
- 基座剥离耗时比预期长(7 个耦合点需逐一解耦)
|
||
- Isar 3.x 扩展方法不随传递 import 传播,必须显式 import
|
||
- Feature Flag 在基座剥离规划中设计完善,但实际实施时未落地到 Cargo.toml
|
||
|
||
## 5. 变更记录
|
||
|
||
| 日期 | 变更 |
|
||
|------|------|
|
||
| 2026-06-02 | 补充三端架构、管理端复用说明、更新活跃问题 |
|
||
| 2026-06-01 | 补充 Feature Flag 状态、超大文件发现 |
|
||
| 2026-06-01 | 初始创建 — 架构决策、基座剥离记录、集成契约 |
|