AGC 资源工作台工具条:把布局状态提示移出动作行,按钮间距不再随提示文案变长而变化
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 4m41s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 4m22s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m2s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 4m25s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 4m36s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m34s
Project CI / Repository checks (pull_request) Failing after 3m33s
Project CI / Frontend tests (pull_request) Successful in 6m19s
Project CI / Native shell tests (pull_request) Successful in 7m26s
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled

- 根因(按真机截图逐像素量出来的):动作行 `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`,新用例变红
This commit is contained in:
2026-09-14 23:33:32 +08:00
parent e272492f25
commit 40e2a1b9b1
4 changed files with 46 additions and 8 deletions
+16 -1
View File
@@ -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;
}
@@ -7719,13 +7719,6 @@ export default function ProjectDevelopmentView({
: `管理未完成编辑 (${pendingResourceEdits.length})`}
</button>
) : null}
<span
className="game-resource-reorder-status"
role="status"
aria-live="polite"
>
{resourceLayoutSaving ? '保存中' : resourceLayoutNotice}
</span>
{/*
/
@@ -7765,6 +7758,19 @@ export default function ProjectDevelopmentView({
? null
: generationTasksEntry}
</div>
{/*
****
flex
`.game-resource-reorder-status`
*/}
<span
className="game-resource-reorder-status"
role="status"
aria-live="polite"
>
{resourceLayoutSaving ? '保存中' : resourceLayoutNotice}
</span>
</div>
{showRunUnavailableHint ? (
@@ -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,
);
});
});
@@ -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 自己的薄壳,只把**纯模型**接进来。