spec.md 9.3 KB

低代码对象设计器字段同步与交互修复

status: done created: 2026-06-13 scope: forge-admin-ui, forge-server/forge-framework/forge-plugin-parent/forge-plugin-generator related: code-copilot/changes/form-first-business-object-designer/spec.md

1. 背景

低代码应用构建的业务对象设计器已经采用表单优先模式,表单画布负责生成字段资产,字段资产负责高级维护。当前实际使用中存在以下影响设计效率和运行态一致性的问题:

  1. 表单设计器新增字段时,“组件字段ID”只能从已有字段中选择,不能直接输入新字段 ID,导致用户无法在拖入组件时明确字段编码。
  2. 表单设计与字段资产的双向同步不完整:表单新增字段要沉淀为字段资产,字段资产改名或改字段编码后也应同步回表单设计器的绑定与展示。
  3. 切换左侧导航时经常提示未保存,即使用户没有做业务修改,说明初始化、预览补水或内部同步触发了错误的 dirty 状态。
  4. 字段配置当前使用右侧抽屉弹层,编辑字段时遮挡上下文,且频繁开关影响效率。
  5. 表单设计器新增字段并同步 DDL 后,数据库列已经存在,但运行态新增/编辑数据时该字段值没有入库。
  6. 曾经拖入后又删除的自动字段仍残留在模型字段中,发布检查继续提示追加已不在表单中的字段列。
  7. 新版画布“显示名称”清空后会立刻被规范化逻辑自动回填,用户不能一次删除完整名称。

2. 目标

  • 表单设计器中的“组件字段ID”支持选择已有字段,也支持手动输入新字段 ID。
  • 手动输入的新字段 ID 在保存/同步设计草稿时自动沉淀到字段资产,字段名称、列名、类型、组件属性沿用现有自动字段资产规则。
  • 字段资产保存后同步更新本地模型、表单 Schema、页面 Schema 和视图 Schema 中的字段引用;服务端保存后的重载仍作为最终一致性来源。
  • 表单设计器仅在真实 schema/page/field 变更时上报 dirty,初始化、setRule、预览选项补水不触发未保存提示。
  • 字段资产页改为列表 + 右侧内嵌属性面板,不再打开 Naive UI Drawer。
  • 运行态新增/编辑数据时,设计器刚保存且已建表列的新字段能够被动态 CRUD 正常写入。
  • 表单删除自动创建字段后,该字段不再参与模型 Schema、DDL 预览和运行态写入。
  • 字段显示名称允许临时清空,保存前不因内部规范化立刻回填。
  • 必填字段的数据库非空约束只在配置了可用默认值时同步,避免无默认值必填字段阻断运行态新增。

3. 非目标

  • 不修改后端字段设计器接口协议。
  • 不重写 fcDesigner
  • 不重写发布链路和运行态 AiCrudPage;动态 CRUD 仅修正新增字段写入白名单。
  • 不新增数据库迁移脚本。
  • 不处理字段编码变更后的历史数据迁移策略,仍沿用当前后端字段设计服务的处理。

4. 设计方案

4.1 字段 ID 输入

forgeBusinessComponents.js 中的字段绑定属性规则继续使用 select 类型,但开启可创建输入能力。用户可以:

  • 从已有字段资产中选择字段 ID。
  • 直接输入新字段 ID。

formCreateToForge.js 已经会从 rule.props.fieldBinding.fieldCoderule.props.fieldCoderule.fieldrule.name 中解析字段编码;本变更保持该转换链路,只补齐属性规则的输入能力。

4.2 双向同步

表单到字段资产:

  • BusinessFormDesigner.syncDesignerDraft() 继续通过 buildAutoFieldAssets()FormDesignerSchema 自动生成字段资产。
  • 手动输入字段 ID 后,组件 fieldBinding.fieldCode 作为稳定字段编码,自动生成字段资产。

字段资产到表单:

  • 字段资产保存时,如果字段编码发生变化,前端在本地同步替换表单 Schema、页面 Schema、视图 Schema 的引用。
  • 字段名称、提示文案、必填、控件类型等仍由现有字段保存和设计器重载兜底同步。

4.3 Dirty 状态

BusinessFormCreateDesigner.flushDesigner() 增加结构比较:

  • 转换出的 Forge Schema 与当前 modelValue 等价时,只刷新内部快照,不触发 update:modelValuedirtyChange(true)
  • 仅用户真实拖拽、删除、排序、改字段绑定或修改属性后才上报 dirty。

BusinessFormDesigner.syncDesignerDraft() 增加比较:

  • 当前表单 Schema、字段资产和页面 Schema 均未变化时返回 dirty: false
  • 左侧导航切换只同步草稿,不制造未保存状态。

4.4 字段配置交互

