发现于 #4786 的实施,真实 SchemaRenderer 探针实测。
教学面
skills/objectui/guides/auth-permissions.md 说「derive permission flags in the dataSource object」,然后给出:
{ "type": "button", "label": "Delete", "hidden": "${!canDeleteContacts}" }实测:裸根不解析,按钮两种取值都消失
dataSource 分别取 { canDeleteContacts: true } 和 { canDeleteContacts: false }:
@@PROBE bare/flag-true text="" ← 有权限,按钮却没了
@@PROBE bare/flag-false text=""
@@PROBE data/flag-true text="Delete" ← 改成 ${!data.canDeleteContacts} 才对
@@PROBE data/flag-false text=""
成因
packages/react/src/SchemaRenderer.tsx 建的求值作用域是
{ ...predicateScope, current_user, data: dataSource, page: pageVariables } ——
predicateScope 来自 usePredicateScope()(user / app / features),不含 dataSource。
所以 dataSource 上的键只能经 data. 根访问;裸名解析成 undefined,!undefined 恒为 true,hidden 恒真。
失效方向恰好是最坏的那个:有权限的用户看不到按钮,而且和权限位取值无关,所以"改一下权限再试"这条最自然的排查路径不会给出任何信号。
#4786 的 PR 改了这个示例的 props 信封("props": { "label": ... } → "label": ...),那部分实测已通过。表达式根写错是另一处独立缺陷,刻意未改 —— 同文件同段落,但不属于信封范围。
需要顺带核一遍同文件里其它裸根表达式(${data.userRole !== 'admin'} 那几处是对的,已实测)。
参考
发现于 #4786 的实施,真实 SchemaRenderer 探针实测。
教学面
skills/objectui/guides/auth-permissions.md说「derive permission flags in the dataSource object」,然后给出:{ "type": "button", "label": "Delete", "hidden": "${!canDeleteContacts}" }实测:裸根不解析,按钮两种取值都消失
dataSource 分别取
{ canDeleteContacts: true }和{ canDeleteContacts: false }:成因
packages/react/src/SchemaRenderer.tsx建的求值作用域是{ ...predicateScope, current_user, data: dataSource, page: pageVariables }——predicateScope来自usePredicateScope()(user / app / features),不含 dataSource。所以 dataSource 上的键只能经
data.根访问;裸名解析成undefined,!undefined恒为true,hidden恒真。失效方向恰好是最坏的那个:有权限的用户看不到按钮,而且和权限位取值无关,所以"改一下权限再试"这条最自然的排查路径不会给出任何信号。
与 #4786 的关系
#4786 的 PR 改了这个示例的
props信封("props": { "label": ... }→"label": ...),那部分实测已通过。表达式根写错是另一处独立缺陷,刻意未改 —— 同文件同段落,但不属于信封范围。需要顺带核一遍同文件里其它裸根表达式(
${data.userRole !== 'admin'}那几处是对的,已实测)。参考
props信封,而渲染器从节点本身读键 —— 照 page-builder.md 写出的页面渲染一片空白框 #4786(发现来源)