# 康师傅看板 · v11 补齐轮(text-box / U+2009 / 微图表 / 间距与动效) > 上一轮(v11)跑到 350 轮上限被中断,两个核心项**写了但没生效**。本轮只补没做完的部分,**不重做已完成项**。 > 已经确认 OK 的不要动:数字/单位分层(32px + 11px 灰 + 1.54px)、阴影 2 变体、1px 描边做进 shadow、46/46 单测、check.mjs 全绿。 --- ## 一、P0-a:text-box 没生效,必须修到实测达标 ### 现状(实测证据,不是猜测) `src/styles/tokens.js` 与各组件里写的是: ```css .b { font-size: 32px; line-height: 1; text-box: trim-both cap alphabetic; } ``` 浏览器 computed style 实测结果: ``` font-size: 32px line-height: 32px text-box: "cap alphabetic" ← trim-both 被丢弃 getBoundingClientRect().height = 32.00px ← 行盒完全没压缩 ``` ### 我在同一个浏览器里做的对照实验(证明浏览器支持,是写法问题) ``` 探针:font-size:32px; line-height:1; display:inline-block 不带 text-box → height = 32.00px 带 text-box:trim-both cap alphabetic → height = 23.28px (-27.2%) ``` **结论:这个 Chrome 版本支持 trimming,但不接受 `text-box` 简写里的 `trim-both`,必须改用两个独立长属性。** ### 要求 改成独立属性,两个都要写: ```css text-box-trim: trim-both; text-box-edge: cap alphabetic; ``` 如果 `text-box-trim` / `text-box-edge` 也拿不到效果,**再试** `text-box: trim-both cap alphabetic` 配合 `@supports (text-box-trim: trim-both)` 兜底,但**首选独立属性**。 **兜底方案(只有前两种都失败才用)**:用负 margin 或 `padding-block` 补偿补偿法,把行盒视觉高度压到 cap 高,但必须在代码注释里写明「浏览器不支持 trimming,用 margin 补偿」。 ### 验收(硬性,必须实测输出,不许估算) 写一个 Node + Playwright 脚本 `scripts/verify-textbox.mjs`,自起 dev server,量三处: 1. `.b` 主数值(32px):输出 `fontSize / lineHeight / computed text-box-trim / boxHeight` 2. **达标线**:`boxHeight <= 26px`(32px 字号 cap 高约 23.3px,留 2.7px 余量) 3. 若 `boxHeight > 26px`,脚本 **exit 1** 并在输出里指明失败项 另外报表里给出:**12px 正文、20px 小标题、32px 主数值** 三档在加/不加 trim 前后的行盒高度对比表(这是本轮要向客户交代的核心数据)。 --- ## 二、P0-b:U+2009 中英混排没接到渲染路径 ### 现状(实测证据) `src/utils/type.js` 里已经写好: ```js export const THIN = '\u2009'; // U+2009 THIN SPACE export function mixCJK(s) { ... } // 汉字↔拉丁/数字两侧插 U+2009 ``` 但页面实测: ``` 元素文本 "S4 机会验证评估 · 13 条" 字符码 83,52,32,26426,... ← 位置 2 是 32(普通空格 U+0020),不是 8201 全页 U+2009 计数 = 0 ``` **函数写了,没人调用。** 必须接到实际渲染路径上。 ### 要求 找出所有渲染「中英混排字符串」的地方并接上 `mixCJK()`(或等价处理),至少覆盖: - 阶段标签(`S1 市场分析`、`S4 机会验证评估 · 13 条`) - 徽标(`A级`、`高证据`、`S3 机会点识别`) - 统计单位旁的数字短语(`近 7 天`、`人均 2.5 份`) - 报告标题中夹英文/数字的(如 `20260420 CX 复盘`) - 时间(`6 小时前`、`40 小时`) **规则(严格)**: - 只在「汉字 ↔ 拉丁字母/阿拉伯数字」**交界两侧**插 U+2009 - 全角空格、普通空格**都不许**冒充 - 连续数字整体算一个单位(`20260420` 内部不插) - 已有的中英文之间如果是普通空格,替换成 U+2009(不要留两个) - **不要**在 ``、URL、文件名、纯英文串里插 ### 验收(硬性) 在 `scripts/verify-textbox.mjs`(或另起 `verify-cjk.mjs`)里: 1. 遍历页面所有文本节点,统计 U+2009 数量 → **必须 > 0**,且 **≥ 20 处**(页面中英混排点很多,20 是下限) 2. 抽 3 个具体元素,输出其 `textContent` 的**完整字符码数组**,证明交界处是 `8201` 3. 反向检查:**不该有** 汉字与英文之间的普通空格残留(正则 `[\u4e00-\u9fa5] [A-Za-z0-9]` 命中数应为 0,或全部来自 ``/URL 例外) 4. 不达标 exit 1 --- ## 三、P1:微图表只做了 sparkline,补齐四类 现状:`kf-spark` 组件 4 个,全是同一种折线/柱状火花线。 补齐,每类都要有真实出现位置(不是造组件放着): | 类型 | 用在哪 | 规格 | |---|---|---| | **sparkline** | 已有 4 处保留 | 宽 64-80px,高 20px,历史柱 opacity .35,最新 .95 | | **进度环 / 进度条** | 机会卡评分(76/80/81.3 分)、阶段完成度、证据强度 | 环 直径 40-48px,描边 3px,数值居中;条 高 4px,圆角 2px | | **对比条(条形对比)** | 报告类型的份数分布(品类1/竞品25/ VOC10/痛点9/概念0)、成员产出对比 | 横向条,最大值占满,其余按比例;数字右对齐 | | **热力小格** | 阶段 × 类型 的交叉分布、成员活跃度 | 格子 12-14px 方形,圆角 2px,4 档不透明度 | **铁律(来自调研,必须遵守)**: - **sparkline / 图不替代数字**,数字始终在旁边(Tufte:Print the number it summarizes beside it) - 纯 CSS 或 SVG,**不引第三方图表库**(项目零构建约束) - 不用渐变色填充图表 - 所有图表元素 `aria-hidden="true"`,旁边配文字数字给读屏 **验收**:截图 + 在页面实测每种图表的 DOM 数量(各 ≥ 1),并说明每种出现在哪个页面哪个位置。 --- ## 四、P1:间距分级 + 「我的推进」虚线框过高 ### 4.1 间距分级(v11 未验证) 统一成四档,不许出现第四种间距值: ``` 卡内 padding 16px 卡内 gap 12px 卡片之间 24px ← 1.5× 区块之间 48px ← 3× ``` **自查方法**:把页面缩到 25% 截图,所有留白宽度一样 → 均匀呼吸(模板感);能看到明确的「块」在呼吸 → 对了。 写个脚本统计页面所有 `margin`/`gap` 的构成值种类,**> 6 种就报警**(排除 0、auto、百分比、负数)。 ### 4.2 「我的推进」虚线占位框过高(客户截图级问题) 实测:该卡片里虚线占位框占近半张卡高,信息密度低。 要求: - 虚线占位框**降到内容需要的高度**(不超过 2 行文字的视觉高度 + padding) - 卡内其余空间要么放真实数据(阶段完成度进度条),要么让卡片自身收缩(`align-items: start` 而非 `stretch`) - **检查全站还有没有同类「撑高留白」**:上一轮同类 bug 是 `.grid2` 被 `align-items:stretch` 拉到 220px,内容只有 78px。全页面扫一遍,`stretch` 导致的空隙 > 24px 的都列出来并修掉 --- ## 五、P1:动效(v11 未验证) | 场景 | 要求 | 禁止 | |---|---|---| | 数字变化 | 只滚变化位(1284→1301 只滚十位个位),500-750ms,`cubic-bezier(.4,0,.2,1)` | 从 0 滚到目标值(AI 味) | | 卡片 hover | `translateY(-1px)`,150ms | `scale(1.05)` 放大 | | 列表进场 | 400ms,错峰 40ms | 所有元素同时淡入 | | 展开收起 | `grid-template-rows: 0fr → 1fr` | `max-height: 999px` | | 全局 | 只写具体属性 | `transition: all` | | 无障碍 | `@media (prefers-reduced-motion: reduce)` 全部关掉 | — | **验收**:grep 证明 `transition: all` 0 命中、`max-height:999px` 0 命中、`scale(1.0[0-9])` hover 0 命中;实测一个数字变化动画的 duration 值在 500-750ms 之间。 --- ## 六、P2:15 条反例逐条自查(逐条报告,不许略过) 逐条对照现有代码,**每条给出「命中/未命中 + 证据(文件:行号)**」: 1. 装饰性渐变 / 渐变文字标题 2. glow 光晕 / blob 色块 / 条纹纹理 / 网格背景 3. **玻璃效果用在所有卡片上**(玻璃只该用于浮层) 4. 彩色左边框告警条 5. emoji 当图标(应使用 SVG) 6. `max-height:999px` 展开动画 7. `transition: all` 8. 阴影超过 3 档 9. 纯 `#000` / `#FFF` 10. 所有间距都是同一个值(均匀呼吸) 11. `box-shadow` 做凸起 / 凹陷(非克制的拟物) 12. 加班式 hover:跳动 > 2px、放大 13. 圆角 > 16px(大圆角廉价感) 14. 强调色面积 > 5% 15. 所有卡片同时入场无错峰 **这一节的输出是本轮交付物的一部分**,写在 `docs/v11b-audit.md`,逐条 1-15 编号。 --- ## 七、字数要求(不许反弹) | 页面 | 上限 | v11 现状 | |---|---|---| | 工作台 | 350 字 | 95(v10 口径,需按同口径复核) | | 报告类型页 | 300 字 | 96 | | 报告中心 | 200 字 | 38 | **口径统一**:只统计可见文本节点的中文字符 + 中文标点,排除 SVG 内文本、`aria-label`、隐藏元素。脚本里写清算式,输出每个页面的数。 --- ## 八、交付要求 1. **每一条验收都必须是脚本实测输出**,不许写「已完成」却没有数字 2. 失败的项**如实报告失败**,不许调低门槛凑通过 3. 输出 `docs/v11b-report.md`: - 逐项验收结果表(项 / 实测值 / 达标线 / 通过与否) - 三档 text-box 前后对比表 - 15 条反例自查 - **明确列出「我没做到的 / 做不到的」**(例如浏览器不支持某项时要说清楚) 4. 所有验证脚本提交到 `scripts/`,可重复运行 5. 跑完 `node scripts/check.mjs` 与 `node --test 'test/*.test.js'` 必须全绿 6. **不要 git commit**,我会自己提交 ## 九、边界 - 不改数据层、不造数据 - 不引第三方依赖(零构建约束) - 不动已达标项(数字单位分层、阴影 2 变体、1px 描边入 shadow) - 无凭据写入任何文件