Files
erp/CLAUDE.md
iven ff352a4c24 feat(plugin): 集成 WASM 插件系统到主服务并修复链路问题
- 新增 erp-plugin crate:插件管理、WASM 运行时、动态表、数据 CRUD
- 新增前端插件管理页面(PluginAdmin/PluginCRUDPage)和 API 层
- 新增插件数据迁移(plugins/plugin_entities/plugin_event_subscriptions)
- 新增权限补充迁移(为已有租户补充 plugin.admin/plugin.list 权限)
- 修复 PluginAdmin 页面 InstallOutlined 图标不存在的崩溃问题
- 修复 settings 唯一索引迁移顺序错误(先去重再建索引)
- 更新 wiki 和 CLAUDE.md 反映插件系统集成状态
- 新增 dev.ps1 一键启动脚本
2026-04-15 23:32:02 +08:00

18 KiB
Raw Permalink Blame History

@wiki/index.md 整个项目对话都使用中文进行,包括文档、代码注释、事件名称等。

ERP 平台底座 — 协作与实现规则

ERP Platform Base 是一个模块化的商业 SaaS ERP 底座,目标是提供核心基础设施(身份权限、工作流、消息、配置),使行业业务模块(进销存、生产、财务等)可以快速插接。

当前阶段: Phase 1 基础设施搭建。 从零构建 Rust workspace + Web 前端 + 核心共享层。

1. 项目定位

1.1 这是什么

一个 底座 + 行业插件 架构的商业 SaaS ERP 平台:

  • 全功能底座 — 身份权限、工作流引擎、消息中心、系统配置
  • 渐进式扩展 — 从小微企业起步,逐步支持中大型企业
  • 多租户 + 私有化 — 默认 SaaS 共享数据库隔离,支持独立 schema 私有部署
  • Web 优先 — 浏览器 SPA 是主力,可选 Tauri 桌面端用于特定行业场景

1.2 决策原则

任何改动都要问:这对 ERP 底座的模块化和可扩展性有帮助吗?

  • 完善模块接口和 trait 定义 → 最高优先
  • 确保多租户隔离的正确性 → 最高优先
  • 按计划推进 Phase 交付物 → 高优先
  • 清晰的模块边界和事件契约 → 高优先
  • 跳过 Phase 顺序提前实现远期功能 → 禁止
  • 在模块间创建直接耦合 → 永远不做
  • 硬编码租户 ID 或绕过多租户中间件 → 永远不做
  • 过度设计未来才需要的能力 → 永远不做

1.3 架构铁律

约束 原因
模块间只通过事件总线和 trait 通信 保证模块可独立拆分为微服务
所有数据表必须含 tenant_id 多租户是核心能力,不可事后补
使用 UUID v7 作为主键 时间排序 + 唯一性,分布式友好
软删除,不硬删除 ERP 数据不可丢失,审计追溯需要
所有 API 使用 /api/v1/ 前缀 版本化是 SaaS 产品的基本要求

2. 项目结构

erp/
├── crates/                    # Rust Workspace
│   ├── erp-core/             # L1: 基础类型、错误、事件、模块 trait
│   ├── erp-common/           # L1: 共享工具、宏
│   ├── erp-auth/             # L2: 身份与权限模块
│   ├── erp-workflow/         # L2: 工作流引擎模块
│   ├── erp-message/          # L2: 消息中心模块
│   ├── erp-config/           # L2: 系统配置模块
│   └── erp-server/           # L3: Axum 服务入口,组装所有模块
│       └── migration/        # SeaORM 数据库迁移
├── apps/
│   └── web/                  # Vite + React 18 SPA (主力前端)
├── packages/
│   └── ui-components/        # React 共享组件库
├── desktop/                  # (可选) Tauri 桌面端,行业需要时启用
├── docker/                   # Docker 开发环境配置
├── docs/                     # 文档
│   └── superpowers/
│       ├── specs/            # 设计规格文档
│       └── plans/            # 实施计划
├── Cargo.toml                # Workspace root
└── CLAUDE.md                 # 本文件 — 协作规则

2.1 Crate 依赖关系

erp-core            (无业务依赖)
erp-common          (无业务依赖)
    ↑
erp-auth            (→ core)
erp-config          (→ core)
erp-workflow        (→ core)
erp-message         (→ core)
    ↑
erp-server          (→ 所有 crate组装入口)

规则:

  • erp-coreerp-common 不依赖任何业务 crate
  • 业务 crate 之间禁止直接依赖,只通过事件总线和 erp-core trait 通信
  • erp-server 是唯一的组装点

2.2 技术栈

