Files
workspace/code/fms/新数据库结构.md
T
2026-07-22 22:25:10 +08:00

332 lines
16 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 新数据库结构
## 设计原则
- `b_module` 是核心元数据对象,统一表示菜单目录、页面和数据模块。
- 字段来源于数据模块配置的查询视图。系统不创建业务字段,只同步视图字段,并维护其展示、编辑、查询和权限配置。
- 页面和业务逻辑不完全元数据化。海运等复杂业务页面由 Vue 页面显式组合多个数据模块,元数据只提供 Table、Form 和 Query 配置。
- 字段基础定义、列表、编辑、查询四个职责分离;一个字段可以只参与其中任一场景。
- 模块权限控制访问,操作权限控制按钮动作;操作权限必须依赖模块访问权限。
- 表名和字段名沿用旧系统的 `b_` 风格。全部 `b_id` 使用 `bigint` 雪花 ID,返回前端时序列化为字符串。
- 布尔字段统一使用 `int`,`1` 表示是、`0` 表示否;`b_xh` 数值越小越靠前。
- 当前按机构使用独立数据库,表中不保存机构编号。表名、视图名和字段名必须由后端白名单校验,不能直接拼接 SQL。
## 整体关系
```text
b_module
|-- parent_id --> b_module
|-- 1:N --------> b_module_field
|-- 1:N --------> b_module_field_edit_group
|-- 1:N --------> b_module_power ---- 1:N ----> b_user_power
`-- 1:N --------> b_user_module
b_module_field
|-- 0:N --------> b_module_field_list -- parent_id --> b_module_field_list
|-- 0:1 --------> b_module_field_edit
`-- 0:1 --------> b_module_field_query
b_module / b_module_field / b_module_field_list / b_module_field_edit_group / b_module_power
`-- b_i18n --> b_i18n.b_key
```
## 模块
### `dbo.b_module`
统一保存目录、页面和数据模块。
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `b_id` | `bigint` | 不可变雪花 ID 主键 |
| `b_code` | `varchar(50)` | 可修改的唯一模块编码,例如 `m_sea`、`d_container` |
| `b_parent_id` | `bigint` | 上级模块 ID;根节点为空 |
| `b_name` | `nvarchar(100)` | 默认中文名称 |
| `b_i18n` | `varchar(150)` | 多语言键 |
| `b_module_type` | `varchar(20)` | `directory`、`page` 或 `data` |
| `b_route` | `varchar(200)` | 页面路由,例如 `/sea/list` |
| `b_viewtable` | `varchar(128)` | 查询来源表或视图;数据模块字段从此处同步 |
| `b_savetable` | `varchar(128)` | 保存目标表 |
| `b_keyfield` | `varchar(50)` | 主键字段,例如 `b_id` |
| `b_orderfield` | `varchar(500)` | 默认排序,例如 `b_xh ASC, b_id DESC` |
| `b_canmenu` | `int` | 是否显示在菜单,默认 `0` |
| `b_canuse` | `int` | 是否启用,默认 `1` |
| `b_xh` | `int` | 同级显示顺序,默认 `0` |
约束:
- `b_parent_id` 外键引用 `b_module.b_id`;保存服务校验父节点不形成循环。
- `b_code` 唯一,格式为 `^[a-z][a-z0-9_]{1,49}$`;`b_route` 非空时唯一。
- `directory` 不能配置 `b_route`、`b_viewtable` 或 `b_savetable`。
- `page` 必须配置 `b_route`,用于路由、菜单和页面编排;其业务数据由页面组合的数据模块提供。
- `data` 不能显示菜单;应配置 `b_viewtable`,保存场景再按需配置 `b_savetable` 与 `b_keyfield`。
- `b_canmenu`、`b_canuse` 只能为 `0` 或 `1`。建议建立 `(b_parent_id, b_xh, b_id)` 索引。
## 字段来源与同步
### `dbo.b_module_field`
保存字段的基础定义,不保存列宽、表单位置、是否显示或查询位置等场景属性。字段来自数据模块的 `b_viewtable`,并以 `(b_module_id, b_field)` 作为稳定标识。
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `b_id` | `bigint` | 雪花 ID 主键 |
| `b_module_id` | `bigint` | 所属数据模块 ID |
| `b_field` | `varchar(50)` | 视图字段名 |
| `b_name` | `nvarchar(100)` | 默认字段名称,由管理员维护 |
| `b_i18n` | `varchar(150)` | 多语言键 |
| `b_field_type` | `varchar(30)` | `string`、`text`、`number`、`date`、`datetime`、`boolean`、`select_id` 或 `select_input` |
| `b_value` | `nvarchar(500)` | 新增时默认值 |
| `b_dict_code` | `varchar(100)` | 字典编码;非字典字段为空 |
| `b_canuse` | `int` | 是否启用 |
| `b_remark` | `nvarchar(500)` | 字段说明 |
| `b_inputdatetime` | `datetime` | 首次同步创建时间 |
约束:
- `b_module_id` 外键引用 `b_module.b_id`,`(b_module_id, b_field)` 唯一。
- `b_canuse` 只能为 `0` 或 `1`。建议建立 `(b_module_id, b_canuse, b_id)` 索引。
- 字段没有 list、edit 或 query 配置记录时,不参与对应场景。
- `select_id` 保存选项 ID;`select_input` 支持从选项中选择或直接输入文本。字典型选择器使用 `b_dict_code`;视图型选择器的来源配置保存在 `b_module_field_edit.b_editor_options`。
### 视图同步规则
字段同步服务仅面向 `b_module_type = 'data'` 且配置了 `b_viewtable` 的模块执行:
1. 后端校验视图名并读取列名、SQL 类型和可空性等结构信息。
2. 按列名查找同模块的 `b_module_field`;新列创建字段基础记录。
3. 同步更新 `b_field`、`b_field_type` 和 `b_canuse`。SQL 类型映射为 `string`、`text`、`number`、`date`、`datetime`、`boolean` 等基础类型;`select_id`、`select_input` 由管理员在同步后按业务语义调整。
4. 本次视图中不存在的已有字段保留其记录和全部场景配置,但将 `b_canuse` 置为 `0`。
5. 不覆盖人工维护的 `b_name`、`b_i18n`、`b_value`、`b_dict_code` 和 `b_remark`,不物理删除字段或场景配置。
## 列表配置
### `dbo.b_module_field_list`
控制 Table 列、显示方式和多级表头。分组节点与字段节点通过 `b_parent_id` 组成任意层级的表头树;只读列表和可编辑 Table 共用本表。
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `b_id` | `bigint` | 雪花 ID 主键 |
| `b_module_id` | `bigint` | 所属模块 ID |
| `b_parent_id` | `bigint` | 上级表头分组 ID;顶层为空 |
| `b_kind` | `varchar(20)` | `group` 或 `field` |
| `b_field_id` | `bigint` | 字段节点关联 `b_module_field.b_id`;分组节点为空 |
| `b_title` | `nvarchar(100)` | 分组标题或字段标题覆盖值;字段为空时使用默认字段名称 |
| `b_i18n` | `varchar(150)` | 分组多语言键或字段标题多语言键覆盖值 |
| `b_visible` | `int` | 是否显示,默认 `1` |
| `b_xh` | `int` | 同一父节点下的显示顺序,默认 `0` |
| `b_width` | `int` | 字段列宽;分组节点为空 |
| `b_sortable` | `int` | 是否允许排序,默认 `0` |
| `b_display_type` | `varchar(30)` | 显示器类型,例如 `text`、`money`、`date`、`datetime`、`tag`;前端按类型使用统一显示规则 |
| `b_canedit` | `int` | 是否允许表格单元格编辑,默认 `0` |
约束:
- `b_module_id` 外键引用 `b_module.b_id`,`b_parent_id` 外键引用本表 `b_id`,`b_field_id` 外键引用 `b_module_field.b_id`。
- `group` 节点必须没有 `b_field_id`、`b_width`,且 `b_canedit = 0`;`field` 节点必须有 `b_field_id`。
- 同一字段在同一模块的列树中最多出现一次,使用非空 `b_field_id` 的过滤唯一索引约束。
- `b_parent_id` 必须指向同模块的 `group` 节点,且不能形成循环,由保存服务校验。
- `b_visible`、`b_sortable`、`b_canedit` 只能为 `0` 或 `1`;`b_canedit = 1` 时必须存在对应编辑规则。
- `b_display_type` 决定显示器及其格式化规则,例如 `money`、`date`、`datetime` 均由前端按统一规则渲染。建议建立 `(b_module_id, b_parent_id, b_xh, b_id)` 索引。
- 不保存 `level`、`colspan`、`rowspan`;前端一次加载全部节点后,按 `b_parent_id`、`b_xh` 组装嵌套 `children` 并计算表头。隐藏分组的后代不显示;没有可见字段后代的分组不渲染。
示例:
```text
费用(group)
|-- 人工费(field)
`-- 海运费(field)
```
## 编辑配置
### `dbo.b_module_field_edit`
控制 Form 和可编辑 Table 的共享编辑规则,以及字段在 Form 中的布局。表单分组仅是视觉分组,不表示页签、动态页面区域或主子表关系;分组标题和多语言由独立分组表维护。
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `b_id` | `bigint` | 雪花 ID 主键 |
| `b_module_id` | `bigint` | 所属模块 ID |
| `b_field_id` | `bigint` | 关联 `b_module_field.b_id` |
| `b_editor` | `varchar(30)` | 例如 `input`、`textarea`、`select`、`date`、`switch` |
| `b_edit_format` | `varchar(100)` | 编辑值格式 |
| `b_editor_options` | `nvarchar(max)` | 编辑器专属 JSON 配置 |
| `b_required` | `int` | 是否必填,默认 `0` |
| `b_readonly` | `int` | 是否只读,默认 `0` |
| `b_disabled` | `int` | 是否禁用,默认 `0` |
| `b_placeholder` | `nvarchar(200)` | 输入提示 |
| `b_canform` | `int` | 是否进入 Form,默认 `1` |
| `b_edit_group` | `varchar(100)` | 关联 `b_module_field_edit_group.b_code`;不分组时为空 |
| `b_edit_xh` | `int` | 编辑区域中的全局顺序,默认 `0` |
| `b_edit_span` | `int` | Form 栅格宽度,默认 `24`,范围 `1` 至 `24` |
约束:
- `b_module_id` 外键引用 `b_module.b_id`,`b_field_id` 外键引用 `b_module_field.b_id`;`(b_module_id, b_field_id)` 唯一,保存服务校验字段属于同一模块。
- `b_required`、`b_readonly`、`b_disabled`、`b_canform` 只能为 `0` 或 `1`;`b_editor_options` 非空时通过 `ISJSON` 校验。
- 非空 `b_edit_group` 必须引用同模块的启用分组;保存服务校验模块一致性。
- 已分组字段按所属分组的 `b_xh` 排列,组内按 `b_edit_xh` 排列;未分组字段作为末尾默认区域,按 `b_edit_xh` 排列。建议建立 `(b_module_id, b_edit_xh, b_id)` 索引。
- `b_canform = 0` 时,编辑规则仍可由可编辑 Table 使用。
### `dbo.b_module_field_edit_group`
保存 Form 的视觉分组标题和多语言配置。一个模块可以有多个分组,字段通过 `b_edit_group` 引用其稳定编码。
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `b_id` | `bigint` | 雪花 ID 主键 |
| `b_module_id` | `bigint` | 所属模块 ID |
| `b_code` | `varchar(100)` | 分组稳定编码,例如 `basic`、`booking` |
| `b_title` | `nvarchar(100)` | 默认分组标题 |
| `b_i18n` | `varchar(150)` | 分组标题多语言键 |
| `b_xh` | `int` | 分组显示顺序,默认 `0` |
| `b_canuse` | `int` | 是否启用,默认 `1` |
约束:
- `b_module_id` 外键引用 `b_module.b_id`,`(b_module_id, b_code)` 唯一。
- `b_canuse` 只能为 `0` 或 `1`。建议建立 `(b_module_id, b_canuse, b_xh, b_id)` 索引。
- 无字段引用的分组不渲染;分组停用时,其关联字段不在 Form 中显示。
视图型选择器的 `b_editor_options` 示例:
```json
{
"source": "view",
"view": "v_partner",
"valueField": "b_id",
"labelField": "b_name",
"allowInput": false
}
```
`select_id` 使用 `allowInput: false` 并保存 `valueField` 的值;`select_input` 可使用 `allowInput: true` 并保存选择值或用户输入文本。视图名、值字段和标签字段均须由后端校验。
## 查询配置
### `dbo.b_module_field_query`
独立控制主列表查询条件,不依赖字段是否配置为可见列表列。
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `b_id` | `bigint` | 雪花 ID 主键 |
| `b_module_id` | `bigint` | 所属模块 ID |
| `b_field_id` | `bigint` | 关联 `b_module_field.b_id` |
| `b_component` | `varchar(30)` | 查询组件 |
| `b_operator` | `varchar(20)` | `=`、`like`、`between` 或 `in` |
| `b_default_value` | `nvarchar(500)` | 默认查询值 |
| `b_xh` | `int` | 查询条件显示顺序,默认 `0` |
| `b_canuse` | `int` | 是否启用,默认 `1` |
约束:
- `b_module_id` 外键引用 `b_module.b_id`,`b_field_id` 外键引用 `b_module_field.b_id`;`(b_module_id, b_field_id)` 唯一,保存服务校验模块一致性。
- `b_canuse` 只能为 `0` 或 `1`;`b_operator` 必须属于定义的操作符集合。
- 查询组件与操作符由后端白名单校验;查询值必须参数化,不能由配置直接拼接 SQL。
- 建议建立 `(b_module_id, b_canuse, b_xh, b_id)` 索引。
## 权限与多语言
### `dbo.b_module_power`
定义模块内可授权的按钮操作。
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `b_id` | `bigint` | 雪花 ID 主键 |
| `b_module_id` | `bigint` | 所属模块 ID |
| `b_code` | `varchar(50)` | 操作编码,例如 `create`、`update`、`delete`、`audit`、`export` |
| `b_name` | `nvarchar(100)` | 操作名称 |
| `b_i18n` | `varchar(150)` | 多语言键 |
| `b_xh` | `int` | 显示顺序 |
| `b_canuse` | `int` | 是否启用,默认 `1` |
约束:`b_module_id` 外键引用 `b_module.b_id`,`(b_module_id, b_code)` 唯一,`b_canuse` 只能为 `0` 或 `1`。
### `dbo.b_user_module`
控制用户能否查看、进入和调用模块。
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `b_id` | `bigint` | 雪花 ID 主键 |
| `b_user_id` | `bigint` | 用户雪花 ID |
| `b_module_id` | `bigint` | 模块 ID |
| `b_inputuser_id` | `bigint` | 授权人雪花 ID |
| `b_inputdatetime` | `datetime` | 授权时间 |
约束:`b_module_id` 外键引用 `b_module.b_id`,`(b_user_id, b_module_id)` 唯一。目录不单独授权;用户拥有下级模块时自动显示上级目录。
### `dbo.b_user_power`
控制用户可执行的按钮操作。
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `b_id` | `bigint` | 雪花 ID 主键 |
| `b_user_id` | `bigint` | 用户雪花 ID |
| `b_power_id` | `bigint` | `b_module_power.b_id` |
| `b_inputuser_id` | `bigint` | 授权人雪花 ID |
| `b_inputdatetime` | `datetime` | 授权时间 |
约束:`b_power_id` 外键引用 `b_module_power.b_id`,`(b_user_id, b_power_id)` 唯一。
权限规则:
1. 用户必须拥有 `b_user_module` 记录,才能进入或调用该模块。
2. 用户必须同时拥有模块权限和对应 `b_user_power` 记录,才能执行按钮动作。
3. 前端据此控制路由进入和按钮可用性;后端接口后续实施同等权限校验。
### `dbo.b_i18n`
统一保存菜单、模块、字段、权限、按钮、提示和校验信息等界面文案。
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `b_id` | `bigint` | 雪花 ID 主键 |
| `b_key` | `varchar(150)` | 多语言键 |
| `b_locale` | `varchar(20)` | 语言编码,例如 `zh-CN` |
| `b_value` | `nvarchar(500)` | 翻译文本 |
约束:`(b_key, b_locale)` 唯一。
## 页面组合示例
海运业务页面由 Vue 显式组合数据模块,不通过字段配置创建动态页面区域:
```text
海运页面 m_sea(page:路由、菜单、权限、页面编排)
|-- 海运主单 d_sea(data:Table / Form / Query)
|-- 费用 d_charge(data:可编辑 Table)
|-- 订舱 d_booking(data:独立表和主键时)
`-- 箱明细 d_container(data:可编辑 Table)
```
若订舱字段实际保存于海运主单表,不创建 `d_booking`,而在 `d_sea` 的 Form 中用 `b_module_field_edit_group` 和 `b_edit_group` 表达视觉分组。主子表关联、加载时机、保存顺序和页面布局均由业务 Vue 页面明确实现。
## 现有字段迁移
当前 `b_module_field` 混合保存基础、列表、编辑和查询属性。迁移应分阶段实施:
| 当前字段 | 目标位置 |
| --- | --- |
| `b_type` | `b_module_field.b_field_type` |
| `b_canlist` | `b_module_field_list.b_visible` |
| `b_width` | `b_module_field_list.b_width` |
| `b_xh` | 初始化 `b_module_field_list.b_xh`、`b_module_field_edit.b_edit_xh` 与 `b_module_field_query.b_xh` |
| `b_canform` | `b_module_field_edit.b_canform` |
| `b_must` | `b_module_field_edit.b_required` |
| `b_readonly` | `b_module_field_edit.b_readonly` |
| `b_canquery` | 创建 `b_module_field_query` 记录 |
| `b_value` | 保留在 `b_module_field.b_value` |
迁移步骤:
1. 新建 list、edit、edit_group、query 表和必要索引,新增 `b_module.b_module_type` 与 `b_module_field.b_field_type` 的兼容列。
2. 为原有字段创建顶层 `field` 列配置;根据原 `b_canform`、`b_canquery` 创建编辑和查询配置;初始 `b_canedit = 0`。
3. 前端和后端改为读取新场景表,查询不再读取 list 配置;模块类型切换为读取 `b_module_type`。
4. 完成视图同步服务并验证新结构的读写稳定后,删除旧混合列和兼容字段。