修复「所有资源」页面缩放读取错误视口

展开态缩放、滚轮、平移和卡片拖动改读 all 专用内存视口 ref

避免复用普通栏目页视口导致按钮按下后倍率被旧状态覆盖

补充所有资源连续缩放 appSurface 回归断言,并同步更新项目决策与踩坑记录
This commit is contained in:
2026-09-12 12:25:27 +08:00
parent 3f7e41e466
commit 349c9d80ce
4 changed files with 46 additions and 4 deletions
@@ -4236,7 +4236,9 @@ export default function ProjectDevelopmentView({
if (!category) {
return;
}
const viewport = resourceCanvasViewportRef.current;
const viewport = resourceBookOpensAllResources
? resourceBookAllViewportRef.current
: resourceCanvasViewportRef.current;
const next = zoomResourceBookViewport(viewport, factor, {
x: anchorX,
y: anchorY,
@@ -4312,7 +4314,9 @@ export default function ProjectDevelopmentView({
return;
}
const result = resolveResourceBookWheelViewport({
viewport: resourceCanvasViewportRef.current,
viewport: resourceBookOpensAllResources
? resourceBookAllViewportRef.current
: resourceCanvasViewportRef.current,
deltaX: event.deltaX,
deltaY: event.deltaY,
shiftKey: event.shiftKey,
@@ -4422,7 +4426,10 @@ export default function ProjectDevelopmentView({
) {
return;
}
const scale = resourceCanvasViewportRef.current.scale;
const scale = (resourceBookOpensAllResources
? resourceBookAllViewportRef.current
: resourceCanvasViewportRef.current
).scale;
if (!Number.isFinite(scale) || scale <= 0) {
return;
}
@@ -4580,7 +4587,9 @@ export default function ProjectDevelopmentView({
category: canvasTarget,
startClientX: event.clientX,
startClientY: event.clientY,
startViewport: resourceCanvasViewportRef.current,
startViewport: resourceBookOpensAllResources
? resourceBookAllViewportRef.current
: resourceCanvasViewportRef.current,
};
return;
}
@@ -9620,6 +9620,23 @@ export function registerProjectAgentStatusTests() {
),
).not.toBeNull(),
);
// 「所有资源」展开态必须复用自己的内存视口:缩放按钮不能拿当前栏目页的旧 ref,
// 否则按钮看起来按了但缩放落点/倍率会回到另一份视口状态。
const allSceneWorld = document.querySelector<HTMLElement>(
'[data-resource-book-view="child"] .game-resource-book-scene-world',
);
expect(allSceneWorld).not.toBeNull();
const allTransformBeforeZoom = allSceneWorld?.style.transform;
fireEvent.click(screen.getByRole('button', { name: '放大画布' }));
await waitFor(() =>
expect(allSceneWorld?.style.transform).not.toBe(allTransformBeforeZoom),
);
// 旧实现第二次点击仍可能使用栏目页 ref;连续点击必须继续推进 all 视口。
const allTransformAfterZoom = allSceneWorld?.style.transform;
fireEvent.click(screen.getByRole('button', { name: '放大画布' }));
await waitFor(() =>
expect(allSceneWorld?.style.transform).not.toBe(allTransformAfterZoom),
);
// 旧的分组网格宿主与网格容器一个都不该再存在;改回旧分支时这三条会立刻红。
expect(
document.querySelector('[data-resource-book-all-host="true"]'),
@@ -8478,3 +8478,11 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
- 验证方式:① 单测 `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 + 分带偏移",本条只改"展开态出不出栏目标题栏"。
## 2026-09-12 「所有资源」交互读取独立内存视口:缩放、滚轮、平移不能复用栏目页 ref
- 背景:上一条决策把「所有资源」定义成一张平铺画布,并明确它没有独立持久化空间;因此它仍需要一份只存在内存中的 `resourceBookAllViewport`,不能塞进按真实栏目键的 `resourceCanvasViewports`
- 决策:展开态所有需要读取当前子画布视口的动作(按钮缩放、滚轮缩放/平移、卡片拖动的缩放换算、画布平移起点)统一读取 `resourceBookAllViewportRef`;普通栏目页继续读取 `resourceCanvasViewportRef`。写侧继续通过 `setResourceCanvasViewport('all', ...)` 进入 all 内存状态,不增加 sidecar 分区或第二套坐标空间。
- 原因:如果读侧沿用栏目 ref,动作会基于最近栏目页的旧缩放/平移值计算,再写入 all;数值碰到缩放边界时用户看到的就是「按钮按了但不动」,且拖动距离也会按错误倍率换算。
- 验证:appSurface 的多栏目「所有资源」用例连续点击两次放大;四处 ref 选择全部变异回旧实现后第二次点击断言红灯,恢复后通过。定向类型检查与 ESLint 均通过。
- 影响范围:`apps/ai-game-creator-shell/src/view/project-development/index.tsx``apps/ai-game-creator-shell/tests/appSurface/project-development.suite.ts``pitfalls.md` 本条。
@@ -5363,3 +5363,11 @@
- **处理**:让"该不该有这个节点"显式化,而不是靠"矩形取不到就兜底":`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 条。
## 2026-09-12 「所有资源」缩放拿错视口 ref:按钮能触发但倍率被另一份栏目视口覆盖
- **现象**:「所有资源」展开页点击放大/缩小后看起来不动,或倍率跳回栏目页当前值;滚轮缩放、画布平移和卡片拖动也可能出现同类落点异常。
- **原因**:展开页的视口是独立的内存态 `resourceBookAllViewportRef`,但缩放/滚轮/拖动起算仍读取普通栏目页的 `resourceCanvasViewportRef`。两份 ref 在首次进入或最近切过栏目后数值可能不同,导致 all 页动作以另一张画布的旧值计算,再写回 all 视口;当旧值已在边界时就表现为「按不动」。
- **处理**:所有需要读取当前子画布视口的交互都按目标选择 ref:`resourceBookOpensAllResources` 时读取 `resourceBookAllViewportRef`,栏目页才读取 `resourceCanvasViewportRef`;写回仍统一经过 `setResourceCanvasViewport`,不新增持久化空间。
- **验证**appSurface 的「所有资源」用例新增连续两次点击放大断言;把四处 all ref 选择变异还原为旧的 `resourceCanvasViewportRef` 后,该用例在第二次点击处红,显示 transform 未变化;恢复后用例通过。
- **关联**`apps/ai-game-creator-shell/src/view/project-development/index.tsx``apps/ai-game-creator-shell/tests/appSurface/project-development.suite.ts``decision-log.md` 2026-09-12 条。