From 417b5ec6306a8efedfd33cf1648cae93ad12ad50 Mon Sep 17 00:00:00 2001 From: Suzumiya Date: Mon, 14 Sep 2026 19:25:21 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=8C=E6=95=B4=E7=90=86=E7=94=BB=E5=B8=83?= =?UTF-8?q?=E3=80=8D=E7=A7=BB=E5=85=A5=E8=B5=84=E6=BA=90=E5=8A=A8=E4=BD=9C?= =?UTF-8?q?=E7=B0=87=EF=BC=9A=E6=8E=92=E5=9C=A8=E3=80=8C=E7=94=9F=E6=88=90?= =?UTF-8?q?=E7=B4=A0=E6=9D=90=E3=80=8D=E4=B9=8B=E5=90=8E=EF=BC=8C=E4=B8=8D?= =?UTF-8?q?=E5=86=8D=E6=8C=82=E5=9C=A8=E8=BF=99=E4=B8=80=E8=A1=8C=E8=A1=8C?= =?UTF-8?q?=E5=B0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - index.tsx:把「整理画布」从 game-workbench-view-actions 行尾(排序 tab 之后) 移到「生成素材」之后、「管理未完成编辑」之前,与其它资源动作同类相邻, 标签仍为 aria-label=\"整理画布\",零 CSS 改动 - index.tsx:语义与行为一字未改——disabled={!resourceLayoutReady}、 aria-busy={resourceLayoutSaving}、onClick 仍调 activeResourceLayout.rederiveNow(), 反馈仍走既有 resourceLayoutNotice / resourceLayoutSaving,changed 门保留 - resourceCanvasManualLayout.test.tsx:位置断言改为钉新位置——该行最后一个按钮不是它、 它在「生成素材」之后(previousElementSibling)、在排序组左侧; 继续保留「资源排列方式」组内只有「按依赖 / 按类型」与本按钮不在该组 / 不在 .game-resource-sort-tabs 内的断言 --- .../src/view/project-development/index.tsx | 41 ++++++++++--------- .../tests/resourceCanvasManualLayout.test.tsx | 25 ++++++++--- 2 files changed, 41 insertions(+), 25 deletions(-) diff --git a/apps/ai-game-creator-shell/src/view/project-development/index.tsx b/apps/ai-game-creator-shell/src/view/project-development/index.tsx index 1b03734ec..31e66f0ce 100644 --- a/apps/ai-game-creator-shell/src/view/project-development/index.tsx +++ b/apps/ai-game-creator-shell/src/view/project-development/index.tsx @@ -7152,6 +7152,27 @@ export default function ProjectDevelopmentView({ 生成素材 ) : null} + {/* + 「整理画布」是一枚资源动作,不是第三种排列方式:它排在「生成素材」之后、 + 「管理未完成编辑」之前,与其他资源动作同类相邻,并留在 + `game-workbench-view-actions` 动作区里——外观直接复用该容器既有的动作按钮 + 样式(有边圆角 + secondary 填充),与分段 pill 的模式切换一眼可分;因此不 + 新增任何 CSS。**不要放到这一行的行尾**:行尾会被读成"针对整个工具条"的动作。 + + 画布不再自动重排,整张整理只由这一次显式动作发起:丢掉全部自动坐标、按当前 + 资源与拓扑重算(手动拖过的卡原地不动)。进行中的保存/重算仍然由既有的 + 「保存中 / 布局已保存」状态位反馈。 + */} + {pendingResourceEdits.length > 0 || pendingResourceEditsLoadState === 'failed' ? ( ) : null} diff --git a/apps/ai-game-creator-shell/tests/resourceCanvasManualLayout.test.tsx b/apps/ai-game-creator-shell/tests/resourceCanvasManualLayout.test.tsx index 28132ffc7..4e92d37dc 100644 --- a/apps/ai-game-creator-shell/tests/resourceCanvasManualLayout.test.tsx +++ b/apps/ai-game-creator-shell/tests/resourceCanvasManualLayout.test.tsx @@ -753,7 +753,7 @@ describe('资源画布手动重排口径', () => { expect(typeWrites(tauri)).toHaveLength(1); }); - it('「整理画布」不属于「资源排列方式」这组模式切换,而是一枚独立动作按钮', async () => { + it('「整理画布」不属于「资源排列方式」这组模式切换,而是一枚资源动作按钮', async () => { const projectPath = '/tmp/manual-layout-surface-project'; const tauri = installLayoutTauri({ projectIdsByPath: { [projectPath]: 'manual-layout-surface-project' }, @@ -783,13 +783,28 @@ describe('资源画布手动重排口径', () => { within(sortGroup).queryByRole('button', { name: '整理画布' }), ).toBeNull(); - // 它仍在同一行、仍是同一枚动作按钮,只是搬出了那个 group。 + // 它仍是同一行里的同一枚动作按钮,只是搬出了那个 group、也离开了行尾。 const rederiveButton = screen.getByRole('button', { name: '整理画布' }); expect(sortGroup.contains(rederiveButton)).toBe(false); expect(rederiveButton.closest('.game-resource-sort-tabs')).toBeNull(); - expect( - rederiveButton.closest('.game-workbench-view-actions'), - ).not.toBeNull(); + const actionsRow = rederiveButton.closest('.game-workbench-view-actions'); + expect(actionsRow).not.toBeNull(); + + // 位置:不再是这一行的最后一个按钮(行尾会被读成"针对整个工具条"的动作), + // 紧跟「生成素材」,并且在排序组左侧。 + const rowButtons = Array.from(actionsRow!.querySelectorAll('button')); + expect(rowButtons.at(-1)).not.toBe(rederiveButton); + const rederiveIndex = rowButtons.indexOf(rederiveButton); + const sortGroupIndex = rowButtons.findIndex((button) => + sortGroup.contains(button), + ); + expect(rederiveIndex).toBeGreaterThanOrEqual(0); + expect(sortGroupIndex).toBeGreaterThanOrEqual(0); + expect(rederiveIndex).toBeLessThan(sortGroupIndex); + expect(rederiveButton.previousElementSibling).toBe( + screen.getByRole('button', { name: '生成素材' }), + ); + // 语义没变:可点性只跟布局就绪绑定,布局读完后它就是可点的。 await waitFor(() => expect(