层级 技术
后端框架 Axum 0.8 + Tokio
ORM SeaORM (异步、类型安全)
数据库 PostgreSQL 16+
缓存 Redis 7+
前端框架 React 18 + TypeScript (Vite)
UI 组件库 Ant Design 5
状态管理 Zustand
路由 React Router 7
样式 TailwindCSS + CSS Variables
API 文档 utoipa (OpenAPI 3)

3. 工作风格

3.1 按计划推进

  • 严格按 Phase 顺序执行 — Phase 2 依赖 Phase 1 的基础设施
  • 每个 Task 完成后立即提交 — 不积压,保持可追溯
  • 先测试后实现 — TDD 流程:写失败测试 → 实现 → 通过 → 提交

3.2 模块化思维

开发任何功能时先问:

  1. 它属于哪个模块? — 不确定就放到 erp-core 共享层
  2. 它的接口是什么? — 先定义 trait再实现
  3. 它需要发什么事件? — 跨模块通知必须走事件总线
  4. 其他模块怎么发现它? — 通过 ErpModule trait 注册

3.3 闭环工作法(强制)

每次改动必须按顺序完成以下步骤,不允许跳过:

  1. 理解需求 — 确认改动的目标模块和影响范围
  2. 最小实现 — 只改必要的代码,保持模块边界
  3. 自动验证cargo check / cargo test / pnpm dev 必须通过
  4. 提交 — 按 §10 规范提交
  5. 文档同步 — 更新相关文档(如果涉及架构变化)

铁律:步骤 4 是任务完成的硬性条件。不允许"等一下再提交"。


4. 实现规则

4.1 错误处理

  • 跨 crate 边界:使用 thiserror 定义类型化错误,转换为 AppError
  • crate 内部:可以使用 anyhow,但永远不跨越 crate 边界
  • 数据库错误:通过 From<sea_orm::DbErr> 自动转换为 AppError
  • 验证错误:包含字段级详情,方便 UI 渲染

4.2 数据库操作

  • 所有 SeaORM Entity 必须包含:id, tenant_id, created_at, updated_at, created_by, updated_by, deleted_at, version
  • 查询时始终tenant_id 过滤(中间件自动注入)
  • 更新时检查 version 字段实现乐观锁
  • 删除使用软删除(设置 deleted_at

4.3 API 设计

  • 所有端点使用 /api/v1/ 前缀
  • 响应统一使用 ApiResponse<T> 包装
  • 分页使用 Pagination + PaginatedResponse<T>
  • utoipa 自动生成 OpenAPI 文档
  • 租户 ID 从 JWT 中间件注入,不在 API 路径中传递(管理员接口除外)

4.4 事件总线

  • 模块间通信只能通过 EventBus
  • 事件必须持久化到 domain_eventsoutbox 模式)
  • 事件处理失败记录到 dead-letter 存储
  • 事件类型命名:{模块}.{动作}user.created, workflow.task.completed

4.5 Rust 代码规范

// 命名snake_case (函数/变量), PascalCase (类型/trait), SCREAMING_SNAKE (常量)
// 模块公开接口通过 lib.rs 统一导出
// 每个 public 函数和 trait 必须有文档注释
// 异步函数返回 Result 时使用 AppResult<T> 类型别名
// 数据库操作使用 SeaORM 的 Entity + Model + Relation 模式

4.6 TypeScript / React 代码规范

// 避免 any优先 unknown + 类型守卫
// 函数组件 + hooks
// 复杂状态收敛到 Zustand store
// API 调用封装到独立的 service 层,不在组件中直接 fetch
// 使用 Ant Design 组件,不自行实现已有组件
// 国际化文案使用 i18n key不硬编码中文

5. 模块开发规范

5.1 新建业务模块清单