BusinessFieldManager.vue 去掉抽屉,改为内嵌工作区:

  • 左侧保持字段列表和筛选工具栏。
  • 右侧固定展示 BusinessFieldPropertyPanel
  • 未选中字段时在右侧展示空状态。
  • 小屏幕下列表与属性面板纵向堆叠。

4.5 运行态新增字段写入

DynamicCrudService 的新增和更新写入白名单不再只依赖 editSchema

  • editSchema 继续作为运行态表单字段白名单。
  • modelSchema 额外补充设计器保存后已存在真实数据库列的新字段。
  • 仅允许启用、非系统、非主键、非自增、非只读、表单可见且数据库列存在的字段写入。
  • 继续过滤 id、租户、创建人、更新时间等不可变系统字段,避免请求体任意字段透传。

4.6 自动字段清理与默认值策略

表单设计器保存草稿时,buildAutoFieldAssets() 只保留当前表单仍绑定的自动创建字段;未绑定的手工字段资产继续保留,避免高级字段资产被误删。

新版画布 schema 规范化时区分“没有 label”和“用户显式清空 label”:字段组件显式传入空字符串时保留空值,不再回退到“字段”。

DDL 同步时,业务字段的 required 主要作为运行态表单校验。只有当字段配置了非空默认值,才把数据库列同步为 NOT NULL DEFAULT ...;未配置默认值时数据库列保持可空。

5. 影响范围

  • forge-admin-ui/src/views/app-center/components/designer/BusinessFieldManager.vue
  • forge-admin-ui/src/views/app-center/components/designer/BusinessFormCreateDesigner.vue
  • forge-admin-ui/src/views/app-center/components/designer/BusinessFormDesigner.vue
  • forge-admin-ui/src/views/app-center/components/designer/form-first/fieldReferenceUtils.js
  • forge-admin-ui/src/views/app-center/components/designer/form-first/forgeBusinessComponents.js
  • forge-admin-ui/src/views/app-center/components/designer/form-first/forgeToFormCreate.js
  • forge-admin-ui/src/views/app-center/components/designer/form-first/formCreateToForge.js
  • forge-admin-ui/src/views/app-center/components/designer/form-first/autoFieldRegistry.js
  • forge-admin-ui/src/views/app-center/components/designer/form-first/formDesignerSchema.js
  • forge-admin-ui/src/views/app-center/components/designer/form-first/viewSchema.js
  • forge-admin-ui/src/views/app-center/object-designer.[objectCode].vue
  • forge-server/forge-framework/forge-plugin-parent/forge-plugin-generator/src/main/java/com/mdframe/forge/plugin/generator/service/DynamicCrudService.java
  • forge-server/forge-framework/forge-plugin-parent/forge-plugin-generator/src/main/java/com/mdframe/forge/plugin/generator/service/lowcode/LowcodeDdlService.java

6. 验收标准

  • 在表单设计器拖入输入组件后,可以在属性面板直接输入 customerLevel 作为组件字段 ID。
  • 保存表单设计后,字段资产中出现 customerLevel,字段编码与数据库列名分别为 customerLevelcustomer_level
  • 在字段资产中把字段编码从 customerLevel 改为 customerGrade 后,表单设计器组件绑定同步为 customerGrade,页面/视图引用不遗留旧字段编码。
  • 只进入设计器并切换左侧导航,不弹出“未保存变更”提示。
  • 字段资产页选择字段后直接在页面右侧编辑属性,不出现右侧抽屉弹层。
  • 拖入 form-create 默认输入组件时,rule.field = inputselect 等设计器内部默认值不能沉淀为业务字段编码或数据库列名;新字段应生成 fieldInput1 等稳定业务字段编码。
  • 组件绑定已有字段资产后,表单组件标题优先回显字段资产名称,例如选择 customerLevel 时标题同步为“客户等级”。
  • 表单设计器新增字段并同步 DDL 后,运行态新增/编辑记录时该字段值能保存到对应数据库列。
  • 表单里删除自动创建字段后,发布检查不再提示追加该字段对应的数据表列。
  • 新版画布字段“显示名称”可以一次性清空,输入过程中不自动回填。
  • 必填字段未配置默认值时,DDL 不生成 NOT NULL 约束;配置默认值后才生成非空默认值约束。
  • 前端构建、ESLint 或后端目标模块编译等对应变更范围的校验通过;如因既有问题无法全量通过,需在执行日志记录失败点和本次变更无关性。

归档记录(HARD-GATE)

  • 状态:done
  • 归档时间:2026-06-27
  • 归档人:yaomd(批量归档)
  • 归档路径:code-copilot/changes/archive/2026-06-27-lowcode-designer-field-sync-ux/
  • 判定依据:任务清单全部完成,execution-log 验证通过(编译/构建/lint 闭环)。