任务书:
TASK-v15-bento.md。本页数字全部来自scripts/verify-v15.mjs与scripts/verify-visual-v12.mjs的实测输出, 没有手填。截图:docs/v15-before-desktop.png(旧版)、docs/v15-after-desktop.png、docs/v15-after-mobile.png。
本轮环境里没有 vision_analyze,用 Read 直接看了 refs/dr6.png 与 refs/dr1.png。看清的结构:
「确定性数据」= 同一份页面数据,但卡池只取前 5 张(改前快照里有 5 张)——状态 / 进程数随时间漂,直接对比两张时间点不同��页面不公平。
基线用 git archive e2eb778 导出旧代码单独起服务测量,代码指纹:改前 view-workbench.js sha1 e8a2dac26a26,改后见每次运行的头部输出。
| 项 | 改前 | 改后 | 要求 |
|---|---|---|---|
| A / B 列宽 | 左卡 50% / 右卡 50%(1.2fr 1fr 两栏) |
8 : 4(744px : 360px) | A 8 列、B 4 列 |
| A / B 高度差 | 同高(两栏 stretch) | 0px | ≤2px |
| B 卡底色 | 粉红整块(tone-danger 6% 染底) |
亮度 0.009(rgb(24,24,27)) | <0.35 |
| B 卡最差对比度 | —(粉底黑字,无深卡) | 8.6 : 1 | ≥7 |
| C/D/E | 四张 KPI 卡 + sparkline,高 77px | 三张短卡,高 194 / 194 / 194,差 0px | ≤2px |
| 区块间距(主列相邻块) | -16 / 24 / 12 / 12 / 0 | 32 / 32 / 32 / 47(页头→Bento 32;三行之间 32;Bento→页脚含分隔线 47) | 区块 32 |
| 卡片内边距 | 16px × 6 | 20px × 8 | 20 |
| 字号档 | 6 档:11 / 13 / 14 / 16 / 20 / 32(11px × 82) | 5 档:12 / 14 / 16 / 20 / 32(无 11px) | ≤5 档、无 11px |
| kf-spark 残留 | 工作台 4 个 | 工作台 0,全站 0 | 0 |
| 普通卡片 backdrop-filter(四页) | 11 / 12 / 42 / 26 | 0 / 0 / 0 / 6(/reports 的 6 个全是打开着的筛选下拉 .panel,属于浮层) |
普通卡片 0 |
| 普通卡片 box-shadow(四页) | 13 / 14 / 44 / 27 | 1 / 1 / 1 / 6(1 = 隐藏且转换的侧滑抽屉,页面上不可见) | 普通卡片无阴影 |
| 空态:未选身份 | 左卡换全员进度(v12 已做) | 保留;A 卡 363px,五阶段全员数据 | 实测 |
| 空态:本月无成果 | 有「本月还没有你的成果」 | 保留;A 卡 561px,C 卡「我的环节 —」 | 实测 |
| 空态:没人卡住 | 粉红卡 + 「大家都在动」 | 仍深底,绿点 + 正向文案;A/B 同高 381 / 381 | 实测 |
| 移动端 393 | 无溢出 | scrollWidth 393 = clientWidth 393;A/B 上下堆叠;C/D/E 一行三张等高;字号 5 档 | 无溢出、竖排 |
| v12 视觉回归 | 11/13 | 9/13 | 见 §5,两项均为 P3 的误报 |
┌───────────────────────────────┬──────────────┐
│ A 我的推进(8 列,浅) │ B 现场(4 列,深)│
│ 身份 + 五阶段 │ 1 人卡住 + 名单 │
│ 卡池进度 | 待评分 | 队友动态 │ 各阶段已交 │
├──────────┬──────────┬─────────┴──────────────┤
│ C 卡池 │ D 最高分 │ E 我的环节 │ ← 三张近方形短卡
├──────────┴──────────┴────────────────────────┤
│ F 最近动过:左 2 张机会卡 + 右「最近动过」时间线 │
└──────────────────────────────────────────────┘
kf-glass-card dark(新增变体),--kf-ink 底 + 反白。有卡住的人 → 橙点 + 大数字 + 名单;没有 → 绿点 + 正向文案。
下方「各阶段已交」在两种状态下都渲染(有数据就画)。playCard:是什么 / 三个数 / 快捷决策)+ 右侧「最近动过」时间线(5 条)。
点卡打开 app 统一的机会卡抽屉(决策 / 多人评分 / 来源 / 关联报告),和卡池里点开是同一个。.kf-card / .kf-glass:实底 #fff + 1px rgba(0,0,0,.06) 描边 + 无阴影;不再有 backdrop-filter、半透明白面、顶部白斑。div.panel.kf-glass.is-overlay(筛选下拉)、kf-drawer、kf-filter-sheet、kf-toast。顶栏与侧栏改成实底白 + 发丝线(常驻首屏,稳定比「透」重要)。#EFF0F3 + 左上角一缕极淡白光。kf-glass-card 总是 height:100%,一行里最高的卡会把同排所有卡的内容「拉散」(43px 空档)。
新增 fill-to 属性:默认卡面按内容收缩,只有需要等高铺满的调用方(A/B/C/D/E、卡池/报告卡)显式开启。kf-app 只在 IntersectionObserver 回调里放行 .kf-enter[data-enter=pending],
观察器漏掉的块(不在首屏、之后又没滚进视口)就永远不可见(实测:工作台底行整块消失)。加 1.2s 兜底释放。kf-app 刷新视图时会把 _drawer 清空;工作台自己再挂一个 kf-drawer 会和它打架(两套抽屉)。改为走 opportunity-open → app 统一抽屉。forMe 未选身份时没有 pendingScores:工作台展开它直接 TypeError(整页空白)。已修。| 检查 | 改前 | 改后 | 说明 |
|---|---|---|---|
| 字号档 ≤5 | ✗ 7 档 | ✓ 5 档(12×999 / 14×131 / 16×157 / 20×54 / 32×9) | 本轮唯一提升的项 |
| 同排卡片高度差 | ✓ 0 | ✓ 0 | |
| 可点元素 hover 反馈 | ✓ | ✓ | 显式换底色(/ 上 37 个可见) |
| P1 筛选栏 | ✓ | ✓ | |
| P2 来源/操作条底边 | ✓ | ✓ | |
| 底部空白 | ✓ | ✓ | |
| 圆角 / 原生控件 / 描边 / 纯黑 | ✓ | ✓ | |
| P3:工作台两栏等高 + 左卡连续空白 ≤32px | ✓(两栏 271/271,空白 0px) | ✗(两栏 363/363,差 0,空白 56px) | 误报,见下 |
P3 为什么判失败,以及为什么我没有为它硬改:
.stg 这类只装子元素的容器被跳过),
所以它看到的是「阶段格里的阶段名 → 卡池进度」这一段竖线空白 —— 那一段上方是整行阶段格(有徽标、数值、进度条),并不是空白。vision_analyze 不存在:用 Read 看图(见 §0)。me.pendingScores 有数据时显示,
文案是固定说明排序口径,不是编造数据。--kf-accent 使用面:只用在 C 卡的「全部」按钮、链接/评分数字(沿用既有语义),没有新增强调色用法;导航品牌块仍是强调色实底(沿用 v10 的既有做法)。969795b feat(v15): 工作台 Bento 骨架 A/B → C/D/E → F + 深色卡 + 内边距 20 + verify-v15 测量脚本
1f5f7dd feat(v15): 去玻璃 —— 普通卡片/面板实底+1px 极浅描边+无阴影,只有浮层保留模糊与阴影
3cb0950 feat(v15): 中性灰白底 + 实底按钮/侧栏/顶栏 + A 卡填满 8 列 + 移动端 393 适配
56dffac feat(v15): kf-glass-card 加 fill-to(卡面按内容收缩,A/B 显式铺满同高);B 卡补各阶段已交;A 卡填满 8 列
41db7ac feat(v15): 字号收敛到 5 档(11/13 → 12/14)+ 工作台底行 = 机会卡 + 时间线 + 卡片抽屉
be97bd6 fix(v15): 工作台卡片全貌改走 app 的统一抽屉……
复现:
node scripts/verify-v15.mjs --tag after --from worktree --json docs/v15-after.json
node scripts/verify-visual-v12.mjs --tag before
npm test # 46/46
node scripts/verify-modules.mjs
verify-v15.mjs --from <rev> 会把该 revision 导出到临时目录并起自己的 server(git archive 不会带 lib/vendor,脚本会拷一份)再测。