From 421fd3fde7d76ab07b52fc31d6c2067264a1bf55 Mon Sep 17 00:00:00 2001 From: Menghuan1918 Date: Sun, 27 Sep 2026 15:59:34 +0800 Subject: [PATCH] =?UTF-8?q?fix(tasks):=20=E5=B0=8F=E6=9D=A1=E7=9A=84?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E8=AF=8D=E4=B8=8E=E6=B4=BB=E5=8A=A8=E8=A1=8C?= =?UTF-8?q?=E7=BB=9F=E4=B8=80=E5=AD=97=E4=BD=93=EF=BC=88=E4=BF=AE=E6=8E=89?= =?UTF-8?q?=201px=20=E5=9F=BA=E7=BA=BF=E9=94=99=E4=BD=8D=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 用户反馈「运行中和正在分析请求没对齐」。实测是字体度量差异,不是布局: 两者行盒完全一致(11px/14px、align-items: center 下同一位置),但 11px 下 sans 字族的 fontBoundingBox ascent/descent 是 11/2,mono 字族是 10/3 —— 基线低 1px。中文在 mono 栈里本来就走同一个 CJK 回退(PingFang SC), mono 只改到句中的拉丁片段,等于半句等宽 + 整体低一像素。 修法:.barActivity 不再声明 font-family,两段文字共用小条自己的字族; 机器文本的等宽语气保留在 meta 行 / 后台任务行 / 终端输出井。 theme.spec 新增守护(.barActivity 不得声明 font-family)。 真机证据:真实运行中卡片的小条(3× DPR 截图 17-bar-real.png)两段同处一行, 两个 span 的 font-family 计算值完全相同;此前同一小条 3× 截图里蓝字明显偏低。 验证:typecheck / lint ✅;pnpm test 1257 passed / 9 skipped(新增 1 例)。 (cherry picked from commit 6816af76828a436eaf201205e385c1aa4f77dcd5) --- docs/plans/2026-09-27-tasks-graph-polish.md | 14 ++++++++++++++ src/client/tasks-graph.module.css | 11 +++++++++-- tests/theme.spec.ts | 12 ++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/docs/plans/2026-09-27-tasks-graph-polish.md b/docs/plans/2026-09-27-tasks-graph-polish.md index e8c5217..b085a66 100644 --- a/docs/plans/2026-09-27-tasks-graph-polish.md +++ b/docs/plans/2026-09-27-tasks-graph-polish.md @@ -156,6 +156,20 @@ client 半(src/client/) (控制条的折叠箭头与卡片逐节点按钮一致)。组件级守护见 `tests/tasks-page.spec.tsx` 的「draws COLLAPSE and EXPAND with different glyphs」。 +### 3. 小条里「运行中」与「正在分析请求」没对齐 → 两者统一字体 + +字体度量问题,不是布局问题:两者的行盒完全一致(都是 11px/14px、`align-items: center` 下 +同一位置),但 11px 下 sans 字族的 ascent/descent 是 **11/2**,而 mono 字族是 **10/3** —— +基线因此低 1px,蓝字看起来就是没对齐。而中文在这个 mono 栈里本来就走同一个 CJK 回退字族 +(PingFang SC),mono 只改到句子里的拉丁片段,等于「半句等宽、整体低一像素」。 + +修法是让两者共用小条自己的字族(`.barActivity` 不再声明 `font-family`);机器文本的等宽语气 +留在它该在的地方(上方 meta 行、后台任务行、终端输出井)。`tests/theme.spec.ts` 增加守护: +`.barActivity` 不得声明 `font-family`。 + +真机证据:真实运行中卡片的小条(3× DPR 截图 `/tmp/dsh-selfcheck/17-bar-real.png`)两段文字 +同处一行,且两个 span 的 `font-family` 计算值完全相同(断言 `new Set(fonts).size === 1` 通过)。 + ## 实施偏差记录(写给复审) 1. **`process-activity.ts` 是裁剪版而不是原样搬运**:本轮「阶段」= 徽标 + 颜色,逐阶段列表没有消费者,留着就是死代码。裁剪后 44 例 → 30 例(阶段相关用例随机制一起删除)。 diff --git a/src/client/tasks-graph.module.css b/src/client/tasks-graph.module.css index 0ba8c3e..b679636 100644 --- a/src/client/tasks-graph.module.css +++ b/src/client/tasks-graph.module.css @@ -370,11 +370,18 @@ } /* The merged activity: the main agent's own wording for the node's newest - range, in the mono voice the page uses for machine text. */ + range. It deliberately keeps the BAR's font — no mono family. The state word + beside it is UI copy, and the two stacks do not share metrics: measured at + 11px, the sans stack reports ascent/descent 11/2 against the mono stack's + 10/3, so a mono activity line sits 1px LOWER than the state word it follows + (the reader reported exactly that misalignment). The mono face bought + nothing here either: every CJK glyph in this line comes from the same + fallback family, so only the Latin fragments changed face — half a sentence + in mono, one pixel off. Machine text keeps its mono voice where it belongs + (the meta row above, the job rows, the terminal well). */ .barActivity { flex: 1; min-width: 0; - font-family: var(--ds-font-family-code, monospace); color: var(--dsw-alias-state-business-primary); white-space: nowrap; overflow: hidden; diff --git a/tests/theme.spec.ts b/tests/theme.spec.ts index b2ac98d..936c2f7 100644 --- a/tests/theme.spec.ts +++ b/tests/theme.spec.ts @@ -181,6 +181,18 @@ describe('skin contract: the plugin owns no color of its own', () => { expect(frames).toContain('transform: translateX(100%)') }) + it('the running bar keeps its state word and activity on ONE font stack', () => { + // Reader report: 运行中 and 正在分析请求 sat at different heights. The + // cause is metric, not layout — at 11px the sans stack is ascent/descent + // 11/2 against the mono stack's 10/3, so a mono activity line rests 1px + // lower. Both texts must therefore inherit the bar's own font. + const styles = readFileSync(resolve(ROOT, 'src/client/tasks-graph.module.css'), 'utf8') + const block = /\.barActivity \{([\s\S]*?)\n\}/.exec(styles)?.[1] + if (block === undefined) throw new Error('the .barActivity rule must exist') + expect(block).not.toContain('font-family') + expect(block).not.toContain('--ds-font-family-code') + }) + it('the empty-pane welcome capsule follows the host guide recipe', () => { // The card is the same surface as DSH's own guide capsule ("pick what // opens here"), so this pins the shared geometry and the token-only