# 模块、表单、虚拟表 这是 xly 元数据模型中的三个核心名词。理解它们,就能读懂框架其余部分。代码库中的词汇并不总是一致:同一概念在不同文件里有不同名字;本页的一部分工作就是统一这些同义词。 ## 模块 系统中“一个可配置对象”的单位。 - [`gdsmodule`](../auto-catalog/tables/gdsmodule.md) 中**每个模块一行**。 - 携带 URL 片段(`sName`)、显示名(`sChinese`、`sEnglish`、`sBig5`)、树位置(`sParentId`、`sAllId`)、产品版本(`sVersionFlowId`,见[切片 2](../slices/02-multi-tenancy.md)),以及可选 CRUD 存储过程名(`sSaveProName`、`sDeleteProName`、`sProcName`、`sCalcProName`、`sSaveProNameBefore`)。 - 当前实时 DB 中有 1,358 行。 Java 代码库把这个概念叫作 “module”、“model”、“models” 和 “modle”(常见拼写错误)。变量 `sModelsId` 和方法 `getModelConfigByModleId` 虽然命名如此,实际都接收模块 `sId`。见[切片 1](../slices/01-hello-world.md)中的命名提醒。 ## 表单 模块的屏幕布局:表头 + N 个字段定义。 - **Master:** [`gdsconfigformmaster`](../auto-catalog/tables/gdsconfigformmaster.md) 中每个表单一行。携带支撑对象(`sTbName`)、支撑对象类型(`sType` ∈ `{table, view, proc}`)、默认 SQL 片段(`sSqlStr`、`sWhere`、`sOrder`)、表格行为(`bGrd`、`iPageSize`)和权限列。 - **Slave:** [`gdsconfigformslave`](../auto-catalog/tables/gdsconfigformslave.md) 中每个*字段*一行。携带字段名(`sName`,匹配支撑对象中的列)、控件类型(`sControlName`)、显示标签、校验规则、默认值、下拉 SQL、按钮指令。 - 模块通过 `gdsconfigformmaster.sParentId = gdsmodule.sId` 连接到表单,这是语义 FK,不强制。(注意:`gdsmodule.sFormId` 虽然存在,但多数模块为空,且不是规范连接。) - 当前实时 DB 中有 2,022 个 master 行、159,371 个 slave 行。 表单是用户可见的产物:当 PM 在**后台**中“创建页面”时,实际是在 INSERT 一个 `gdsconfigformmaster` 行和 5 到 50 个 `gdsconfigformslave` 行。 ## 虚拟表 xly 对“由元数据定义的表”的术语和表前缀。它不是 `CREATE TABLE` 语句创建的真实表,而是元数据声明的“表”。 - [`gdsconfigtbmaster`](../auto-catalog/tables/gdsconfigtbmaster.md) 中每个虚拟表一行。 - [`gdsconfigtbslave`](../auto-catalog/tables/gdsconfigtbslave.md) 中每个虚拟列一行。 - 当前实时 DB 中有 307 个 master 行、14,385 个 slave 行。 虚拟表让 PM 能声明“我想要这种形状的东西”,不必直接找工程师。多数虚拟表最终映射到真实物理表(框架支持迁移步骤,或预创建通用“宽表”供 PM 填充),但运行时看到的*抽象*是元数据声明,而不是底层存储。 这不同于数据库**视图**:虚拟表是元数据;视图是 `CREATE VIEW` SQL 对象。两者都可以支撑表单(通过 `gdsconfigformmaster.sType = 'table'` 或 `'view'`)。视图支撑的情况见[切片 3](../slices/03-report.md)。 ## 它们如何组合 ```text gdsmodule (模块,1 行) └── (通过 sParentId 连接) gdsconfigformmaster (表单 master,每个表单 1 行) ├── gdsconfigformslave (字段,N 行) ├── gdsconfigformcustomslave (每租户字段,N 或 0) └── gdsconfigformuserslave (每用户微调,N 或 0) gdsmodule.sName → gdsroute 中注册的路由(URL 白名单) gdsmodule.sFormId → (大多为空,历史字段) ``` 每个表单恰好有一个模块。每个模块*应该*最多有一个表单,但少数模块有多个 `gdsconfigformmaster` 行指向同一 `sParentId`,表示带多个面板或子 tab 的页面。 ## 三个名词,一个引擎 运行时(`BusinessBaseController` 和 `BusinessBaseServiceImpl`,见[切片 1](../slices/01-hello-world.md))知道如何渲染任意模块 / 表单 / 虚拟表组合。不存在每模块专用 Java 代码。PM 创建新模块是在创建新行,不是在创建新代码路径。