base-paint 0.3.2 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,8 +1,101 @@
1
1
  # base-paint help模板铁律
2
2
 
3
3
  1. 新页面只许 blocks 组装,禁新巨串:HTML/CSS/JS 大字面量不得进 `src`(走子路径 `base-paint/blocks` 组合或本 help模板管线)。
4
- 2. 改模板只改源:`assets/help-template.html`(唯一真相源;3 槽注释 + 前缀 `__HELP_TITLE__` 占位即契约;行尾 CRLF 禁转 LF)。
4
+ 2. 改模板只改源:`assets/help-template.html`(唯一真相源;3 槽注释 + 前缀 `__HELP_TITLE__` 占位即契约;行尾 CRLF 禁转 LF)。**还原/变异回写这一件时**:它被 `.gitattributes` 钉了 `text eol=crlf`(库内存 LF、检出 CRLF),故**不要**拿 `git show HEAD:<路径>` 的原文直接写回(那是 LF,会让 `gen-help-shell.cjs` 的 CRLF 断言当场抛错);用工作树原文读进写出(`readFileSync` → `writeFileSync`)即逐字节安全。
5
5
  3. 改后跑 gen:一键 `pnpm --filter base-paint gen:help-shell`(重写 `src/helpShell.ts`+测试哈希;字节锁随 `pnpm test` 在 CI 验 drift,`gen:help-shell:check` 本地同口径)。
6
6
  4. 过门:字节锁(`test/help-shell-136.test.mjs` 哈希)+像素门(skill-calorie `help-shell-134` 双端/覆盖序)+ `tsc -b` 全绿。
7
7
  5. 手改生成物(`src/helpShell.ts`/测试哈希)必红:`--check` 非 0+字节锁红。
8
8
  6. 源不进包:`files` 仅 `dist`(省约 105KB;追溯靠仓库+哈希锁),包内只留 `dist/helpShell.js`。
