Files
SpineWallpaper/.scratch/build-pipeline/issues/19-single-bgm-missing.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

92 lines
3.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 19 — 单档分发里没有「背景音乐选择」
Status: resolved
Type: bug
## 现象
> 昔涟内有两首背景音乐,怎么没有看到切换选项?
`wallpapers/hsr/xilian/meta.json` 里确实声明了两首(「再度和你」/「昔涟」),
但 `single-hsr-xilian` 的 `project.json` 里**根本没有 `bgm` 属性**,所以那档分发里没有切换入口。
## 根因
`tools/lib/generate.ts` 里:
```ts
if (!isCollection) {
// 单档分发:只剩一档壁纸,"壁纸预设切换"没有意义。整条属性删掉
delete properties.preset;
delete properties.preset_note;
delete properties.bgm; // ← 问题在这一行
delete properties.bgm_note;
}
```
那句注释对**预设切换**成立——只剩一档壁纸,切预设确实没意义。
但它对**背景音乐**不成立:**一档壁纸照样可以带好几首曲子**。两件事被一起删了。
而且 `bgm` 的选项只在 `else`(合集)分支里算,所以即使只删掉 delete,下拉也会是空的。
## 改法
把 `bgmOptions` 的计算提到分支**之外**(单档合集都要算),再按内容决定留不留:
```ts
if (isCollection) {
// preset 的选项照旧
} else {
delete properties.preset;
delete properties.preset_note;
}
// 只剩"随预设"+ 至多一首时这个下拉是句废话(两个选项效果完全一样),删掉。
if (bgmOptions.length <= 2) {
delete properties.bgm;
delete properties.bgm_note;
} else {
(properties.bgm as ComboProperty).options = bgmOptions;
properties.bgm = orderProperty(...);
}
```
结果:
| 分发 | 音源数 | bgm |
| --- | --- | --- |
| `single-hsr-xilian` | 2 | **有**:随预设 / 「再度和你」 / 昔涟 |
| `single-hsr-kv37` | 1 | 没有(两个选项效果一样,是废话) |
| `collection-hsr` / `collection-all` | 3 | 有(不变) |
`collection-all` 的产物**逐字段未变**:`diff-project` 仍是 14 处差异,与本次无关。
## 为什么之前没人发现
**没有任何断言盯着"用户能不能切歌"这件事。** `test-props.mjs` 验的是 bgm 的**语义**
(选择、跨壁纸回落、优先级),它跑在 `collection-all` 上——那里 bgm 一直是好的。
`test-acceptance.mjs` 也只断言合集分发"bgm 含「随预设」档"。
所以这是一个**只影响单档分发、且只在用户实际去看的时候才暴露**的缺陷。
## 验证
新增两层,都盯着"用户能不能切":
- `tools/checks/verify-panel.mts` 第 ⑫ 组(浏览器,端到端):
- `single-hsr-xilian` 有「背景音乐选择」,下拉里就是 `随预设 / 「再度和你」 / 昔涟`
- 默认值是 `auto`(随预设)——与合集分发一致,不是"第一首"
- `single-hsr-kv37` **没有**这个下拉(只有一首)
- `tools/checks/check-single-bgm.mts`(**选项在 ≠ 切得动**):
在 `single-hsr-xilian` 里选「昔涟」→ `<audio>.src` 真的变成 `xilian-src.flac`;再选回来 → 变回去。
其余回归全绿:`pnpm check`、调试服与浏览器冒烟、四档自包含包、静态托管预览、sim 门禁、
内联守卫、`test-props` / `test-resize` / `test-acceptance` / `verify-fitter`、
6 组渲染逐像素相同。
## 一点反思
「单档分发只剩一档壁纸,所以切换类的东西都没意义」是个**看起来对、实际不对**的推理:
它把"壁纸维度的切换"和"音源维度的切换"混成了一个。加属性时如果顺手问一句
"这条属性删掉之后,哪个用户可见的功能会消失",就能避免。