Skip to content

[console/actions] 无 locations 的动作会渲染到所有位置 —— 聚合批量动作(execution: 'aggregate')因此在列表工具栏留下一个必然失败的按钮 #3142

Description

@os-zhuang

现象

packages/components/src/renderers/action/action-bar.tsx:137 的过滤规则:

a => !a.locations || a.locations.length === 0 || a.locations.includes(schema.location!)

不声明 locations(或声明为空数组)的动作会出现在每一个 action:bar 位置,包括列表工具栏。ObjectViewobjectDef.actions 原样交给 action:bar(localizedToolbarActions,ObjectView.tsx:406),由渲染器过滤,所以这条宽松规则直接决定了工具栏内容。

(注意 DeclaredActionsBar.tsx:254 用的是严格规则 Array.isArray(a.locations) && a.locations.includes(location) —— 同一个「动作该出现在哪」的问题,仓内有两套相反的答案。)

为什么现在成了问题

#3139 / #3141 落地的聚合批量动作(bulkActionDefs[].execution: 'aggregate')引入了一类天然只对选中集有意义的动作:它被调用一次、拿到 params._selectedIds,产出单一聚合产物(打包 zip / 合并 PDF / 批量打印)。这类动作没有合理的单记录位置,作者的自然写法就是不写 locations

结果(showcase 实测,浏览器验证):动作按预期出现在批量选择条(工作正常,一次调用带全部 id),同时出现在列表工具栏 —— 那里没有选中集,分发出去的 body 里没有 _selectedIds,服务端必然拒绝(实测 HTTP 400 recordId required)。也就是说,按最自然的方式声明一个聚合动作,就会白送一个 100% 失败的按钮。

建议

  1. 让两个渲染器对齐到严格规则(缺省 locations 不再等于「到处显示」)。这是 ADR-0078「不要静默无效的元数据」的同类问题:一个位置不明的动作被放到它跑不通的地方,失败发生在用户点击时,而不是发布时。需要评估存量影响(有多少现有动作靠这条宽松默认露出)。
  2. 或者给「只服务于选中集」一个显式表达 —— 例如 ActionLocationSchema 增一个 list_selection 位置,或在 spec 侧规定聚合 def 命名的动作不参与位置渲染。这条更贴合语义,但要动 spec。
  3. 无论走哪条,content/docs/ui/actions.mdx 应写明 locations 缺省的实际含义 —— 今天完全没说。

现状规避

showcase 的聚合 specimen(showcase_recalc_selection)已改为显式 locations: ['record_more'] + recordIdParam,把单记录入口放在跑得通的地方、同时不落到工具栏(objectstack-ai/objectstack#4461)。

Metadata

Metadata

Assignees

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