9
+
10
+ ---
11
+
12
+ ## 组件目录(发现口)
13
+
14
+ **包名说明**:目录叫 `packages/base-render`,npm 包名叫 `base-paint`——是同一个包,下文均用包名,引用时照抄即可。
15
+
16
+ 本节回答“该调谁”。help 铁律见上,一字未动。机读正身在 `src/spec/`(冻结签名)+契约正本 `../../docs/base-paint-contract.md`;行为示例看 `test/`。
17
+
18
+ ### 速查三问
19
+
20
+ | 我要画 | 调谁 | 从哪引 |
21
+ |---|---|---|
22
+ | 分布条 | `renderDistributionRows` | `base-paint/blocks`(子路径) |
23
+ | 徽章 | `renderStatusBadge`(空态/失败回执另有 `renderEmptyState`/`renderErrorReceipt`) | `base-paint` 根 |
24
+ | 环图 | `charts`(`donut` 种)+ `chartsCss` 取样式 + `buildChartsHelpersJs` 取脚本 | `base-paint` 根 |
25
+
26
+ 注意:`blocks` 整组只走子路径 `base-paint/blocks`,根出口没有它;以下除注明外均走 `base-paint` 根。
27
+
28
+ ### 区块组装(`base-paint/blocks`)——新页面只许 blocks 组装
29
+
30
+ | 函数 | 一句话 |
31
+ |---|---|
32
+ | `renderPageShell` | 页面容器与标题区,每页外层 |
33
+ | `renderTocBlock` | 目录区块 |
34
+ | `renderCaliberLine` | 口径说明行(一行小字) |
35
+ | `renderConclusionBar` | 结论条(一句话总结) |
36
+ | `renderMiniBar` | 细进度条 |
37
+ | `renderDistributionRows` | 分布行(名+条+值,窄槽语义见包内测试) |
38
+ | `renderChips` | 标签片组 |
39
+ | `renderChangeRows` | 变化行(涨跌对照) |
40
+ | `renderKpiCard`/`renderKpiGrid` | 指标卡/指标卡宫格 |
41
+ | `renderDataTable` | 数据表 |
42
+ | `renderChartBlock` | 图表容器块(承 `charts` 的产出) |
43
+ | `renderListRows` | 列表行 |
44
+ | `renderPreBlock` | 预排文本块(命令/CLI 展示) |
45
+ | `renderDetailSection` | 详情分区 |
46
+ | `renderDisclosure` | 折叠展开区 |
47
+ | `renderParamForm` | 参数表单 |
48
+ | `renderEmptyBlock` | 空态块 |
49
+ | `renderCopyBlock` | 可复制文本块 |
50
+ | `renderFeedbackBlock` | 反馈块 |
51
+ | `blocksCss` | 区块样式唯一产出者(配 `BLOCK_STYLE_SECTIONS` 分段表) |
52
+
53
+ 示例:`test/blocks.test.mjs`;源:`src/blocks.ts`。
54
+
55
+ ### 控件(根)——原子交互与状态
56
+
57
+ | 函数 | 一句话 |
58
+ |---|---|
59
+ | `renderToast`/`createToastController` | 轻提示与它的控制器(含堆叠语义) |
60
+ | `copyText`/`createCopyRuntime`/`bindCopyAction` | 复制三件套(双通道+提示反馈,唯一实现) |
61
+ | `buildSharedHelpersJs` | 共享脚本唯一产出者(`SHARED-HELPERS` 槽填充物) |
62
+ | `renderActionBar` | 操作条 |
63
+ | `renderStatusBadge` | 状态徽标(`ok`/`warn`/`danger`/`empty`) |
64
+ | `renderEmptyState` | 空态 |
65
+ | `renderErrorReceipt` | 失败回执 |
66
+ | `TOAST_ICON_GLYPHS` | 提示图标表 |
67
+
68
+ 示例:`test/controls.test.mjs`、`test/copy-*.test.mjs`;源:`src/controls.ts`。
69
+
70
+ ### 图表(根)——8 种纯字符串产出
71
+
72
+ - `charts`:统一入口,`bar`/`line`/`donut`/`progress`/`combo`/`sparkline`/`gauge`/`scatter`(CSS+SVG 字符串,无 canvas)。
73
+ - `buildChartsHelpersJs`:图表脚本唯一产出者;`chartsCss`:图表样式。
74
+ - 示例:`test/charts.test.mjs`;源:`src/charts.ts`;种定义:`src/spec/charts.ts`。
75
+
76
+ ### 页面级(根)——整页怎么摆,不参与区块组合
77
+
78
+ - 形状件(`src/pageShapes.ts`):`renderFactStrip` 事实条;`renderMediaFigure`/`renderMediaPlaceholder` 图片与媒体占位;`renderTimelineRows` 时间轴行;`pageShapeCss` 形状样式;`MEDIA_RATIOS` 比例表。
79
+ - 移动端配方(`src/pageUi.ts`):`pageUiCss` 断点/触摸区/安全区样式;`PAGE_UI_CLASS`/`PAGE_UI_VIEWPORT` 挂载常量。是否启用由整页装配决定,不启用则产出逐字节不变。
80
+
81
+ ### 管线与契约(根)
82
+
83
+ | 函数 | 一句话 |
84
+ |---|---|
85
+ | `fillTemplate` | 占位符填充器(模板+数据组装,失败抛错不返空页) |
86
+ | `buildStyleSheet`/`cx`/`token` | 样式表唯一产出者与类名工具(`STYLE_TOKENS` 11 个 token 唯一真相源) |
87
+ | `buildDataText`/`buildLogText` | 复制文本序列化(`text`/`json`/`csv` 三格式) |
88
+ | `renderPage`/`renderReco` | 页面与推荐渲染;`escapeHtml` 转义;`RenderError` |
89
+ | `mountInjector`/`openPage` | 多页挂载与开页 |
90
+ | `createPageRegistry`/`pageOrReco`/`recoDescriptor` | 页面注册与推荐描述 |
91
+ | `BODY_FONT_STACK` | 正文字体栈 |
92
+ | `renderHelpShell` | 数据页分型 help 模板渲染 |
93
+
94
+ ### 错误类口径
95
+
96
+ `RenderError` 根有导出;其余 `*Error`(`TemplateError`/`ControlsError`/`TextError`/`ChartError`/`BlocksError`/`HelpSchemaError`)不在根导出——冻结面无条目,调用方按 `name`/`code` 判定。
97
+
98
+ ### 正身与测试索引
99
+
100
+ - 冻结签名正身:`src/spec/`(7 件)↔ `../../docs/base-paint-contract.md`,由 `test/contract-signatures.test.mjs` 逐字锁死。
101
+ - 分组示例:`test/render.test.mjs`、`test/template.test.mjs`、`test/style.test.mjs`、`test/text.test.mjs`、`test/help.test.mjs`、`test/help-shell-136.test.mjs`(字节锁)、`test/ui-fix-154.test.mjs`。
package/dist/blocks.d.ts CHANGED
@@ -60,7 +60,8 @@ export interface TocBlockInput {
60
60
  readonly items: readonly TocItem[];
61
61
  }
62
62
  /** #420-1 页内导航区块(`<nav aria-label="页内导航">` + 逐项 `<a href="#id">`)。
63
- * 空列表=不出这一块(与「没内容不留空块」同口径,返回空串);非数组/项缺 `id`/`text` → `bad-input`。 */
63
+ * 空列表=不出这一块(与「没内容不留空块」同口径,返回空串);缺失(`undefined`)→ `bad-input`
64
+ * (非数组即拒);项缺 `id`/`text` → `bad-input`。 */
64
65
  export declare function renderTocBlock(input: TocBlockInput): string;
65
66
  /** #420-2 口径说明行(纯文本单参;五字符转义表与区块层其余函数同源 `esc`)。
66
67
  * 聚合数字旁那句灰色小字(例如「周目标口径=每日目标 × 7」)的唯一落点。
@@ -111,7 +112,8 @@ export interface DistributionRowsInput {
111
112
  readonly rows: readonly DistributionRowInput[];
112
113
  }
113
114
  /** #421-2 分布条行:`名称 | 条 | 数值` 一格三栏,逐行拼出(行即件,不另加容器类)。
114
- * `rows: []` = 空串(与「没内容不留空块」同口径);行内校验逐条 fail-fast。 */
115
+ * `rows: []` = 空串(与「没内容不留空块」同口径);缺失(`undefined`)→ `bad-input`(非数组即拒);
116
+ * 行内校验逐条 fail-fast。 */
115
117
  export declare function renderDistributionRows(input: DistributionRowsInput): string;
116
118
  export interface ChipItemInput {
117
119
  readonly text: string;
@@ -120,7 +122,7 @@ export interface ChipsInput {
120
122
  readonly items: readonly ChipItemInput[];
121
123
  }
122
124
  /** #421-3 徽章(并列小标签,如分类/标签这类短词并排):逐项 `<span class="ilife-block-chip">`。
123
- * 项即件(不另加容器类);`items: []` = 空串。 */
125
+ * 项即件(不另加容器类);`items: []` = 空串;缺失(`undefined`)→ `bad-input`(非数组即拒)。 */
124
126
  export declare function renderChips(input: ChipsInput): string;
125
127
  export interface ChangeRowInput {
126
128
  readonly label: string;
@@ -136,7 +138,7 @@ export interface ChangeRowsInput {
136
138
  }
137
139
  /** #421-4 字段变更行(回执页「改前 → 改后」对照):`字段名 | 改前 | 箭头 | 改后`。
138
140
  * `arrow: false` 只把字形藏起来、不删栏位(与老技能同一手法:左右栏靠箭位对齐);
139
- * `rows: []` = 空串。 */
141
+ * `rows: []` = 空串;缺失(`undefined`)→ `bad-input`(非数组即拒)。 */
140
142
  export declare function renderChangeRows(input: ChangeRowsInput): string;
141
143
  export interface KpiCardInput {
142
144
  readonly label: string;
@@ -145,20 +147,35 @@ export interface KpiCardInput {
145
147
  readonly detail?: string;
146
148
  readonly status?: StatusKind;
147
149
  readonly statusText?: string;
150
+ /** 可选进度条(#418):百分比 0–100;不给=不产条(零变)。 */
151
+ readonly bar?: {
152
+ readonly pct: number;
153
+ };
148
154
  }
149
155
  /** B-02:单张 KPI 卡(value 带 `tnum`;非法 status 由冻结语义降级 `empty`)。 */
150
156
  export declare function renderKpiCard(input: KpiCardInput): string;
157
+ /** B-02 伴生布局的标题选项(#513 段标题槽):只 `title` 一位,与 `renderChartBlock`/`copyArea`
158
+ * 的 `title` 位同形(非空字符串 ⇒ 段标题 h2;缺省/空串 ⇒ 零渲染)。 */
159
+ export interface KpiGridOptions {
160
+ readonly title?: string;
161
+ }
151
162
  /** B-02 伴生布局:KPI 卡网格(不是第 13 个区块,无独立样式区,用 `kpiCard` 区)。 */
152
- export declare function renderKpiGrid(cards: readonly KpiCardInput[]): string;
163
+ export declare function renderKpiGrid(cards: readonly KpiCardInput[], opts?: KpiGridOptions): string;
153
164
  export type DataTableAlign = 'left' | 'center' | 'right';
154
165
  export interface DataTableColumn {
155
166
  readonly key: string;
156
167
  readonly label: string;
157
168
  readonly align?: DataTableAlign;
158
169
  }
170
+ /** 表格行(#513 行标记槽):单元格映射+可选 `marker`(非空字符串 ⇒ 首格前插行徽标;
171
+ * 缺省/空串 ⇒ 不产出。非字符串非 undefined 即 `bad-input`)。列 key 叫 `marker` 的表不受影响——
172
+ * 全仓既有调用点无此列键(#513 实施时 grep 实测),见证据件。 */
173
+ export type DataTableRow = Readonly<Record<string, unknown> & {
174
+ marker?: unknown;
175
+ }>;
159
176
  export interface DataTableInput {
160
177
  readonly columns: readonly DataTableColumn[];
161
- readonly rows: readonly Readonly<Record<string, unknown>>[];
178
+ readonly rows: readonly DataTableRow[];
162
179
  readonly caption?: string;
163
180
  readonly emptyText?: string;
164
181
  /** 单元格 HTML(#567 状态列):`(列 key, 单元格原值) => 受信 HTML/undefined`。
@@ -1 +1 @@
1
- {"version":3,"file":"blocks.d.ts","sourceRoot":"","sources":["../src/blocks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"blocks.d.ts","sourceRoot":"","sources":["../src/blocks.ts"],"names":[],"mappings":"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"}
package/dist/blocks.js CHANGED
@@ -172,7 +172,8 @@ export function renderPageShell(input) {
172
172
  return parts.join('');
173
173
  }
174
174
  /** #420-1 页内导航区块(`<nav aria-label="页内导航">` + 逐项 `<a href="#id">`)。
175
- * 空列表=不出这一块(与「没内容不留空块」同口径,返回空串);非数组/项缺 `id`/`text` → `bad-input`。 */
175
+ * 空列表=不出这一块(与「没内容不留空块」同口径,返回空串);缺失(`undefined`)→ `bad-input`
176
+ * (非数组即拒);项缺 `id`/`text` → `bad-input`。 */
176
177
  export function renderTocBlock(input) {
177
178
  assertPlainObject(input, 'renderTocBlock: input');
178
179
  assertNoInlineHandler(input, 'renderTocBlock: input');
@@ -290,7 +291,10 @@ function isRgbFunction(raw) {
290
291
  /** 色值入参(#421/#431):`undefined` 透传(缺省色走样式段的冻结 token);清单内的写法**逐字透传**
291
292
  * (裸 token 名 `--x` 包成 `var(--x)`)。允许清单=`#rgb`/`#rrggbb`/`rgb()`/`rgba()`/
292
293
  * `var(--<冻结 token 名>)`/CSS 具名色;**清单外一律 `bad-input`**——`;`/`expression(`/`url(` 这类
293
- * 注入形态在这一步挡住,不让 `;` 穿进内联声明列表(审查 S3-6)。 */
294
+ * 注入形态在这一步挡住,不让 `;` 穿进内联声明列表(审查 S3-6)。
295
+ * 迁移提示(#441 实测,复核 D1 补第 4 处):生产侧显式传色 4 处(`diet/nutritionPortDocs.ts:339` 一处带 3 个 `#rrggbb` 值、
296
+ * `render/sportPortDocs.ts:609/775` 两处经 `categoryColor()` 取 4 个 `#rrggbb` 值,`diet/reviewDocs.ts:339-341` 一处经 `MEAL_COLORS` 由 `diet/todayDocs.ts:242` 进入生产),均属允许形态,
297
+ * 无须改动;其余生产调用不传色,走缺省冻结 token;新增写法先对清单,清单外改走冻结 token 或具名色。 */
294
298
  function optColor(value, field) {
295
299
  if (value === undefined)
296
300
  return undefined;
@@ -349,7 +353,8 @@ export function renderMiniBar(input) {
349
353
  + '</span>';
350
354
  }
351
355
  /** #421-2 分布条行:`名称 | 条 | 数值` 一格三栏,逐行拼出(行即件,不另加容器类)。
352
- * `rows: []` = 空串(与「没内容不留空块」同口径);行内校验逐条 fail-fast。 */
356
+ * `rows: []` = 空串(与「没内容不留空块」同口径);缺失(`undefined`)→ `bad-input`(非数组即拒);
357
+ * 行内校验逐条 fail-fast。 */
353
358
  export function renderDistributionRows(input) {
354
359
  assertPlainObject(input, 'renderDistributionRows: input');
355
360
  assertNoInlineHandler(input, 'renderDistributionRows: input');
@@ -379,7 +384,7 @@ export function renderDistributionRows(input) {
379
384
  }).join('');
380
385
  }
381
386
  /** #421-3 徽章(并列小标签,如分类/标签这类短词并排):逐项 `<span class="ilife-block-chip">`。
382
- * 项即件(不另加容器类);`items: []` = 空串。 */
387
+ * 项即件(不另加容器类);`items: []` = 空串;缺失(`undefined`)→ `bad-input`(非数组即拒)。 */
383
388
  export function renderChips(input) {
384
389
  assertPlainObject(input, 'renderChips: input');
385
390
  assertNoInlineHandler(input, 'renderChips: input');
@@ -398,7 +403,7 @@ export function renderChips(input) {
398
403
  }
399
404
  /** #421-4 字段变更行(回执页「改前 → 改后」对照):`字段名 | 改前 | 箭头 | 改后`。
400
405
  * `arrow: false` 只把字形藏起来、不删栏位(与老技能同一手法:左右栏靠箭位对齐);
401
- * `rows: []` = 空串。 */
406
+ * `rows: []` = 空串;缺失(`undefined`)→ `bad-input`(非数组即拒)。 */
402
407
  export function renderChangeRows(input) {
403
408
  assertPlainObject(input, 'renderChangeRows: input');
404
409
  assertNoInlineHandler(input, 'renderChangeRows: input');
@@ -424,6 +429,14 @@ export function renderChangeRows(input) {
424
429
  + '</div>';
425
430
  }).join('');
426
431
  }
432
+ /** #418 条位判档(只此一处):>=90 高档/>=60 中档/其余低档。 */
433
+ function kpiBarClass(pct) {
434
+ if (pct >= 90)
435
+ return 'bar-high';
436
+ if (pct >= 60)
437
+ return 'bar-mid';
438
+ return 'bar-low';
439
+ }
427
440
  /** B-02:单张 KPI 卡(value 带 `tnum`;非法 status 由冻结语义降级 `empty`)。 */
428
441
  export function renderKpiCard(input) {
429
442
  assertPlainObject(input, 'renderKpiCard: input');
@@ -442,6 +455,17 @@ export function renderKpiCard(input) {
442
455
  const detail = optText(card.detail);
443
456
  if (detail !== undefined)
444
457
  parts.push('<div class="' + blockPart('kpiCard', 'detail') + '">' + esc(detail) + '</div>');
458
+ const bar = card.bar;
459
+ if (bar !== undefined) {
460
+ assertPlainObject(bar, 'renderKpiCard: bar');
461
+ const pct = bar.pct;
462
+ if (typeof pct !== 'number' || !Number.isFinite(pct) || pct < 0 || pct > 100) {
463
+ badInput('renderKpiCard: bar.pct 必须在 0–100 之间');
464
+ }
465
+ parts.push('<div class="' + blockPart('kpiCard', 'bar') + '">'
466
+ + '<div class="' + blockPart('kpiCard', 'bar-fill') + ' ' + blockPart('kpiCard', kpiBarClass(pct)) + '" style="width:' + pct + '%"></div>'
467
+ + '</div>');
468
+ }
445
469
  if (card.status !== undefined) {
446
470
  const status = STATUS_KINDS.includes(card.status) ? card.status : 'empty';
447
471
  const badge = renderStatusBadge(card.statusText === undefined ? { status } : { status, text: card.statusText });
@@ -451,11 +475,22 @@ export function renderKpiCard(input) {
451
475
  return parts.join('');
452
476
  }
453
477
  /** B-02 伴生布局:KPI 卡网格(不是第 13 个区块,无独立样式区,用 `kpiCard` 区)。 */
454
- export function renderKpiGrid(cards) {
478
+ export function renderKpiGrid(cards, opts) {
455
479
  if (!Array.isArray(cards) || cards.length === 0)
456
480
  badInput('renderKpiGrid: cards 必须是非空数组');
457
- return '<div class="' + blockPart('kpiCard', 'grid') + '">'
481
+ if (opts !== undefined) {
482
+ assertPlainObject(opts, 'renderKpiGrid: opts');
483
+ assertNoInlineHandler(opts, 'renderKpiGrid: opts');
484
+ }
485
+ const grid = '<div class="' + blockPart('kpiCard', 'grid') + '">'
458
486
  + cards.map((card) => renderKpiCard(card)).join('') + '</div>';
487
+ // #513:不给 title 即返回原 grid 串(与改前逐字节同);给了即标题 h2 +原 grid
488
+ // (与页面当刻手写形一致,页面票后迁可逐字节对)。标题类复用 #507 已落盘的 `kpi-card-title`
489
+ //(15px/700),不新增类名、不新增样式区。
490
+ const title = opts === undefined ? undefined : optText(opts.title);
491
+ if (title === undefined)
492
+ return grid;
493
+ return '<h2 class="' + blockPart('kpiCard', 'title') + '">' + esc(title) + '</h2>' + grid;
459
494
  }
460
495
  const TABLE_ALIGNS = ['left', 'center', 'right'];
461
496
  function cellText(value, field) {
@@ -497,7 +532,14 @@ export function renderDataTable(input) {
497
532
  const head = '<thead><tr>' + columns.map((column) => '<th scope="col" class="' + blockPart('dataTable', 'cell-' + column.align) + '">' + esc(column.label) + '</th>').join('') + '</tr></thead>';
498
533
  const body = '<tbody>' + table.rows.map((row, ri) => {
499
534
  assertPlainObject(row, 'renderDataTable: input.rows[' + ri + ']');
500
- return '<tr>' + columns.map((column) => {
535
+ // #513 行标记槽:可选 `marker`(非空字符串 ⇒ 首格前插行徽标;缺省/空串 ⇒ 零渲染,
536
+ // 本行与改前逐字节同);非字符串非 undefined 即 `bad-input`(与 `cellText` 同严格)。
537
+ const rawMarker = row.marker;
538
+ if (rawMarker !== undefined && typeof rawMarker !== 'string') {
539
+ badInput('renderDataTable: input.rows[' + ri + '].marker 必须是非空字符串/undefined');
540
+ }
541
+ const marker = rawMarker === undefined ? undefined : optText(rawMarker);
542
+ return '<tr>' + columns.map((column, ci) => {
501
543
  const raw = row[column.key];
502
544
  // #567 `cellHtml`:给了且对本格返回字符串即受信透传(调用方已转义);
503
545
  // 返回 `undefined` 即走缺省转义文本。不给 `cellHtml` 时本行与改前逐字同。
@@ -518,8 +560,12 @@ export function renderDataTable(input) {
518
560
  const text = trusted === undefined
519
561
  ? cellText(raw, 'renderDataTable: input.rows[' + ri + '].' + column.key)
520
562
  : trusted;
521
- return '<td class="' + blockPart('dataTable', 'cell-' + column.align) + '" data-label="' + esc(column.label) + '">'
522
- + text + '</td>';
563
+ const open = '<td class="' + blockPart('dataTable', 'cell-' + column.align) + '" data-label="' + esc(column.label) + '">';
564
+ // #513:行标记只进首格(转义后前插;`cellHtml` 受信透传不受影响)。
565
+ const head = ci === 0 && marker !== undefined
566
+ ? '<span class="' + blockPart('dataTable', 'row-marker') + '">' + esc(marker) + '</span>'
567
+ : '';
568
+ return open + head + text + '</td>';
523
569
  }).join('') + '</tr>';
524
570
  }).join('') + '</tbody>';
525
571
  const caption = optText(table.caption);
@@ -1053,6 +1099,87 @@ const BLOCK_SECTION_BUILDERS = {
1053
1099
  ' font-size: 15px;',
1054
1100
  ' font-weight: 600;',
1055
1101
  '}',
1102
+ // #434 操作卡头部(#422 共用件 `operationHead()` 的根类+四色档+四子件;样式落本区,不新增区)。
1103
+ // 形态对齐老实物 `crud_receipt` 的 `id-card` 左色条(样张 `t156-样张-写后回执.html:153-160`:
1104
+ // `border-left:4px solid` 随 op 切):基规则出卡片+ 4px 左条(缺省中性 `var(--line)`),
1105
+ // 四色档只改 `border-left-color`。版式把页级四条覆盖收编(`sportUi.ts` 的 `.ilife-page …`
1106
+ // 四条本票删除后落点):图标+徽章+标题同排,记录号/时刻行各占整行(`flex:1 0 100%`)。
1107
+ // 内距取同族卡片档 14px(`kpiCard`/`chartBlock`/`detailSection` 同值),样张的 18px 20px
1108
+ // 是 throwaway 密度不照搬;块级 `margin:16px 0` 取 #154 同族值(与 #457 相邻兄弟规则折叠恒 16)。
1109
+ '.' + p + 'block-op-head {',
1110
+ ' display: flex;',
1111
+ ' flex-wrap: wrap;',
1112
+ ' align-items: center;',
1113
+ ' gap: 8px 12px;',
1114
+ ' margin: 16px 0;',
1115
+ ' padding: 14px;',
1116
+ ' border: 1px solid var(--line);',
1117
+ ' border-left: 4px solid var(--line);',
1118
+ ' border-radius: ' + RADIUS_MD + 'px;',
1119
+ ' background: var(--card);',
1120
+ '}',
1121
+ // 四色档(`OPERATION_TONES` ok/warn/danger/empty 的样式落点;只改左条色)。
1122
+ // 色值口径:ok 取冻结 token `var(--ok)`(值 `#34c759`,与样张 `opColors` 同值);
1123
+ // 冻结表无 warn/danger 灯位,故 warn/danger 取同仓状态徽章同源 D-5 常量
1124
+ // (`src/style.ts` statusBadge 区 warn `#a25b00`/danger `#a83228`,不新增 token 名);
1125
+ // empty 取冻结 `var(--fg2)`(与 empty 徽章字色同值,中性)。
1126
+ // 样张的 `#0071e3` 在 H-01 禁色表内(`test/style.test.mjs:241`),一律不用;
1127
+ // 色条是非文本,不套 #179 的文本对比度档。
1128
+ '.' + p + 'block-op-head-ok {',
1129
+ ' border-left-color: var(--ok);',
1130
+ '}',
1131
+ '.' + p + 'block-op-head-warn {',
1132
+ ' border-left-color: #a25b00;',
1133
+ '}',
1134
+ '.' + p + 'block-op-head-danger {',
1135
+ ' border-left-color: #a83228;',
1136
+ '}',
1137
+ '.' + p + 'block-op-head-empty {',
1138
+ ' border-left-color: var(--fg2);',
1139
+ '}',
1140
+ // 子件四条(`operationHead()` 的 `-icon`/`-title`/`-id`/`-time`)。
1141
+ // 图标 40px 中性盒(样张 12px 圆角按 D-5 收进闭集取 14;底色取中性 `var(--soft)`,
1142
+ // 色档由左条+徽章承担,图标不跟色);标题 18px/700 取 `detail-section-title` 档
1143
+ // (#567 J4 标题 18 吸收 17/18/20/22);记录号 13px 取 `--fg2`;时刻行 12px 取
1144
+ // `--fg2`(#179:12px 小字须 4.5:1,`--fg3` 3.62:1 不用)。
1145
+ // 时刻行首的「写入时间 」键(`sportUi.ts` 迁回):`actionAt` 即写入时间
1146
+ // (`body/receipt.ts:162` 同值同词 `{ k: '写入时间', v: actionAt }`),CSS 内容只进
1147
+ // 渲染层;第二消费族出现时提到调用方文案面并删此条(过渡债务,本票如实记)。
1148
+ '.' + p + 'block-op-head-icon {',
1149
+ ' display: inline-flex;',
1150
+ ' align-items: center;',
1151
+ ' justify-content: center;',
1152
+ ' width: 40px;',
1153
+ ' height: 40px;',
1154
+ ' border-radius: ' + RADIUS_MD + 'px;',
1155
+ ' background: var(--soft);',
1156
+ ' color: var(--fg);',
1157
+ ' font-size: 20px;',
1158
+ ' line-height: 1;',
1159
+ '}',
1160
+ '.' + p + 'block-op-head-title {',
1161
+ ' display: inline-flex;',
1162
+ ' align-items: center;',
1163
+ ' margin: 0;',
1164
+ ' color: var(--fg);',
1165
+ ' font-size: 18px;',
1166
+ ' font-weight: 700;',
1167
+ '}',
1168
+ '.' + p + 'block-op-head-id {',
1169
+ ' flex: 1 0 100%;',
1170
+ ' margin: 0;',
1171
+ ' color: var(--fg2);',
1172
+ ' font-size: 13px;',
1173
+ '}',
1174
+ '.' + p + 'block-op-head-time {',
1175
+ ' flex: 1 0 100%;',
1176
+ ' margin: 0;',
1177
+ ' color: var(--fg2);',
1178
+ ' font-size: 12px;',
1179
+ '}',
1180
+ '.' + p + 'block-op-head-time::before {',
1181
+ ' content: "写入时间 ";',
1182
+ '}',
1056
1183
  // #421 页面融合四件的样式随本区落盘(同 #420 处置:四件都是页面级、不属 12 区块,
1057
1184
  // `BLOCK_STYLE_SECTIONS` 由 `test/blocks.test.mjs` 钉死 12 项,故不新增样式区、不新增 token)。
1058
1185
  // **色值口径(#431 定稿)**:区块自身不写死任何色值字面量——样式里只出现冻结 token。不给 `color`
@@ -1204,7 +1331,20 @@ const BLOCK_SECTION_BUILDERS = {
1204
1331
  ' gap: 12px;',
1205
1332
  ' margin: 16px 0;',
1206
1333
  '}',
1334
+ // #507 桌面列数上限(用户点名:6 张 KPI 在宽屏挤成一行):基座 `auto-fit minmax(150px,1fr)`
1335
+ // 无上限,越宽列越多。只加 ≥1024 一档 `repeat(3,…)`,基座一行不动;窄屏 2×2(#507 窄屏档)
1336
+ // 与 400 单列(`pageUi` ⑦)各管各档。断点取票面值 1024;选择器挂祖先类(与窄屏档同法),
1337
+ // 同名基座仍恰 1 条(`declsOf` 口径),不新类名、不新样式区。
1338
+ '@media (min-width: 1024px) {',
1339
+ ' .' + p + 'block-page-shell .' + p + 'block-kpi-card-grid {',
1340
+ ' grid-template-columns: repeat(3, minmax(0, 1fr));',
1341
+ ' }',
1342
+ '}',
1343
+ // #513 徽章贴底:卡片改纵向 flex 列(子元素仍纵向满宽,`align-items` 缺省 `stretch`、
1344
+ // 无子元素设交叉轴尺寸 ⇒ 视觉同块流),余量由徽章的 `margin-top: auto` 吃掉(见下)。
1207
1345
  '.' + p + 'block-kpi-card {',
1346
+ ' display: flex;',
1347
+ ' flex-direction: column;',
1208
1348
  ' padding: 14px;',
1209
1349
  ' border: 1px solid var(--line);',
1210
1350
  ' border-radius: ' + RADIUS_MD + 'px;',
@@ -1249,8 +1389,33 @@ const BLOCK_SECTION_BUILDERS = {
1249
1389
  ' font-size: 12px;',
1250
1390
  ' overflow-wrap: anywhere;',
1251
1391
  '}',
1392
+ // #513(续):`margin-top: auto` 把徽章压到底;`padding-top: 8px` 保住改前 8px 最小间距
1393
+ // (最高卡无余量时徽章位置与改前一致,只动有余量的短卡——正是要修的那几张)。
1252
1394
  '.' + p + 'block-kpi-card-badge {',
1395
+ ' margin-top: auto;',
1396
+ ' padding-top: 8px;',
1397
+ '}',
1398
+ // #418 条位:detail 之后 badge 之前产条(见 renderKpiCard)。色值单源(甲路):
1399
+ // 三档各一处字面量,源 spec/charts.ts CHART_PALETTE[1..3],与状态徽章底色同值。
1400
+ '.' + p + 'block-kpi-card-bar {',
1401
+ ' height: 6px;',
1402
+ ' border-radius: ' + RADIUS_PILL + 'px;',
1403
+ ' background: var(--line);',
1253
1404
  ' margin-top: 8px;',
1405
+ ' overflow: hidden;',
1406
+ '}',
1407
+ '.' + p + 'block-kpi-card-bar-fill {',
1408
+ ' height: 100%;',
1409
+ ' border-radius: ' + RADIUS_PILL + 'px;',
1410
+ '}',
1411
+ '.' + p + 'block-kpi-card-bar-high {',
1412
+ ' background: #34c759;',
1413
+ '}',
1414
+ '.' + p + 'block-kpi-card-bar-mid {',
1415
+ ' background: #ff9500;',
1416
+ '}',
1417
+ '.' + p + 'block-kpi-card-bar-low {',
1418
+ ' background: #ff3b30;',
1254
1419
  '}',
1255
1420
  // #507 段标题统一(审查必改 #5):`blocks.ts` 从 #401 起就给过这条类名产出器的位置
1256
1421
  // (`homeDocs.ts:247` 用 `<h2 class="ilife-block-kpi-card-title">` 出「今日速览」段标题),
@@ -1264,13 +1429,13 @@ const BLOCK_SECTION_BUILDERS = {
1264
1429
  ' font-size: 15px;',
1265
1430
  ' font-weight: 700;',
1266
1431
  '}',
1267
- // #507 窄屏档(审查必改 #4):`auto-fit minmax(150px,1fr)` 只在容器有效宽 ≥474px 时排 3 列
1432
+ // #507 窄屏档(审查必改 #4)+ #427 收窄为单列:`auto-fit minmax(150px,1fr)` 只在容器有效宽 ≥474px 时排 3 列
1268
1433
  // (3×150 + 2×12 间隙),而手机端页面模板 `padding:20px 16px`(见本区 ≤640px 段)——
1269
1434
  // 512 视口下栅格有效宽仅 480px ⇒ 正好卡在 3 列下沿,第 4 张卡单独占一行、宽度只有前三张的
1270
1435
  // 1/3(`grid-auto-rows:1fr` 又让它与前三张**等高**),看着像漏了一张。
1271
- // 本条只加**窄屏一档**:≤640px 显式 2 列 ⇒ 4 张卡排成整齐 2×2;`minmax(0,1fr)` 里的 0
1272
- // 是下限(不是 `auto` 那种取内容最小宽),长值卡不会被撑破。桌面档一行不动
1273
- // (桌面列数上限是另一票的事,本票不碰)。断点取本文件既有先例:`dataTable` 与 `pageShell`
1436
+ // #427(#507§8 三条窄屏归 #427,同一段代码):≤640 显式单列 ⇒ 390 每张占整行上下排列;
1437
+ // `minmax(0,1fr)` 的 0 是下限(不是 `auto` 那种取内容最小宽),长值卡不会被撑破。
1438
+ // 桌面档一行不动(桌面列数上限 #507 的 1024 三列帽另管)。断点取本文件既有先例:`dataTable` 与 `pageShell`
1274
1439
  // 两处都是 `@media (max-width: 640px)`。
1275
1440
  // 选择器是 `.ilife-block-page-shell .ilife-block-kpi-card-grid`(基础类名前挂一个祖先类),
1276
1441
  // **不是**同名再写一条:① 网格落在页面模板正文里(`renderKpiGrid` 的唯一用法),该祖先恒成立;
@@ -1278,7 +1443,7 @@ const BLOCK_SECTION_BUILDERS = {
1278
1443
  // 判账,同名再起一条会被数成 2 条而红;`dataTable` 区那条同名 640px 规则是历史写法,本票不动它。
1279
1444
  '@media (max-width: 640px) {',
1280
1445
  ' .' + p + 'block-page-shell .' + p + 'block-kpi-card-grid {',
1281
- ' grid-template-columns: repeat(2, minmax(0, 1fr));',
1446
+ ' grid-template-columns: minmax(0, 1fr);',
1282
1447
  ' }',
1283
1448
  '}',
1284
1449
  ].join(LF),
@@ -1312,6 +1477,22 @@ const BLOCK_SECTION_BUILDERS = {
1312
1477
  ' font-weight: 600;',
1313
1478
  ' text-align: left;',
1314
1479
  '}',
1480
+ // #513 行标记槽:首格前插的行徽标(`renderDataTable` 的 `rows[i].marker`)。行内小徽标:
1481
+ // 色走冻结 token(底 `--soft`+字 `--blue2`,与 `block-chip` 同口径,不新增 token;
1482
+ // 12px 小字对比度约 5.4:1,#179 口径达 AA);`white-space: nowrap` 保徽标不断行;
1483
+ // 只吃内容宽,不改窄屏档位(横溢口径见证据件)。
1484
+ '.' + p + 'block-data-table-row-marker {',
1485
+ ' display: inline-block;',
1486
+ ' margin-right: 6px;',
1487
+ ' padding: 1px 7px;',
1488
+ ' border-radius: ' + RADIUS_PILL + 'px;',
1489
+ ' background: var(--soft);',
1490
+ ' color: var(--blue2);',
1491
+ ' font-size: 12px;',
1492
+ ' font-weight: 600;',
1493
+ ' white-space: nowrap;',
1494
+ ' vertical-align: baseline;',
1495
+ '}',
1315
1496
  '.' + p + 'block-data-table th {',
1316
1497
  ' padding: 10px 14px;',
1317
1498
  ' border-bottom: 1px solid var(--line);',
@@ -1340,6 +1521,13 @@ const BLOCK_SECTION_BUILDERS = {
1340
1521
  '.' + p + 'block-data-table tr:last-child td {',
1341
1522
  ' border-bottom: none;',
1342
1523
  '}',
1524
+ // #507 表格斑马纹(用户点名的两条之一;另一条数值列等宽栈已由 #507 视觉底座落地,本票不重做):
1525
+ // 偶数数据行取 `var(--bg)`(既有冻结 token,不新增语义 token)。只染 `tbody` 行,列头不动;
1526
+ // 背景落 `td`(本表 `border-collapse: collapse`,行背景不可靠)。伪类挂既有类上,不新类名、
1527
+ // 不新样式区;窄屏行卡化(#457)下偶数卡整格同底,仍可读。
1528
+ '.' + p + 'block-data-table tbody tr:nth-child(even) td {',
1529
+ ' background-color: var(--bg);',
1530
+ '}',
1343
1531
  '.' + p + 'block-data-table-cell-left {',
1344
1532
  ' text-align: left;',
1345
1533
  '}',
@@ -1686,6 +1874,13 @@ const BLOCK_SECTION_BUILDERS = {
1686
1874
  '.' + p + 'block-disclosure[open] > .' + p + 'block-disclosure-summary::before {',
1687
1875
  ' transform: rotate(90deg);',
1688
1876
  '}',
1877
+ // #507 减动效归零档(照老壳 `style.ts` 归零档补:本区唯一的 `transition` 在此归零;
1878
+ // 只停过渡,`rotate(90deg)` 开合终态照走)。
1879
+ '@media (prefers-reduced-motion: reduce) {',
1880
+ ' .' + p + 'block-disclosure-summary::before {',
1881
+ ' transition: none;',
1882
+ ' }',
1883
+ '}',
1689
1884
  '.' + p + 'block-disclosure-body {',
1690
1885
  ' padding: 0 14px 14px;',
1691
1886
  '}',