/** * 票 102 静态闸门(二):一级菜单的位置不得由右侧内容决定。 * * 维护者 2026-11-02:「按钮在居中偏左的位置(略微左移,不与背景装饰线条重合); * 目前由于时间字体的长短不平均,时间跳动会导致按钮位置左右移动,需避免。」 * * 接缝同样是外壳源码契约。这里锁的是**位置的决定权归谁**: * 三条声明分别关掉三个能让菜单移动的入口 —— 列宽随内容、菜单参与再分配、槽位吃内容宽度。 * 可传源码路径复核历史版本(提交前的暂存副本必须是红的)。 */ import assert from 'node:assert/strict' import fs from 'node:fs' const source = process.argv[2] ? fs.readFileSync(process.argv[2], 'utf8') : fs.readFileSync(new URL('../src/modules/cockpit/CockpitShell.vue', import.meta.url), 'utf8') // 入口一:右列按内容最小宽度兜底 = 内容改写列宽 = 中列被推着走。 assert.ok( source.includes('grid-template-columns: minmax(240px, 1fr) auto minmax(0, 1fr);'), '右列必须吃等分,不能再按内容撑宽' ) assert.ok(!source.includes('minmax(min-content, 1fr)'), '按内容撑宽的右列必须撤掉') // 入口二:整组平移只影响这一格的视觉位置,不重新参与 grid 分配, // 所以位置不再有任何「随内容变化」的来源。居中偏左、并避开底边光路与两侧装饰线。 assert.ok(source.includes('transform: translateX(calc(-32 * var(--u)));'), '一级菜单必须固定居中偏左') assert.ok(!/cockpit-shell__modes\s*\{[^}]*margin-left/.test(source), '位移不得用 margin(会被再分配)') // 入口三:时钟读数宽度必须恒由声明决定,而不是由「这一刻是几点几分几秒」决定。 // 槽位宽度须大于最宽的一次读数(2384×1160 实测一次读数占 101u,--u≈1.433px)。 assert.ok(source.includes('display: inline-block'), '时钟槽位要能吃到 min-width') assert.ok(source.includes('flex: 0 0 auto'), '时钟槽位不参与挤压') assert.ok(source.includes('min-width: calc(128 * var(--u));'), '时钟需要固定宽度的数字槽位') assert.ok(source.includes('text-align: right'), '时钟槽位内右对齐') assert.ok(source.includes('font-variant-numeric: tabular-nums'), '时钟数字必须等宽') // 位置改动只许动位置:导航语义与按钮本身不变。 assert.ok(source.includes('aria-label="一级模式"'), '一级模式导航保持原样') assert.ok(source.includes('v-for="item in MODES"'), '一级模式导航保持原样') assert.ok(source.includes('cockpit-shell__home'), '归位按钮保持原样') assert.ok(source.includes('cockpit-shell__clock'), '时钟保持原样') console.log('t102-topbar-layout: 14/14')