「所有资源」展开态改回平铺画布:不再为每个栏目渲染标题栏
Project CI / Repository checks (pull_request) Successful in 2m50s
Project CI / Frontend tests (pull_request) Successful in 3m19s
Project CI / Backend tests (pull_request) Successful in 7m23s
Project CI / Native shell tests (pull_request) Successful in 19m4s

展开态真实栏目不再渲染栏目标题栏,整个场景只留 all 那一条钉在视口上、带「资源总览」收起入口的标题栏

原因是分带只为有可见资源的栏目生成,空栏目拿不到标题栏矩形后全部回落到世界原点叠成一摞(空项目必现,现场是 7 条)

ResourceBookSceneCategoryPlan 新增 titlebar 字段,渲染层按它决定是否产出标题栏节点

分带去掉标题栏横带的高度预留与矩形换算,删除 RESOURCE_BOOK_ALL_BAND_TITLE_HEIGHT 与 resourceBookAllTitlebarRects

拖动写回口径不变(resourceBookAllBandLocalPoint 一行未改),零 CSS 变更

resourceBookLayout.test 与 appSurface 两条「所有资源」用例加反向守卫;变异验证改回旧行为时两条同时红(got 7)

decision-log 与 pitfalls 记这次倒因为「缺一路坐标输入时不要静默回落到原点」
This commit is contained in:
2026-09-12 09:38:03 +08:00
parent 5b62d1e4ef
commit 3f7e41e466
7 changed files with 114 additions and 115 deletions
@@ -8469,3 +8469,12 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
- 与"历史手动坐标只读恢复、不删除、不重置、不迁移"的关系:**不冲突**。写侧只做"把这一张卡在它自己栏目里的坐标设为手动 + 新 x/y",正是栏目页拖动的同一操作(`moveResourceCanvasPosition` 只改该 `(resourceId, section)` 一条并置 `manuallyPlaced: true`);读时归并(`normalizeResourceCanvasPosition`)与"不触发 automatic 重排"的既有口径都未改动。
- 验证方式:`resourceBookAllBandLocalPoint` 两条单测(减带原点 / 栏目页与无带时原样返回);变异验证:去掉减带原点 → 用例红(实测 `{x:100,y:260}` vs 期望 `{x:100,y:160}`)。真机判据(用户可自证"同一份数据"):在展开态把某张卡拖到新位置 → 进它所属栏目页,同一张卡就在新位置;反向在栏目页拖一张 → 回展开态看它在带内同步。
- 关联文档:`docs/technical/【测试用例】AGC资源工作台V3端到端验收-2026-09-11.md`S7 判据含这条往返)、`apps/ai-game-creator-shell/src/view/project-development/{useProjectResourceCanvasLayout.ts,resourceBookLayout.ts,index.tsx}`
## 2026-09-12 「所有资源」展开态去掉每栏一条标题栏:那一页是一张平铺画布,只留 `all` 那一条
- 背景:用户报「所有资源里的 UI 样式有点问题,还有,我希望这里面所有资源都平铺开,和其他普通画布一样」。真机截图(空项目、0 项)里画布中央浮着一块带阴影的「项目版本 0 项」面板,其余栏目看不见——这就是上一版"每条分带配一条标题栏"的直接后果:**分带只对"有可见资源"的栏目生成**(`buildResourceBookAllLayout``resources.length === 0 → continue`),而标题栏矩形只从分带里取(旧 `resourceBookAllTitlebarRects`),于是空栏目的标题栏拿不到矩形,全部回落到 `ResourceBookScene``rect?.left ?? 0 / rect?.top ?? 0 / width ?? 280px` 默认值 ⇒ **7 个真实栏目的标题栏在世界原点叠成一摞**,最后画的那个(栏目顺序末位)浮在最上面。空项目恰恰是必现现场:一条带都没有。
- 决策:**展开态的真实栏目不再渲染栏目标题栏**(`ResourceBookSceneCategoryPlan` 新增 `titlebar: boolean`,展开态真实栏目为 `false`),整个场景只留 `all` 那一条钉在视口上、带「资源总览」收起入口的标题栏。于是「所有资源」在结构上与栏目页完全同形:**一条钉住的标题栏 + 一张平铺的画布**(点阵底、卡片可拖、可滚轮缩放平移、可框选),不再有"每组一个浮动面板"。分带保留(它仍是"局部坐标 → 世界坐标"的唯一偏移,见 2026-09-11 那条拖动写回决策),但带内**只剩卡片**:删掉标题栏横带的高度预留(`RESOURCE_BOOK_ALL_BAND_TITLE_HEIGHT`)与它的矩形换算(`resourceBookAllTitlebarRects`),带原点直接等于游标,带间距就是 `RESOURCE_BOOK_ALL_BAND_GAP`
- 不做什么:不动总览态与栏目态(两者每一组都要标题栏:总览态靠它承载计数徽标,栏目态靠它承载当前栏目与返回入口);不动拖动写回口径(`resourceBookAllBandLocalPoint` 一行未改);不动转场层;**零 CSS 变更**(`.game-resource-book-scene-titlebar` 规则全部保留,只是展开态少渲染几个节点)。
- 验证方式:① 单测 `resourceBookLayout.test` 钉住"展开态真实栏目 `titlebar === false``all``true`",并删掉只服务旧标题栏矩形的断言与那个已不存在的导出;② appSurface 两条「所有资源」用例各加一条反向守卫 `document.querySelectorAll('.game-resource-book-scene-titlebar:not([data-resource-book-category="all"])')` 长度为 0(空项目那条正是用户现场);③ **变异验证(已实测红灯)**:把展开态真实栏目的 `titlebar` 改回 `true` → 两条守卫同时红,报 `expected … to have a length of +0 but got 7`——这个 `7` 就是七个真实栏目叠在原点的实证。
- 影响范围:`apps/ai-game-creator-shell/src/view/project-development/{resourceBookLayout.ts,index.tsx}``apps/ai-game-creator-shell/tests/{resourceBookLayout.test.ts,appSurface/project-development.suite.ts}``docs/technical/【测试用例】AGC资源工作台V3端到端验收-2026-09-11.md`S7 行措辞)。
- 关联:本条**收窄**(不推翻)2026-09-11 的「所有资源」页画本场景决策:那一条定的是"同一套场景 + 同一颗 renderCard + 分带偏移",本条只改"展开态出不出栏目标题栏"。
@@ -5354,3 +5354,12 @@
- **处理**:push 前按链路逐条跑,不要只跑子集;`&&` 链在某一步失败时,**必须把失败步之后的每一步单独再跑一遍**(上列 10 步 + `git diff --check`),逐条记 exit code(取 exit code 不要接管道)。凡改动碰到 `package.json` / `.husky/` / `scripts/` 下的门禁资产,**`check:git-hooks` 是必跑项**——它钉住 hook 与 lint-staged 配置的形状,增删键都会让它以 `deepStrictEqual` 失败。
- **验证**:本次 `check:git-hooks` 因本机 Windows EBUSY 中断后,把其后各步单独跑齐:`check:spacetime-schema` / `check:production-ops` / `check:preview-deployer` / `check:maintenance-page` / `lint:eslint` / `typecheck` / `check:encoding` 全部 `exit 0` —— 即「因为前一步红而没跑到」的部分本来是全绿的;只有 `check:rustfmt` 红,且红在别人在途的 `.rs``assets.rs:519` 落在其未提交 hunk `+470,62``commands.rs:3079` 落在其未提交 hunk `+3068,58`)。变异验证:把 `*.rs``package.json` 摘掉 → `check:git-hooks` 第 1 个用例以同样的 `deepStrictEqual` operator 变红(`# fail 2`);还原(`package.json` SHA256 与改前一致)后该用例回 `ok`
- **关联**`package.json``lint` / `check:git-hooks` / `check:rustfmt``scripts/check-repository-ci.sh``scripts/git-hooks.test.mjs``.husky/pre-commit`、提交 `dd7cf401a` / `2a7bfadd7` / `15660a98b`
## 2026-09-12 「矩形从哪来」缺一路输入时,别让它静默回落到世界原点:7 条栏目标题栏在空项目里叠成一摞
- **现象**:空项目(0 项)进「所有资源」,画布正中央浮着一块带阴影的「项目版本 0 项」面板,其余六个栏目看不见——用户报"UI 样式有点问题"。它们并不是被谁隐藏,而是**七块面板叠在同一个位置**,只看得见最后渲染的那一块。
- **原因**`ResourceBookScene` 的栏目标题栏位置只有一路输入 `overviewRects.get(category)`,取不到就用 `rect?.left ?? 0 / rect?.top ?? 0 / width ?? 280px` 兜底。而展开态这一路输入来自分带矩形(旧 `resourceBookAllTitlebarRects`),分带又只对**有可见资源**的栏目生成(`buildResourceBookAllLayout``resources.length === 0 → continue`)⇒ 空栏目永远拿不到矩形,全部回落到世界原点;栏目顺序七项,最后画的「项目版本」压在最上面。空项目是必现现场(一条带都没有),用户截图正是这种。
- **识别特征**:出现的不是"某一个错位面板",而是**栏目顺序里最后一项**的名字(本例 = 栏目顺序末位「项目版本」),且它随视口平移一起动 —— 即"坐标系原点上的同类节点堆叠",而不是定位算错。
- **处理**:让"该不该有这个节点"显式化,而不是靠"矩形取不到就兜底":`ResourceBookSceneCategoryPlan``titlebar: boolean`,展开态的真实栏目为 `false`(那一页只留 `all` 一条钉住的标题栏),渲染层按它决定是否产出节点;同时删掉只服务旧形态的 `RESOURCE_BOOK_ALL_BAND_TITLE_HEIGHT` / `resourceBookAllTitlebarRects`。**`?? 0` 兜底本身不是错,错在它同时承担"没有布局信息"和"布局信息恰好是原点"两种语义**——凡是一个坐标有多路来源(测量 / 计算 / 静态),缺某一路时要么显式不渲染,要么让缺路成为可观测的信号,不要静默给默认值。
- **验证**appSurface 两条「所有资源」用例加反向守卫 `querySelectorAll('.game-resource-book-scene-titlebar:not([data-resource-book-category="all"])')` 长度为 0(含空项目那条);变异验证:把展开态真实栏目的 `titlebar` 改回 `true` → 两条同时红,报 `expected … to have a length of +0 but got 7`(7 = 七个真实栏目,实证是"一摞"而不是"一个错位框")。
- **关联**`apps/ai-game-creator-shell/src/view/project-development/{resourceBookLayout.ts,index.tsx}``apps/ai-game-creator-shell/tests/{resourceBookLayout.test.ts,appSurface/project-development.suite.ts}``decision-log.md` 2026-09-12 条。