康师傅产品创新看板:机会卡池 + 多Agent成果展示

pengzhikang 2278290d2c docs: summarize workshop workflow, skill, data and board delivery 21 часов назад
data b65f28ef82 feat: 五端模拟演示视图(A 驾驶舱 / B 情报洞察 / C 共创工作台 / D 验证评审 / E 课堂运营) 1 день назад
deploy 3e9c57bbee feat: resolve WeCom employee identity automatically on digital-human uploads 1 день назад
docs 2278290d2c docs: summarize workshop workflow, skill, data and board delivery 21 часов назад
legacy ec05b37ac8 初始化:康师傅产品创新看板 v10 5 дней назад
lib d14d02fd35 feat(workshop): connect public board data and project progress 3 дней назад
refs e2eb7784c1 chore(v15): 视觉重构任务书 + 参考图 dr6/dr1 4 дней назад
scripts 2278290d2c docs: summarize workshop workflow, skill, data and board delivery 21 часов назад
server a68bfe1e81 feat: ask once and persist workshop employee display names 22 часов назад
skills a68bfe1e81 feat: ask once and persist workshop employee display names 22 часов назад
src a68bfe1e81 feat: ask once and persist workshop employee display names 22 часов назад
test a68bfe1e81 feat: ask once and persist workshop employee display names 22 часов назад
.gitattributes b6b3c0f3d6 feat: orchestrate trusted employee identity in workshop skill 1 день назад
.gitignore 46aa789571 feat: integrate isolated five-view demo and showcase pages 1 день назад
README.md ec05b37ac8 初始化:康师傅产品创新看板 v10 5 дней назад
TASK-v11b.md 07efdc2f6f refactor(cjk): 中英混排从全局监视器改为数据边界落地 5 дней назад
TASK-v11c.md 07efdc2f6f refactor(cjk): 中英混排从全局监视器改为数据边界落地 5 дней назад
TASK-v12-visual.md 434e428ee8 feat(cjk+visual): 中英混排全站落地 679处,text-box 行盒 -27.2%,修复 /reports 白屏与卡住时长 5 дней назад
TASK-v13-fix.md 884d74224e feat(visual): v12 深度视觉重构 13项验收 11项达标 5 дней назад
TASK-v14-fix.md fd0db6ebf2 fix(visual): v13 三项修复 4/4 达标 5 дней назад
TASK-v15-bento.md e2eb7784c1 chore(v15): 视觉重构任务书 + 参考图 dr6/dr1 4 дней назад
TASK-v16-research.md 2020104b84 chore(v16): 先调研后改造的任务书 4 дней назад
TASK-visual-v11.md ec05b37ac8 初始化:康师傅产品创新看板 v10 5 дней назад
index.html 8d40579260 wip(v11): 中文排版与视觉精度升级(未完成,被 350 轮上限中断) 5 дней назад
package.json a27ded3a9d feat(v12-P3): 工作台未选身份时左卡改为全员阶段进度(真实数据),左右等高;池子加收尾页脚 5 дней назад

README.md

康师傅产品创新看板 · v6(展示逻辑重构:五类报告页 + 阶段产出 + 液态玻璃)

研发中心 AI 赋能实战营的组织资产系统:30–40 位学员共用一个机会卡池、一份证据台账、一组分析报告。 本版按 fmode-code-lit 规范重写骨架,并把前四轮谈定的业务全部落进来 —— 是「用新规范做出旧需求」,不是缩水重做。

  • 入口:index.html(由 scripts/config.mjs 生成,零构建)
  • 旧版(IIFE + window.KF_* + innerHTML)原样保留在 legacy/,只作业务逻辑参考,不参与部署
  • 代码规模:src/ 6,216 行(含 src/dev/ 两个开发辅助)· test/ 529 行(46 个 Node 单测)
  • v6 只改展示逻辑,不动 v5 的分层骨架:新增 core/library/(报告类型归类)、五个报告类型页、阶段产出内容视角、玻璃令牌重做(见第 8 节)。

1. 目录结构与分层

