Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

记录详情页的 lookup 字段渲染成纯文本+复制按钮,不可点击跳转到被引用记录(列表页的链接列正常) #4336

Closed

Description

@baozhoutao

现象

记录详情页(record detail)上的 lookup 关系字段渲染成纯文本 + 复制按钮,不是可点击的链接——看得到被引用记录的显示名,却没法从这里跳过去。

在一个业务项目(17.0.0-rc.6)上观察到,同一张详情页上多个 lookup 字段行为一致:

  • 关联维修派工单(lookup → 维修派工单,readonly: true)—— 纯文本 TYG1WX20260812001001,不可点击;
  • 点检任务(lookup → 任务,非 readonly)—— 纯文本 #1072b埋弧焊机日常点检(TYWI003),同样不可点击;
  • 任务版本(lookup,readonly)—— 同上。

另一个对象(安灯记录)详情页上的 生成的维修派工单 字段也是同样表现,所以看起来与具体对象、与字段是否 readonly 都无关。

期望

详情页上的 lookup 字段值应可点击,跳到被引用记录的详情页(与列表页里 link: true 的列、以及相关表里行点击进详情的体验一致)。

单据之间互相引用是业务系统的常态(点检记录 → 派生的维修单 → 关联设备 → …),详情页不给跳转,用户只能复制编号再回列表搜,链路上每跨一张单都要绕一圈。

复现

  1. 任意对象 A 上定义一个 lookup 字段指向对象 B;
  2. 建一条 A 记录并让该字段有值;
  3. 打开这条 A 记录的详情页(非列表、非相关表);
  4. 该字段值区域:是纯文本 + 一个复制按钮,鼠标悬停无链接态,点击无反应。

readonly / 非 readonly 都一样。

