diff --git a/apps/ai-game-creator-shell/src/view/project-development/resourceBookController.ts b/apps/ai-game-creator-shell/src/view/project-development/resourceBookController.ts index edfedcc9c..41a04cc08 100644 --- a/apps/ai-game-creator-shell/src/view/project-development/resourceBookController.ts +++ b/apps/ai-game-creator-shell/src/view/project-development/resourceBookController.ts @@ -285,7 +285,12 @@ export function createResourceBookTransitionController() { return; } const target = capture(manager); - const keys = new Set([...source.keys(), ...target.keys()]); + // 先按目标场景的 DOM 顺序排,再补上只存在于来源里的 key。层级相同的卡片 + // 由 DOM 顺序决定遮挡关系,顺序不一致会让动画结束的瞬间发生跳变。 + const keys = [ + ...target.keys(), + ...Array.from(source.keys()).filter((key) => !target.has(key)), + ]; if (!target.size) { settle(); return; diff --git a/apps/ai-game-creator-shell/tests/resourceBookController.test.ts b/apps/ai-game-creator-shell/tests/resourceBookController.test.ts index 4d238116f..e041fbf50 100644 --- a/apps/ai-game-creator-shell/tests/resourceBookController.test.ts +++ b/apps/ai-game-creator-shell/tests/resourceBookController.test.ts @@ -178,6 +178,46 @@ describe('resource book FLIP controller', () => { controller.dispose(); }); + it('appends clones in the target DOM order so equal z-index cards keep their occlusion', () => { + Object.defineProperty(Element.prototype, 'animate', { + configurable: true, + writable: true, + value: () => ({ + finished: Promise.resolve({} as Animation), + cancel: () => undefined, + }), + }); + const root = document.createElement('div'); + root.innerHTML = `