src/
  app.config.js         全应用唯一配置(Parse 地址 / 表名 / 阈值),只有公开 App ID,无凭据
  app.js                入口:注入设计令牌、注册外壳、打印启动横幅
  core/                 [core] 纯 ESM 逻辑:不碰 window/document/fetch,不 import Lit,Node 可测
    taxonomy/             阶段 / 层 / 优先级 / 状态 / 决策 / 上传方式 + 字段归一(S1品类分析、S1 品类分析、S1 都认)
    opportunity/          机会卡建模、多人评分统计、排序、状态流转(statusPatch 只产出 patch,不写库)
    evidence/chain.js     证据链双向反查(结论↔成果↔归纳↔机会卡),全部返回「名字 + 人名」
    kfs/                  Parse 行 → 业务模型(buildModel)、台账六维筛选(ledger)、派生统计(stats)
    report.js             报告章节 / 管线 / 结论块 / 概览
    index.js              唯一公共出口(74 个导出)
  components/           [wc] 组件库:extends LitElement,只渲染与交互,零业务
    kf-glass-card / kf-stat / kf-badge / kf-empty / kf-table / kf-drawer / kf-toast
    kf-opportunity-card  机会卡:五要素 + 来源四要素 + 状态快捷切换 + 内嵌报告链接(stopPropagation)
    kf-score-panel       多人评分面板(平均 / 人工 / Agent / 逐条明细 / 我来评分)
    kf-evidence-chain    证据链:成果→引用它的结论;归纳→来源报告
    kf-pipeline          数据管线
  layout/               [page] 外壳
    kf-app               布局 / 路由订阅 / 全局抽屉 / 写操作(改状态、评分)/ 所有交互事件的唯一入口
    kf-nav / kf-topbar   导航(池子数、卡住人数)/ 顶栏(「我是谁」、同步状态、刷新)
  pages/                [page] 七个视图:工作台 / 池 / 阶段 / 报告目录 / 报告阅读 / 台账 / 成员
  services/             board-service:取数(http)→ core.buildModel → signal;写 Parse 后局部合并 + 后台刷新
  utils/                router.js(History、子路径安全)/ http.js(唯一网络出口、分页、超时重试)/ storage.js
  styles/tokens.js      设计令牌 + 玻璃基元(Constructable StyleSheet,各组件 shadow root 内 `adoptedStyleSheets` 引入)
  dev/serve.mjs         本地预览服务器(History 回退 200 / `/parse` 同源代理 / 子路径挂载)—— 不参与部署
lib/vendor/             vendored 依赖(见第 2 节)
scripts/                config / vendor / check / verify-modules / verify-render / verify-browser / seed / deploy.sh
test/                   core 单测(node:test,无 jsdom)

分层边界(越界即返工):core 不认识 DOM(scripts/check.mjs 第 5 项硬校验);components 不 import services、不 fetch;layout/pages 组装一切,写库只经过 services → utils/http。


2. 依赖走哪条路:方案 B(本地 vendor)

实测(2026-10-29,本机直连):

地址 结果
https://repose.fmode.cn/npm/importmap/lit-v3.json 404
https://kangshifu.fmode.cn/npm/importmap/lit-v3.json 404
https://app.fmode.cn/npm/importmap/lit-v3.json 404
https://kangshifu.fmode.cn/npm/lit/v3.3.3/lit.js 404

方案 A(探测真实 Repose)无果:本机 .credentials 与工作目录中没有任何 Repose 地址或凭据,三条已知候选路径全部 404。

因此 vendor 化:scripts/vendor.mjs 用 npm pack 下载(不 npm install、不留 node_modules),解到 lib/vendor/<包>/v<版本>/,去掉 .ts / .d.ts / .map / src / development / decorators / test,并校验 package.json 入口文件存在。

包 版本 importmap 入口
lit 3.3.3 lib/vendor/lit/v3.3.3/index.js
lit-html 3.3.3 lib/vendor/lit-html/v3.3.3/lit-html.js
lit-element 4.2.2 lib/vendor/lit-element/v4.2.2/index.js
@lit/reactive-element 2.1.2 lib/vendor/@lit/reactive-element/v2.1.2/reactive-element.js
@lit/context 1.1.6 lib/vendor/@lit/context/v1.1.6/index.js
@lit-labs/signals 0.3.0 lib/vendor/@lit-labs/signals/v0.3.0/index.js
signal-polyfill 0.2.2 lib/vendor/signal-polyfill/v0.2.2/dist/index.js