每个新模块(如 erp-auth, erp-workflow必须包含:

  1. Cargo.toml — 依赖 erp-core
  2. src/lib.rs — 模块入口,实现 ErpModule trait
  3. src/error.rs — 模块错误类型wrap AppError
  4. src/entity/ — SeaORM Entity 定义
  5. src/service/ — 业务逻辑层
  6. src/handler/ — Axum 路由处理器
  7. src/event.rs — 模块事件定义和处理器

5.2 ErpModule trait 实现

pub struct AuthModule;

impl ErpModule for AuthModule {
    fn name(&self) -> &str { "auth" }
    fn version(&self) -> &str { env!("CARGO_PKG_VERSION") }
    fn dependencies(&self) -> Vec<&str> { vec![] }  // auth 是基础模块,无依赖

    fn register_routes(&self, router: Router) -> Router {
        router.nest("/api/v1", auth_routes())
    }

    fn register_event_handlers(&self, bus: &EventBus) {
        // 订阅其他模块的事件
    }

    async fn on_tenant_created(&self, tenant_id: Uuid) -> AppResult<()> {
        // 初始化默认角色、管理员等
        Ok(())
    }
}

5.3 数据库迁移

  • 迁移文件放在 crates/erp-server/migration/src/
  • 命名格式:m{YYYYMMDD}_{6位序号}_{描述}.rs
  • 迁移必须可回滚(实现 down 方法)
  • 新增表必须包含所有标准字段§1.3
  • 迁移必须幂等(使用 if_not_exists

6. 测试与验证

6.1 测试要求

测试类型 覆盖目标 工具
单元测试 每个 service 函数 #[cfg(test)] + tokio::test
集成测试 API 端点 → 数据库 cargo test + 真实 PostgreSQL
多租户测试 数据隔离验证 独立测试 crate
前端测试 组件交互 Vitest (未来)

6.2 验证命令

# 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"

6.3 Phase 完成标准

每个 Phase 完成时必须满足:

  • cargo check 全 workspace 通过
  • cargo test 全部通过
  • Docker 环境正常启动
  • 所有迁移可正/反向执行
  • API 端点可通过 Swagger UI 测试
  • 桌面端可正常启动并展示对应 UI
  • 所有代码已提交

7. 安全注意事项

7.1 认证安全

  • 密码存储: Argon2 哈希,禁止明文
  • JWT: access token 15min + refresh token 7d
  • Refresh Token 轮换: 每次使用后签发新的,旧的作废
  • Token 存储: 桌面端使用 Tauri secure store
  • 密码修改: 使所有已签发的 JWT 失效

7.2 多租户安全

  • 中间件注入: tenant_id 从 JWT 中提取,应用层不可伪造
  • 数据隔离: 所有查询自动过滤 tenant_id
  • 越权防护: 禁止跨租户数据访问
  • 租户 provisioning: on_tenant_created 钩子初始化数据

7.3 通用安全

  • 不硬编码密钥 — 使用环境变量或配置文件
  • 用户输入验证 — 所有 API 端点验证输入
  • SQL 注入防护 — SeaORM 参数化查询
  • 限流 — Redis token bucket登录等敏感接口限流
  • CORS — 白名单制,默认拒绝
  • 审计日志 — 所有关键操作记录变更前后状态

8. 桌面端 UI 规范

8.1 布局结构

经典 SaaS 后台管理布局(响应式,支持移动端):

┌─────────────────────────────────────────────┐
│  LOGO    搜索...        🔔 5  👤 Admin  ▾   │  ← 顶部导航栏
├─────────┬───────────────────────────────────┤
│ 📊 首页 │                                   │
│ 👥 用户 │         主内容区域                │
│ 🔐 权限 │         (多标签页切换)            │
│ 📋 流程 │                                   │
│ 💬 消息 │                                   │
│ ⚙️ 设置 │                                   │
│─────────│                                   │
│ 📦 进销存│                                   │
│ 🏭 生产  │                                   │
│ 💰 财务  │                                   │
│─────────│                                   │
│ ▸ 更多  │                                   │
└─────────┴───────────────────────────────────┘

8.2 UI 规则

  • 使用 Ant Design 组件库,不自造轮子
  • 中文优先,所有文案通过 i18n key 引用
  • 支持暗色/亮色主题切换
  • 侧边栏按模块分组:基础模块 / 行业模块
  • 表单验证使用 Ant Design Form 的 validateRules

9. 常用命令

# === Rust ===
cargo check                        # 编译检查
cargo test --workspace             # 运行所有测试
cargo run -p erp-server            # 启动后端服务
cargo fmt --check                  # 检查格式
cargo clippy -- -D warnings        # Lint 检查

# === Docker ===
cd docker && docker compose up -d  # 启动 PostgreSQL + Redis
docker compose -f docker/docker-compose.yml ps   # 查看服务状态
docker compose -f docker/docker-compose.yml down  # 停止服务

# === 前端 ===
cd apps/web && pnpm install        # 安装依赖
cd apps/web && pnpm dev            # 开发模式
cd apps/web && pnpm build          # 构建生产版本

# === 数据库 ===
docker exec -it erp-postgres psql -U erp  # 连接数据库

# === WASM 插件 ===
cargo build -p erp-plugin-test-sample --target wasm32-unknown-unknown --release  # 编译测试插件
wasm-tools component new target/wasm32-unknown-unknown/release/erp_plugin_test_sample.wasm -o target/erp_plugin_test_sample.component.wasm  # 转为 Component
cargo test -p erp-plugin-prototype  # 运行插件集成测试

# === 一键启动 (PowerShell) ===
.\dev.ps1                 # 启动前后端(自动清理端口占用)
.\dev.ps1 -Stop           # 停止前后端
.\dev.ps1 -Restart        # 重启前后端
.\dev.ps1 -Status         # 查看端口状态

10. 提交规范

<type>(<scope>): <description>

类型:

  • feat — 新功能
  • fix — 修复问题
  • refactor — 重构
  • docs — 文档更新
  • test — 测试相关
  • chore — 杂项(构建、配置等)
  • perf — 性能优化

Scope 对应 crate 或模块名:

scope 范围
core erp-core
common erp-common
auth erp-auth
workflow erp-workflow
message erp-message
config erp-config
server erp-server
plugin erp-plugin-prototype / erp-plugin-test-sample
web Web 前端
ui React 组件
db 数据库迁移
docker Docker 配置

示例:

feat(auth): 添加用户管理 CRUD
feat(core): 实现事件总线和模块注册
fix(server): 修复数据库连接池配置
refactor(auth): 拆分 RBAC 和 ABAC 权限模型
chore(docker): 添加 PostgreSQL 健康检查

11. 设计文档索引

文档 说明
docs/superpowers/specs/2026-04-10-erp-platform-base-design.md 平台底座设计规格
docs/superpowers/plans/2026-04-10-erp-platform-base-plan.md 平台底座实施计划
docs/superpowers/specs/2026-04-13-wasm-plugin-system-design.md WASM 插件系统设计规格
docs/superpowers/plans/2026-04-13-wasm-plugin-system-plan.md WASM 插件原型验证计划

所有设计决策以设计规格文档为准。实施计划按阶段拆分,每阶段开始前细化。


12. 当前架构快照

开发进度

Phase 内容 状态
Phase 1 基础设施 (workspace + core + Docker + 桌面端) 完成
Phase 2 身份与权限 (Auth) 完成
Phase 3 系统配置 (Config) 完成
Phase 4 工作流引擎 (Workflow) 完成
Phase 5 消息中心 (Message) 完成
Phase 6 整合与打磨 完成
- WASM 插件原型 (V1-V6) 验证通过
- 插件系统集成到主服务 已集成

已实现模块

Crate 功能 状态
erp-core 错误类型、共享类型、事件总线、ErpModule trait、审计日志 完成
erp-common 共享工具 完成
erp-server Axum 服务入口、配置、数据库连接、CORS 完成
erp-auth 身份与权限 (用户/角色/权限/组织/部门/岗位) 完成
erp-workflow 工作流引擎 (BPMN 解析/Token 驱动/任务分配) 完成
erp-message 消息中心 (CRUD/模板/订阅/通知面板) 完成
erp-config 系统配置 (字典/菜单/设置/编号规则/主题) 完成
erp-plugin 插件管理 (WASM 运行时/生命周期/动态表/数据CRUD) 已集成
erp-plugin-prototype WASM 插件 Host 运行时 (Wasmtime + bindgen + Host API) 原型验证
erp-plugin-test-sample WASM 测试插件 (Guest trait + Host API 回调) 原型验证

13. 反模式警告

  • 不要在业务 crate 之间创建直接依赖 — 只通过事件和 trait 通信
  • 不要跳过多租户中间件 — 所有数据操作必须带 tenant_id 过滤
  • 不要硬编码配置值 — 使用 config.toml + 环境变量
  • 不要跳过迁移直接建表 — 所有 schema 变更通过 SeaORM Migration
  • 不要在前端组件中直接调用 HTTP — 封装到 service 层
  • 不要使用 anyhow 跨越 crate 边界 — 内部可用,对外必须转 AppError
  • 不要假设只有单租户 — 从第一天就按多租户设计
  • 不要提前实现远期功能 — 严格按 Phase 计划推进
  • 不要忽略 version 字段 — 所有更新操作必须检查乐观锁

场景化指令

  • 当遇到新增模块 → 实现 ErpModule traiterp-server 注册
  • 当遇到跨模块通信 → 定义事件类型,通过 EventBus 发布/订阅
  • 当遇到数据查询 → 确保包含 tenant_id 过滤,检查软删除条件
  • 当遇到新增 API → 添加 utoipa 注解,确保 OpenAPI 文档同步
  • 当遇到新增表 → 创建 SeaORM migration + Entity包含所有标准字段
  • 当遇到新增页面 → 使用 Ant Design 组件i18n key 引用文案
  • 当遇到新增业务模块插件 → 参考 wiki/wasm-plugin.md 的插件制作完整流程,创建 cdylib crate + 实现 Guest trait + 编译为 WASM Component