# v15 报告:按 dr6 + dr1 重构工作台视觉 > 任务书:`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`。 ## 0. 先看图(没做到 vision_analyze,用 Read 直接看) 本轮环境里没有 `vision_analyze`,用 Read 直接看了 `refs/dr6.png` 与 `refs/dr1.png`。看清的结构: - **dr6**:12 栅格 Bento;一行四张短数据卡(标签 / 大数字 / 一行说明);**整页浅色只有一块深色卡**(右侧 Time Tracker); 强调色只有一种,只出现在进度、关键数字和一个按钮上;其余全是灰阶。 - **dr1**:单色(森林绿)+ 大量留白;数据卡「标签 + 大数字 + 一行说明」;状态用色点 / 标签,不用整块色底;右侧一块深色「Onboarding Task」卡。 - 两者共同的骨架是:**浅底 → 一块深卡锚注意力 → 一排短数据卡 → 内容块**。本轮照这个骨架重排工作台。 ## 1. 改前 / 改后(verify-v15:桌面 1440,确定性数据) 「确定性数据」= 同一份页面数据,但卡池只取前 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** 的误报 | ## 2. 结构:A / B / C·D·E / F ``` ┌───────────────────────────────┬──────────────┐ │ A 我的推进(8 列,浅) │ B 现场(4 列,深)│ │ 身份 + 五阶段 │ 1 人卡住 + 名单 │ │ 卡池进度 | 待评分 | 队友动态 │ 各阶段已交 │ ├──────────┬──────────┬─────────┴──────────────┤ │ C 卡池 │ D 最高分 │ E 我的环节 │ ← 三张近方形短卡 ├──────────┴──────────┴────────────────────────┤ │ F 最近动过:左 2 张机会卡 + 右「最近动过」时间线 │ └──────────────────────────────────────────────┘ ``` - **A**:阶段格加阶段名;下半拆分「卡池进度 / 待评分 / 队友动态(没卡住但空闲最久的人)」。所有数据来自现有 core,无新算���。 - **B**:`kf-glass-card dark`(新增变体),`--kf-ink` 底 + 反白。有卡住的人 → 橙点 + 大数字 + 名单;没有 → 绿点 + 正向文案。 下方「各阶段已交」在两种状态下都渲染(有数据就画)。 - **C/D/E**:标签 → 大数字 → 一行说明。C 卡上是**全页唯一的强调色实心元素**(「全部 →」按钮)。 原来的「已决策」和 A 卡卡池进度重复,换成「我的环节」(最近一条成果落在哪个阶段)—— 更像「我」的推进,不再是管理员视角的汇总。 - **F**:两张「安静」机会卡(`playCard`:是什么 / 三个数 / 快捷决策)+ 右侧「最近动过」时间线(5 条)。 点卡打开 **app 统一的机会卡抽屉**(决策 / 多人评分 / 来源 / 关联报告),和卡池里点开是同一个。 ## 3. 去玻璃(kf-glass-card 与全站卡片) - `.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`。顶栏与侧栏改成实底白 + 发丝线(常驻首屏,稳定比「透」重要)。 - 状态色(tone)只改 1px 描边,不再给卡片裹一层 6% 染底。 - 页面背景:去掉了彩色光斑(卡片实底后,玻璃后面的色斑只剩「页面上乱飘的色块」),改中性灰白 `#EFF0F3` + 左上角一缕极淡白光。 ## 4. 顺带修掉的问题(都不在任务书字面上,但不修页面就是错的) 1. **卡片高度约定(P3 的根因)**:`kf-glass-card` 总是 `height:100%`,一行里最高的卡会把同排所有卡的内容「拉散」(43px 空档)。 新增 `fill-to` 属性:默认卡面**按内容收缩**,只有需要等高铺满的调用方(A/B/C/D/E、卡池/报告卡)显式开启。 2. **入场动画可能把内容永久停在 opacity:0**:`kf-app` 只在 IntersectionObserver 回调里放行 `.kf-enter[data-enter=pending]`, 观察器漏掉的块(不在首屏、之后又没滚进视口)就永远不可见(实测:工作台底行整块消失)。加 1.2s 兜底释放。 3. **工作台机会卡点开没有反应**:`kf-app` 刷新视图时会把 `_drawer` 清空;工作台自己再挂一个 `kf-drawer` 会和它打架(两套抽屉)。改为走 `opportunity-open` → app 统一抽屉。 4. **`forMe` 未选身份时没有 `pendingScores`**:工作台展开它直接 TypeError(整页空白)。已修。 5. **报告中心类型卡**:字号上调后「最多 N 份」被挤成竖条、来源行压扁;改成阶段条独占一行、标签右上角、来源行贴底。 ## 5. v12 回归:11/13 → 9/13,两项都是 P3 的误报 | 检查 | 改前 | 改后 | 说明 | |---|---|---|---| | 字号档 ≤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 为什么判失败,以及为什么我没有为它硬改:** - 旧版能过 0px,是因为旧左卡**没有被人为拉高**:右卡只有 271px。现在右卡(B,深)多了一块「各阶段已交」(5 行),行高变成 363px; 左卡被拉高 90px,多出的空间必然出现在某处。 - v12 的空白算法只取「有自己的文字节点」的叶子元素(`.stg` 这类只装子元素的容器被跳过), 所以它看到的是「阶段格里的阶段名 → 卡池进度」这一段竖线空白 —— 那一段上方是整行阶段格(有徽标、数值、进度条),并不是空白。 - 我试过的「硬凑」:把阶段格撑满、把下半区贴底、把行距压到 0 —— 都只能把 56px 挪个位置,要么让阶段格内部空 3/4,要么让卡片中段出现更大的洞; 任何一个都更难看,所以没有提交。 - 结论:**不达标**。如果判定以这个数为准,需要的结果是「A 卡内不要有任何 32px 以上的竖直空隙」, 在当前数据(我的成果 2 份、五阶段只填了 1 格)下,只能靠往卡片里塞与「我的推进」无关的内容去填满,我没做。 ## 6. 没做到 / 打了折的 1. **`vision_analyze` 不存在**:用 Read 看图(见 §0)。 2. **「像不像一个时代」**:这一条只能主观判断。我的判断是:骨架(Bento + 浅底深卡 + 一排短卡 + 灰阶为主、强调色只在一个按钮) 已经和 dr6/dr1 同一套语言;页面的「现代感」差距主要在字体(只有 Inter latin 子集,中文走系统雅黑)和内容密度上,本轮没有动字体。 3. **P3 连续空白 56px 未达标(见 §5)**。 4. **A 卡「待评分」的说明行**:「候选卡里还没有你打分的卡,按最近上传排」——这行只在 `me.pendingScores` 有数据时显示, 文案是固定说明排序口径,不是编造数据。 5. **B 卡「各阶段已交」**:为了让 B 卡与 A 卡同高、并且深卡里不是一块空黑,加了这块内容;它属于「现场」的合理范围(每阶段的在册人数), 但确实是**为了视觉平衡新增的信息**,如实记录。 6. **`--kf-accent` 使用面**:只用在 C 卡的「全部」按钮、链接/评分数字(沿用既有语义),没有新增强调色用法;导航品牌块仍是强调色实底(沿用 v10 的既有做法)。 ## 7. 提交 ``` 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 ` 会把该 revision 导出到临时目录并起自己的 server(`git archive` 不会带 `lib/vendor`,脚本会拷一份)再测。