演示

工作原理

Quark ERP 的核心模块负责模块加载与基础能力;插件是你编写的业务应用。元数据与 pluginDependencies 决定身份、兼容性与启动顺序。

概述

系统分两层。核心模块是主宿主:发现模块、按依赖顺序加载,并提供认证、安全、DI、路由、内置数据、菜单与 SPA 核心等基础能力。插件是你编写的应用——库存、POS、HR 等领域的后端 API、数据表与 React 界面。

  • 核心 = 模块加载 + 基础平台能力
  • 插件 = 写在 plugins/<name>/ 下的应用
  • 加载发生在启动 / 浏览器侧,而非编译期单体
  • 禁止导入其他插件的 src/

1. 结构示意

运行时产品 = 核心 + 已安装插件。源码在 plugins/,构建在 available-plugins/,核心只加载 installed-plugins/。

  • 源码 — plugins/<name>/
  • 可用 — base/available-plugins/<name>/<version>/
  • 已安装 — base/backend/installed-plugins/<name>/
  • 目录名、metadata.name、包身份必须一致
SHproject layout
1base/ # core runtime (Docker) 2├── backend/ # core host process 3│ └── installed-plugins/<name>/ # active plugin copies 4├── frontend/ # SPA core (menus, chrome) 5└── available-plugins/<name>/<ver>/# staged builds 6 7plugins/<name>/ # your plugin app (edit here) 8├── backend/ 9├── frontend/ 10└── module.metadata.json # identity + dependencies

2. module.metadata.json

每个插件根目录都有 module.metadata.json。核心用它读取名称、版本、所需 base 线,以及必须先存在的其他插件。

  • name 用于安装行、DI 与依赖映射
  • requiredBasedVersion 须对齐运行中的核心
  • 重命名或升版本时同步元数据
  • 构建产物会带上同一份元数据
字段用途
name稳定插件 id — 须与目录名 / 安装身份一致
pluginVersion本插件 semver
description模块 / 安装界面说明
moduleEntryObject后端入口导出名(通常为 "Module")
requiredBasedVersion兼容的核心 / @quan-erp/* 版本线
pluginDependencies其他插件名 → 须先加载的 semver 范围
JSONplugins/inventory/module.metadata.json
1{ 2 "name": "inventory", 3 "type": "", 4 "pluginVersion": "1.0.0", 5 "description": "Inventory management", 6 "moduleEntryObject": "Module", 7 "requiredBasedVersion": "1.0.0", 8 "pluginDependencies": { 9 "products": "^1.0.0", 10 "accounting": "^1.0.0" 11 } 12}

3. 模块依赖

pluginDependencies 声明本模块需要的其他插件及其版本范围。核心按拓扑顺序先启动依赖方,再启动依赖者;缺失或不兼容会阻断正常启动。

  • 键是提供者的 metadata.name
  • 值是提供者 pluginVersion 的 semver 范围
  • 使用 @Inject(Service, "other-plugin") 或导出 API 时必须声明
  • {} 表示无插件依赖 — 仍可使用核心内置能力
  • 禁止 src 互导 — 用导出 / 注入
TSdependency map shape
"pluginDependencies": { "products": "^1.0.0", // provider name → semver of its pluginVersion "accounting": "^1.0.0" }

4. 核心如何加载模块

启动时合并文件系统构建与 module 表;仅已安装行会被激活。按依赖顺序加载后端,再在浏览器加载前端入口并 register(AppRegistry)。

  • available-plugins 在安装前不会生效
  • 仅属性 @Inject — 不支持构造函数注入
  • 详见模块生命周期与前端插件生命周期 Doc
  1. 01

    发现

    读取 installed-plugins 元数据并匹配 module 表。

  2. 02

    排序

    由 pluginDependencies 构图,提供者先于消费者。

  3. 03

    后端

    IPlugin → @Module → DI → @OnInit / @OnAllModuleLoaded。

  4. 04

    前端

    提供资源 → 动态导入 → 调用一次 register(AppRegistry)。

5. 下一步

运行核心栈,创建插件,并用 CLI watch / 安装循环迭代。

  • 禁止导入其他插件 src/
  • 对齐 @quan-erp/* 与 requiredBasedVersion
  • 目录名 = metadata.name
  • 跨插件注入前先写 pluginDependencies