# 如何定义表单 这是创建可在**后台**和**前台**中工作的模块 + 表单所需元数据行的配方。当你想新增页面且不写 Java 时使用。 ## 要插入什么 按顺序插入三类行,分别位于三张表;还可以按需插入字段、权限和单据编号相关行。 ### 1. 模块 — `gdsmodule` 一行注册模块存在。必需列: | 列 | 值 | |---|---| | `sId` | 唯一 ID;使用 `IdGen` next-id helper,或任何未被占用的 32 字符串 | | `sName` | URL 片段,例如 `/indexPage/commonList`(使用共享页面模板 URL,见[切片 3](../../slices/03-report.md#why-this-module)) | | `sChinese` / `sEnglish` / `sBig5` | 三种语言显示名 | | `sParentId` | 父模块 `sId`,决定菜单树位置 | | `sBrandsId` / `sSubsidiaryId` | 租户作用域;应为你的租户 ID,标准 / 系统级可用 `'1111111111'` | | `sVersionFlowId` | 该模块所属产品版本(查 `sisversionflow`) | | `bVisible` | `1` 表示在菜单中显示 | | `bInvalid` | `0` 表示启用 | 除非需要自定义 CRUD,否则保持 `sSaveProName`、`sDeleteProName`、`sCalcProName`、`sProcName`、`sSaveProNameBefore` 为空(见[运行时参考](../maintainer/runtime.md))。 ### 2. 表单 master — `gdsconfigformmaster` 每模块每表单一行。必需列: | 列 | 值 | |---|---| | `sId` | 唯一表单 ID | | `sParentId` | 第 1 步模块的 `sId` | | `sTbName` | 支撑对象名称:真实表、视图或存储过程 | | `sType` | `'table'`、`'view'` 或 `'proc'` | | `sSqlStr` | 读取 SQL 骨架,通常是 `SELECT ... FROM {sTbName} WHERE ...` | | `sWhere` | 默认 WHERE 谓词(运行时自动添加租户过滤) | | `sOrder` | 默认 ORDER BY | | `iPageSize` | 表格每页行数 | | `bGrd` | `1` 表示表格布局,`0` 表示单记录表单 | | `sBrandsId` / `sSubsidiaryId` | 租户作用域 | 只读报表使用 `sType = 'view'`,并让 `sTbName` 指向 [`viw_*` 视图](../../slices/03-report.md)。框架不会渲染保存 / 删除按钮。 ### 3. 字段 — `gdsconfigformslave`,每字段一行 常用列(该表有 60+ 列,大多有合理默认值): | 列 | 值 | |---|---| | `sId` | 唯一字段 ID | | `sParentId` | 第 2 步表单的 `sId` | | `iOrder` | 表格排序顺序 | | `sName` | 支撑对象中的列名 | | `sChinese` / `sEnglish` / `sBig5` | 显示标签 | | `sControlName` | UI 控件类型:`文本框`、`下拉框`、`日期`、`数字` 等 | | `bVisible` | `1` 显示 | | `bNotEmpty` | `1` 必填 | | `bReadonly` | `1` 仅展示 | | `bCanInput` | `1` 可编辑 | | `iColValue` | 表单布局中的列跨度 | | `sDefault` | 默认值 | | `sChineseDropDown` | 下拉 SQL(如适用):`SELECT sId AS sValue, sChinese AS sText FROM ...` | | `sActiveId` / `sActiveKey` | popup lookup 控件,指向另一个模块 | ## 可选层 ### 单据编号 — `sysbillnosettings` 如果模块记录需要自动生成单号(工单号、报价单号等),在这里按表单 `sId` 增加一行。运行时会在 `getModelBysId` 响应的 `billnosetting` 中返回它。 ### 权限 — `gdsjurisdiction` 见[如何设置权限](permissions.md)。每个(模块、按钮或数据、角色)元组一行。 ### 租户覆盖 需要不同表单视图的租户,可在 `gdsconfigformpersonalize`(表单级覆盖)或 `gdsconfigformcustomslave`(字段级覆盖)中插入行。见[切片 4](../../slices/04-custom-field.md)。 ## 验证 所有行插入后,SPA 下一次请求 `getModelBysId/{your-module-sId}` 应返回你的表单元数据。点击新侧边栏项,表单应渲染。如果没有: 1. 检查 `gdsmodule.bVisible = 1`。 2. 检查 `gdsroute` 是否有 URL 项(多数部署会自动添加)。 3. 检查每行的 `sBrandsId` / `sSubsidiaryId` 是否与用户租户匹配。 4. 检查表单 `sParentId` 是否精确匹配模块 `sId`;这是语义 FK,写入时没有跨行校验。 ## 缓存失效 插入后,运行时缓存仍可能持有*之前*的空状态,直到 JMS 消息触发。**后台**构建器保存变更时,xly 的缓存失效监听器(`ConsumerChangeGdsModuleThread`)会处理;如果你通过原始 SQL 插入,可能需要重启运行服务或等待 TTL 过期。见[元数据变更后的缓存失效](../maintainer/cache-invalidation.md)。