| 问题 | 根因 | 影响 |
|---|---|---|
| 引用对象选择器出现重复选项 | businessObjectList({}) 返回同一 objectCode 的多条记录(跨套件),未做去重 |
用户困惑 |
| 引用对象选择器没法搜索 | 属性面板已有 filterable,但运行时 n-select 未启用远程搜索 |
大量选项时难以定位 |
| 主子表关系配置太复杂 | 14+ 字段全部平铺在一个 3 列网格中,无渐进式展示 | 用户不知如何配置 |
| 子表选择器报"缺少业务对象编码" | 关系配置中的 recordSelector.objectCode 未正确透传到运行时子表表单字段 |
选择器无法打开 |
参考飞书多维表格的关联字段设计:
目标:解决引用对象选择器中的重复选项和搜索体验问题
文件修改:
forge-admin-ui/src/views/app-center/components/designer/BusinessFieldPropertyPanel.vue
loadBusinessObjectOptions 函数增加 objectCode 去重forge-admin-ui/src/views/app-center/components/designer/forge-form-designer/ForgePropertyPanel.vue
loadBusinessObjectOptions 去重forge-admin-ui/src/views/app-center/components/designer/BusinessRelationDesigner.vue
loadBusinessObjects 函数按 objectCode 去重forge-admin-ui/src/components/ai-form/AiFormItem.vue
remote + on-search 支持远程关键词搜索关键逻辑:
// 去重逻辑
const seen = new Set()
businessObjectOptions.value = list
.filter(item => {
if (seen.has(item.objectCode)) return false
seen.add(item.objectCode)
return true
})
.map(item => ({ ... }))
目标:将 objectReference 和 recordSelector 两种配置合并为一个"关联配置"区域
文件修改:
forge-admin-ui/src/views/app-center/components/designer/BusinessFieldPropertyPanel.vueUI 改造:
┌─ 关联配置 ────────────────────────────────────┐
│ 选择方式: ○ 下拉选择 ○ 弹窗选择器 │
│ │
│ 目标对象: [选择业务对象 ▾] (filterable) │
│ │
│ ─── 自动推断结果(只读提示)─── │
│ 显示字段: name (自动推断) [可修改] │
│ 值字段: id (默认) [可修改] │
│ │
│ ▸ 高级配置 │
│ └ 搜索字段 / 字段映射 / 过滤参数 ... │
└────────────────────────────────────────────────┘
自动推断规则(选择目标对象后自动填充):
目标:将 14 字段密集表单改为 2 步极简配置 + 折叠高级选项
文件修改:
forge-admin-ui/src/views/app-center/components/designer/BusinessRelationDesigner.vue新 UI 结构:
┌─ 关系卡片(折叠后只看标题行)──────────────────┐
│ ▾ 采购入库单 → 拥有多条 → 入库明细 │
│ │
│ 关系类型: [拥有多条目标记录 ▾] │
│ 目标对象: [入库明细 ▾] │
│ ── 自动推断(可覆盖)── │
│ 匹配方式: id = purchaseOrderId (自动推断) │
│ 显示字段: productName (自动推断) │
│ │
│ ▸ 显示选项(详情页签/新增编辑内嵌/排序) │
│ ▸ 子表选择器(启用/候选对象/映射/筛选) │
│ ▸ 高级设置(保存模式/默认筛选/说明) │
└────────────────────────────────────────────────┘
改造要点:
n-collapse 中,展开后保持当前的可视化映射 UI目标:解决点击选择按钮时提示"选择器缺少业务对象编码"
根因分析:
form.recordSelectorObjectCoderecordSelector.objectCode 配置formDesignerSchema.js 的 buildComponentProps 透传AiFormItem.vue 的 normalizeRecordSelectorConfig 解析断点定位:在 buildComponentProps 中,已有透传逻辑:
if (field.recordSelector || field.props?.recordSelector)
props.recordSelector = field.recordSelector || field.props?.recordSelector
但问题是当配置来自字段属性面板时,objectCode 可能保存在 field.basicProps.recordSelector.objectCode 或单独的 field.recordSelectorObjectCode 中。
修复方案:
formDesignerSchema.js 的 buildComponentProps 中增加兜底:当 field.recordSelectorObjectCode 存在时,合成 recordSelector 配置对象BusinessFieldPropertyPanel.vue 的 normalizePayload 确保将散落的 recordSelector 字段合并为完整的 recordSelector 对象保存文件修改:
forge-admin-ui/src/views/app-center/components/designer/form-first/formDesignerSchema.jsforge-admin-ui/src/views/app-center/components/designer/BusinessFieldPropertyPanel.vue目标:当选项数量 > 20 时自动启用远程搜索
文件修改:
forge-admin-ui/src/components/ai-form/AiFormItem.vue改造:
// objectReference n-select 增加 remote 属性
<n-select
v-else-if="field.type === 'objectReference'"
:value="resolveOptionValue(value)"
:options="currentOptions"
:loading="remoteLoading"
:clearable="field.clearable !== false"
filterable
remote <!-- 新增 -->
@search="handleObjectReferenceSearch" <!-- 新增 -->
@update:value="handleUpdate"
/>
在 buildObjectReferenceOptionSource 中增加 keyword 支持:
params: {
objectCode: config.objectCode,
keyword: searchKeyword, // 动态传入
displayFields: [...],
keywordFields: [config.labelField],
}
在所有修改完成后:
npx eslint 检查修改的文件pnpm build 确保编译通过