importmap 里每个包都同时映射 pkg 与 pkg/(子路径),保证 lit 系单实例(模块图实测:46 个模块中,vendor 只出现 lit@v3.3.3(含 directives/class-map.js)、lit-html@v3.3.3、@lit/reactive-element@v2.1.2、@lit-labs/signals@v0.3.0 各一个版本;其余 41 个是本仓 src/ 文件)。所有 vendor 路径都写在 <base href> 前缀下,与业务码同源同前缀,随 base 走。

以后 Repose 恢复:把 scripts/config.mjs 里 importMapJson() 的 vendor 路径换成 /npm/... 即可,源码零改动(源码只 import 裸标识符)。

依赖注入(@lit/context)的取舍

@lit/context 已 vendor 进 importmap,但本版未使用:应用只有一个全局服务(boardService 单例 + signals),页面层直接 import 单例、组件靠属性与事件通信,少一层间接。若之后拆成多团队协作的模块化页面,再按规范接 provide()/ContextConsumer。这是刻意没做的一项,不是遗漏。


3. 机会卡为什么这么建模:新建 KfOpportunity,不复用 KfArtifact

维度 成果 KfArtifact 机会卡
生命周期 一次交付,写完即历史(改它等于篡改台账) 候选 → 立项 / 否决,反复流转
状态 无 status + decision + decisionLog(每次改都留痕)
评分 无 scores[] 多人评分,平均分随人变化
组织含义 过程资产(过程 / 沉淀 / 记录) 组织资产:研发中心的机会储备

把两者合在一个类里,客户「改一次卡片状态」就会污染「成果台账」(updatedAt 变了、证据链追溯的成果也跟着变)。所以:

  • 机会卡单独一个类,关联只存 id(linkedArtifacts[] / linkedProject),成果被删卡片不消失,只标「库里已不存在」;
  • 卡片上的「谁 · 哪个 Agent · 什么方式 · 什么时候」是四要素 + 两个扩展位(agentId、sourceSession),为后续多个数字分身留好位置,不写死单分身;
  • 一处 oneLiner 是历史测试残留的占位符("x")→ core 里按「未填写」处理,不编造内容。

4. 22 项验收:怎么验、实测结果

复现命令(全部在本机实跑过):

node scripts/config.mjs local                 # 生成 index.html(base / importmap / 前缀三处同源)
node --test 'test/*.test.js'                  # core 单测:38/38 通过
node scripts/check.mjs                        # 静态体检:CHECK OK(14 组断言:A 组 1–9 + 凭据 + 语法 + importmap + 元素注册 + wc 用 Lit)
node src/dev/serve.mjs --port 4173 &          # 本地:History 回退 200 + /parse 同源代理
node scripts/verify-modules.mjs http://127.0.0.1:4173/            # MODULE GRAPH OK
node scripts/verify-modules.mjs http://127.0.0.1:4174/kangshifu/dev/inno-board/   # 子路径:MODULE GRAPH OK
node scripts/verify-render.mjs                # jsdom 渲染冒烟:RENDER SMOKE OK(含写库闭环)
CHROME_PATH=<chrome> node scripts/verify-browser.mjs             # 真实浏览器:BROWSER VERIFY OK(36/36)

A. 规范合规