环境

  • @objectstack/*@17.0.0-rc.6
  • Console UI(/_console),桌面视口
  • 单租户模式

备注

来自一个使用 ObjectStack 的业务项目在验收测试中的观察。如果这是有意设计(比如详情页刻意不做跳转以避免层层下钻),麻烦说一声,我们按现状调整用户预期;如果只是还没做,想问下有没有排期,或者有没有当前版本可用的声明方式(试过在字段上找可选项,没找到相关开关)。

Activity

  1. os-zhuang commented on Aug 11, 2026

    @os-zhuang
    Contributor

    Triage: pm:queue (+ bug).

    • Classification: concrete, reproducible gap on a shipped surface, reported from a real deployment's acceptance testing (rc.6): lookup values on the record detail page render as plain text + copy button while the list page's link: true columns and related-table rows already navigate. The consistency evidence reads as "not yet wired", not a deliberate design — and cross-document navigation (inspection record → work order → equipment …) is the everyday path in exactly the business systems this serves. If the executing seat finds an on-record ruling that detail pages deliberately do not link, escalate instead of closing.
    • Repro: as filed — any lookup field with a value, detail page, both readonly and non-readonly, multiple objects.
    • Dedup: repo-scoped search finds no open card on detail-page lookup linkification ([UX Enhancement] Always show "Browse All" button to open RecordPickerDialog in Lookup fields #1091 was the picker's Browse All, closed; feat(record-detail): 记录详情页头部增加手动刷新按钮(不 reload 浏览器即可刷新详情/相关/计数) #3460 was the refresh button, closed). Nothing in flight touches the detail field renderer for this.
    • Routing note: fix lands in the record-detail field rendering path (whole-repo backlog — no lane labels in this repo). Release-board stamping is the objectui seat's call, but flagging for that seat: this is user-visible on every record page with a lookup, worth the target: test.

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  2. baozhoutao commented on Aug 12, 2026

    @baozhoutao
    ContributorAuthor

    追加材料:同现象在 rc.6 再次出现,并且相关表(related list)里的 lookup 列也一样是纯文本

    同一个业务项目,另一轮验收(设备维保场景)又撞到这条,补两点材料——其中第 2 点与本单标题括号里的「列表页的链接列正常」以及分诊结论里的 "related-table rows already navigate" 略有出入,想请确认范围。

    1. 详情页:再添一个复现对象

    • 对象「维保履历」详情页上的 来源维保派工单(lookup → 维保派工单)= 纯文本 TSD110420260811005001,鼠标悬停无链接态,点击 URL 原地不动;页面 main 区域内不存在含该编号的 <a>。
    • 与原报告一致:与对象无关、与 readonly 无关。

    2. 相关表里的 lookup 列同样不是链接(可能超出本单当前描述的范围)

    在设备详情页 →「相关」页签 →「维保履历」子列表上:

    • 行本身能导航——点整行会跳到那条维保履历的记录详情,这一点与分诊结论一致;
    • 但子列表的各个单元格里,指向第三个对象的 lookup 列是纯文本:该子列表的 执行责任人、管理责任人(均为 lookup → 人员)以及后来补上的 来源维保派工单 列,逐格取 href 全部为 null,整行 6 个单元格没有任何 <a>。

    也就是说:相关表能跳的只有「行 → 这一行自己那条记录」;行内 lookup 指向的别的对象,一样跳不过去。所以「缺链接」的面比原标题写的更宽一点,不止详情页。

    如果这是同一处渲染路径,那本单一并覆盖即可;如果相关表列走的是另一套 cell 渲染,可能需要拆成第二张单,请按仓库习惯处理。

    3. 已排除权限因素

    一开始怀疑是无读权导致 expand 静默降级成裸值,实测排除:

    • 两个观察账号对目标对象(维保派工单)都是 CRUD_ALL;
    • 单元格里显示的是正常解析出来的显示名/编号(DOM 里 title 属性是记录 id、可见文本是编号),不是裸 UUID。

    所以是渲染层没做链接,不是数据层降级。

    4. 下游绕法,以及一个附带发现(形状不一致)

    我们这边暂时把跳转做成了 type:'url' 行动作(行尾「…」一跳直达),不打补丁。做的过程中发现一处形状差异,顺带报一下:

    同一个 lookup 字段,通过 ${param._rowRecord.<lookup>} 取值时——

    • 在记录页头动作里拿到的是 expand 过的对象(必须写 .id 才能取到记录 id);
    • 在列表 / 子列表行动作里拿到的是裸 id 字符串(再写 .id 会插值成空串,URL 跳成 /record/ 后面什么都没有)。

    结果是同一个「跳到这一行 lookup 指向的记录」的需求,必须拆成两条动作分别声明。若这是有意的形状差异,建议在文档里点明;若不是,可能值得单独收一下。

    环境

    • @objectstack/*@17.0.0-rc.6,Console(/_console),桌面视口,单租户。

    截图在我们项目的私有仓里,直接贴链接你们看不到,就不贴了;需要的话我可以另出一组脱敏截图。

  3. self-assigned this
    on Aug 12, 2026
  4. yinlianghui commented on Aug 12, 2026

    @yinlianghui
    Contributor

    CLAIM — session session_017Qqyix2QcnpUC9XeYVDzx3, branch claude/issue-4336-detail-lookup-links.

    Ruling (delegated authority; open veto window): linkify. Cross-document navigation is the everyday path in exactly the business systems this serves (the reporter's chain: 点检记录 → 维修单 → 设备), and the consistency evidence (readonly-independent, object-independent, list link: true columns already navigate) reads as not-yet-wired, per triage. Per the triage escalation clause: if an on-record ruling that detail pages deliberately do not link is found, STOP and escalate rather than fix.

    1. Detail page (the card's core): lookup field display values become links to the referenced record's detail page. One-resolver requirement: measure how the list page's link: true columns and related-row navigation build record URLs and reuse THAT mechanism — no hand-built URL assembly (the console: copied invitation link is unusable — buildAcceptUrl rebuilds the trailing-dot host that resolveHomeUrl already retired #4472/finding(app-shell): AiChatPage's publicShareBase is a third hand-rolled console-mount resolution — correct today, drift risk under the one-resolver rule #4482 lesson). Keep the copy button; link and copy coexist. readonly irrelevant (display mode).
    2. Related-list cells (the follow-up's widening): measure the render path FIRST. If related-list lookup cells share the detail renderer's path, cover them here; if they are a separate cell-rendering path, fix the detail page here and FILE the related-list half as its own card with the path measurement — the reporter explicitly asked for the split to follow repo convention.
    3. The rowRecord shape inconsistency (expand-object in header actions vs bare-id in row actions, from the follow-up's item 4): NOT in scope — if your measurement confirms it in passing, file it as a separate finding; do not fix.

    Red-first: detail page with a valued lookup — pre-fix the value region contains NO <a> (the reporter's own DOM check), post-fix an anchor navigating to the referenced record's URL; must-not-change: display name/title resolution unchanged, copy button still present and functional, non-lookup fields untouched.

    Grading: patch per touched package (.d.ts-checked; if the field component's public props grow, minor per #4403/#4177 — measure).

    Surface (mutual exclusion): the record-detail field rendering path (packages/plugin-detail/** and/or the lookup field's display component in packages/fields/** — ⛔ NOT packages/fields/src/index re-export lines, #4431 owns those) + shared cell renderer ONLY if measurement proves same-path + tests + changesets. Disjoint from in-flight #4431 (chatbot/core/fields-index/ledger), #4452 (plugin-calendar), #4462 (plugin-list ListView/plugin-report/app-shell print styles), #4474 (console/organizations).


    Generated by Claude Code


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions