diff --git a/apps/ai-game-creator-shell/src/styles.css b/apps/ai-game-creator-shell/src/styles.css index 046a93732..ba86fce33 100644 --- a/apps/ai-game-creator-shell/src/styles.css +++ b/apps/ai-game-creator-shell/src/styles.css @@ -7517,11 +7517,21 @@ iframe.preview-frame { 所以列表上那个 `padding-bottom: 196px`(本意是给「浮起来的输入框」留位)从来没有对应 的定位规则,那个模型压根没成立过。 - `:has(.plan-gdd-surface)` 只在策划面在场时命中,做游戏与做素材保持 master 的 block - 列原样不动。用 flex 列而不是 grid:子元素个数随待确认命令的有无浮动,固定行模板会 - 错位;而且下面那条 `.plan-gdd-surface { flex: 0 0 auto }` 本来就是照 flex 写的,容器 - 变成 flex 之后它才真正生效——在此之前它一直是死声明。 */ -.game-workbench-chat .project-supervisor-conversation:has(.plan-gdd-surface) { + 命中判据是两个类的并集,两个都只属于策划链路,做游戏与做素材保持 master 的 block + 列原样不动。为什么不能只认策划面:`PlanGddSurface` 在 `planGddState === null` 时整个 + 返回 null,而 `planGddState` 初值就是 null、要靠一次独立的 IPC 才填上。首帧竞态、以及 + hydrate 持续失败时,策划 run 照跑、澄清卡照渲染,只认策划面就会漏掉这一格,裁剪原样 + 复发。窄条自己在场就等价于「有东西要用户动手」,把它并进来之后,「卡片存在」和「列 + 布局生效」才是同一件事。 + + 用 flex 列而不是 grid:子元素个数随待确认命令的有无浮动,固定行模板会错位;而且下面 + 那条 `.plan-gdd-surface { flex: 0 0 auto }` 本来就是照 flex 写的,容器变成 flex 之后它 + 才真正生效——在此之前它一直是死声明。 */ +.game-workbench-chat + .project-supervisor-conversation:has( + .plan-gdd-surface, + .planning-lane-runtime-strip + ) { display: flex; flex-direction: column; gap: 10px; @@ -7535,7 +7545,10 @@ iframe.preview-frame { 输入框定高),由列表吸收剩余空间。`height: 100%` 必须撤掉,否则它照旧独吞整列; `padding-bottom` 也一并收回,输入框已经回到文档流里,不再需要给它留空。 */ .game-workbench-chat - .project-supervisor-conversation:has(.plan-gdd-surface) + .project-supervisor-conversation:has( + .plan-gdd-surface, + .planning-lane-runtime-strip + ) .project-supervisor-message-list { flex: 1 1 auto; height: auto; @@ -7547,13 +7560,22 @@ iframe.preview-frame { /* 这三个成员不参与压缩:消息列表变长时不能把它们挤没——它们正是用户唯一需要动手的 地方(澄清卡、输入框)。 */ .game-workbench-chat - .project-supervisor-conversation:has(.plan-gdd-surface) + .project-supervisor-conversation:has( + .plan-gdd-surface, + .planning-lane-runtime-strip + ) .planning-lane-runtime-strip, .game-workbench-chat - .project-supervisor-conversation:has(.plan-gdd-surface) + .project-supervisor-conversation:has( + .plan-gdd-surface, + .planning-lane-runtime-strip + ) .project-supervisor-composer, .game-workbench-chat - .project-supervisor-conversation:has(.plan-gdd-surface) + .project-supervisor-conversation:has( + .plan-gdd-surface, + .planning-lane-runtime-strip + ) .project-supervisor-workspace-status { flex: 0 0 auto; } diff --git a/apps/ai-game-creator-shell/tests/appSurface/plan-gdd.suite.ts b/apps/ai-game-creator-shell/tests/appSurface/plan-gdd.suite.ts index d6ed7813b..fd20d253e 100644 --- a/apps/ai-game-creator-shell/tests/appSurface/plan-gdd.suite.ts +++ b/apps/ai-game-creator-shell/tests/appSurface/plan-gdd.suite.ts @@ -578,5 +578,13 @@ export function registerPlanGddApprovalTests() { expect(styles).toMatch( /\.game-workbench-layout\.is-conversation-only \.game-workbench-stage\s*\{[^}]*display:\s*none/s, ); + // 工作台里的会话列是 `overflow: hidden` 的定高列。策划链路比另外两条多出窄条 + // (澄清卡 / 失败恢复),只有把这一列排成 flex 列、窄条不参与压缩,它才落在可视 + // 区里;否则组件照常渲染却被静默裁到线外,屏幕上什么都没有。命中判据必须包含窄条 + // 自身——只认 `.plan-gdd-surface` 时,`planGddState` 还没 hydrate 出来的那一格里 + // 澄清卡照样被裁。 + expect(styles).toMatch( + /\.game-workbench-chat\s+\.project-supervisor-conversation:has\([^)]*\.planning-lane-runtime-strip[^)]*\)\s*\{[^}]*display:\s*flex/s, + ); }); }