Skip to content

ListView/DetailView/DetailSection 关联字段&类型显示一致性重大缺陷($expand、objectSchema enrichment、类型推断) #943

@hotlong

Description

@hotlong

问题背景 & 影响

当前 ObjectUI 在列表页和记录详情页存在如下重大字段类型显示缺陷:

  • lookup、master_detail 等关联字段在列表和详情页始终显示原始 ID(如 o1p1),而非展开后的名称。
  • 即便服务端已实现 $expand,客户端 fetch 时机和字段类型推断逻辑存在竞争和脱节。
  • 不同 view(ObjectGrid / ListView / DetailView / DetailSection)对字段类型和 objectSchema enrichment 支持不一致,部分代码直接 fallback 至原始值/ID。

用户反馈截图

列表页 — Order/Product 字段显示 o1p1 等原始 ID:

列表页字段显示异常

详情页 — ORDER 显示 o1,PRODUCT 显示 p1

详情页字段显示异常


具体问题归纳(3个独立根因)

Bug 1: ListView $expand 竞争条件

位置: packages/plugin-list/src/ListView.tsx

// ListView.tsx L509-513
const expandFields = React.useMemo(
    () => buildExpandFields(objectDef?.fields, schema.fields),
    [objectDef?.fields, schema.fields],
);
  • expandFields 依赖异步加载的 objectDef,首次 fetch 时 objectDef 可能仍为 null,导致 expandFields = []
  • 数据请求不带 $expand,服务端返回的 lookup 字段为原始 ID 字符串
  • 即使后续 objectSchema 加载完成,数据本身已经是 "o1" 而非展开对象,LookupCellRenderer 没有 options 可以 resolve label

Bug 2: DetailView 不传 $expand,也不加载 objectSchema

位置: packages/plugin-detail/src/DetailView.tsx

// DetailView.tsx L86-92
if (dataSource && schema.objectName && schema.resourceId) {
    dataSource.findOne(objectName, resourceId).then((result) => {
        setData(result);
    });
}
  • findOne() 调用完全不传 $expand 参数
  • DetailView 不加载 objectSchema(不像 ObjectGrid 那样调用 getObjectSchema
  • 因此不知道哪些字段是 lookup/master_detail 类型,无法计算需要 expand 的字段
  • 传给 DetailSection 的 fields 缺少 type 属性

Bug 3: DetailSection 缺少 objectSchema enrichment

位置: packages/plugin-detail/src/DetailSection.tsx

// DetailSection.tsx L76-86
const displayValue = (() => {
    if (value === null || value === undefined) return '-';
    if (field.type) {                      // ← 没有 type 就跳过 CellRenderer
        const CellRenderer = getCellRenderer(field.type);
        if (CellRenderer) {
            return <CellRenderer value={value} field={field} />;
        }
    }
    return String(value);                   // ← 直接 String()
})();
  • field.type 未指定时直接 String(value)
  • 即使数据被 expand 成对象也可能显示 [object Object]
  • select、percent 等类型也无法走到正确的 CellRenderer

根因总结

# 组件 问题 影响
1 ListView $expand 依赖异步 objectDef,首次 fetch 时 objectDef=null → 不带 $expand → 数据是原始 ID 列表 lookup 字段始终显示 ID
2 DetailView findOne() 不传 $expand,不加载 objectSchema 详情页 lookup 字段显示原始 ID
3 DetailSection field.type 未指定时直接 String(value) → 无法利用类型感知的 CellRenderer 所有无 type 的字段渲染失败

修复建议

  1. ListView:确保 objectDef 加载完成后再发起数据 fetch(或在 objectDef 变化后 re-fetch 带上 $expand
  2. DetailView:参照 ObjectGrid,先加载 objectSchemabuildExpandFieldsfindOne(resourceId, { $expand }),并将 objectSchema 传给 DetailSection
  3. DetailSection:当 field.type 为空时,从 objectSchema 中查找字段类型、options 等元数据,参考 ObjectGrid generateColumns 的 enrichment 逻辑

涉及文件

  • packages/plugin-list/src/ListView.tsx
  • packages/plugin-grid/src/ObjectGrid.tsx
  • packages/plugin-detail/src/DetailView.tsx
  • packages/plugin-detail/src/DetailSection.tsx

验收标准

  • 列表页 lookup/master_detail 字段显示展开后的名称(非原始 ID)
  • 详情页 lookup/master_detail 字段显示展开后的名称
  • percent 字段在详情页正确显示百分比格式
  • select 字段在详情页和列表页正确显示 label
  • 空值/null 统一显示 -
  • 补充相关 UT/Snapshot 测试
  • pnpm test 全部通过
  • 更新 ROADMAP.md

关联

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions