base-paint 0.3.2 → 0.3.4
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 +94 -1
- package/dist/blocks.d.ts +31 -6
- package/dist/blocks.d.ts.map +1 -1
- package/dist/blocks.js +307 -22
- package/dist/blocks.js.map +1 -1
- package/dist/charts.d.ts.map +1 -1
- package/dist/charts.js +48 -3
- package/dist/charts.js.map +1 -1
- package/dist/controls.d.ts +4 -4
- package/dist/controls.d.ts.map +1 -1
- package/dist/controls.js +11 -15
- package/dist/controls.js.map +1 -1
- package/dist/docShell.d.ts +34 -0
- package/dist/docShell.d.ts.map +1 -0
- package/dist/docShell.js +66 -0
- package/dist/docShell.js.map +1 -0
- package/dist/help.d.ts.map +1 -1
- package/dist/help.js +20 -3
- package/dist/help.js.map +1 -1
- package/dist/helpShell.d.ts.map +1 -1
- package/dist/helpShell.js +2 -2
- package/dist/helpShell.js.map +1 -1
- package/dist/spec/charts.d.ts +4 -0
- package/dist/spec/charts.d.ts.map +1 -1
- package/dist/spec/charts.js.map +1 -1
- package/dist/spec/controls.d.ts.map +1 -1
- package/dist/spec/controls.js +5 -3
- package/dist/spec/controls.js.map +1 -1
- package/dist/spec/help.d.ts +30 -2
- package/dist/spec/help.d.ts.map +1 -1
- package/dist/spec/help.js +19 -2
- package/dist/spec/help.js.map +1 -1
- package/dist/style.d.ts.map +1 -1
- package/dist/style.js +22 -8
- package/dist/style.js.map +1 -1
- package/dist/text.d.ts.map +1 -1
- package/dist/text.js +7 -2
- package/dist/text.js.map +1 -1
- package/package.json +2 -1
package/dist/blocks.js
CHANGED
|
@@ -149,6 +149,37 @@ const PRINTABLE_PAGE_NAME = 'printable';
|
|
|
149
149
|
function pageLevelBlock(name) {
|
|
150
150
|
return STYLE_PREFIX + 'block-' + name;
|
|
151
151
|
}
|
|
152
|
+
/* ══════════════════════════════════════════════════════════════
|
|
153
|
+
* B-01 共享页面模板/标题区
|
|
154
|
+
* ══════════════════════════════════════════════════════════════ */
|
|
155
|
+
/** 页面级「并列分隔符」(U+FF5C 全角竖线):**公共层唯一**被当作「并列」的输入分隔符。
|
|
156
|
+
*
|
|
157
|
+
* 语义:调用方写一句「甲 | 乙 | 丙」,公共层把它拆成逐段 `<span>`,段间那条细线由 CSS 的
|
|
158
|
+
* `border-left` 出——**字符不进产物**,分隔只活在版式里(#514 立规、t154-r3 在口径行落地,
|
|
159
|
+
* t728 把同一条机制推广到页头眉标:一条口径只许一处实现)。
|
|
160
|
+
*
|
|
161
|
+
* 为什么输入仍要写它:调用方只需要说「这几段是并列的」,怎么说由本件定;把「怎么分」留给
|
|
162
|
+
* 调用方(各写各的 `·`/`/`/`、`)就是同一件事在 40 处定义。 */
|
|
163
|
+
const PARALLEL_SEP = '|';
|
|
164
|
+
/** 眉标里那几段的类名:第一段是**品牌位**,其余是**域位**(`pageLevelPart` 同族命名,不进 12 区闭集)。 */
|
|
165
|
+
function eyebrowSegmentClass(index) {
|
|
166
|
+
return blockPart('pageShell', index === 0 ? 'eyebrow-app' : 'eyebrow-scope');
|
|
167
|
+
}
|
|
168
|
+
/** 把一句「甲 | 乙」按并列分隔符拆段:两头剪白、空段丢弃。不带分隔符 ⇒ 原样一段。 */
|
|
169
|
+
function splitSegments(text) {
|
|
170
|
+
if (!text.includes(PARALLEL_SEP))
|
|
171
|
+
return [text];
|
|
172
|
+
return text.split(PARALLEL_SEP).map((seg) => seg.trim()).filter((seg) => seg !== '');
|
|
173
|
+
}
|
|
174
|
+
/** 眉标的 HTML:带并列分隔符(且拆得出 ≥2 段)⇒ 逐段一枚 `<span>`,段间那条细竖线由 CSS 出,
|
|
175
|
+
* **字符不进产物文本**;不带 ⇒ 逐字节同旧版(一个纯文本节点的 `<p>`)。
|
|
176
|
+
* 拆不出两段(如只有一条竖线收尾)⇒ 不拆,照原样文本落盘(不静默吞字符,与口径行同一条口径)。 */
|
|
177
|
+
function eyebrowHtml(eyebrow) {
|
|
178
|
+
const segs = splitSegments(eyebrow);
|
|
179
|
+
if (segs.length < 2)
|
|
180
|
+
return esc(eyebrow);
|
|
181
|
+
return segs.map((seg, i) => '<span class="' + eyebrowSegmentClass(i) + '">' + esc(seg) + '</span>').join(' ');
|
|
182
|
+
}
|
|
152
183
|
/** B-01:单页容器+标题三件套(eyebrow/title/subtitle)+正文。 */
|
|
153
184
|
export function renderPageShell(input) {
|
|
154
185
|
assertPlainObject(input, 'renderPageShell: input');
|
|
@@ -162,7 +193,7 @@ export function renderPageShell(input) {
|
|
|
162
193
|
const parts = ['<section class="' + rootClass + '">'];
|
|
163
194
|
const eyebrow = optText(shell.eyebrow);
|
|
164
195
|
if (eyebrow !== undefined)
|
|
165
|
-
parts.push('<p class="' + blockPart('pageShell', 'eyebrow') + '">' +
|
|
196
|
+
parts.push('<p class="' + blockPart('pageShell', 'eyebrow') + '">' + eyebrowHtml(eyebrow) + '</p>');
|
|
166
197
|
parts.push('<h1 class="' + blockPart('pageShell', 'title') + '">' + esc(title) + '</h1>');
|
|
167
198
|
const subtitle = optText(shell.subtitle);
|
|
168
199
|
if (subtitle !== undefined)
|
|
@@ -172,7 +203,8 @@ export function renderPageShell(input) {
|
|
|
172
203
|
return parts.join('');
|
|
173
204
|
}
|
|
174
205
|
/** #420-1 页内导航区块(`<nav aria-label="页内导航">` + 逐项 `<a href="#id">`)。
|
|
175
|
-
*
|
|
206
|
+
* 空列表=不出这一块(与「没内容不留空块」同口径,返回空串);缺失(`undefined`)→ `bad-input`
|
|
207
|
+
* (非数组即拒);项缺 `id`/`text` → `bad-input`。 */
|
|
176
208
|
export function renderTocBlock(input) {
|
|
177
209
|
assertPlainObject(input, 'renderTocBlock: input');
|
|
178
210
|
assertNoInlineHandler(input, 'renderTocBlock: input');
|
|
@@ -190,10 +222,8 @@ export function renderTocBlock(input) {
|
|
|
190
222
|
}
|
|
191
223
|
return '<nav class="' + pageLevelBlock('toc') + '" aria-label="页内导航">' + links.join('') + '</nav>';
|
|
192
224
|
}
|
|
193
|
-
/**
|
|
194
|
-
|
|
195
|
-
* **公共层一次还掉**:该字符不再进产物文本,分隔改由版式承担(见 `renderCaliberLine` 与本区 CSS)。 */
|
|
196
|
-
const CALIBER_SEP = '|';
|
|
225
|
+
/** 口径行的并列分隔符=公共层那条**唯一**的并列分隔符(`PARALLEL_SEP`,定义见 B-01 区开头)。 */
|
|
226
|
+
const CALIBER_SEP = PARALLEL_SEP;
|
|
197
227
|
/** #420-2 口径说明行(纯文本单参;五字符转义表与区块层其余函数同源 `esc`)。
|
|
198
228
|
* 聚合数字旁那句灰色小字(例如「周目标口径=每日目标 × 7」)的唯一落点。
|
|
199
229
|
*
|
|
@@ -290,7 +320,10 @@ function isRgbFunction(raw) {
|
|
|
290
320
|
/** 色值入参(#421/#431):`undefined` 透传(缺省色走样式段的冻结 token);清单内的写法**逐字透传**
|
|
291
321
|
* (裸 token 名 `--x` 包成 `var(--x)`)。允许清单=`#rgb`/`#rrggbb`/`rgb()`/`rgba()`/
|
|
292
322
|
* `var(--<冻结 token 名>)`/CSS 具名色;**清单外一律 `bad-input`**——`;`/`expression(`/`url(` 这类
|
|
293
|
-
* 注入形态在这一步挡住,不让 `;` 穿进内联声明列表(审查 S3-6)。
|
|
323
|
+
* 注入形态在这一步挡住,不让 `;` 穿进内联声明列表(审查 S3-6)。
|
|
324
|
+
* 迁移提示(#441 实测,复核 D1 补第 4 处):生产侧显式传色 4 处(`diet/nutritionPortDocs.ts:339` 一处带 3 个 `#rrggbb` 值、
|
|
325
|
+
* `render/sportPortDocs.ts:609/775` 两处经 `categoryColor()` 取 4 个 `#rrggbb` 值,`diet/reviewDocs.ts:339-341` 一处经 `MEAL_COLORS` 由 `diet/todayDocs.ts:242` 进入生产),均属允许形态,
|
|
326
|
+
* 无须改动;其余生产调用不传色,走缺省冻结 token;新增写法先对清单,清单外改走冻结 token 或具名色。 */
|
|
294
327
|
function optColor(value, field) {
|
|
295
328
|
if (value === undefined)
|
|
296
329
|
return undefined;
|
|
@@ -349,7 +382,8 @@ export function renderMiniBar(input) {
|
|
|
349
382
|
+ '</span>';
|
|
350
383
|
}
|
|
351
384
|
/** #421-2 分布条行:`名称 | 条 | 数值` 一格三栏,逐行拼出(行即件,不另加容器类)。
|
|
352
|
-
* `rows: []` =
|
|
385
|
+
* `rows: []` = 空串(与「没内容不留空块」同口径);缺失(`undefined`)→ `bad-input`(非数组即拒);
|
|
386
|
+
* 行内校验逐条 fail-fast。 */
|
|
353
387
|
export function renderDistributionRows(input) {
|
|
354
388
|
assertPlainObject(input, 'renderDistributionRows: input');
|
|
355
389
|
assertNoInlineHandler(input, 'renderDistributionRows: input');
|
|
@@ -379,7 +413,7 @@ export function renderDistributionRows(input) {
|
|
|
379
413
|
}).join('');
|
|
380
414
|
}
|
|
381
415
|
/** #421-3 徽章(并列小标签,如分类/标签这类短词并排):逐项 `<span class="ilife-block-chip">`。
|
|
382
|
-
* 项即件(不另加容器类);`items: []` =
|
|
416
|
+
* 项即件(不另加容器类);`items: []` = 空串;缺失(`undefined`)→ `bad-input`(非数组即拒)。 */
|
|
383
417
|
export function renderChips(input) {
|
|
384
418
|
assertPlainObject(input, 'renderChips: input');
|
|
385
419
|
assertNoInlineHandler(input, 'renderChips: input');
|
|
@@ -396,9 +430,20 @@ export function renderChips(input) {
|
|
|
396
430
|
+ esc(reqText(entry.text, field + '.text')) + '</span>';
|
|
397
431
|
}).join('');
|
|
398
432
|
}
|
|
433
|
+
/** #728 徽章行(**并列标签要对齐成一行**时用这一件):把 `renderChips` 那一串裸 `<span>` 收进一个
|
|
434
|
+
* 容器 `<div>`,行距/换行/对齐交 CSS,调用方仍然只给标签文本。
|
|
435
|
+
*
|
|
436
|
+
* 为什么需要它(不是「再包一层」的洁癖):`pageUi`(#525 页面级移动端配方)在 ≥1001px 把
|
|
437
|
+
* `.ilife-block-page-shell-body` 变成栅格,`> *` 一律落到中间那一列 —— **裸 `<span>` 也是栅格项**,
|
|
438
|
+
* 于是「一行徽章」会被摊成「一行一枚」。有了本件,徽章行是一个块级子件,栅格里占一格。
|
|
439
|
+
* `items: []` = 空串(与 `renderChips` 同口径:没内容不留空块);缺失/非数组 → `bad-input`。 */
|
|
440
|
+
export function renderChipRow(input) {
|
|
441
|
+
const inner = renderChips(input);
|
|
442
|
+
return inner === '' ? '' : '<div class="' + pageLevelBlock('chip-row') + '">' + inner + '</div>';
|
|
443
|
+
}
|
|
399
444
|
/** #421-4 字段变更行(回执页「改前 → 改后」对照):`字段名 | 改前 | 箭头 | 改后`。
|
|
400
445
|
* `arrow: false` 只把字形藏起来、不删栏位(与老技能同一手法:左右栏靠箭位对齐);
|
|
401
|
-
* `rows: []` =
|
|
446
|
+
* `rows: []` = 空串;缺失(`undefined`)→ `bad-input`(非数组即拒)。 */
|
|
402
447
|
export function renderChangeRows(input) {
|
|
403
448
|
assertPlainObject(input, 'renderChangeRows: input');
|
|
404
449
|
assertNoInlineHandler(input, 'renderChangeRows: input');
|
|
@@ -424,6 +469,14 @@ export function renderChangeRows(input) {
|
|
|
424
469
|
+ '</div>';
|
|
425
470
|
}).join('');
|
|
426
471
|
}
|
|
472
|
+
/** #418 条位判档(只此一处):>=90 高档/>=60 中档/其余低档。 */
|
|
473
|
+
function kpiBarClass(pct) {
|
|
474
|
+
if (pct >= 90)
|
|
475
|
+
return 'bar-high';
|
|
476
|
+
if (pct >= 60)
|
|
477
|
+
return 'bar-mid';
|
|
478
|
+
return 'bar-low';
|
|
479
|
+
}
|
|
427
480
|
/** B-02:单张 KPI 卡(value 带 `tnum`;非法 status 由冻结语义降级 `empty`)。 */
|
|
428
481
|
export function renderKpiCard(input) {
|
|
429
482
|
assertPlainObject(input, 'renderKpiCard: input');
|
|
@@ -442,6 +495,17 @@ export function renderKpiCard(input) {
|
|
|
442
495
|
const detail = optText(card.detail);
|
|
443
496
|
if (detail !== undefined)
|
|
444
497
|
parts.push('<div class="' + blockPart('kpiCard', 'detail') + '">' + esc(detail) + '</div>');
|
|
498
|
+
const bar = card.bar;
|
|
499
|
+
if (bar !== undefined) {
|
|
500
|
+
assertPlainObject(bar, 'renderKpiCard: bar');
|
|
501
|
+
const pct = bar.pct;
|
|
502
|
+
if (typeof pct !== 'number' || !Number.isFinite(pct) || pct < 0 || pct > 100) {
|
|
503
|
+
badInput('renderKpiCard: bar.pct 必须在 0–100 之间');
|
|
504
|
+
}
|
|
505
|
+
parts.push('<div class="' + blockPart('kpiCard', 'bar') + '">'
|
|
506
|
+
+ '<div class="' + blockPart('kpiCard', 'bar-fill') + ' ' + blockPart('kpiCard', kpiBarClass(pct)) + '" style="width:' + pct + '%"></div>'
|
|
507
|
+
+ '</div>');
|
|
508
|
+
}
|
|
445
509
|
if (card.status !== undefined) {
|
|
446
510
|
const status = STATUS_KINDS.includes(card.status) ? card.status : 'empty';
|
|
447
511
|
const badge = renderStatusBadge(card.statusText === undefined ? { status } : { status, text: card.statusText });
|
|
@@ -451,11 +515,22 @@ export function renderKpiCard(input) {
|
|
|
451
515
|
return parts.join('');
|
|
452
516
|
}
|
|
453
517
|
/** B-02 伴生布局:KPI 卡网格(不是第 13 个区块,无独立样式区,用 `kpiCard` 区)。 */
|
|
454
|
-
export function renderKpiGrid(cards) {
|
|
518
|
+
export function renderKpiGrid(cards, opts) {
|
|
455
519
|
if (!Array.isArray(cards) || cards.length === 0)
|
|
456
520
|
badInput('renderKpiGrid: cards 必须是非空数组');
|
|
457
|
-
|
|
521
|
+
if (opts !== undefined) {
|
|
522
|
+
assertPlainObject(opts, 'renderKpiGrid: opts');
|
|
523
|
+
assertNoInlineHandler(opts, 'renderKpiGrid: opts');
|
|
524
|
+
}
|
|
525
|
+
const grid = '<div class="' + blockPart('kpiCard', 'grid') + '">'
|
|
458
526
|
+ cards.map((card) => renderKpiCard(card)).join('') + '</div>';
|
|
527
|
+
// #513:不给 title 即返回原 grid 串(与改前逐字节同);给了即标题 h2 +原 grid
|
|
528
|
+
// (与页面当刻手写形一致,页面票后迁可逐字节对)。标题类复用 #507 已落盘的 `kpi-card-title`
|
|
529
|
+
//(15px/700),不新增类名、不新增样式区。
|
|
530
|
+
const title = opts === undefined ? undefined : optText(opts.title);
|
|
531
|
+
if (title === undefined)
|
|
532
|
+
return grid;
|
|
533
|
+
return '<h2 class="' + blockPart('kpiCard', 'title') + '">' + esc(title) + '</h2>' + grid;
|
|
459
534
|
}
|
|
460
535
|
const TABLE_ALIGNS = ['left', 'center', 'right'];
|
|
461
536
|
function cellText(value, field) {
|
|
@@ -497,7 +572,14 @@ export function renderDataTable(input) {
|
|
|
497
572
|
const head = '<thead><tr>' + columns.map((column) => '<th scope="col" class="' + blockPart('dataTable', 'cell-' + column.align) + '">' + esc(column.label) + '</th>').join('') + '</tr></thead>';
|
|
498
573
|
const body = '<tbody>' + table.rows.map((row, ri) => {
|
|
499
574
|
assertPlainObject(row, 'renderDataTable: input.rows[' + ri + ']');
|
|
500
|
-
|
|
575
|
+
// #513 行标记槽:可选 `marker`(非空字符串 ⇒ 首格前插行徽标;缺省/空串 ⇒ 零渲染,
|
|
576
|
+
// 本行与改前逐字节同);非字符串非 undefined 即 `bad-input`(与 `cellText` 同严格)。
|
|
577
|
+
const rawMarker = row.marker;
|
|
578
|
+
if (rawMarker !== undefined && typeof rawMarker !== 'string') {
|
|
579
|
+
badInput('renderDataTable: input.rows[' + ri + '].marker 必须是非空字符串/undefined');
|
|
580
|
+
}
|
|
581
|
+
const marker = rawMarker === undefined ? undefined : optText(rawMarker);
|
|
582
|
+
return '<tr>' + columns.map((column, ci) => {
|
|
501
583
|
const raw = row[column.key];
|
|
502
584
|
// #567 `cellHtml`:给了且对本格返回字符串即受信透传(调用方已转义);
|
|
503
585
|
// 返回 `undefined` 即走缺省转义文本。不给 `cellHtml` 时本行与改前逐字同。
|
|
@@ -518,8 +600,12 @@ export function renderDataTable(input) {
|
|
|
518
600
|
const text = trusted === undefined
|
|
519
601
|
? cellText(raw, 'renderDataTable: input.rows[' + ri + '].' + column.key)
|
|
520
602
|
: trusted;
|
|
521
|
-
|
|
522
|
-
|
|
603
|
+
const open = '<td class="' + blockPart('dataTable', 'cell-' + column.align) + '" data-label="' + esc(column.label) + '">';
|
|
604
|
+
// #513:行标记只进首格(转义后前插;`cellHtml` 受信透传不受影响)。
|
|
605
|
+
const head = ci === 0 && marker !== undefined
|
|
606
|
+
? '<span class="' + blockPart('dataTable', 'row-marker') + '">' + esc(marker) + '</span>'
|
|
607
|
+
: '';
|
|
608
|
+
return open + head + text + '</td>';
|
|
523
609
|
}).join('') + '</tr>';
|
|
524
610
|
}).join('') + '</tbody>';
|
|
525
611
|
const caption = optText(table.caption);
|
|
@@ -924,8 +1010,21 @@ const BLOCK_SECTION_BUILDERS = {
|
|
|
924
1010
|
' color: var(--fg);',
|
|
925
1011
|
' font-feature-settings: "tnum";',
|
|
926
1012
|
'}',
|
|
1013
|
+
// t728 D-T2「页头三级一眼分得开,且不与正文徽章同规格」:
|
|
1014
|
+
// 改前眉标与正文徽章是**同一套字体规格**(12px/600/`var(--blue2)`),只差一层浅底与圆角,
|
|
1015
|
+
// 于是「这是页头」与「这是页里的一枚状态标签」在视觉上分不出来(R3)。
|
|
1016
|
+
// 拆口径:眉标走**面包屑**(无底、有字距、品牌位与域位分色),徽章走**胶囊**(有底、有边框)——
|
|
1017
|
+
// 两者不再共用「同字号同字重同色」这一组值。
|
|
1018
|
+
// 分段落法:`display:flex` + `> span + span` 的 hairline(与口径行 `renderCaliberLine` 同一机制、
|
|
1019
|
+
// 同一色档 `LINE_RGB` 的 .6 透明档),并列符因此不进产物文本(t508 门判据)。
|
|
1020
|
+
// 只写 `display:flex` 不加 `gap`:单段眉标(不带并列符的调用点)里那一段是匿名 flex 项,
|
|
1021
|
+
// 版面与改前的 `<p>` 纯文本逐值相同。
|
|
927
1022
|
'.' + p + 'block-page-shell-eyebrow {',
|
|
1023
|
+
' display: flex;',
|
|
1024
|
+
' flex-wrap: wrap;',
|
|
1025
|
+
' align-items: center;',
|
|
928
1026
|
' margin: 0;',
|
|
1027
|
+
// 缺省色=改前那一档(单段眉标不带 span,取的就是这条):别的调用点版面不动。
|
|
929
1028
|
// #179 对比度:12px 小字压白底,`--blue` 4.02:1 不到 AA 的 4.5:1 → 同族深一档 `--blue2`(5.6:1)。
|
|
930
1029
|
' color: var(--blue2);',
|
|
931
1030
|
' font-size: 12px;',
|
|
@@ -933,8 +1032,23 @@ const BLOCK_SECTION_BUILDERS = {
|
|
|
933
1032
|
' letter-spacing: .08em;',
|
|
934
1033
|
' text-transform: uppercase;',
|
|
935
1034
|
'}',
|
|
1035
|
+
// 品牌位:中性灰(`--fg2` 4.94:1,过 AA),不抢域位。
|
|
1036
|
+
'.' + p + 'block-page-shell-eyebrow-app {',
|
|
1037
|
+
' color: var(--fg2);',
|
|
1038
|
+
'}',
|
|
1039
|
+
// 域位:`--blue2`(5.6:1),与品牌位分色 ⇒ 两段的关系由颜色与那条 hairline 说明。
|
|
1040
|
+
'.' + p + 'block-page-shell-eyebrow-scope {',
|
|
1041
|
+
' color: var(--blue2);',
|
|
1042
|
+
'}',
|
|
1043
|
+
// 段间那条细竖线:与口径行同一条 hairline、同一色档,不新增色值、不新增 token。
|
|
1044
|
+
'.' + p + 'block-page-shell-eyebrow > span + span {',
|
|
1045
|
+
' padding-left: 8px;',
|
|
1046
|
+
' margin-left: 8px;',
|
|
1047
|
+
' border-left: 1px solid rgba(' + LINE_RGB + ', .6);',
|
|
1048
|
+
'}',
|
|
936
1049
|
'.' + p + 'block-page-shell-title {',
|
|
937
|
-
|
|
1050
|
+
// t728 间距网格:页头 4 处的 `6px 0 0` 破 4px 网格(R4),统一到 8px(4 的倍数)。
|
|
1051
|
+
' margin: 8px 0 0;',
|
|
938
1052
|
// #567 J4(§5.2 大数 28 吸收 26/28/32/40):页标题 32→28。
|
|
939
1053
|
' font-size: 28px;',
|
|
940
1054
|
' font-weight: 700;',
|
|
@@ -942,10 +1056,17 @@ const BLOCK_SECTION_BUILDERS = {
|
|
|
942
1056
|
' line-height: 1.2;',
|
|
943
1057
|
'}',
|
|
944
1058
|
'.' + p + 'block-page-shell-subtitle {',
|
|
945
|
-
' margin:
|
|
1059
|
+
' margin: 8px 0 0;',
|
|
946
1060
|
' color: var(--fg2);',
|
|
947
1061
|
' font-size: 15px;',
|
|
948
1062
|
'}',
|
|
1063
|
+
// t728 页头与正文之间那一条分隔:页头三级(眉标/标题/副题)是一个整体,正文另起一段——
|
|
1064
|
+
// 改前两者只靠 16px 间距分开,长表单页里「页头在哪里结束」看不出边界。
|
|
1065
|
+
// 落在副题上(它恒在页头末位、且页壳是 flex-less 的普通块,`border-bottom` 只画一条线)。
|
|
1066
|
+
'.' + p + 'block-page-shell-subtitle:last-of-type {',
|
|
1067
|
+
' padding-bottom: 16px;',
|
|
1068
|
+
' border-bottom: 1px solid var(--line);',
|
|
1069
|
+
'}',
|
|
949
1070
|
'.' + p + 'block-page-shell-body {',
|
|
950
1071
|
' display: block;',
|
|
951
1072
|
' margin-top: 16px;',
|
|
@@ -1053,6 +1174,87 @@ const BLOCK_SECTION_BUILDERS = {
|
|
|
1053
1174
|
' font-size: 15px;',
|
|
1054
1175
|
' font-weight: 600;',
|
|
1055
1176
|
'}',
|
|
1177
|
+
// #434 操作卡头部(#422 共用件 `operationHead()` 的根类+四色档+四子件;样式落本区,不新增区)。
|
|
1178
|
+
// 形态对齐老实物 `crud_receipt` 的 `id-card` 左色条(样张 `t156-样张-写后回执.html:153-160`:
|
|
1179
|
+
// `border-left:4px solid` 随 op 切):基规则出卡片+ 4px 左条(缺省中性 `var(--line)`),
|
|
1180
|
+
// 四色档只改 `border-left-color`。版式把页级四条覆盖收编(`sportUi.ts` 的 `.ilife-page …`
|
|
1181
|
+
// 四条本票删除后落点):图标+徽章+标题同排,记录号/时刻行各占整行(`flex:1 0 100%`)。
|
|
1182
|
+
// 内距取同族卡片档 14px(`kpiCard`/`chartBlock`/`detailSection` 同值),样张的 18px 20px
|
|
1183
|
+
// 是 throwaway 密度不照搬;块级 `margin:16px 0` 取 #154 同族值(与 #457 相邻兄弟规则折叠恒 16)。
|
|
1184
|
+
'.' + p + 'block-op-head {',
|
|
1185
|
+
' display: flex;',
|
|
1186
|
+
' flex-wrap: wrap;',
|
|
1187
|
+
' align-items: center;',
|
|
1188
|
+
' gap: 8px 12px;',
|
|
1189
|
+
' margin: 16px 0;',
|
|
1190
|
+
' padding: 14px;',
|
|
1191
|
+
' border: 1px solid var(--line);',
|
|
1192
|
+
' border-left: 4px solid var(--line);',
|
|
1193
|
+
' border-radius: ' + RADIUS_MD + 'px;',
|
|
1194
|
+
' background: var(--card);',
|
|
1195
|
+
'}',
|
|
1196
|
+
// 四色档(`OPERATION_TONES` ok/warn/danger/empty 的样式落点;只改左条色)。
|
|
1197
|
+
// 色值口径:ok 取冻结 token `var(--ok)`(值 `#34c759`,与样张 `opColors` 同值);
|
|
1198
|
+
// 冻结表无 warn/danger 灯位,故 warn/danger 取同仓状态徽章同源 D-5 常量
|
|
1199
|
+
// (`src/style.ts` statusBadge 区 warn `#a25b00`/danger `#a83228`,不新增 token 名);
|
|
1200
|
+
// empty 取冻结 `var(--fg2)`(与 empty 徽章字色同值,中性)。
|
|
1201
|
+
// 样张的 `#0071e3` 在 H-01 禁色表内(`test/style.test.mjs:241`),一律不用;
|
|
1202
|
+
// 色条是非文本,不套 #179 的文本对比度档。
|
|
1203
|
+
'.' + p + 'block-op-head-ok {',
|
|
1204
|
+
' border-left-color: var(--ok);',
|
|
1205
|
+
'}',
|
|
1206
|
+
'.' + p + 'block-op-head-warn {',
|
|
1207
|
+
' border-left-color: #a25b00;',
|
|
1208
|
+
'}',
|
|
1209
|
+
'.' + p + 'block-op-head-danger {',
|
|
1210
|
+
' border-left-color: #a83228;',
|
|
1211
|
+
'}',
|
|
1212
|
+
'.' + p + 'block-op-head-empty {',
|
|
1213
|
+
' border-left-color: var(--fg2);',
|
|
1214
|
+
'}',
|
|
1215
|
+
// 子件四条(`operationHead()` 的 `-icon`/`-title`/`-id`/`-time`)。
|
|
1216
|
+
// 图标 40px 中性盒(样张 12px 圆角按 D-5 收进闭集取 14;底色取中性 `var(--soft)`,
|
|
1217
|
+
// 色档由左条+徽章承担,图标不跟色);标题 18px/700 取 `detail-section-title` 档
|
|
1218
|
+
// (#567 J4 标题 18 吸收 17/18/20/22);记录号 13px 取 `--fg2`;时刻行 12px 取
|
|
1219
|
+
// `--fg2`(#179:12px 小字须 4.5:1,`--fg3` 3.62:1 不用)。
|
|
1220
|
+
// 时刻行首的「写入时间 」键(`sportUi.ts` 迁回):`actionAt` 即写入时间
|
|
1221
|
+
// (`body/receipt.ts:162` 同值同词 `{ k: '写入时间', v: actionAt }`),CSS 内容只进
|
|
1222
|
+
// 渲染层;第二消费族出现时提到调用方文案面并删此条(过渡债务,本票如实记)。
|
|
1223
|
+
'.' + p + 'block-op-head-icon {',
|
|
1224
|
+
' display: inline-flex;',
|
|
1225
|
+
' align-items: center;',
|
|
1226
|
+
' justify-content: center;',
|
|
1227
|
+
' width: 40px;',
|
|
1228
|
+
' height: 40px;',
|
|
1229
|
+
' border-radius: ' + RADIUS_MD + 'px;',
|
|
1230
|
+
' background: var(--soft);',
|
|
1231
|
+
' color: var(--fg);',
|
|
1232
|
+
' font-size: 20px;',
|
|
1233
|
+
' line-height: 1;',
|
|
1234
|
+
'}',
|
|
1235
|
+
'.' + p + 'block-op-head-title {',
|
|
1236
|
+
' display: inline-flex;',
|
|
1237
|
+
' align-items: center;',
|
|
1238
|
+
' margin: 0;',
|
|
1239
|
+
' color: var(--fg);',
|
|
1240
|
+
' font-size: 18px;',
|
|
1241
|
+
' font-weight: 700;',
|
|
1242
|
+
'}',
|
|
1243
|
+
'.' + p + 'block-op-head-id {',
|
|
1244
|
+
' flex: 1 0 100%;',
|
|
1245
|
+
' margin: 0;',
|
|
1246
|
+
' color: var(--fg2);',
|
|
1247
|
+
' font-size: 13px;',
|
|
1248
|
+
'}',
|
|
1249
|
+
'.' + p + 'block-op-head-time {',
|
|
1250
|
+
' flex: 1 0 100%;',
|
|
1251
|
+
' margin: 0;',
|
|
1252
|
+
' color: var(--fg2);',
|
|
1253
|
+
' font-size: 12px;',
|
|
1254
|
+
'}',
|
|
1255
|
+
'.' + p + 'block-op-head-time::before {',
|
|
1256
|
+
' content: "写入时间 ";',
|
|
1257
|
+
'}',
|
|
1056
1258
|
// #421 页面融合四件的样式随本区落盘(同 #420 处置:四件都是页面级、不属 12 区块,
|
|
1057
1259
|
// `BLOCK_STYLE_SECTIONS` 由 `test/blocks.test.mjs` 钉死 12 项,故不新增样式区、不新增 token)。
|
|
1058
1260
|
// **色值口径(#431 定稿)**:区块自身不写死任何色值字面量——样式里只出现冻结 token。不给 `color`
|
|
@@ -1109,6 +1311,9 @@ const BLOCK_SECTION_BUILDERS = {
|
|
|
1109
1311
|
' text-align: right;',
|
|
1110
1312
|
'}',
|
|
1111
1313
|
// 12px 小字取 `--blue2`(压 `--soft` 约 5.4:1);`--blue` 4.02:1 不到 AA 的 4.5:1(#179 口径)。
|
|
1314
|
+
// t728:`margin` 由每枚徽章自带改成**行容器**统一给(`row-gap` / `column-gap`)——改前靠
|
|
1315
|
+
// `margin: 0 6px 6px 0` 凑间距,右端与下沿各多出 6px 悬空,且末枚右边距在 `text-align:right`
|
|
1316
|
+
// 的父容器里会把整行推歪。裸 `renderChips`(不在行容器里)的调用点仍吃这条 margin,版面不变。
|
|
1112
1317
|
'.' + p + 'block-chip {',
|
|
1113
1318
|
' display: inline-block;',
|
|
1114
1319
|
' margin: 0 6px 6px 0;',
|
|
@@ -1121,6 +1326,18 @@ const BLOCK_SECTION_BUILDERS = {
|
|
|
1121
1326
|
' font-weight: 600;',
|
|
1122
1327
|
' line-height: 1.5;',
|
|
1123
1328
|
'}',
|
|
1329
|
+
// 徽章行:一枚容器吃掉「并列标签」这件事——间距走 `gap`(末枚不再多出右边距),
|
|
1330
|
+
// 行高走 `min-height`(v 对齐不靠 `line-height` 凑),窄屏 `flex-wrap` 自动换行。
|
|
1331
|
+
'.' + p + 'block-chip-row {',
|
|
1332
|
+
' display: flex;',
|
|
1333
|
+
' flex-wrap: wrap;',
|
|
1334
|
+
' align-items: center;',
|
|
1335
|
+
' gap: 6px 8px;',
|
|
1336
|
+
' margin: 0 0 8px;',
|
|
1337
|
+
'}',
|
|
1338
|
+
'.' + p + 'block-chip-row > .' + p + 'block-chip {',
|
|
1339
|
+
' margin: 0;',
|
|
1340
|
+
'}',
|
|
1124
1341
|
'.' + p + 'block-change-row {',
|
|
1125
1342
|
' display: flex;',
|
|
1126
1343
|
' align-items: baseline;',
|
|
@@ -1204,7 +1421,20 @@ const BLOCK_SECTION_BUILDERS = {
|
|
|
1204
1421
|
' gap: 12px;',
|
|
1205
1422
|
' margin: 16px 0;',
|
|
1206
1423
|
'}',
|
|
1424
|
+
// #507 桌面列数上限(用户点名:6 张 KPI 在宽屏挤成一行):基座 `auto-fit minmax(150px,1fr)`
|
|
1425
|
+
// 无上限,越宽列越多。只加 ≥1024 一档 `repeat(3,…)`,基座一行不动;窄屏 2×2(#507 窄屏档)
|
|
1426
|
+
// 与 400 单列(`pageUi` ⑦)各管各档。断点取票面值 1024;选择器挂祖先类(与窄屏档同法),
|
|
1427
|
+
// 同名基座仍恰 1 条(`declsOf` 口径),不新类名、不新样式区。
|
|
1428
|
+
'@media (min-width: 1024px) {',
|
|
1429
|
+
' .' + p + 'block-page-shell .' + p + 'block-kpi-card-grid {',
|
|
1430
|
+
' grid-template-columns: repeat(3, minmax(0, 1fr));',
|
|
1431
|
+
' }',
|
|
1432
|
+
'}',
|
|
1433
|
+
// #513 徽章贴底:卡片改纵向 flex 列(子元素仍纵向满宽,`align-items` 缺省 `stretch`、
|
|
1434
|
+
// 无子元素设交叉轴尺寸 ⇒ 视觉同块流),余量由徽章的 `margin-top: auto` 吃掉(见下)。
|
|
1207
1435
|
'.' + p + 'block-kpi-card {',
|
|
1436
|
+
' display: flex;',
|
|
1437
|
+
' flex-direction: column;',
|
|
1208
1438
|
' padding: 14px;',
|
|
1209
1439
|
' border: 1px solid var(--line);',
|
|
1210
1440
|
' border-radius: ' + RADIUS_MD + 'px;',
|
|
@@ -1249,8 +1479,33 @@ const BLOCK_SECTION_BUILDERS = {
|
|
|
1249
1479
|
' font-size: 12px;',
|
|
1250
1480
|
' overflow-wrap: anywhere;',
|
|
1251
1481
|
'}',
|
|
1482
|
+
// #513(续):`margin-top: auto` 把徽章压到底;`padding-top: 8px` 保住改前 8px 最小间距
|
|
1483
|
+
// (最高卡无余量时徽章位置与改前一致,只动有余量的短卡——正是要修的那几张)。
|
|
1252
1484
|
'.' + p + 'block-kpi-card-badge {',
|
|
1485
|
+
' margin-top: auto;',
|
|
1486
|
+
' padding-top: 8px;',
|
|
1487
|
+
'}',
|
|
1488
|
+
// #418 条位:detail 之后 badge 之前产条(见 renderKpiCard)。色值单源(甲路):
|
|
1489
|
+
// 三档各一处字面量,源 spec/charts.ts CHART_PALETTE[1..3],与状态徽章底色同值。
|
|
1490
|
+
'.' + p + 'block-kpi-card-bar {',
|
|
1491
|
+
' height: 6px;',
|
|
1492
|
+
' border-radius: ' + RADIUS_PILL + 'px;',
|
|
1493
|
+
' background: var(--line);',
|
|
1253
1494
|
' margin-top: 8px;',
|
|
1495
|
+
' overflow: hidden;',
|
|
1496
|
+
'}',
|
|
1497
|
+
'.' + p + 'block-kpi-card-bar-fill {',
|
|
1498
|
+
' height: 100%;',
|
|
1499
|
+
' border-radius: ' + RADIUS_PILL + 'px;',
|
|
1500
|
+
'}',
|
|
1501
|
+
'.' + p + 'block-kpi-card-bar-high {',
|
|
1502
|
+
' background: #34c759;',
|
|
1503
|
+
'}',
|
|
1504
|
+
'.' + p + 'block-kpi-card-bar-mid {',
|
|
1505
|
+
' background: #ff9500;',
|
|
1506
|
+
'}',
|
|
1507
|
+
'.' + p + 'block-kpi-card-bar-low {',
|
|
1508
|
+
' background: #ff3b30;',
|
|
1254
1509
|
'}',
|
|
1255
1510
|
// #507 段标题统一(审查必改 #5):`blocks.ts` 从 #401 起就给过这条类名产出器的位置
|
|
1256
1511
|
// (`homeDocs.ts:247` 用 `<h2 class="ilife-block-kpi-card-title">` 出「今日速览」段标题),
|
|
@@ -1264,13 +1519,13 @@ const BLOCK_SECTION_BUILDERS = {
|
|
|
1264
1519
|
' font-size: 15px;',
|
|
1265
1520
|
' font-weight: 700;',
|
|
1266
1521
|
'}',
|
|
1267
|
-
// #507 窄屏档(审查必改 #4
|
|
1522
|
+
// #507 窄屏档(审查必改 #4)+ #427 收窄为单列:`auto-fit minmax(150px,1fr)` 只在容器有效宽 ≥474px 时排 3 列
|
|
1268
1523
|
// (3×150 + 2×12 间隙),而手机端页面模板 `padding:20px 16px`(见本区 ≤640px 段)——
|
|
1269
1524
|
// 512 视口下栅格有效宽仅 480px ⇒ 正好卡在 3 列下沿,第 4 张卡单独占一行、宽度只有前三张的
|
|
1270
1525
|
// 1/3(`grid-auto-rows:1fr` 又让它与前三张**等高**),看着像漏了一张。
|
|
1271
|
-
//
|
|
1272
|
-
// 是下限(不是 `auto`
|
|
1273
|
-
//
|
|
1526
|
+
// #427(#507§8 三条窄屏归 #427,同一段代码):≤640 显式单列 ⇒ 390 每张占整行上下排列;
|
|
1527
|
+
// `minmax(0,1fr)` 的 0 是下限(不是 `auto` 那种取内容最小宽),长值卡不会被撑破。
|
|
1528
|
+
// 桌面档一行不动(桌面列数上限 #507 的 1024 三列帽另管)。断点取本文件既有先例:`dataTable` 与 `pageShell`
|
|
1274
1529
|
// 两处都是 `@media (max-width: 640px)`。
|
|
1275
1530
|
// 选择器是 `.ilife-block-page-shell .ilife-block-kpi-card-grid`(基础类名前挂一个祖先类),
|
|
1276
1531
|
// **不是**同名再写一条:① 网格落在页面模板正文里(`renderKpiGrid` 的唯一用法),该祖先恒成立;
|
|
@@ -1278,7 +1533,7 @@ const BLOCK_SECTION_BUILDERS = {
|
|
|
1278
1533
|
// 判账,同名再起一条会被数成 2 条而红;`dataTable` 区那条同名 640px 规则是历史写法,本票不动它。
|
|
1279
1534
|
'@media (max-width: 640px) {',
|
|
1280
1535
|
' .' + p + 'block-page-shell .' + p + 'block-kpi-card-grid {',
|
|
1281
|
-
' grid-template-columns:
|
|
1536
|
+
' grid-template-columns: minmax(0, 1fr);',
|
|
1282
1537
|
' }',
|
|
1283
1538
|
'}',
|
|
1284
1539
|
].join(LF),
|
|
@@ -1312,6 +1567,22 @@ const BLOCK_SECTION_BUILDERS = {
|
|
|
1312
1567
|
' font-weight: 600;',
|
|
1313
1568
|
' text-align: left;',
|
|
1314
1569
|
'}',
|
|
1570
|
+
// #513 行标记槽:首格前插的行徽标(`renderDataTable` 的 `rows[i].marker`)。行内小徽标:
|
|
1571
|
+
// 色走冻结 token(底 `--soft`+字 `--blue2`,与 `block-chip` 同口径,不新增 token;
|
|
1572
|
+
// 12px 小字对比度约 5.4:1,#179 口径达 AA);`white-space: nowrap` 保徽标不断行;
|
|
1573
|
+
// 只吃内容宽,不改窄屏档位(横溢口径见证据件)。
|
|
1574
|
+
'.' + p + 'block-data-table-row-marker {',
|
|
1575
|
+
' display: inline-block;',
|
|
1576
|
+
' margin-right: 6px;',
|
|
1577
|
+
' padding: 1px 7px;',
|
|
1578
|
+
' border-radius: ' + RADIUS_PILL + 'px;',
|
|
1579
|
+
' background: var(--soft);',
|
|
1580
|
+
' color: var(--blue2);',
|
|
1581
|
+
' font-size: 12px;',
|
|
1582
|
+
' font-weight: 600;',
|
|
1583
|
+
' white-space: nowrap;',
|
|
1584
|
+
' vertical-align: baseline;',
|
|
1585
|
+
'}',
|
|
1315
1586
|
'.' + p + 'block-data-table th {',
|
|
1316
1587
|
' padding: 10px 14px;',
|
|
1317
1588
|
' border-bottom: 1px solid var(--line);',
|
|
@@ -1340,6 +1611,13 @@ const BLOCK_SECTION_BUILDERS = {
|
|
|
1340
1611
|
'.' + p + 'block-data-table tr:last-child td {',
|
|
1341
1612
|
' border-bottom: none;',
|
|
1342
1613
|
'}',
|
|
1614
|
+
// #507 表格斑马纹(用户点名的两条之一;另一条数值列等宽栈已由 #507 视觉底座落地,本票不重做):
|
|
1615
|
+
// 偶数数据行取 `var(--bg)`(既有冻结 token,不新增语义 token)。只染 `tbody` 行,列头不动;
|
|
1616
|
+
// 背景落 `td`(本表 `border-collapse: collapse`,行背景不可靠)。伪类挂既有类上,不新类名、
|
|
1617
|
+
// 不新样式区;窄屏行卡化(#457)下偶数卡整格同底,仍可读。
|
|
1618
|
+
'.' + p + 'block-data-table tbody tr:nth-child(even) td {',
|
|
1619
|
+
' background-color: var(--bg);',
|
|
1620
|
+
'}',
|
|
1343
1621
|
'.' + p + 'block-data-table-cell-left {',
|
|
1344
1622
|
' text-align: left;',
|
|
1345
1623
|
'}',
|
|
@@ -1686,6 +1964,13 @@ const BLOCK_SECTION_BUILDERS = {
|
|
|
1686
1964
|
'.' + p + 'block-disclosure[open] > .' + p + 'block-disclosure-summary::before {',
|
|
1687
1965
|
' transform: rotate(90deg);',
|
|
1688
1966
|
'}',
|
|
1967
|
+
// #507 减动效归零档(照老壳 `style.ts` 归零档补:本区唯一的 `transition` 在此归零;
|
|
1968
|
+
// 只停过渡,`rotate(90deg)` 开合终态照走)。
|
|
1969
|
+
'@media (prefers-reduced-motion: reduce) {',
|
|
1970
|
+
' .' + p + 'block-disclosure-summary::before {',
|
|
1971
|
+
' transition: none;',
|
|
1972
|
+
' }',
|
|
1973
|
+
'}',
|
|
1689
1974
|
'.' + p + 'block-disclosure-body {',
|
|
1690
1975
|
' padding: 0 14px 14px;',
|
|
1691
1976
|
'}',
|