# 项 怎么验 实测结果
1 无装饰器 check.mjs 去注释后匹配 @customElement/@property/@state/... ✓ 0 命中
2 相对 import 带 .js 扫描 from './x'、import('./x'),并检查目标文件存在 ✓ 全部带 .js 且存在
3 无 window.KF_* grep src/ ✓ 0 命中
4 无 innerHTML 去注释后 grep ✓ 0 命中(全部 Lit 模板)
5 core 不碰 DOM core 下逐行 grep window/document/fetch/localStorage/navigator/HTMLElement/CustomEvent(跳过 import 行) ✓ 0 命中
6 视图不直接 fetch pages/layout/components 下 grep fetch(;services 也只经 utils/http.js ✓ 0 命中,fetch( 只出现在 utils/http.js
7 base 三处同源 config.mjs 由前缀文件生成 base / importmap / 入口,写完反向自检;check.mjs --env 再校一次 ✓ base === deploy/prefix/local.txt === importmap 前缀,14 条映射全部以 base 开头
8 无 @lit-labs/router grep src + index.html ✓ 0 命中;路由自写 utils/router.js
9 lit 单实例 importmap 每包只出现一个版本目录;源码不直引 lib/vendor;模块图爬取里 vendor 路径去重 ✓ 两处都过
10 模块图全 200 verify-modules.mjs:index → 入口 → 递归静态 import(含动态 import 字面量)→ 裸标识符按 importmap 解析(含 / 前缀映射)→ 逐个请求断言 200 + text/javascript;再断言深链接 6 条 200 ✓ 根部署:46 个模块全部 200;子路径 /kangshifu/dev/inno-board/:同样 46 个全部 200;深链接 6 条(含不存在路径)全部 200 且无重定向

B. 功能

真实浏览器(Chromium 156 headless,1440×960)逐项实测,截图在 docs/screenshots/。

# 项 怎么触发的 实测输出
11 真实取数 页面直连 Parse(本地经 /parse 同源代理) 26 成果 / 9 机会卡 / 11 成员 / 4 归纳 / 4 原材料;卡片数、成员数、卡住人数均来自库,与 core 计算一致(见 12 的一致性断言)
12 6 维筛选叠加 /pool 点「候选」→「S 级」→「拌面」;/ledger 六行筛选条(优先级/品类/阶段/人/层/状态) 页面结果与 core.applyFilter 结果逐 id 相等(测试从页面取 DOM、从 core 取期望值比较);分面计数受其他维度约束(0 条的置灰)
13 URL 状态保留、刷新不丢 筛选后读 URL → page.reload() URL = /pool?status=candidate&priority=S&category=拌面&sort=score;刷新后按钮仍 aria-pressed=true,列表 id 集合不变
14 深链接直接访问 直接打开 /pool/<id>、/report/<id>、/ledger?focus=…、/stages、不存在路径;子路径部署同一套 抽屉直接打开正确卡片;台账高亮行;不存在路径落「页面不存在」;子路径 /kangshifu/dev/inno-board/ 下 46 个模块 200、深链接 6 条 200
15 卡片五要素 /pool 读每张卡的文本与数据 9 张卡的优先级/品类/阶段、名字、一句话、评分/证据/引用、决策行、来源行全部齐全(断言:每张卡都有这些字段且文本里有「决策:」与「N 人评分 · 平均」)
16 谁 + Agent + 方式 + 时间 同上,断言四要素非空且文本里出现 例:张伟 · 康师傅产品创新助手 · 会话上传 · 10月29日 08:32;3 个 Agent(主分身 / 品类调研 / 概念设计)都出现;缺字段的卡显示「未记录」而不是编造
17 多人评分显示平均 打开有一张 6 人评分的卡 大字 81.3 /100 平均,明细:李娜 86、吴敏 90、周涛 84、评价 Agent 88、赵磊 78、郑凯 62;人工平均 80 · Agent 平均 88 · 分歧 28
18 改状态可持久 抽屉里点「已立项」→ 刷新 → 重新拉库 刷新后仍是 approved,决策 by=张伟,决策记录新增一条;seed 二次执行不覆盖人工改过的状态
19 排序切换顺序真实变化 /pool 点「综合评分」 优先级序 [neS5…, qVpN…, ws5X…, …] → 评分序 [neS5…, 8fmk…, qVpN…, …],顺序不同且平均分单调不增;URL 写入 ?sort=score
20 首页三视角 + 痛点对照 /,顶栏选「张伟」 三视角齐全;「给你的」显示 张伟,你已提交 3 份成果、还差 4 个阶段没交:S2、S3、S4、S5;池子视角 9 张卡 + 状态分布 + 最新 3 张卡片形态 + 最高分;现场看板 5×11 矩阵 + 点名 何雨 G3 · 停在 S4 · 会话 13 条 · 31 小时没动静;五大痛点 5 行对照
21 五阶段板块 /stages 5 个板块,各显示份数 / 产出人数 / 引用 / 机会卡数 + 最新 4 条(带作者、方式、Agent、时间)+ 谁产的;S3=5 份成果、4 张机会卡
22 证据链双向、点名到人 报告页点结论旁「看证据链」→ 抽屉;「在台账中高亮」;台账点成果行 → 反查;「打开证据链」 抽屉:4 人独立提到 / 4 条原文 / 3 条支撑成果,列出 夜宵场景低卡高蛋白拌面(张伟)、办公室3分钟速食拌面(李娜)、学生党实惠大份拌面(王芳),原文带平台·点赞·作者(抖音评论·点赞 412·夜宵党_312…);跳台账后对应行高亮;反查:成果 → 「被这些结论引用」逐条列出结论原文与报告名 + 被哪些归纳引用 + 出现在哪张机会卡

报告页(保留 v3 能力):吸顶章节导航 + 滚动高亮 + 点章节写回 ?ch=(刷新还原)、每章「这章在回答:」、数据管线 2,727 → 1,190 → 730,过滤率 73%、KPI、交叉分析表、结论块、附录「结论 × 证据」总表 —— 以上均由浏览器脚本断言。

C. 红线

项 结果
前端无凭据 check.mjs 按 .credentials 里每个真实值逐条比对 src/ 与 index.html:0 泄露;masterKey 字符串 0 命中;源码里的长随机串白名单校验通过
控制台无报错 真实浏览器全程监听 console.error + pageerror:0 条(网络断开的 ERR 与 favicon 除外)
对比度 ≥ 4.5:1 浏览器脚本在真实渲染后的 DOM 上逐个文字节点取 getComputedStyle 颜色,沿 shadow 宿主向上合成背景色后计算 WCAG 对比度:460 个可量化节点,最差 6.28:1。2 个未量化:品牌方块「康」与头像「伟」——白字压在多色渐变上,不可逐像素取色,属装饰层

5. 这一版没做什么(明确列出)

  1. 线上部署未执行:scripts/deploy.sh 写好了(同源前缀校验 → 体检 → 模块图 → 先删后传 index.html → 带 no-cache → 上传后复验),但本机没有 OBS 凭据 / obsutil,未上传到 kangshifu.fmode.cn。因此「线上模块图 + 线上深链接刷新」未验证;子路径部署是在本地用同前缀结构(/kangshifu/dev/inno-board/)+ 404 边界模拟验证的。
  2. CDN 回退规则:需要 CDN 侧把「非静态资源路径」200 返回 index.html;本版用 src/dev/serve.mjs 模拟了这条规则,线上是否配置未验证。
  3. @lit/context 未接入(理由见第 2 节)。
  4. 原材料库页面未做:工作台痛点表里「原材料库」的一行链到台账 ?layer=raw(数据里有 4 条原材料),没有单独的原材料浏览页。按第 9 节优先级,把厚度放在池子 / 工作台 / 报告 / 台账上。
  5. 搜索最多 1000 条/表:Parse 单次上限 1000,超过会分页(最多 50 页)并在 UI 标「数据被截断」;当前数据量远小于上限。
  6. 多人同时写同一条卡:没有冲突检测(后写覆盖)。客户当前规模(30–40 人、改状态操作稀疏)可接受,未来可按 updatedAt 做乐观锁。
  7. 历史测试残留的数据未清理:如「夜宵低卡拌面(与 seed-opp-1 重复)」及其 decisionLog 里旧验收脚本写的条目;本版只做展示纠正(占位一句话不显示),没有删客户库里的数据。

6. 示例数据

  • 所有示例卡都带 seedKey,卡片右上角显示「示例」徽标,与学员真实提交可区分
  • node scripts/seed.mjs 幂等:已存在的卡只补空字段和缺失的示例评分,不覆盖任何人改过的状态 / 决策;旧版 seed-opp-* 按标题认领,不会产生重复卡
  • node scripts/seed.mjs --check:校验每张示例卡的四要素齐全(✓ SEED CHECK OK(6 张))
  • 凭据只从环境变量 PARSE_MASTER_KEY 读,只用于脚本,不进前端

7. 本地运行

node --version                       # ≥ 20(用到 fetch / node:test)
node scripts/vendor.mjs              # 首次:把 lib/vendor 补齐(已有则可跳过)
node scripts/config.mjs local        # 生成根部署的 index.html
node src/dev/serve.mjs --port 4173   # 打开 http://127.0.0.1:4173/
# 子路径部署预览:
node scripts/config.mjs local-sub
node src/dev/serve.mjs --port 4174 --mount /kangshifu/dev/inno-board
# 打开 http://127.0.0.1:4174/kangshifu/dev/inno-board/

生产:./scripts/deploy.sh prod(需 OBS_BUCKET;上传后设置 CDN_BASE 复验)。


8. v6:展示逻辑(这一轮改了什么、怎么验的)

客户原话只落三件事:「每个阶段的产出在里面我们可以看到」、「竞品分析、品类分析……单独分类用页面展示」、「展示的逻辑能不能够做的比较好」;明确说流程推进不是重点、数据由别人灌。所以 v6 的全部改动都在这三件事上,机会卡流转 / 写库 / 状态机一行没动。

8.1 路由表(v6)

路径 视图 展示什么
/reports <view-reports> 报告中心 五类各几份(条形长度 = 占比、近 7 天新增、几人做过、几份可看全文)+ 每类最新两份 + 跨类型最新 6 份 + 阶段 × 类型总账 + 未归类如实列出
/reports/category <view-report-type type=category> 品类分析 赛道分布(每赛道份数 / 竞品篇数 / 参与人 / 平均证据)+ 阶段 × 份数(竞争密度)+ 卡片流
/reports/competitor 同上 type=competitor 竞品分析 对比矩阵(对位 × 阶段 / 原文)+ 空档标记 + 卡片流
/reports/voc 同上 type=voc VOC / 用户洞察 原文摘录(平台 · 点赞 · 作者 · 出处)+ 原文量排行 + 卡片流
/reports/pain 同上 type=pain 痛点清单 频次 × 证据图表(同一条痛点按报告结论归并)+ 对应机会卡(立项的标出)+ 卡片流
/reports/concept 同上 type=concept 概念提案 方案 × 关联机会的多人平均分 + 卡片流(当前库里 0 条,空态按「将来会出现什么」展示)
/stages <view-stages> 五阶段产出 阶段总览条 + 每阶段按类型分组的卡片流 + 谁产的 + 全部 / 只看我的 / 只看有证据
/report/:id <view-report> 报告阅读 执行摘要 → 章节速览(每章一句,点跳)+ 吸顶章节导航 + 章节内结论 / 表格 / 矩阵 + 附录「结论 × 证据」
/report — 兼容旧链接,落到报告中心

每个类型页都可加 ?stage=S1(按阶段二次筛选 —— 报告类型与阶段不是一一对应)、?ev=1(只看有证据的)、?scope=mine(只看我的,全选中的人);全部写进 URL,刷新不丢。

每条产出的通用件(卡片上一行齐):谁上传的 · 哪个 Agent · 什么方式 · 什么时候 · 属于哪个阶段 · 证据强度;能看正文的给「阅读全文」,只有登记信息的如实写「仅登记信息」。

8.2 展示逻辑的几条硬规则(都在 core,单测覆盖)

  • 归类:core/library/types.js 的 REPORT_TYPES 定义五类;core/library/reports.js 的 TYPE_FOR_ARTIFACT 把 artifactType 映射到类型页(opportunity_card → 竞品页,且在竞品 / VOC 页同时作为「证据」出现)。映射不到的进报告中心「未归类」表,不隐藏。
  • 指标对齐:每张卡固定 4 个指标,列名由类型页统一定义(metricLabels),取不到的显示「—」而不塌列——同一行卡片能直接横着比。
  • 数字有参照:每类有「占全部 %」「近 7 天新增 / 无新增」「N 人做过」「x/y 可看全文」;卡片上「只看有证据的 N」「N / 总数份」实时跟着筛选变。
  • 关键结论来自算得出来的地方:报告执行摘要 > 报告副标题 > 正文开头 > 机会卡一句话 > 原文摘录,都没有就写「正文未入知识库」——不生成一句话。
  • 有证据 = 原文 / 佐证:成果按 verified / supported 算,机会卡按三档 高 / 中 算;模型推测不算(core.hasEvidence,类型页与阶段页共用)。
  • 痛点归并:同一份报告结论(evidence 锚点)被多人整理成多份 pain_list 时合并为一条,频次 = 份数;严重度没有字段就是「待标注」,不猜。
  • 空态说人话:每个类型的空态给四行——会出现什么 / 谁来填(阶段 + Agent)/ 对应字段 / 填完长什么样 + 现在能做什么。全应用 <kf-empty> 的默认标题也从「暂无数据」改成「这里将来会出现内容」。

8.3 视觉:液态玻璃(任务书第 3 节,数值照抄)

项 做法 实测
3.1 玻璃基元 卡片 .kf-card 白面 rgba(255,255,255,.60 → .55) + backdrop-filter: blur(24px) saturate(180%) computed backdrop-filter=blur(24px) saturate(1.8);背景里无实底 background-color: rgba(0,0,0,0)
3.2 发丝边 border: 1px solid transparent + padding-box 白面 + border-box 135° 上亮下暗渐变 + inset 0 1px 0 rgba(255,255,255,.7) computed:border=1px solid rgba(0,0,0,0),background-image 第三层为 linear-gradient(135deg, rgba(255,255,255,.92) 0%, rgba(255,255,255,.22) 40%, rgba(10,20,48,.1) 100%)
3.3 三层纵纵深 底层光场(4 个色斑,单层 alpha ≤ .14,慢移)→ 面板 .46 → 卡片 .55–.60 → 抽屉 .85–.94 导航面板实测 alpha 0.46;卡片 0.60 → 0.55;抽屉 0.90
3.4 hover translateY(-2px) + 高光条横扫(background-position)+ 阴影加深 hover 后 matrix(…, 0, -2);高光 120% → -13%
3.5 对比度 文字全部实色;按「玻璃后是最深光场」算最坏合成色 3 个页共 1,856 个文字节点,最差 4.63:1(类型页)/ 4.88:1(阶段页 / 报告中心)

v5 被否决的根因(修掉的两个 bug):

  1. 卡片当时被组件里的实底 rgba(255,255,255,.88) 覆盖 → 现在只改 --kf-glass-alpha,外层仍是半透明。
  2. 共享表的 .kf-glass 用 var(--kf-glass-alpha) 写进 linear-gradient —— Chrome 实测整条声明失效(导航背景 bg=none,这就是「写了 blur 却看不出玻璃」的另一个原因)→ 改成字面量 alpha,逐条实测生效。

8.4 16 项验收:实测结果

复现命令(全部实跑过,2026-10-29):

node scripts/check.mjs                                         # CHECK OK(14 组)
node --test 'test/*.test.js'                                   # 46/46(v5 的 38 项全过 + v6 新增 8 项)
node scripts/verify-modules.mjs http://127.0.0.1:4173/         # MODULE GRAPH OK(47 模块 + 深链接)
node src/dev/fixture-server.mjs --port 4176 --dir /tmp/kfcache &   # 可选:快照回放(数据为真实 Parse 的一次原样抓取)
node scripts/verify-render.mjs --url http://127.0.0.1:4176     # RENDER SMOKE OK(jsdom,27 项)
CHROME_PATH=<chromium> node scripts/verify-glass.mjs           # GLASS VERIFY OK(8 项,第 10–15 项)
CHROME_PATH=<chromium> node scripts/verify-browser.mjs         # BROWSER VERIFY OK(48 项,含 v5 的 36 项 + v6 的 12 项)
# 项 怎么验(实测) 结果
1 报告中心各类型数量 + 最新 /reports 读 5 张类型卡的份数 品类 1 · 竞品 25 · VOC 10 · 痛点 9 · 概念 0(合计 45,未归类 0)
2 五个类型页独立访问、刷新不丢 逐页 goto → reload,断网模式下用 localStorage 快照重建 5/5:视图 VIEW-REPORT-TYPE,卡片数 = 库内原始行按同一映射算出的数(1 / 26 / 12 / 10 / 1),F5 后一致
3 按阶段二次筛选 竞品页点 S1 25 → 4 份;URL 带 ?stage=S1;F5 后仍 4(?stage=S4&ev=1 组合后 4 份,见 v6-12)
4 来源四要素 读卡片文本 例:张伟 · 康师傅产品创新助手 · Skill 上传 · 5 小时前
5 阶段页全部产出按类型分组 /stages 读 5 个阶段板块 S1 6(竞品 3 / 痛点 2 / 机会卡 1)、S2 8、S3 9、S4 6、S5 6,合计 35
6 只看我的 / 只看有证据 点 只看有证据的(证据等级纠正为「成果原始等级 / 机会卡高中」后) 35 → 26,关掉恢复 35;卡片上「有证据 N」随之变化
7 卡片横向比较 见 v6-05b-pain-cards.png:每张卡「频次 / 严重度 / 解决状态 / 阶段」四列同宽同序 指标缺失显示「—」,不塌列
8 空态说清将来会出现什么 /reports/concept(库里 0 条) 「会出现 / 谁来填 / 对应字段 / 填完后 / 现在能做」五行 + 结论面占位说明
9 长报告章节导航 + 结论摘要 /report/bCld0Iy77e 执行摘要 4 条 → 章节速览 6 条(每章一句,点跳)→ 吸顶导航 6 章(滚动高亮、?ch= 写回)
10 卡片半透明 + blur 生效 computed style background-image 白层 alpha 0.60/0.55,background-color 透明,backdrop-filter: blur(24px) saturate(1.8)
11 边框是渐变 computed style border: 1px solid rgba(0,0,0,0) + 135° 三色渐变作为边框层
12 背景有光场 同一块区域移除卡片前后像素对比 背景 RGB 范围 [244,234,217](有色斑);玻璃卡片平均亮度 239 vs 背景 236
13 三层纵深 面板 / 卡片 / 抽屉的 alpha 0.46 / 0.60–0.55 / 0.85–0.94(截图 11-glass-layers-drawer.png)
14 hover 位移 + 高光 hover 前后 computed translateY(-2px);高光 background-position 120% → -13%;阴影变化
15 对比度 ≥ 4.5:1 verify-glass 逐文字节点 1,856 个节点,最差 4.63:1;verify-browser 另量 460 个节点最差 7.31:1(旧量法按浅色底)
16 截图 6 张 docs/screenshots/ v6-01 中心 · v6-02..06 五类 · v6-07/08 阶段页(全部 / S1)· v6-10 报告页 · 另附 11/12/13(三层 / hover 前后)

截图清单:docs/screenshots/v6-01-reports-center.png、v6-02-type-category.png、v6-03-type-competitor.png、v6-03b-type-competitor-S1.png、v6-04-type-voc.png、v6-05-type-pain.png、v6-05b-pain-cards.png(卡片横向比较)、v6-06-type-concept.png(空态)、v6-07-stages.png、v6-08-stages-S1.png、v6-09-stages-evidence.png、v6-10-report.png、v6-11-concept-empty-plan.png、v6-12-type-filtered.png、11-glass-layers-drawer.png、12-hover-before.png、13-hover-after.png。

8.5 v6 没做什么(明确列出)

  1. 不造业务数据:类型页各块按「库里有什么显示什么」;概念提案 页当前 0 条,显示的是空态说明书,不是假卡片。品类页当前只有 1 条 KfSource,没有「赛道 / SKU / 竞争密度」字段,所以赛道显示为「未归类」——这是如实显示,等别人按 KfSource.payload 灌进来就会按赛道分组。
  2. 流程推进没动:机会卡状态、评分、决策记录、写库逻辑与 v5 完全一致。
  3. VOC 的情感 / 主题 / 人群切分没有自己算:库里的 voc_report 没有这些字段,代码不按标题猜;字段到了就显示,没到显示「未标注」。同理「严重度」没有字段时显示「待标注」。
  4. 类型归属是单值:一份 opportunity_card 只归竞品页,VOC 页里它作为「证据补充」出现;如果客户想把同一份卡同时归到两个类型页,需要在 REPORT_TYPES 里改成多值映射(一行改动)。
  5. 线上部署仍未执行(与 v5 相同):本机没有 OBS 凭据;scripts/deploy.sh 未运行。
  6. jsdom 渲染冒烟在真实 Parse 下偶发卡住:后端抖动时 jsdom 的网络会话偶尔不回调;已提供 src/dev/fixture-server.mjs + --url 快照回放模式(数据来自真实 Parse 的一次原样抓取,不做任何加工,也不生成数据),验收用的就是这一模式。
  7. 「只看我的」在没选「我是谁」时不按人筛(全量显示并在计数旁写「未选人,未按人筛」),不假装筛过。