From 40e2a1b9b1180ebda421f152b4d907e7913885b6 Mon Sep 17 00:00:00 2001 From: Suzumiya Date: Mon, 14 Sep 2026 23:33:32 +0800 Subject: [PATCH] =?UTF-8?q?AGC=20=E8=B5=84=E6=BA=90=E5=B7=A5=E4=BD=9C?= =?UTF-8?q?=E5=8F=B0=E5=B7=A5=E5=85=B7=E6=9D=A1=EF=BC=9A=E6=8A=8A=E5=B8=83?= =?UTF-8?q?=E5=B1=80=E7=8A=B6=E6=80=81=E6=8F=90=E7=A4=BA=E7=A7=BB=E5=87=BA?= =?UTF-8?q?=E5=8A=A8=E4=BD=9C=E8=A1=8C=EF=BC=8C=E6=8C=89=E9=92=AE=E9=97=B4?= =?UTF-8?q?=E8=B7=9D=E4=B8=8D=E5=86=8D=E9=9A=8F=E6=8F=90=E7=A4=BA=E6=96=87?= =?UTF-8?q?=E6=A1=88=E5=8F=98=E9=95=BF=E8=80=8C=E5=8F=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 根因(按真机截图逐像素量出来的):动作行 `game-workbench-view-actions` 里除了按钮还挂着 `game-resource-reorder-status` 这个 `role="status"` 提示,它是 flex 子项、`white-space: nowrap`,文案从空 →「保存中」→「布局已保存」→ 失败原因会越变越长,于是把右侧按钮按文本宽度顶开:同一份截图里「资源面板→生成素材」「生成素材→整理画布」的空隙是 64/66px,而「整理画布→生成任务」是 80px,差值正是这条提示当时的宽度(10px × 8 字符 ≈ 16px) - 修法:把它从动作行里搬出来,改成工具条内的绝对定位(`bottom: 4px; left: 12px`,`max-width` + 省略号兜底),不再参与行内排版;四枚动作按钮的内容宽度实测都是 132~134px,间距因此只剩一套 - 保留上一笔的分段控件 `margin-left: 17px`:它解决的是另一半——分段控件内部 0 间距导致它与前一按钮只隔 10px,而其余按钮之间是 24px - 用例:新增「布局状态提示不参与动作行排版,不会按文案宽度顶开按钮」,钉住 `position: absolute` 与锚点;既有「布局已保存」文本断言(按文本查,不依赖它在哪个容器)不受影响 - 文档:AGC 入口矩阵补「工具条动作行的间距只有一套」口径,写清提示为什么不进这一行 验证:tsc --noEmit 通过;appSurface 全量 441 条通过;侧栏开合与入口 5 条、画布手动布局 9 条通过;变异验证:把提示改回 `position: static`,新用例变红 --- apps/ai-game-creator-shell/src/styles.css | 17 +++++++++++++++- .../src/view/project-development/index.tsx | 20 ++++++++++++------- ...nvasGenerationTasksSidebarDismiss.test.tsx | 15 ++++++++++++++ ...C】栏目画布底部工具栏入口矩阵-2026-09-13.md | 2 ++ 4 files changed, 46 insertions(+), 8 deletions(-) diff --git a/apps/ai-game-creator-shell/src/styles.css b/apps/ai-game-creator-shell/src/styles.css index be246cb0e..c10ce1526 100644 --- a/apps/ai-game-creator-shell/src/styles.css +++ b/apps/ai-game-creator-shell/src/styles.css @@ -5650,10 +5650,23 @@ iframe.preview-frame { color: var(--platform-button-primary-text); } +/** + * 布局状态提示:**绝对定位,不参与动作行的排版**。 + * + * 它不是按钮,但曾经是动作行里的一个 flex 子项:文案从空 →「保存中」→「布局已保存」→ + * 失败原因会随保存过程变长,于是把右侧那几枚按钮按文本宽度顶开——同一行在不同时刻的按钮 + * 间距就不一样(实测同一份截图里「整理画布 → 生成任务」的空隙 80px,其余两处 64/66px, + * 差值正是这条提示当时的宽度)。定位后位置固定,行内只剩按钮之间那一套间距。 + */ .game-resource-reorder-status { - min-width: 0; + position: absolute; + bottom: 4px; + left: 12px; + max-width: calc(100% - 24px); + overflow: hidden; color: #9a725f; font-size: 10px; + text-overflow: ellipsis; white-space: nowrap; } @@ -10856,3 +10869,5 @@ button.design-workspace-tree__entry:hover, font: inherit; opacity: 0.8; } + + 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 dc964bfbe..b8fc97384 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 @@ -7719,13 +7719,6 @@ export default function ProjectDevelopmentView({ : `管理未完成编辑 (${pendingResourceEdits.length})`} ) : null} - - {resourceLayoutSaving ? '保存中' : resourceLayoutNotice} - {/* 「生成任务」入口排在「依赖 / 类型」排列方式之前:一个是开合任务侧栏的动作, 一个是画布排列方式——动作在前、排列方式收在行尾。运行页签下由下面同一枚 @@ -7765,6 +7758,19 @@ export default function ProjectDevelopmentView({ ? null : generationTasksEntry} + {/* + 布局状态提示**不进动作行**:它是一段随保存过程变长的文案(空 →「保存中」→ + 「布局已保存」→ 失败原因),作为 flex 子项会把右侧那几枚按钮按文本宽度顶开—— + 同一行不同时刻的按钮间距就会不一样。放到工具条上做绝对定位(见 + `.game-resource-reorder-status`),位置固定、不再参与行内排版。 + */} + + {resourceLayoutSaving ? '保存中' : resourceLayoutNotice} + {showRunUnavailableHint ? ( diff --git a/apps/ai-game-creator-shell/tests/resourceCanvasGenerationTasksSidebarDismiss.test.tsx b/apps/ai-game-creator-shell/tests/resourceCanvasGenerationTasksSidebarDismiss.test.tsx index 6d2d598d2..5e94acb39 100644 --- a/apps/ai-game-creator-shell/tests/resourceCanvasGenerationTasksSidebarDismiss.test.tsx +++ b/apps/ai-game-creator-shell/tests/resourceCanvasGenerationTasksSidebarDismiss.test.tsx @@ -154,4 +154,19 @@ describe('「生成任务」侧栏的开合与入口位置', () => { ); expect(styles).toMatch(/\.game-resource-sort-tabs\s*\{[^}]*padding:\s*0/s); }); + + it('布局状态提示不参与动作行排版,不会按文案宽度顶开按钮', () => { + const styles = readFileSync( + resolve(process.cwd(), 'apps/ai-game-creator-shell/src/styles.css'), + 'utf8', + ); + // 它是随保存过程变长的文案(空 →「保存中」→「布局已保存」→ 失败原因)。作为 flex 子项 + // 会把右侧按钮按文本宽度顶开,同一行的按钮间距就会随时刻变化;绝对定位后位置固定。 + expect(styles).toMatch( + /\.game-resource-reorder-status\s*\{[^}]*position:\s*absolute/s, + ); + expect(styles).toMatch( + /\.game-resource-reorder-status\s*\{[^}]*bottom:\s*4px[^}]*left:\s*12px/s, + ); + }); }); diff --git a/docs/technical/【AGC】栏目画布底部工具栏入口矩阵-2026-09-13.md b/docs/technical/【AGC】栏目画布底部工具栏入口矩阵-2026-09-13.md index 941a04074..9314085b3 100644 --- a/docs/technical/【AGC】栏目画布底部工具栏入口矩阵-2026-09-13.md +++ b/docs/technical/【AGC】栏目画布底部工具栏入口矩阵-2026-09-13.md @@ -54,6 +54,8 @@ ## 5. 参数口径与复用程度 +- **工具条动作行的间距只有一套**:行内按钮之间统一 24px(行 `gap: 7px` + 按钮左右 `padding: 11px`;「依赖 / 类型」分段控件内部是 0 间距的连通分段,靠 `margin-left: 17px` 与前一按钮保持同样的 24px)。**布局状态提示(`game-resource-reorder-status`)不进这一行**——它是随保存过程变长的文案(空 →「保存中」→「布局已保存」→ 失败原因),作为 flex 子项会把右侧按钮按文本宽度顶开,同一行不同时刻的按钮间距就会不一样;它改为工具条内的绝对定位,位置固定。 + - **复用**:比例 / 尺寸选项与默认值来自网页端美术画布的纯模型 `src/components/image-editor/ImageCanvasGenerationModel.ts`(`EDITOR_IMAGE_DIMENSION_OPTIONS` / `IMAGE_MODEL_NANOBANANA2`),尺寸标签复用 `resolveEditorImageSizeLabel`;提示词上限复用 AGC 自己的 `resourceEditPromptMaxLength`(图片类默认 32000,与 Rust `LOCAL_PROJECT_ASSET_MAX_PROMPT_CHARS` 同口径);「AI 润色」复用 `ResourcePromptPolishSlot`(`polish_local_project_prompt`);面板外壳复用 AGC 的 `ThemedModal`(与「生成素材」面板同一套宿主 chrome)。 - **收窄**:本地 IPC 的比例白名单是 `1:1 / 2:3 / 3:2 / 9:16 / 16:9`,网页端还有 `4:3`。前端做的是「主站纯模型 ∩ 本地白名单」,不是另抄一份选项表(测试钉住两者包含关系与 `4:3` 缺席)。 - **没有复用到的**:网页端的生成 composer 子视图(`ImageCanvasBasicGenerationComposerView` / `ImageCanvasCharacterGenerationComposerView` / `ImageCanvasIconSpritesheetComposerView` / `ImageCanvasSpecGenerationPanelView` / `ImageCanvasGenerationImageOptionsView`)。原因有二:① 它们的比例选项含本地通道拒绝的 `4:3`;② 它们自带模型选择器、参考图槽位、BFF 直连(`ImageCanvasSpecGenerationPanelView` 直连 `/api/editor/llm/icon-specs/*`,AGC 无该通道),本地 IPC 既没有 `model` 也没有参考图入参,照搬会渲染一批改不了请求的假控件。因此面板是 AGC 自己的薄壳,只把**纯模型**接进来。