Files
workspace/code/fms/FMS元数据驱动架构重构方案.md
T
2026-10-11 22:14:13 +08:00

435 lines
30 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.
# FMS 元数据驱动架构整体重构方案
> 文档版本:V0.1(方案草案)
> 编制日期:2026-10-10
> 范围:元数据模型、模块配置、模块运行时及相关数据库结构
> 状态:待评审,尚未实施
## 1. 结论摘要
本次重构保留并强化**元数据驱动**这一核心概念。模块定义、字段语义、关系、页面视图和通用行为由元数据描述,通用运行时读取已发布的元数据运行;列表、查询、保存、权限、关系、工作流和公式等能力统一通过通用接口执行,复杂逻辑由 SQL、函数库和业务处理器补充。
项目属于草稿 / Demo 阶段,不要求兼容现有元数据表结构和配置 JSON。可以重做元数据数据库,并整体替换配置和运行时主链路;不需要新旧格式长期双写或并行维护。
```text
物理数据源与表结构 → 模块元数据 → 模板 / 默认值 → 校验 / 编译 / 发布
↓
统一模块运行时 + 通用代码协议 → SQL 业务表 / 视图
```
SQL Server 中的真实业务表和视图继续作为业务数据事实来源。元数据描述如何理解、呈现和操作这些数据,通用 SQL、函数库和业务处理器协议可以补充复杂逻辑;不采用 EAV 存储所有业务记录,也不让元数据引擎任意生成业务表。
## 2. 重构目标与边界
- 元数据仍是通用模块的运行时核心,不退化为页面备注或少量展示配置。
- 常见模块通过数据源、模板和少量字段选择即可完成基础配置。
- 一个字段只定义一次;列表、表单、查询、详情等视图引用字段,不重复维护语义。
- 默认配置可推导、可重复生成;用户明确调整过的配置不被覆盖。
- 元数据发布前经过统一校验,运行时消费同一份有效定义。
- 元数据数据库可以整体重做,不受 `s_module`、`s_field`、`s_module_schema` 现有结构约束。
- 列表、查询、保存、权限、关系、工作流和公式均提供元数据默认实现,并保留统一 SQL / 函数库 / 业务处理器协议。
- 后端通过通用接口绑定 SQL、函数和处理器,不为具体模块增加特殊 API,也不在元数据中保存可执行代码。
- 不将所有字段值改为 EAV 或通用 JSON;业务表仍通过 SQL migration / 数据库变更管理。
- 不建设可执行任意脚本的规则引擎,不把库存、财务、结算等复杂事务强行塞进配置;复杂逻辑通过受控的代码扩展实现。
- 不为本次目标无差别重写认证、文件、导出等稳定模块,只调整必要集成点。
- 不要求兼容旧元数据格式;需要保留的 Demo 数据可一次性导入,否则重建 / 播种。
## 3. 总体架构
```text
┌──────────────────── 配置面 ────────────────────┐
│ 元数据工作台 → 草稿定义 → 校验 / 预览 → 发布版本 │
└────────────────────────┬───────────────────────┘
↓
元数据目录 / 发布快照
↓
┌──────────────────── 运行面 ────────────────────┐
│ 元数据解析与缓存 → 查询 / 保存 / 权限 / 页面渲染 │
└────────────────────────┬───────────────────────┘
↓
SQL Server 表、视图与只读查询 SQL
↓
统一模块接口、SQL、函数库及业务处理器
```
### 配置面
工作台负责选择数据源、导入物理字段、指定业务语义、应用模板、调整视图并预览。编辑内容为草稿,通过校验后才能发布。
### 元数据编译与校验
后端维护权威校验与解析逻辑。发布时将模块定义、模板默认值和用户覆盖项合成为有效定义,并检查字段引用、数据源、视图、关系和查询条件。前端预览使用后端返回的有效定义,避免前后端分别推导默认规则。
### 运行面
后端只提供统一的模块接口。统一接口读取已发布的 `ModuleDefinition`,负责列表、查询、保存、权限、关系、工作流和公式等通用能力;查询值参数化,保存和动作在统一事务上下文中执行。SQL、公式函数和业务代码作为通用接口内部的实现来源,不为每个模块新增专用 API。
### 通用接口与代码控制
每项能力都遵循同一套调用方式:
1. 元数据提供模块、字段、视图、关系和默认规则。
2. 通用接口根据模块定义执行默认列表、查询、保存、权限、关系、工作流和公式逻辑。
3. 需要代码控制时,在通用接口内部调用统一的 SQL、函数或业务处理器协议;调用方式不随模块变化。
| 能力 | 元数据默认职责 | 代码扩展或接管职责 |
|---|---|---|
| 列表 | 数据源、字段、过滤、排序、分页和列展示 | 自定义查询、聚合、行转换和复杂数据范围 |
| 查询 | 条件字段、操作符、条件组和参数定义 | 特殊条件解析、跨表查询和只读 SQL |
| 保存 | 标准增删改、字段校验、主键和关系处理 | 事务编排、状态流转、库存扣减和保存前后钩子 |
| 权限 | 模块、字段、角色和数据范围声明 | 上下文权限判断、动态授权和特殊拒绝规则 |
| 关系 | 主从、引用、多对多和加载规则 | 复杂关联加载、级联校验和同步逻辑 |
| 工作流 | 节点、连线、参与者和状态定义 | 审批条件、业务动作、会签规则和外部调用 |
| 公式 | 表达式、字段依赖和受限通用函数 | 通用函数库、复杂计算、跨单据取数和异步计算 |
代码实现通过后端统一注册表或 SQL 目录管理,不在数据库中保存 Java 类名、脚本或任意可执行内容。通用权限约束不能被业务代码绕过;业务代码可以补充通用接口的规则。模块只声明需要的标准能力和参数,不声明专用接口。
## 4. 元数据逻辑模型
运行时使用统一逻辑对象 `ModuleDefinition`。它是稳定契约,不要求与单张数据库表或单个 JSON 一一对应。
### 模块
包含稳定编码、名称、多语言键、类型、状态、组织层级、查询数据源、标准保存目标 / 主键、数据范围字段、字段、关系、视图、模板和发布版本。模块类型收敛为少数明确类别,如标准数据、只读查询、业务动作模块。
### 字段
区分物理事实和业务语义:
- **物理事实**:来源表 / 视图、列名、SQL 类型、长度、精度、可空性等,优先由数据库结构检查得到,不重复手工维护。
- **业务语义**:标签、多语言键、语义类型、关联目标、是否可编辑 / 列表展示 / 查询 / 排序 / 导出等,由元数据表达。
- **界面属性**:控件、宽度、格式等仅在需要覆盖默认值时配置。
字段使用模块内稳定编码;视图引用字段编码,不复制物理属性和业务语义。
### 关系、视图与行为
- 关系元数据表达主从、引用和多对多关系,包含源 / 目标模块字段及规则,发布时校验完整性。
- 表单、列表、查询、详情是不同视图类型,只保存顺序、分组、布局、列宽、排序、操作符等视图特有信息;布局采用可读、可校验的结构化定义,不保存画布坐标。
- 字段参与视图的默认状态由字段能力、模板和默认策略推导;个性化差异作为显式覆盖。
- 简单校验和通用 CRUD 可由元数据表达;复杂业务动作映射到稳定的后端处理器编码。
- 列表、查询、保存、权限、关系、工作流和公式通过统一模块接口接入;这些能力引用模块定义和已发布快照,不为每个模块建立特殊接口。
## 5. 元数据数据库重构
以下是逻辑实体职责,最终表名和列定义在元数据契约评审后确定。可重做元数据表结构,但业务记录仍存放于真实 SQL 表。
| 逻辑实体 | 职责 | 建议存储 |
|---|---|---|
| 模块 | 身份、类型、状态、树结构、数据源和通用运行参数 | 规范化关系表 |
| 模块字段 | 字段编码、物理映射、业务语义、能力标记 | 规范化关系表;模块内编码唯一 |
| 模块关系 | 关系类型及源 / 目标字段 | 规范化关系表;发布时校验引用 |
| 模块视图 | 表单、列表、查询、详情及布局 | `s_module_schema`,按视图类型保存受校验 JSON |
| 模板 | 默认字段能力、视图结构、推荐规则 | 可版本化定义 |
| 发布版本 | 不可变快照、版本号、校验结果、发布时间 | 版本记录;运行时按已发布版本读取 |
### 推荐目标表结构
建议继续使用现有的 `s_` 前缀和核心表。后端是通用接口,因此不再为数据源、视图和代码扩展分别增加运行时表:模块数据源保留在 `s_module`,视图 JSON 保留在 `s_module_schema`,复杂代码由后端统一实现和注册。只新增发布版本和快照表解决草稿与运行态隔离。
| 目标实体 | 关键字段 / 组成 | 说明 |
|---|---|---|
| 模块 `s_module` | 模块编码、父级、名称、多语言键、模块类型、查询/保存来源、主键、数据范围和默认排序 | 保留当前模块主表,清理无约束的大 JSON;数据源由通用接口读取 |
| 模块字段 `s_field` | 模块、字段编码、来源类型、来源名称/别名、名称、多语言键、语义类型、字段能力、启用状态 | 支持物理列、查询别名、计算字段和虚拟字段;物理 SQL 类型仍优先从数据库读取 |
| 模块视图 `s_module_schema` | 模块、视图类型、结构版本、`b_schema_json` | JSON 保存分组、字段引用、列属性、查询条件、控件和公式;发布时统一校验 |
| 模块关系 `s_relation` | 关系编码、源/目标模块字段、关系类型、用途、基数、加载规则、删除策略 | 发布时校验模块和字段引用,保留现有删除语义 |
| 模块版本 `s_module_version` | 模块、版本号、草稿/已发布/废弃状态、校验摘要、发布人、发布时间 | 管理草稿与当前有效版本边界 |
| 发布快照 `s_module_snapshot` | 版本、编译后的 `ModuleDefinition`、快照摘要、生成时间 | 运行时只读取不可变快照,不直接读取编辑态表 |
| 模板及模板版本 `s_template` / `s_template_version` | 模板编码、版本、默认字段能力、视图 JSON、推荐规则 | 模板是可编辑初始值,不是硬编码页面 |
| 用户偏好 `s_user_module_pref` | 用户、模块、视图、相对默认值的覆盖 | 可选保留,只能改变布局偏好,不能改变语义、权限或数据源 |
`s_module_schema.b_schema_json` 不是无约束 JSON:必须包含 `schemaVersion`,只能引用本模块已登记的字段和关系,并由后端 JSON Schema 和发布校验共同约束。编辑态以 `s_module_schema` 为事实来源,发布后编译成 `s_module_snapshot`。
### 推荐 DDL(示例)
```sql
create table dbo.s_module (
b_id varchar(80) not null primary key,
b_parent_id varchar(80) null,
b_depth int not null default 0,
b_path varchar(1500) not null,
b_name nvarchar(200) not null,
b_i18n varchar(150) null,
b_module_type varchar(20) not null, -- module / data / virtual
b_view_table varchar(256) null,
b_save_table varchar(256) null,
b_key_field varchar(80) null,
b_scope_field varchar(80) null,
b_order_sql varchar(500) null,
b_query_sql nvarchar(max) null,
b_config_json nvarchar(max) null,
b_canuse tinyint not null default 1,
b_xh int not null default 0,
b_bz nvarchar(2000) null,
b_updated_by varchar(50) null,
b_updated_at datetime2 null
);
create table dbo.s_field (
b_module_id varchar(80) not null,
b_field varchar(80) not null,
b_source_type varchar(20) not null, -- physical / alias / computed / virtual
b_source_name varchar(256) null,
b_name nvarchar(200) not null,
b_i18n varchar(150) null,
b_semantic_type varchar(40) not null,
b_can_read tinyint not null default 1,
b_can_edit tinyint not null default 0,
b_can_filter tinyint not null default 0,
b_can_sort tinyint not null default 0,
b_can_export tinyint not null default 0,
b_canuse tinyint not null default 1,
b_xh int not null default 0,
primary key (b_module_id, b_field)
);
create table dbo.s_module_schema (
b_module_id varchar(80) not null,
b_schema_type varchar(20) not null, -- view / edit / query / detail
b_schema_version int not null default 1,
b_schema_json nvarchar(max) not null,
b_canuse tinyint not null default 1,
b_updated_by varchar(50) null,
b_updated_at datetime2 null,
primary key (b_module_id, b_schema_type)
);
create table dbo.s_relation (
b_relation_code varchar(100) not null primary key,
b_source_module_id varchar(80) not null,
b_source_field varchar(80) not null,
b_target_module_id varchar(80) not null,
b_target_field varchar(80) not null,
b_relation_type varchar(30) not null, -- one_to_one / one_to_many / many_to_one
b_usage varchar(30) not null, -- reference / detail / selector / load
b_load_mode varchar(20) not null default 'lazy',
b_on_delete varchar(20) not null default 'restrict',
b_canuse tinyint not null default 1,
b_xh int not null default 0
);
create table dbo.s_module_version (
b_id varchar(100) not null primary key,
b_module_id varchar(80) not null,
b_version_no int not null,
b_status varchar(20) not null, -- draft / published / retired
b_checksum varchar(128) null,
b_published_by varchar(50) null,
b_published_at datetime2 null,
b_created_by varchar(50) null,
b_created_at datetime2 not null default sysdatetime(),
unique (b_module_id, b_version_no)
);
create table dbo.s_module_snapshot (
b_version_id varchar(100) not null primary key,
b_module_id varchar(80) not null,
b_snapshot_json nvarchar(max) not null,
b_checksum varchar(128) not null,
b_created_at datetime2 not null default sysdatetime()
);
create table dbo.s_user_module_pref (
b_user_id varchar(50) not null,
b_module_id varchar(80) not null,
b_schema_type varchar(50) not null,
b_preference_json nvarchar(max) not null,
b_updated_at datetime2 null,
primary key (b_user_id, b_module_id, b_schema_type)
);
```
模板表沿用相同原则:`s_template` 保存模板身份,`s_template_version` 保存版本、默认字段能力和视图 JSON;模板应用只是生成模块草稿,不直接成为运行时配置。
```sql
create table dbo.s_template (
b_id varchar(80) not null primary key,
b_name nvarchar(200) not null,
b_template_type varchar(30) not null, -- master_data / document / detail / readonly
b_canuse tinyint not null default 1
);
create table dbo.s_template_version (
b_id varchar(100) not null primary key,
b_template_id varchar(80) not null,
b_version_no int not null,
b_default_fields_json nvarchar(max) not null,
b_views_json nvarchar(max) not null,
b_extensions_json nvarchar(max) null,
b_status varchar(20) not null, -- draft / published / retired
b_created_at datetime2 not null default sysdatetime(),
unique (b_template_id, b_version_no)
);
```
推荐补充以下约束和发布检查:
- `s_field.b_module_id`、`s_module_schema.b_module_id`、`s_module_version.b_module_id` 必须引用存在的模块;模块树字段由业务层校验不能成环。
- `s_module` 的数据源字段由模块类型和通用接口校验组合有效性;查询 SQL 只允许用于受控的只读查询,排序字段必须来自字段定义。
- `s_module_schema.b_schema_json`、`s_module.b_config_json` 和模板 JSON 使用 `ISJSON` 做基础检查,并由后端 JSON Schema 检查 `schemaVersion`、字段引用和关系引用。
- `s_module_snapshot`、已发布的 `s_module_version` 和已发布模板版本不可原地修改;回滚通过切换当前有效版本完成。
- 动态业务表不因为元数据引用而强制建立数据库外键;元数据内部引用使用外键或等效约束,跨 JSON 引用由发布校验保证。
### Demo 数据示例
以下示例定义一个客户资料模块,业务事实表为 `b_othercompany`,只读查询视图为 `v_b_othercompany`:
```text
s_module
base.customer → 基础资料 / 客户资料 / data / v_b_othercompany / b_othercompany / b_id
s_field
base.customer.b_ywid → physical / b_ywid / 客户编码 / code / read+edit+filter+sort
base.customer.b_name → physical / b_name / 客户名称 / text / read+edit+filter+sort
base.customer.b_owner_id → physical / b_owner_id / 业务员 / user_reference / read+edit+filter
s_module_schema
base.customer / list → schema JSON:列、宽度、排序
base.customer / form → schema JSON:分组、控件、必填、公式
base.customer / query → schema JSON:条件字段、组件、操作符
```
列表 JSON 示例:
```json
{
"schemaVersion": 1,
"columns": [
{ "field": "b_ywid", "visible": true, "width": 140, "sortable": true },
{ "field": "b_name", "visible": true, "width": 220, "sortable": true },
{ "field": "b_owner_id", "visible": true, "width": 120 }
],
"defaultSort": [{ "field": "b_name", "direction": "asc" }]
}
```
### 现有表到目标表的改造映射
- `s_module.b_view_table`、`b_query_sql`、`b_save_table`、`b_key_field`、`b_scope_field`、`b_order_sql` 继续由 `s_module` 保存;删除或收紧无约束的 `b_config_json` 内容。
- `s_field` 保留模块字段身份,并补充来源映射、语义类型和能力标记;列表、表单、查询的顺序和显示属性保留在对应 `s_module_schema.b_schema_json` 中。
- `s_module_schema.view/edit/query` 保留为视图配置的主要存储格式,增加 `b_schema_version` 和后端 JSON Schema 校验。
- `s_relation` 保留已有源/目标字段和删除策略,增加稳定关系编码、用途、加载规则等字段;历史关系先一次性导入,再由发布校验补足引用检查。
- 现有模块配置可通过一次性导入工具转换;不在新旧表之间长期双写,也不让旧表继续作为第二事实来源。
### 不需要整体重做的表
- 真实业务表和业务视图继续由 SQL migration 管理,不因为元数据重构而改成 EAV 或通用 JSON。
- `wf_definition`、`wf_version`、`wf_binding` 及工作流运行表可继续使用;`wf_binding` 需要改为引用模块的已发布版本或在发布时校验模块版本。
- 现有权限主体和授权表可以保留;权限运行时通过通用接口读取已发布字段和模块定义。
- 公式不要求新增业务数据表;简单公式随模块快照发布,复杂函数由通用公式接口调用后端函数库。
### 对现有核心表的评估
**结论:需要重构元数据配置表,但不需要仅因配置器难用而整体重做所有业务数据表。** 当前表结构能表达基本模块、字段和关系;主要问题是职责混放、字段能力分散到视图 JSON,以及缺少可发布的版本边界。
- **`s_module`**:继续保存模块身份、树结构和默认数据源,因为后端统一通过模块接口读取这些定义;`b_config_json` 只保留少量经过 schema 校验的低频配置,模块草稿 / 发布时间由版本模型管理。
- **`s_field`**:当前主要保存名称、业务类型、启用和顺序,尚未明确区分物理列、查询别名、计算 / 虚拟字段。建议增加明确的字段来源种类与来源映射、语义类型和模块级能力;数据库物理类型由 SQL Server 结构检查获得。表单 / 列表 / 查询中的显示顺序和控件差异放到对应视图字段配置,不塞回字段主定义。
- **`s_module_schema`**:继续按 `view/edit/query` 保存视图 JSON,增加结构版本和发布校验;不新增 `s_module_view`、`s_module_view_group` 或 `s_module_view_field`。
- **`s_relation`**:保留关系作为独立元数据,但建议引入稳定关系编码 / 标识,显式描述关系用途、基数、展示 / 加载规则,并对模块和字段引用建立数据库约束。现有删除策略等已表达的业务含义应迁移保留,不因改表而丢失。
- **`s_user_module_pref`**:如保留个性化配置,只允许保存列表列、查询布局等用户偏好覆盖,不得改变模块字段语义、数据源、权限或保存行为。若 Demo 暂无真实个性化需求,可先不纳入新核心模型。
- **新增发布版本实体**:使用 `s_module_version` 保存草稿与已发布版本的边界,使用 `s_module_snapshot` 保存不可变运行快照;发布失败不替换当前有效版本。
- **代码扩展**:不新增模块扩展绑定表;后端统一接口通过 SQL 目录、公式函数库和通用业务处理器协议调用代码实现,模块只使用通用参数和元数据配置。
元数据表之间应使用主键、唯一约束和可表达的外键保障内部引用完整性,并用发布校验补足跨 JSON / 动态数据源的检查。不要为了引用元数据而给所有动态业务表强行建立数据库外键。
### 规范化与 JSON 边界
- 模块、字段、关系、版本等有稳定身份、查询和引用的对象采用关系表。
- 表单布局、列表列布局、查询 UI、公式和少量扩展属性继续存 JSON,但其中只能引用已定义字段和关系;JSON 必须带 `schemaVersion` 并通过结构校验。
- 发布快照可采用 JSON 作为编译产物,不作为编辑态唯一事实来源。
- 对模块编码、模块内字段编码、模块 / 视图类型、版本号等建立唯一约束;可表达的元数据引用建立外键或等效约束,并由发布校验再次检查。
- 明确删除、改名和关系变更策略,不依赖前端操作顺序保证一致性。
- 不将业务字段值存入 `entity_id / field_id / value` 三元 EAV 表;不把所有配置塞进单个无约束 JSON。
- 不复制 SQL 物理列定义后再要求长期人工同步;物理结构优先读取,元数据维护业务语义。
### 草稿、发布与回滚
建议区分编辑草稿与当前发布版本。草稿保存不改变运行中配置;发布时完成校验、生成不可变快照并原子切换当前版本。保留基本发布历史用于问题定位和回滚。Demo 第一版不建设复杂审批、多用户锁或多环境发布平台。
## 6. 配置体验
配置流程采用“默认优先、逐步展开”:
1. 选择模块模板和数据源类型。
2. 选择表 / 视图,读取物理字段并映射业务语义。
3. 确认字段能力,自动生成表单、列表、查询初始定义。
4. 预览常用页面,再按需进入结构化的高级视图配置。
5. 运行发布校验,通过后发布。
首批模板建议包含基础资料、单据主表、明细表、只读查询 / 报表。模板提供可编辑初始值,不是硬编码页面。
### 不采用拖拽式设计器
表单和列表不再采用画布式拖拽设计器,也不保留绝对坐标 / 自由定位配置。拖拽交互难以精确、重复配置,布局结构也不利于阅读、差异比较和长期维护。
- **表单**:采用模板、分组和字段清单配置。通过字段选择、分组设置、列数 / 排序等结构化属性定义布局;字段顺序使用排序值或批量排序操作,不依赖画布拖动。
- **列表**:采用列配置表 / 字段矩阵,集中设置是否显示、顺序、宽度、格式、对齐、排序和汇总等属性;支持批量添加、移除和套用模板。
- **预览**:配置面板旁提供实时预览,但预览仅用于检查结果,不作为拖放编辑画布。
- **元数据**:保存语义结构和字段引用,不保存像素坐标、拖拽路径或依赖编辑器内部实现的状态。
- **高级场景**:通过分组、布局模板、字段显示规则及通用接口配置解决;不以重新引入自由拖拽作为兜底。
默认规则:
- 根据 SQL 类型推导候选字段类型和控件;语义不明确时要求确认,不做危险猜测。
- 根据业务语义推导筛选组件、操作符、格式和建议列宽。
- 新增字段补默认配置;已显式调整的配置不被重置;重置需显式操作。
- 默认生成必须幂等,同一输入重复应用不产生重复节点或配置漂移。
- 字段能力集中在矩阵中维护;布局通过模板、分组和排序等结构化配置调整,不使用拖拽画布。
## 7. 现状与重构方向
当前模块配置将字段、列表、表单、查询拆成不同面板,字段参与状态会修改多份界面 JSON;现有表单 / 列表设计器还采用拖拽式交互。本次重构不迁移现有画布和拖拽实现,改用模板、字段矩阵、分组 / 排序表格及实时只读预览。项目已有类型默认值和列表—查询联动逻辑,可保留其业务规则并重新组织。
- `fms-vue/src/views/module/module-management/ModuleFieldsPanel.vue:3`:字段定义与表单 / 列表 / 查询参与关系。
- `fms-vue/src/views/module/module-management/components/fieldDefaults.js:1`:列表和查询默认值规则。
- `fms-vue/src/views/module/module-management/components/design-editor/common/schemaModel.js:540`:视图字段节点新增 / 移除。
- `fms-vue/src/views/module/module-management/index.vue:1431`:配置面板分区导航和绑定。
重构保留已验证的行为意图,但不要求保留当前组件边界、JSON 结构或数据库表结构。
## 8. 整体重构范围与顺序
不做新旧格式长期并行或渐进兼容;按依赖顺序拆分实施任务,便于验证:
1. **确定元数据契约**:模块类型、字段语义、关系、视图、默认覆盖、发布和通用接口契约。
2. **重建元数据数据库**:调整模块、字段、视图 JSON 和关系表,新增版本与快照表,补充主键 / 唯一约束 / 引用约束;决定 Demo 配置重建还是一次性导入。
3. **实现后端目录与编译器**:读取物理结构、校验字段和视图 JSON、默认合成、生成快照、发布、版本切换、缓存失效和回滚。
4. **替换配置工作台**:数据源检查、字段导入、模板初始化、能力矩阵、预览、发布。
5. **替换运行时消费链路**:列表、查询、表单、保存统一读取发布定义。
6. **接入通用能力**:在统一模块接口中接入列表、查询、保存、权限、关系、工作流和公式的标准实现,并接入统一 SQL、函数库和业务处理器协议。
7. **删除旧路径**:完成一次性导入或确认弃用后,删除旧 `s_module_schema` JSON 结构适配和重复逻辑;保留新格式下的同一张表作为唯一视图配置来源。
虽然不需要渐进兼容,仍建议用一个基础资料、一个主从单据、一个只读查询模块验证新契约,再批量建立 Demo 配置。这是新架构验收,不是要求新旧架构并行运行。
## 9. 验收标准
- 新建基础资料模块,无需分别手工搭建字段、表单、列表和查询的基础配置。
- 表单和列表均可通过结构化配置完成,不需要拖拽画布、绝对坐标或依赖设计器内部状态。
- 列表列和表单字段可以通过清单 / 矩阵批量配置、排序和复用模板,配置差异可读、可校验。
- 模块字段只有一个权威定义;多个视图引用字段,不重复维护语义。
- 默认配置可重复生成,且不覆盖显式配置。
- 无效字段引用、数据源列缺失、关系目标错误、非法查询规则在发布时给出明确错误。
- 运行时只消费已发布版本;发布失败不影响当前可用版本。
- 编辑态使用模块、字段、视图 JSON 和关系表;运行态使用对应的不可变发布快照。
- 列表、查询、保存、权限、关系、工作流和公式均可使用元数据默认实现,并可通过统一 SQL、函数库和业务处理器协议补充复杂逻辑。
- 统一接口的参数、字段引用和依赖关系在发布时校验;接口执行失败有明确错误和审计信息。
- 简单 CRUD 使用通用运行时;复杂业务动作由明确的后端处理器完成。
- 真实 SQL Server 业务表仍是业务数据事实来源,不引入 EAV 业务数据主存储。
- 旧元数据路径已删除或仅作为一次性导入工具,不存在双重事实来源。
## 10. 需要同步修订的文档
目前架构文档存在方向冲突:部分草案提出以业务域代码包取代元数据运行时,而本方案采用元数据主导、通用接口承载复杂逻辑的模式。本方案评审通过后应统一修订:
- `FMS新系统核心架构设计.md`:明确元数据运行时是通用能力核心,业务域代码通过统一模块接口、SQL 和业务处理器协议接入复杂逻辑。
- `FMS新系统核心架构实施计划.md`:增加元数据数据库、编译器、工作台、运行时和通用接口实现任务。
- `FMS新系统核心表结构设计.md`:重新定义元数据表,不再将现有 `s_module`、`s_field`、`s_module_schema` 作为不可变前提。
- `开发规范.md`:明确元数据契约、发布定义、查询 / 保存边界和通用接口约定。
## 11. 假设与待定项
- 暂保留 SQL Server 作为数据库目标;允许重做元数据表,不主动改变租户数据库路由模式。
- 元数据和 Demo 配置可重建;是否保留样例数据,实施前决定重建或一次性导入。
- 本文确定架构方向,不冻结最终 DDL、API、类名或 Vue 目录;这些在元数据契约评审后设计。
- 需要确定权限、工作流、公式、多语言及通用接口实现是否随模块发布版本整体冻结,并定义接口版本兼容、事务边界、错误模型和规则优先级。