来源:#972 / PR #983 实施过程的测量结论。#972 的「Open Tasks 徽章计入 Completed」那一半按 measure-first 判定为平台能力缺口、本仓不硬改,故把测量结果单独记在这里,免得随 #972 关闭一起丢失。PR #983 已在本仓侧加了守卫挡住写法,但守卫只能挡,不能补能力。
测量对象是本仓实际装的 @objectstack/console@17.0.0-rc.3 与 @objectstack/spec@17.0.0-rc.3 的产物字符串,未做浏览器实测。
实况:rail entry 只有三个键被读
参考栏对每个 entry 只发这一条查询(node_modules/@objectstack/console/dist/assets/plugins-views-CJKuyDvq.js):
find(objectName, { $filter: { [relationshipField]: parentId }, $top: limit ?? 3, $count: true })
标题解析是:
entry.title || (i18n.objectLabel ? i18n.objectLabel({ name: entry.objectName, label: humanize(entry.objectName) }) : humanize(entry.objectName))
即实际被消费的只有 objectName / relationshipField / limit / title(外加 icon、displayField 用于卡片内的行渲染)。组件注册的 inputs 只声明了 hideEmpty 一项。
三条各自独立的缺口
1. entry 没有 filter 通道,而写了不会报错
参考栏的卡片只能表达「关联的全部记录」,无法表达「关联的、且满足某谓词的记录」。商机详情页想要的「未完成任务」在 Related 页签的关联列表里是一行 filter: [{ field: 'status', op: 'neq', value: 'completed' }],在 rail entry 上则无处可写。
比「不支持」更值得记的是它不报错:@objectstack/spec 的 ComponentPropsMap 里没有 record:reference_rail 这一行,页面组件的 properties 是 z.record(z.string(), z.unknown()),.d.ts 里也不存在 ReferenceRailEntry 类型。所以在 entry 上补 filter 会解析通过、typecheck 通过、objectstack validate 通过、构建进产物、发布上线,然后什么也不做 —— 徽章照旧计入全部记录,而源码从此声称自己过滤了。这正是 AI 写元数据最容易踩、也最难在 review 里看出来的一类错。
2. 标题只能拿 label,拿不到 pluralLabel
objectLabel 查的键是 objects.*.label。一张带「关联记录总数」徽章、列最多三条记录的卡片,语义上要的是复数标签(objects.*.pluralLabel,本仓四个语言包都写齐了),拿到的却是单数。PR #983 删掉硬编码 title 之后,英文界面的三张卡片就是 Quote / Opportunity Line Item / Task —— 本地化对了,但数词不对。这条是纯观感,不影响任何功能。
3. title 是不可翻译的字面量
同一份产物里 record:alert 的 title 走 gt(n.title, language)(内联译文映射解析器,支持 { en, 'zh-CN', … }),参考栏则把 entry.title 当作原始 React child 直接渲染。所以 rail entry 的 title 只有两种状态:要么不写(回落到本地化对象标签),要么写一个压过所有语言包的字面量。没有「写一个会被翻译的标题」这个选项。PR #983 选择了不写,代价见第 2 条。
可能的上游修法(仅列出,不预判取舍)
- 只补声明不补能力:在 spec 的
ComponentPropsMap 里给 record:reference_rail 补一行严格 schema。这样第 1 条的「静默失效」立刻变成发布时的响亮拒绝,代价最小,且不需要判断有没有业务拉力。
- 补 filter:entry 加可选
filter,与 record:related_list 同款谓词形状,渲染侧并进 $filter。
- 补标题通道:entry 的 title 接受内联译文映射(与
record:alert 对齐),或让无 title 时按「是列表卡片」取 pluralLabel。
按「初创聚焦、能力扩张要有真实业务拉力」的口径,第 1 条与第 2、3 条的性质不同:第 1 条是把已经存在的形状说清楚(收紧,不扩张),第 2、3 条才是新增授权面 —— 目前的真实消费方只有本仓商机详情页这一个参考栏(全仓 grep 命中一处),拉力是否够,请维护者判断。
本仓侧已做的挡板
PR #983 在 test/metadata-references.test.ts 加了三道守卫(entry 必须指向真实对象与关系字段、不得声明字面 title、不得声明 filter),并在 test/i18n-references.test.ts 加了一道(参考栏涉及的对象在四个语言包里必须都有 label —— 因为 rail 的兜底不是英文 label 而是 humanize(objectName),缺译文比没有 i18n 还糟)。第三道在干净树上是空过的,已用「植入 filter → 转红」单独证伪过,不是靠什么也没产出而通过。
重复检查
search_issues 在本仓 open issue 上查 reference rail filter、reference_rail —— 命中的只有 #972(本条来源)与 #733(同一栏 Products 卡片显示原始记录 ID,是 entries 的另一种失真,与本条不同)。无既有单。若与他人同小时立单重复,烦请 PM race-close。
Refs #972 #733
来源:#972 / PR #983 实施过程的测量结论。#972 的「Open Tasks 徽章计入 Completed」那一半按 measure-first 判定为平台能力缺口、本仓不硬改,故把测量结果单独记在这里,免得随 #972 关闭一起丢失。PR #983 已在本仓侧加了守卫挡住写法,但守卫只能挡,不能补能力。
测量对象是本仓实际装的
@objectstack/console@17.0.0-rc.3与@objectstack/spec@17.0.0-rc.3的产物字符串,未做浏览器实测。实况:rail entry 只有三个键被读
参考栏对每个 entry 只发这一条查询(
node_modules/@objectstack/console/dist/assets/plugins-views-CJKuyDvq.js):标题解析是:
即实际被消费的只有
objectName/relationshipField/limit/title(外加icon、displayField用于卡片内的行渲染)。组件注册的inputs只声明了hideEmpty一项。三条各自独立的缺口
1. entry 没有 filter 通道,而写了不会报错
参考栏的卡片只能表达「关联的全部记录」,无法表达「关联的、且满足某谓词的记录」。商机详情页想要的「未完成任务」在 Related 页签的关联列表里是一行
filter: [{ field: 'status', op: 'neq', value: 'completed' }],在 rail entry 上则无处可写。比「不支持」更值得记的是它不报错:
@objectstack/spec的ComponentPropsMap里没有record:reference_rail这一行,页面组件的properties是z.record(z.string(), z.unknown()),.d.ts里也不存在ReferenceRailEntry类型。所以在 entry 上补 filter 会解析通过、typecheck 通过、objectstack validate通过、构建进产物、发布上线,然后什么也不做 —— 徽章照旧计入全部记录,而源码从此声称自己过滤了。这正是 AI 写元数据最容易踩、也最难在 review 里看出来的一类错。2. 标题只能拿 label,拿不到 pluralLabel
objectLabel查的键是objects.*.label。一张带「关联记录总数」徽章、列最多三条记录的卡片,语义上要的是复数标签(objects.*.pluralLabel,本仓四个语言包都写齐了),拿到的却是单数。PR #983 删掉硬编码 title 之后,英文界面的三张卡片就是 Quote / Opportunity Line Item / Task —— 本地化对了,但数词不对。这条是纯观感,不影响任何功能。3. title 是不可翻译的字面量
同一份产物里
record:alert的 title 走gt(n.title, language)(内联译文映射解析器,支持{ en, 'zh-CN', … }),参考栏则把entry.title当作原始 React child 直接渲染。所以 rail entry 的 title 只有两种状态:要么不写(回落到本地化对象标签),要么写一个压过所有语言包的字面量。没有「写一个会被翻译的标题」这个选项。PR #983 选择了不写,代价见第 2 条。可能的上游修法(仅列出,不预判取舍)
ComponentPropsMap里给record:reference_rail补一行严格 schema。这样第 1 条的「静默失效」立刻变成发布时的响亮拒绝,代价最小,且不需要判断有没有业务拉力。filter,与record:related_list同款谓词形状,渲染侧并进$filter。record:alert对齐),或让无 title 时按「是列表卡片」取pluralLabel。按「初创聚焦、能力扩张要有真实业务拉力」的口径,第 1 条与第 2、3 条的性质不同:第 1 条是把已经存在的形状说清楚(收紧,不扩张),第 2、3 条才是新增授权面 —— 目前的真实消费方只有本仓商机详情页这一个参考栏(全仓
grep命中一处),拉力是否够,请维护者判断。本仓侧已做的挡板
PR #983 在
test/metadata-references.test.ts加了三道守卫(entry 必须指向真实对象与关系字段、不得声明字面 title、不得声明 filter),并在test/i18n-references.test.ts加了一道(参考栏涉及的对象在四个语言包里必须都有 label —— 因为 rail 的兜底不是英文 label 而是humanize(objectName),缺译文比没有 i18n 还糟)。第三道在干净树上是空过的,已用「植入 filter → 转红」单独证伪过,不是靠什么也没产出而通过。重复检查
search_issues在本仓 open issue 上查reference rail filter、reference_rail—— 命中的只有 #972(本条来源)与 #733(同一栏 Products 卡片显示原始记录 ID,是 entries 的另一种失真,与本条不同)。无既有单。若与他人同小时立单重复,烦请 PM race-close。Refs #972 #733