关联配置体验重构_1e744c2a.md 7.8 KB

关联配置体验重构

问题诊断

问题 根因 影响
引用对象选择器出现重复选项 businessObjectList({}) 返回同一 objectCode 的多条记录(跨套件),未做去重 用户困惑
引用对象选择器没法搜索 属性面板已有 filterable,但运行时 n-select 未启用远程搜索 大量选项时难以定位
主子表关系配置太复杂 14+ 字段全部平铺在一个 3 列网格中,无渐进式展示 用户不知如何配置
子表选择器报"缺少业务对象编码" 关系配置中的 recordSelector.objectCode 未正确透传到运行时子表表单字段 选择器无法打开

设计理念

参考飞书多维表格的关联字段设计:

  • 最少操作:用户只需选择目标对象 + 关系类型,其余自动推断
  • 统一入口:字段属性面板中合并为"关联配置"区域,通过"选择方式"切换下拉/弹窗
  • 渐进展示:核心配置(目标对象)第一屏展示,高级配置(字段映射、筛选)折叠隐藏
  • 即时反馈:选择目标对象后立即自动推断显示字段、值字段、搜索字段

Task 1: 修复 objectReference 选项重复 + 远程搜索

目标:解决引用对象选择器中的重复选项和搜索体验问题

文件修改

  • 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
    • objectReference 运行时 n-select 增加 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 => ({ ... }))

Task 2: 统一字段属性面板"关联配置"入口

目标:将 objectReference 和 recordSelector 两种配置合并为一个"关联配置"区域

文件修改

  • forge-admin-ui/src/views/app-center/components/designer/BusinessFieldPropertyPanel.vue

UI 改造

┌─ 关联配置 ────────────────────────────────────┐
│ 选择方式:  ○ 下拉选择   ○ 弹窗选择器         │
│                                                │
│ 目标对象:  [选择业务对象 ▾]  (filterable)     │
│                                                │
│ ─── 自动推断结果(只读提示)───                │
│ 显示字段:  name (自动推断)    [可修改]        │
│ 值字段:    id (默认)          [可修改]        │
│                                                │
│ ▸ 高级配置                                     │
│   └ 搜索字段 / 字段映射 / 过滤参数 ...        │
└────────────────────────────────────────────────┘

自动推断规则(选择目标对象后自动填充):

  1. 显示字段:优先找 name/title 字段
  2. 值字段:默认 id
  3. 搜索字段:name + code 类字段
  4. 当切换"选择方式"时自动迁移已有配置

Task 3: 重构 BusinessRelationDesigner 为极简向导

目标:将 14 字段密集表单改为 2 步极简配置 + 折叠高级选项

文件修改

  • forge-admin-ui/src/views/app-center/components/designer/BusinessRelationDesigner.vue

新 UI 结构

┌─ 关系卡片(折叠后只看标题行)──────────────────┐
│ ▾ 采购入库单 → 拥有多条 → 入库明细            │
│                                                │
│   关系类型:   [拥有多条目标记录 ▾]            │
│   目标对象:   [入库明细 ▾]                    │
│   ── 自动推断(可覆盖)──                      │
│   匹配方式:   id = purchaseOrderId (自动推断)  │
│   显示字段:   productName (自动推断)           │
│                                                │
│   ▸ 显示选项(详情页签/新增编辑内嵌/排序)     │
│   ▸ 子表选择器(启用/候选对象/映射/筛选)      │
│   ▸ 高级设置(保存模式/默认筛选/说明)         │
└────────────────────────────────────────────────┘

改造要点

  1. 将 3 列 grid 改为自然流式布局(1-2列为主)
  2. "自动推断"结果作为只读默认值呈现,旁边有"修改"按钮展开 select
  3. 子表选择器配置折叠在 n-collapse 中,展开后保持当前的可视化映射 UI
  4. 向导弹窗只保留:关系类型 + 目标对象,确认后自动推断所有字段

Task 4: 修复 recordSelector objectCode 透传

目标:解决点击选择按钮时提示"选择器缺少业务对象编码"

根因分析

  1. 字段属性面板配置 form.recordSelectorObjectCode
  2. 保存时写入字段的 recordSelector.objectCode 配置
  3. 运行时经过 formDesignerSchema.jsbuildComponentProps 透传
  4. AiFormItem.vuenormalizeRecordSelectorConfig 解析

断点定位:在 buildComponentProps 中,已有透传逻辑:

if (field.recordSelector || field.props?.recordSelector)
  props.recordSelector = field.recordSelector || field.props?.recordSelector

但问题是当配置来自字段属性面板时,objectCode 可能保存在 field.basicProps.recordSelector.objectCode 或单独的 field.recordSelectorObjectCode 中。

修复方案

  • formDesignerSchema.jsbuildComponentProps 中增加兜底:当 field.recordSelectorObjectCode 存在时,合成 recordSelector 配置对象
  • BusinessFieldPropertyPanel.vuenormalizePayload 确保将散落的 recordSelector 字段合并为完整的 recordSelector 对象保存

文件修改

  • forge-admin-ui/src/views/app-center/components/designer/form-first/formDesignerSchema.js
  • forge-admin-ui/src/views/app-center/components/designer/BusinessFieldPropertyPanel.vue

Task 5: objectReference 运行时远程搜索

目标:当选项数量 > 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],
}

Task 6: ESLint 检查 + 构建验证

在所有修改完成后:

  1. npx eslint 检查修改的文件
  2. pnpm build 确保编译通过
  3. 手动列出核心变更清单供用户验证

实施顺序

  1. Task 1 (去重 + 基础修复) → 立即可见效果
  2. Task 4 (objectCode 透传修复) → 修复阻塞性 bug
  3. Task 5 (远程搜索) → 提升运行时体验
  4. Task 2 (统一入口) → UX 重构
  5. Task 3 (极简向导) → UX 重构
  6. Task 6 (验证) → 质量保障