fix(plugin-report): report chart 的度量显示名按三级回落解析,不再印原始 name (#4020) - #4879
Conversation
数据集绑定的 report chart 把度量原样交给图表组件(`series: [{ dataKey }]`,
无 label),于是 `ChartRenderer` 用 dataKey 填 `config[dataKey].label`,图例、
标记 tooltip 与单值卡片说明文字一起在全中文控制台上打出
`potential_upside_tons`;同一张报表下方的汇总表、以及绑定同一数据集的
dashboard 图表都能正确解析授权 `label`。`ReportChartSchema` 自 rc.1 起声明的
`series[].label` 也从未被读取——立卡人实测其为惰性元数据,属实。
按三级回落解析一次,系列图与单值族共用:
1. `chart.series[]` 中 `name` 命中该度量的条目的 `label`(spec 的 I18nLabel,
经 `pickLocalized` 按控制台语言解析;同名重复第一条为准,与 dashboard 的
`mergeAuthoredPresentation` 同裁定);
2. 绑定数据集的度量 label(结果字段 `label`)——`headerLabel` 读的正是这一个
值,所以图与其下方汇总表在一屏上只有一种拼写;
3. 度量 `name` 兜底(`headerLabel` 自己的最后一档)。
语言取 `useObjectTranslation().language` 而非 `useDisplayLocale()`:后者优先
租户区域 locale(ADR-0053)以喂 `Intl` 数字格式,而数字按 de-DE 格式化的工作区
若控制台跑 zh,标签仍应读 zh 那一支。
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Claude <noreply@anthropic.com>
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
|
【PM 验收 · ACCEPT】objectui 分片 PM(session_01GTRjn8xBqp75dk7kFupVRt)对 #4020 的实施验收: 实物核验:3 文件(DatasetReportRenderer +67/-4、新钉 10 条、changeset patch),零越包、模型标识 0、releases 0。前置硬规兑现:objectstack#5141 源单全线程读毕(分诊裁定与本卡一致、迁移属「移走非驳回」、无 hold 条件)。口径纪律:②③ 复用 反向验证(双探针):A(还原真实旧两行)与 B(name 直读)各 9 红 1 绿且绿点不同,预判全对上;探针 A 还记录了「单值族原已有 ②③、系列图三档全无」的真实事实 —— 撤法歧义被如实拆解而非硬套模板。CI 亲读:19 项全 completed(17 success + 2 skipped),零失败。 留否决窗一处:① 对 I18nLabel 按控制台语言解析,与 plugin-charts/dashboard 两处 locale-blind 的「第一个字符串胜」存在有意取向差异 —— 本支更正确(zh 控制台不吞英文支)且不同屏不打架,已在代码注释与 PR 声明;若维护者倾向全仓一致,反向收敛(charts 侧改 pickLocalized)另开一单即可。新 findings #4877(转发丢 chrome 且 处置:undraft + auto-merge(SQUASH)。 Generated by Claude Code |
Fixes #4020
病灶
数据集绑定的 report chart 把度量原样交给图表组件,实测转发出去的 schema 键只有六个:
其中
series是[{ dataKey: yAxis }]—— 没有 label。ChartRenderer随后用s.label || s.dataKey填config[dataKey].label,于是图例、标记 tooltip 的 name、以及单值族卡片的说明文字同时落回 dataKey,在全中文控制台上打出potential_upside_tons。同一张报表下方的汇总表读headerLabel()(结果字段label)一直是对的,绑定同一数据集的 dashboard 图表走buildChartSeries(fields[].label)也一直是对的 —— 报表图是唯一两边都不查的那一面,立卡人的定位准确。ReportChartSchema.series[].label自 rc.1 起就已声明,但这条路径从未读过它。立卡人把它实测为惰性元数据,属实:作者因此没有任何可授权的手段控制这个字符串。修法
在
DatasetReportChart里把度量显示名解析一次,系列图分支与单值族分支共用(原先两条分支各写各的,正是漂移的温床):chart.series[]中name命中该度量的条目的label—— spec 的I18nLabel,经pickLocalized按控制台语言解析;同名重复以第一条为准,与 dashboard 的mergeAuthoredPresentation同一裁定;label—— 即结果字段的label,headerLabel()读的正是这一个值,所以图和它下方的汇总表在一屏上只有一种拼写;name兜底,headerLabel()自己的最后一档。复用而非新造口径:② 和 ③ 直接落在既有共享 helper
buildDatasetFieldHelpers().headerLabel(@object-ui/core,汇总表、矩阵表头、dashboard 表格、DatasetPreview 都在用);① 的 i18n 记录形用@object-ui/i18n的pickLocalized—— 全仓解析I18nLabel的那一个 helper。没有引入第三份拼写。语言取
useObjectTranslation().language而非本组件已有的useDisplayLocale():后者优先租户区域 locale(ADR-0053)因为它喂Intl数字格式;数字按 de-DE 格式化的工作区若控制台跑 zh,标签仍应读 zh 那一支。tooltip / legend 同源同修:三者读的是同一个
config[dataKey].label,所以一处 label 落位,图例、tooltip、单值说明文字一起对 —— 不是第二次解析,是同一个输入。反向验证:两种探针,方向分别预判后再跑,都对上了
"把修改撤掉看钉子红"在这张卡上是歧义的 —— 有两种撤法,动的不是同一批用例。两种都先写预判再跑:
探针 B(
measureLabel = yAxis,name 直读):预判 9 红 1 绿,绿的必须是 ③。实测一致:③ 活下来是必然而非侥幸:name 直读与三级回落的第 ③ 档重合,这条用例在原理上就分辨不了两者。每条失败打印的都是
potential_upside_tons—— 立卡正文报的症状原样复现。探针 A(还原改动前的真实两行):预判同样 9 红 1 绿,但绿的是另一条。实测一致:
③ 在这里转红:改动前转发的 series 根本没有
label键,值是undefined而不是 name。唯一的绿是 "a kpi caption still falls back to the dataset measure label" —— 它记录了一个真实事实:单值族分支改动前就已解析 ② 和 ③,缺的只有 ①;系列图分支三档一档都没有。所以 ③ 的职责不是"改前红",而是守住兜底仍落在 name 上、没变成
undefined或[object Object]—— 这正是改动前代码真实具备的缺陷,而 ① ② 两条看不见它。两种探针的方向差异已如实写进用例文件头,不按"改前绿改后红"的模板硬套。测试
新增
DatasetReportRenderer.chartMeasureLabel.test.tsx(10 条):三级各一、命名了别的度量的条目不得越权改名、命中但无可用 label 落回 ②、同名重复第一条胜、i18n 记录形按控制台语言取 zh 支、table 与 chart 同度量同名(本卡病灶的反面)、单值族 ① 与 ②。消费半径按规矩点过:
DatasetReportRenderer的调用方是 app-shell 的ReportView与 metadata-admin 的ReportPreview,两者的 dataset 用例均绿;没有任何别处 fixture 断言这条转发出去的 series 形状。顺手发现,不扩围(已另立单)
showLegend: falsestill draws a legend,colors/showDataLabelsare inert #4877 —— 同一行转发丢掉了全部授权 chrome:实测showLegend: false/colors/showDataLabels都没进 schema,而AdvancedChartImpl的showLegend !== false让缺省等于开,作者的显式false不是被忽略而是被反转。立卡人自己的报表正authored 了showLegend: false。buildChartSeries, which the report path does not call #4878 —— 同一行从不给 NULL 分类分桶:实测data = [{"owner":null,...}]原样送达渲染器,正是 A NULL-keyed group is dropped from a bar chart, leaving an axis with no marks and no empty state — the default first-boot state of System Overview's "Events by User" #4466 测得"完全不画标记"的输入。A NULL-keyed group is dropped from a bar chart, leaving an axis with no marks and no empty state — the default first-boot state of System Overview's "Events by User" #4466/A NULL first-dimension value is still dropped by the multi-dimension pivot branch of buildChartSeries (the sibling of #4466) #4497/buildChartSeries' pivot branch silently drops a null SECOND-dimension group: its measure is written to the bucket but never becomes a series, so the value vanishes from the chart #4673/DatasetWidget renders the English '(None)' null-bucket floor in a zh app — one argument short of localized #4500/The chart null-category bucket has two identity collisions: it merges a null group with an empty-string group, and collides with a stored value spelling the label #4508 整族修的都是buildChartSeries,而报表图这条路径不调它。两条都是实测到接缝、非代码阅读推断;均未认领,留给 PM 分诊。
Generated by Claude Code