diff --git a/apps/ai-game-creator-shell/src/styles.css b/apps/ai-game-creator-shell/src/styles.css index 991d3314e..031b3fe47 100644 --- a/apps/ai-game-creator-shell/src/styles.css +++ b/apps/ai-game-creator-shell/src/styles.css @@ -7088,8 +7088,16 @@ iframe.preview-frame { /* 审批卡是这一列里唯一没有天花板的成员:Fast GDD 的决定项越多它越高,能把消息列表和运行 时面板一起挤出可视区。和 `.agent-runtime-status` 一样给它自己的上限加内部滚动,而不是 让它去挤别人。 */ +/* 这个面不参与 flex 压缩。它自己不会长高:标题栏是固定几行,审批卡下面有自己的 + max-height 和内滚,所以高度天然有界。让它可压缩的话,`overflow: hidden`(画圆角 + 要的)会把底部切掉——批准后交付行正好在那儿,表现是路径和两个按钮凭空消失。 */ .game-workbench-chat .plan-gdd-surface { - flex: 0 1 auto; + flex: 0 0 auto; +} + +/* 只有审批卡在场时才需要「标题栏定高 + 正文占余下」的两行轨道。批准后卡片收掉, + 面里只剩标题栏,这条声明会给它套上一个不存在的第二行。 */ +.game-workbench-chat .plan-gdd-surface--with-card { min-height: 0; grid-template-rows: auto minmax(0, 1fr); } diff --git a/apps/ai-game-creator-shell/tests/appSurface/project-development.suite.ts b/apps/ai-game-creator-shell/tests/appSurface/project-development.suite.ts index 7c65cfb49..75b65c8cc 100644 --- a/apps/ai-game-creator-shell/tests/appSurface/project-development.suite.ts +++ b/apps/ai-game-creator-shell/tests/appSurface/project-development.suite.ts @@ -816,7 +816,9 @@ export function registerProjectWorkbenchFoundationTests() { 'workbench-art-viewport-memory', '美术资源视口记忆', ); - const codeTask = manifest.tasks.find((task) => task.id === 'code-prototype'); + const codeTask = manifest.tasks.find( + (task) => task.id === 'code-prototype', + ); expect(codeTask).toBeDefined(); codeTask!.status = 'completed'; manifest.assets = [ @@ -1114,7 +1116,9 @@ export function registerProjectWorkbenchFoundationTests() { ).not.toBeNull(); fireEvent.click(within(outline).getByRole('button', { name: /设计文档/ })); - dispatchPageWheel(screen.getByRole('button', { name: /下一页\s*美术资源/ })); + dispatchPageWheel( + screen.getByRole('button', { name: /下一页\s*美术资源/ }), + ); expect( screen.getByRole('region', { name: '美术资源资源画布' }), ).not.toBeNull(); @@ -1177,9 +1181,7 @@ export function registerProjectWorkbenchFoundationTests() { name: /打开资源详情:设计文档 section\.md/, }), ); - expect( - screen.getByRole('dialog', { name: 'section.md' }), - ).not.toBeNull(); + expect(screen.getByRole('dialog', { name: 'section.md' })).not.toBeNull(); dispatchPageWheel(dependencyCanvas); expect( screen.getByRole('region', { name: '美术资源资源画布' }), @@ -1321,9 +1323,7 @@ export function registerProjectWorkbenchFoundationTests() { }), ); }); - fireEvent.click( - within(outline).getByRole('button', { name: /项目版本/ }), - ); + fireEvent.click(within(outline).getByRole('button', { name: /项目版本/ })); await act(async () => { await new Promise((resolve) => setTimeout(resolve, 220)); }); @@ -1331,9 +1331,7 @@ export function registerProjectWorkbenchFoundationTests() { screen.getByRole('region', { name: '项目版本资源画布' }), ).not.toBeNull(); - fireEvent.click( - within(outline).getByRole('button', { name: /设计文档/ }), - ); + fireEvent.click(within(outline).getByRole('button', { name: /设计文档/ })); act(() => { dependencyCanvas.dispatchEvent( new WheelEvent('wheel', { @@ -3747,10 +3745,7 @@ export function registerProjectWorkbenchFoundationTests() { '[data-resource-viewport]', ); const viewportScale = Number( - viewportElement - ?.getAttribute('data-resource-viewport') - ?.split(',') - .at(2), + viewportElement?.getAttribute('data-resource-viewport')?.split(',').at(2), ); expect(viewportScale).toBeGreaterThan(0); const expectedX = Math.round(12 + (-100 - 20) / viewportScale); @@ -4191,6 +4186,20 @@ export function registerProjectWorkbenchFoundationTests() { expect(styles).toMatch( /\.game-workbench-chat \.planning-lane-runtime-strip\s*\{[^}]*max-height:\s*clamp\([^)]*\)/s, ); + // 策划面画圆角要 `overflow: hidden`,所以它绝不能参与 flex 压缩:一旦可压缩,被压到 + // 内容高度以下时裁掉的正是最底下那行——批准后的交付出口(路径 + 两个按钮)就这么 + // 凭空消失过一次。它也不需要可压缩,审批卡自己有上限和内滚,高度天然有界。 + const planGddSurfaceRule = styles.match( + /\.game-workbench-chat \.plan-gdd-surface\s*\{[^}]*\}/s, + ); + expect(planGddSurfaceRule).not.toBeNull(); + expect(planGddSurfaceRule?.[0]).toMatch(/flex:\s*0 0 auto/); + // 「标题栏定高 + 正文占余下」的两行轨道只在审批卡在场时成立;批准后面里只剩标题栏, + // 套上不存在的第二行只会让它错位。 + expect(planGddSurfaceRule?.[0]).not.toMatch(/grid-template-rows/); + expect(styles).toMatch( + /\.game-workbench-chat \.plan-gdd-surface--with-card\s*\{[^}]*grid-template-rows:\s*auto minmax\(0, 1fr\)/s, + ); expect(styles).toMatch( /\.game-workbench-chat \.project-runtime-summary\s*\{[^}]*position:\s*sticky[^}]*top:\s*-10px/s, );