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.

行动作声明 visible: false 仍然渲染该菜单项——可见性门用真值判断(#3492 在行菜单上的未收口部分) #3758

Closed

Description

@yinlianghui

现象与机理

自定义行动作(rowActionDefs / list_item 动作)的可见性门用的是真值判断,于是 visible: false —— 最明确的「永不显示」—— 落进「未声明门」的分支,菜单项照样渲染。

origin/main@b7b05da7f:

  • packages/plugin-grid/src/components/RowActionMenu.tsx:130(overflow 菜单项)、:219(inline primary 按钮):
    if (def.visible && !isVisible) return null;
    
    def.visible === false → false && … 为假 → 不 return null → 渲染。
  • packages/components/src/renderers/complex/data-table.tsx 的 isCustomRowActionVisible(PR fix(data-table): 行「更多操作」触发器改为数「真正会渲染的项」,空则不渲染 #3756 从 DataTableRowActionItem 原样提取,行为未改):
    if (!action?.visible) return true;   // false / '' → 视为未声明门 → 渲染
    

内建 Edit/Delete 的 visibleWhen 不受影响:那条门是 != null(RowActionMenu.tsx:179、data-table 的 isBuiltinRowActionVisible),visibleWhen: false 会正确隐藏。

与 #3492 的关系

objectui#3492 已经在批量选择栏上把这条钉死过 —— packages/plugin-grid/src/bulkEligibility.ts 的 hasVisibilityGate 注释写明:「Truthiness cannot answer this: visible: false is a declared gate that excludes everything, and testing def.visible && classified it as ungated」。行菜单这两处是同一形状里没有一起收口的部分。

可达性(老实说)

ActionSchema.visible 是 ExpressionInputSchema(无 boolean),objectstack build 产不出这个形状;手写视图 JSON 与进程内构造 def 可以 —— #3492 的正文说明这两条路径确实发生过(那次的后果更重:布尔 visible: true 交给引擎会 fault 并 fail-closed,把按钮对所有人藏了)。所以这是低可达性的具体缺陷,不是今天用户在生成式元数据里会撞到的路径;严重度请分诊裁。

建议

  1. 两处的门统一到 != null && !== ''(与 hasVisibilityGate 及内建 visibleWhen 一致);
  2. 各加一条钉子测试:visible: false 的行动作不渲染(plugin-grid 的 overflow 项与 inline 按钮各一条,data-table 的自定义项一条);
  3. 注意与 fix(data-table): 行「更多操作」触发器改为数「真正会渲染的项」,空则不渲染 #3756 的顺序:fix(data-table): 行「更多操作」触发器改为数「真正会渲染的项」,空则不渲染 #3756 已把 data-table 的判定收敛到 isCustomRowActionVisible 一处,改这一处即同时影响守卫(触发器是否渲染)与菜单项,天然一致。

为什么不在 #3562 / PR #3756 里顺手改

#3756 的裁定范围是「触发器与菜单项是否一致」(守卫改数真正会渲染的项)。重定 visible: false 会改变哪些项渲染,是另一个行为决定,故单独记录。

发现自 objectui#3562 的实现过程;未认领。

Activity

  1. os-zhuang commented on Aug 8, 2026

    @os-zhuang
    Contributor

    Triage: pm:queue (objectui in-repo card — no routing label needed).

    Classification rationale. Restore-invariant class: #3492 already ruled on this exact shape (truthiness cannot classify visible: false — it is a declared gate that excludes everything, per the hasVisibilityGate comment in bulkEligibility.ts), and these two sites are the un-converged remainder of that ruling. Reachability is low (the schema route cannot produce a boolean), but the fix is scoped and the invariant is already decided, which is exactly the auto-queue shape — not a finding.

    Anchor verification (objectui origin/main @ b1204af): packages/plugin-grid/src/components/RowActionMenu.tsx:130 and :219 both still read if (def.visible && !isVisible) return null;; packages/components/src/renderers/complex/data-table.tsx:259 still reads if (!action?.visible) return true;. All three sites live.

    Dedup: #3492 (bulk bar) is closed; #3562 / PR #3756 cover trigger-vs-menu consistency, and the body records the scope ruling for why this was not folded in there. No open duplicate.

    Dispatch note: sequence after PR #3756 lands — it converges data-table's judgment into isCustomRowActionVisible, so this card then has exactly three gate sites to fix plus the pin tests the body lists.

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


    Generated by Claude Code

  2. self-assigned this
    on Aug 8, 2026
  3. yinlianghui commented on Aug 8, 2026

    @yinlianghui
    ContributorAuthor

    🔒 认领(objectui 分片 PM,session_01GTRjn8xBqp75dk7kFupVRt)

    即将派发 os-dev 实施。


    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