Files
workspace/code/g3soft-erp/docs/后端架构设计.md
T
2026-10-12 17:32:50 +08:00

7.6 KiB

FMS 后端架构设计

文档版本:V1.1(精简方案) 编制日期:2026-10-12 状态:待评审 适用范围:沿用现有 FMS API 与 SQL Server 模块配置方式 配套文档:核心表结构设计.md

1. 设计目标

本文以已经使用的 FMS 数据库和 fms-api 接口为基础,只补充模块配置的版本历史能力。目标是让新 ERP 后端和其他 IT 团队能够沿用熟悉的表结构、SQL 和通用数据接口,而不是重新建设一套元数据运行时。

  • 保留 s_module、s_field、s_module_schema、s_relation 的现有职责和字段约定。
  • 元数据描述常用模块、字段和页面配置;SQL 是可选的正式扩展方式,遇到配置不便表达的查询时使用。
  • 沿用通用数据 API、机构上下文和 SQL Server 数据源路由;不为每个业务模块新增专用 CRUD API。
  • 只新增轻量模块版本历史;不引入模板引擎、编译发布管线、运行时快照目录或复杂审批流程。

2. 总体结构

模块管理界面
  ├─ s_module:模块树、表/视图、SQL、保存目标
  ├─ s_field:模块字段及业务类型
  ├─ s_module_schema:列表 / 表单 / 查询 JSON
  └─ s_relation:模块数据关系
          │
          ├─ 普通数据请求 → 现有 /data 通用接口 → SQL Server
          ├─ 自定义查询 SQL → 只读 SQL 校验 → SQL Server
          └─ 显式版本保存/恢复 → s_module_version

运行时继续读取现有模块配置表。s_module_version 只做历史记录与恢复,不成为普通业务请求的读取入口。

3. 模块配置如何驱动请求

3.1 模块与页面配置

  • 模块编码 s_module.b_id 是稳定业务编码,由配置方提供,不使用运行时雪花 ID。
  • b_module_type 使用现有 module、data、virtual 约定:分组、标准数据对象和虚拟业务对象。
  • b_view_table、b_save_table、b_key_field 描述普通查询和保存目标;数据库对象默认使用 dbo。
  • s_field 声明模块字段编码、名称和业务类型;具体 SQL 类型通过数据库结构探测获得。
  • s_module_schema 的 view、edit、query JSON 控制列表、表单和查询界面;字段语义不在多个 JSON 中重复定义。
  • s_relation 声明模块间字段关系;b_parent_id 只用于模块树,不表示业务数据关系。

3.2 SQL 兜底

  • 常规简单查询使用配置的 b_view_table 和通用查询接口。
  • 关联、聚合或其他配置表达起来不合适的查询,可在模块配置中使用 b_query_sql;它是模块配置数据,不要求在后端代码中为每家公司登记 SQL 编码。
  • 对于按机构隔离的数据库,机构数据源路由继续使用现有 OrgContext / OrgDataSourceManager。各机构可在自己的配置库维护不同模块 SQL,不新增租户配置层。
  • 运行查询 SQL 必须经过现有只读校验路径;只允许查询语句,不允许用查询 SQL 执行新增、修改、删除或 DDL。写入走现有保存/删除接口或明确的业务服务。
  • b_order_sql 是模块默认排序;排序标识符按现有 DbUtils 校验规则处理。查询参数和值不得通过未校验的字符串拼接进入 SQL。

4. 沿用的通用数据 API

已有的 /data/* 契约继续作为数据访问入口,不因模块配置版本化而更换:

接口 用途
POST /data/loaddata 按表/视图、条件、排序和字段列表查询
POST /data/page 分页查询
POST /data/loaddatabysql 执行只读 SELECT / WITH 查询
POST /data/saveobjt 在一个事务中保存多表新增、修改
POST /data/delete 按模块或受控目标删除
POST /data/describe 探测表或视图列结构
POST /data/nextid、/data/nextcode 取雪花 ID 或模块业务编码

loaddata / page 使用表或视图名、结构化筛选和排序参数;loaddatabysql 用于复杂只读查询。已有 DbUtils 负责标识符验证、SQL 只读检查和 SQL 执行。通用保存服务依据真实表结构生成参数化写入,不通过 b_query_sql 写业务数据。

新接入系统应沿用这些请求/响应格式和既有身份、机构、权限上下文;模块管理页面负责读取模块配置并组织请求,不需要另造一套模块专属 CRUD API。

5. 模块配置版本历史

5.1 行为边界

  • 版本功能只增加 s_module_version 一张表;快照 JSON 包含模块及其字段、界面、关系和相关模块级扩展配置。
  • 显式创建版本时,后端从现有配置表读取当前状态,分配递增版本号并保存不可变快照。
  • 查看历史只读取版本表;恢复历史版本时,后端校验后在一个事务中恢复现有模块配置表。
  • 恢复成功后业务运行仍读取原有 s_module 等表;不切换运行时版本指针,也不改变 /data/* 接口。
  • 恢复内容可另存为新的版本记录;禁止覆盖历史快照。

因此这项能力是配置备份、版本查看与恢复,不是草稿/发布隔离。配置当前仍按现有保存机制生效;若之后出现明确的灰度发布需求,再单独扩展。

5.2 最小后端改动

增加一个模块版本服务,负责:

  1. 创建版本:在数据库事务中读取模块及子配置,验证并序列化快照。
  2. 查询版本:按模块编码列出版本号、说明、创建人和时间。
  3. 恢复版本:校验快照结构和关联目标,在同一事务内更新模块配置,并记录恢复结果。

版本操作可通过模块管理 API 暴露;业务数据 API、模块表主键、普通保存流程和 SQL 查询流程不变。版本号由后端分配,不依赖客户端提供。

6. SQL 与数据安全约定

  • 客户端不能以任意表名或列名绕过后端标识符验证。
  • 普通查询的筛选值以参数传递;字段、排序方向等 SQL 标识由校验后的配置控制。
  • b_query_sql 和 /data/loaddatabysql 仅用于只读查询,并使用现有 DbUtils.validateReadOnlySql() 校验。
  • SQL 配置及执行需经过现有机构、用户和数据范围权限上下文;不能因为使用 SQL 扩展绕过权限校验。
  • 写操作使用 /data/saveobjt、/data/delete 或已有业务服务,并纳入现有事务和审计规则。
  • 版本恢复同样执行配置权限校验、引用校验和事务处理。

7. 不在本次范围内

  • 不重构现有 FMS DataController 接口,也不改变 SQL Server、JDBC 或机构数据源路由方式。
  • 不增加 s_template / s_template_version、s_module_snapshot、用户偏好新表或权限/工作流新表。
  • 不强制运行时从 JSON 快照读取模块定义,不引入 ModuleDefinition 编译缓存层。
  • 不把 SQL 移到后端固定代码目录;保留模块配置中的可选 SQL 兜底。
  • 不重新定义业务表、菜单、用户、权限、工作流、文件和审计子系统。
  • 不把模块版本管理等同于数据库 migration;业务表结构仍通过已有 SQL migration 管理。

8. 接入检查清单

  1. 确认机构/数据库连接按现有路由建立,业务对象位于 dbo。
  2. 普通表格和表单配置 s_module、s_field、s_module_schema;复杂查询按需配置 b_query_sql。
  3. 用 /data/describe 检查实际表/视图字段,用 s_field 和视图 JSON 保持编码一致。
  4. 查询、保存、删除分别调用现有通用接口;不从客户端接收未经验证的 DML SQL。
  5. 重要配置变更后显式保存模块版本;恢复时通过版本服务执行,不手工覆盖版本历史表。