# ERP 插件平台演进路线图 — 设计规格 > 日期: 2026-04-18 > 来源: 无主题发散式互动探讨 > 状态: Draft --- ## 1. 背景与动机 ERP 平台已完成 Phase 1-6 核心开发和 Q2-Q4 成熟度路线图。当前有两个行业插件(CRM + 进销存)运行在 WASM 插件系统上。通过分析发现四大系统性缺口: 1. **跨插件数据引用完全不支持** — 进销存的 `customer_id` 只能存裸 UUID 2. **插件无通用业务能力** — 导入导出/打印/配置/视图每个插件都要自己实现 3. **无质量保障机制** — 第三方插件的安全性和性能无法保证 4. **无发现和分发渠道** — 用户无法自助发现和安装插件 **目标:** 通过搭建财务/应收插件来验证和推动这些平台能力的实现。 **核心设计原则:** - 插件间**完全独立**,任何插件可自由安装/卸载,不受其他插件影响 - 跨插件引用**声明式**,通过 plugin.toml 零代码实现 - 通用业务能力**平台层提供**,插件声明式接入 - 外部引用问题永远是**软警告**,永不硬阻塞用户操作 --- ## 2. 跨插件数据引用系统 ### 2.1 Entity Registry (平台实体注册表) 插件安装时将其所有实体注册到平台级 Entity Registry,其他插件通过 registry 动态发现和引用。 **数据结构:** ``` entity_registry: - entity_name: string # 实体名 (如 "customer") - plugin_id: string # 注册该实体的插件 ID - display_fields: string[] # 用于下拉显示的字段列表 - search_fields: string[] # 用于搜索的字段列表 - status: active | inactive # 插件卸载时标记 inactive - registered_at: timestamp - tenant_id: uuid # 多租户隔离 ``` **生命周期:** - 插件安装 → 注册所有 entities 到 registry - 插件启用 → status = active - 插件禁用 → status = inactive(数据保留) - 插件卸载 → status = inactive + 标记为 orphaned ### 2.2 plugin.toml 扩展 ```toml # 可选依赖声明 [dependencies.crm] optional = true description = "客户管理 — 自动关联客户数据,未安装时客户字段为手动输入" [dependencies.inventory] optional = true description = "进销存 — 自动关联商品数据" # 跨插件引用字段 [[schema.entities.fields]] name = "customer_id" field_type = "uuid" display_name = "客户" ref_entity = "customer" # 目标实体名 ref_scope = "external" # "internal" (默认) | "external" ref_display_field = "name" # 下拉框显示字段 ref_search_fields = ["name", "phone"] # 搜索字段 ref_fallback_label = "外部客户" # 降级时显示文本 ``` ### 2.3 运行时行为 **写入时校验:** | 源插件状态 | 写入行为 | 读取行为 | 前端展示 | |-----------|---------|---------|---------| | 已安装 (active) | 强校验 UUID 存在性 | JOIN 富化 display_field | ✅ 绿色链接 "张三" | | 未安装 (inactive) | 无校验,接受任意 UUID | 返回原始 UUID | ⬜ 灰色 "外部客户" | | 刚重新启用 | 新写入强校验,不回溯已有 | 后台对账扫描 | ⚠️ 黄色警告 (悬空) | **悬空引用处理 (插件重新启用时):** 1. 后台扫描所有 `ref_scope=external` 且指向本插件实体的字段 2. 验证每个 UUID 是否存在于本插件表中 3. 生成对账报告: `{ valid: N, dangling: M, details: [...] }` 4. 前端展示对账结果,用户逐条处理(映射/清空/忽略) 5. 永不硬阻塞用户操作 ### 2.4 需要改造的文件 | 文件 | 改动 | 复杂度 | |------|------|--------| | `crates/erp-plugin/src/manifest.rs` | 新增 `ref_scope`, `ref_display_field`, `ref_search_fields`, `ref_fallback_label`; 新增 `DependenciesSection` | 低 | | `crates/erp-plugin/src/entity_registry.rs` (新) | 实体注册/发现/inactive 标记/对账 | 中 | | `crates/erp-plugin/src/data_service.rs` | `validate_ref_entities` 支持运行时发现外部引用 | 中 | | `crates/erp-plugin/src/host.rs` | 新增 `resolve_ref_entity` Host API | 中 | | `crates/erp-plugin/wit/plugin.wit` | 新增 `resolve-ref-entity` 接口 | 低 | | `crates/erp-plugin/src/service.rs` | 插件安装/卸载时维护 Entity Registry | 中 | | `apps/web/src/` 前端 | entity_select 组件支持跨插件数据源 + 降级显示 + 对账 UI | 高 | --- ## 3. 插件平台通用服务层 (P1) ### 3.1 数据导入导出服务 插件在 plugin.toml 中声明哪些实体支持导入导出,平台提供统一的导入导出 UI 和引擎。 ```toml [[schema.entities]] name = "invoice" display_name = "发票" importable = true exportable = true import_template = "invoice_import_template.xlsx" ``` **平台能力:** - 自动生成导入模板(基于 schema entities fields) - Excel/CSV 解析 + schema 字段校验 - 批量写入(支持事务 + 错误行级报告) - 导出为 Excel/CSV(支持筛选条件) - 导入历史记录 + 回滚 **实现位置:** `crates/erp-plugin/src/import_export.rs` + 前端 `ImportExportModal` 通用组件 ### 3.2 打印模板引擎 平台提供 HTML → PDF 的模板渲染能力,插件定义模板和字段映射。 ```toml [[templates]] name = "invoice_pdf" display_name = "发票" entity = "invoice" format = "pdf" template_file = "templates/invoice.html" ``` **平台能力:** - HTML 模板渲染 → PDF 下载 - 模板变量替换(基于实体字段) - 租户级模板自定义(覆盖默认模板) - 打印预览 ### 3.3 插件配置 UI 插件在 plugin.toml 中声明配置项,平台自动生成配置页面。 ```toml [settings] [[settings.fields]] name = "default_tax_rate" display_name = "默认税率" field_type = "number" default_value = 0.13 [[settings.fields]] name = "invoice_prefix" display_name = "发票前缀" field_type = "text" default_value = "INV" ``` **平台能力:** - 根据 settings 声明自动生成配置表单 - 配置数据存储在 `plugin_settings` 表(tenant_id + plugin_id + key/value) - 配置变更时通知插件(通过事件) - 支持配置权限控制(仅管理员可改) ### 3.4 自定义视图 用户可以保存列表页的列配置和筛选条件。 ``` user_views: - id: uuid - user_id: uuid - plugin_id: string - entity_name: string - view_name: string - columns: string[] - filters: json - sort: json - is_default: boolean ``` ### 3.5 通知规则 插件在 plugin.toml 中声明可触发的事件,平台提供通知规则配置 UI。 ```toml [[trigger_events]] name = "invoice.overdue" display_name = "发票逾期" description = "发票超过付款期限未收款" ``` **平台能力:** - 规则引擎: WHEN event THEN notify [user/role/department] - 复用 erp-message 的通知渠道 - 租户级规则配置 ### 3.6 编号规则 (已有基础扩展) 复用 erp-config 的编号规则服务,扩展为插件可接入。 ```toml [[numbering]] entity = "invoice" prefix = "INV" format = "{PREFIX}-{YEAR}-{SEQ:4}" reset_rule = "yearly" ``` --- ## 4. 插件质量保障 ### 4.1 上传时校验 ``` 插件上传 → Schema 校验 → WASM 二进制验证 → 安全扫描 → 性能基准 → 发布/拒绝 ``` | 阶段 | 校验内容 | 现状 | |------|---------|------| | Schema 校验 | plugin.toml 格式、字段类型、权限码一致性 | 部分已有 | | WASM 验证 | 二进制格式、WIT 兼容性、导出函数检查 | 已有 | | 安全扫描 | 动态表 SQL 注入风险、Fuel 耗尽、内存泄漏 | 缺失 | | 性能基准 | 标准 CRUD 操作在 N 条数据下的响应时间 | 缺失 | | 兼容性 | 平台版本匹配、依赖插件版本兼容 | 缺失 | ### 4.2 运行时监控 ``` plugin_runtime_metrics: - plugin_id: string - error_rate: float - avg_response_ms: float - fuel_consumption: float - memory_peak_mb: float - active_instances: int ``` **告警规则:** 错误率 > 5% / 平均响应 > 2s / Fuel 消耗异常 / 内存持续增长 --- ## 5. 插件市场/商店 | 功能 | 说明 | |------|------| | 插件目录 | 按行业/功能分类浏览 | | 搜索 | 按名称/标签/行业搜索 | | 详情页 | 截图、演示、功能描述、权限说明 | | 一键安装 | 上传 → 自动安装 → 配置 → 启用 | | 评分/评论 | 用户评分和使用反馈 | | 版本管理 | 版本列表、更新日志、回滚 | | 依赖提示 | 安装时提示可选依赖 | --- ## 6. 验证计划 — 财务/应收插件 ### 6.1 实体设计 | 实体 | 字段概要 | 跨插件引用 | |------|---------|-----------| | invoice (发票) | 编号/客户/金额/税额/状态/到期日 | customer_id → CRM.customer | | invoice_line (发票行) | 发票/商品/数量/单价/税额 | product_id → Inventory.product | | payment (收款) | 发票/金额/方式/日期/状态 | invoice_id → 本插件内部 | | quote (报价单) | 编号/客户/有效期/状态 | customer_id → CRM.customer | | quote_line (报价行) | 报价单/商品/数量/单价 | product_id → Inventory.product | ### 6.2 验证矩阵 | 能力 | 验证方式 | 预期结果 | |------|---------|---------| | 跨插件引用 (CRM 安装) | 创建发票时选择客户 | entity_select 下拉显示 CRM 客户列表 | | 跨插件引用 (CRM 卸载) | 创建发票时输入客户 | 降级为文本输入,不阻塞 | | 悬空引用对账 | CRM 卸载→创建发票→重新安装 CRM | 对账报告显示悬空引用,用户可修复 | | 数据导入 | 导入 Excel 客户清单 | 解析+校验+批量写入 | | 数据导出 | 导出发票列表为 Excel | 筛选+下载 | | 打印模板 | 打印发票 PDF | HTML→PDF 渲染 | | 插件配置 | 设置税率/发票前缀 | 自动生成的配置页面 | | 编号规则 | 创建发票自动编号 | INV-2026-0001 | | 通知规则 | 发票逾期通知 | 规则引擎触发通知 | | 独立安装 | 不安装 CRM 单独安装财务 | 所有功能正常,客户字段降级 | --- ## 7. 实施优先级 ``` P0 (已完成/进行中): P0 平台能力升级 + 插件系统增强 P1 (跨插件引用): Entity Registry + ref_scope 扩展 + 前端 entity_select 改造 这是所有后续能力的基础 P2 (平台通用服务): 数据导入导出 → 插件配置 UI → 编号规则扩展 → 通知规则 P3 (质量保障): 上传时安全扫描 → 性能基准 → 运行时监控 P4 (插件市场): 插件目录 → 一键安装 → 版本管理 → 评分评论 验证: 财务/应收插件贯穿 P1-P2,每完成一个 P 就用财务插件验证 ``` --- ## 8. 风险与缓解 | 风险 | 影响 | 缓解措施 | |------|------|---------| | Entity Registry 查询性能 | 每次数据操作都要查注册表 | 内存缓存 + DashMap,注册表数据量极小 | | 悬空引用数据量过大 | 对账扫描耗时长 | 异步后台任务 + 分批处理 + 进度条 | | Excel 导入内存占用 | 大文件解析 OOM | 流式解析 + 批量提交 + 文件大小限制 | | 打印模板安全 | 模板注入攻击 | 沙箱渲染 + 变量白名单 | | 插件市场审核成本 | 人工审核效率低 | 自动化扫描 + 人工抽查 + 社区举报 | --- ## 9. 讨论溯源 本文档基于 2026-04-18 的无主题发散式互动探讨产出,完整讨论过程记录在 `plans/skill-cosmic-pancake.md`。 关键决策历程: - **Round 1:** 发现跨插件数据引用完全不支持(进销存的 customer_id 是裸 UUID) - **Round 2:** 确定声明式引用 + 完全独立(无硬依赖)+ 软警告对账方案 - **Round 3:** 确定导入导出/打印/配置/视图/通知应为平台通用服务 - **Round 4:** 收敛为统一设计规格,以财务插件为验证载体