Files
SpineWallpaper/.scratch/build-pipeline/issues/18-panel-preview.md
T
Shuery 3f11426964 feat: TS 构建管线、Spine 抓取器与 wallpapers/ 唯一真相来源
把项目从「手写 dist/」改成「wallpapers/ 是唯一真相来源,dist/ 由 pnpm build 生成」,
并补上配套的类型、门禁与抓取器。一次提交落地整条管线,因为拆开会留下不能构建的中间态。

- src/:运行时与模拟器源码(TS,strict),编译到 build/ 再拷进各分发
- tools/:build / dev / check-{syntax,paths,dist},以及抓取器与回归门禁 tools/checks/
  (.scratch/ 下那批一次性脚本移入 tools/checks/ 并入库为长期门禁)
- wallpapers/:七档壁纸的源数据 + README.md(id/音频/预设的完整规范)
- docs/adr/0005-0008:构建管线与分发拓扑、模拟器契约、自包含 sim、每骨架资源布局
- .gitignore:排除 .scratch/ 的参考资料副本(上游 spine 整仓克隆 ~1.2 GB、
  抓取侦查数据 ~680 MB)与调试转储;这些是本地调查材料,补偿会让仓库无法克隆
- 归一化 .gitignore/CONTEXT.md 行尾(工作区 CRLF、索引 LF 造成的整文件假 diff)

同时修掉三档卡住构建的未完工壁纸:
- kv45 的 meta.json 里 id 还是抓取期场景名 scene_main,经 downloader promote 正名为 kv45
- shajin / zhigengniao_juheye 的 meta.json 误用了骨架描述文件(name/spine/animations/pages)、
  且都缺 preset.template.json;现按规范重建:骨架沉到 spines/<名>/(spine-ts 按 atlas 所在
  目录解析贴图页)、补上元数据与单骨架预设,并清掉 zhigengniao 骨架里指向作者机的绝对路径
- 顺带 promote 已在 sources.yml 里的 kv46(月升之前,与兽共舞)

pnpm check 五道门全绿:10 个分发 / 7 档壁纸 / 141 处引用自包含。
2026-10-02 01:27:02 +08:00

4.6 KiB
Raw Blame History

18 — 设置面板上方的预览图

Status: resolved Type: task

需求

wallpaper engine 的设置面板上方是会展示 preview.gif 的,你确认一下之前给的截图中的样式,还原一下

先量,再写

用户第一张截图还在 attachments 里,我直接把它读回来、裁出预览区放大 3 倍看,并逐像素采样取几何与配色—— 而不是凭记忆估:

量到的东西 值
面板底色 #222222
预览区左右内缩 各 20px(内容宽 298,高 237 ≈ 5:4)
箭头按钮 36×26 的 #3c3c3c 方块
箭头字形 #4082f5 的 ‹ ›(蓝色,不是白色)
箭头位置 贴预览的左右边缘、距预览底 26px
预览图本体 preview.gif 是 160×160(方形),面板里按 5:4 裁切显示

左右箭头:量到了,但最后去掉了

我一开始照着截图把那对箭头也做了出来,用"切换本分发的预设"当最近的对应。用户随后指出:

预览图上的上一个、下一个按钮在 wallpaper engine 中是切换壁纸用的,我们不需要,直接把那两按钮去掉

判断是对的,而且理由比"不需要"更硬:

  • WE 那对箭头切的是已安装的壁纸列表,模拟器里没有那个列表——所谓"最近的对应"其实是另一件事。
  • 面板上本来就有「壁纸预设切换」下拉,两个箭头只是重复。
  • 更糟的是它会误导:看起来像在切壁纸,实际切的是预设。

所以 CSS 与 DOM 一起删掉,并在 verify-panel.mts 里留了一条防回归断言(navs.length === 0), 免得以后又照着截图把它加回来。

那个 3 倍放大的裁剪图留在 .scratch/shots/ref-preview-area.png,以后要再核对就用它。 (注意:那张图里有箭头——它是官方原样,不是我们的目标形态。)

打通链路

预览图不被 preset.js 引用,所以它不在原有的资源收集范围里,得单独接:

  1. project.json 的 preview → 驱动(SIMULATOR_DRIVER)多带一个 preview 字段
  2. 三条注入路径都要传:调试服(dev.ts)、静态构建(build.ts 的 renderIndexHtml)、自包含包(bundle.ts)
  3. 面板渲染预览区;URL 走与运行时同一套解析(__simAssetRoot + __simSwap)
  4. collectAssets 把预览图也内联成 data: URL

第 2 步我漏了自包含包那一处,于是自包含页的预览区整块不出现。补上后才对。

为什么自包含包必须内联它

自包含页在 <分发根>/sim/ 下,而预览图在 <分发根>/preview.gif。 file:// 下 ../preview.gif 是跨目录读取,浏览器直接拒绝——所以只能内联成 data: URL。 这和别的资源是同一个理由,不是额外讲究。

三个分支都验过

分发 有 preview 结果
collection-all ✓ 预览区在,图片解码出 160×160,箭头可用
single-hsr-xilian ✓ 同上
single-hsr-kv37 ✗ 整块不出现(与发布产物一致:project.json 里没有 preview)
collection-hsr ✗ 同上

自包含包里:data: URL + 能解码。静态托管(--with-sim)下:子路径里 0 个 404。

左右箭头(已去掉,见上)

官方那两个箭头是切换"已安装的壁纸"。这里切本分发的预设——语义最近的对应: 读 preset combo 的 options,点一下切到上一个/下一个,单档分发(连 preset 属性都没有)两个都禁用。

验证

tools/checks/verify-panel.mts 第 ⑪ 组 + tools/checks/verify-sim-page.mts 的新断言,全绿:

  • 预览区已渲染、src 指向分发根的 preview.gif、naturalWidth 真的是 160×160(不是坏图)
  • 预览上没有左右箭头(防回归:它们曾经存在过)
  • 自包含页:src 是 data: 且能解码

其余回归全绿:pnpm check、调试服与浏览器冒烟、面板还原度、热更新、开发模式构建开关、 test-props / test-resize / test-acceptance / verify-fitter、sim 门禁、内联守卫、模块改写、 6 组渲染逐像素相同、diff-project 仍是 14 处(预览改动没有动发布产物)。

两个环境注意

  • 内联守卫测试会改 src/vendor/spine-player.js,而调试服的热更新在监听 src/—— 两者会抢构建,跑那个测试时要先停调试服。同理 pnpm build sim 与 watcher 也会抢 dist/。
  • pnpm build:sim 只编译模拟器(tsc),不产出 sim 页;改完面板要跑 pnpm build sim 才会重新内联。