美化生图浮层:紧凑排布不再出现滚动条,画布卡片外形收敛到基类 token
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled

- 字段行改两列(标签在左、控件在右),比例与尺寸并排一行,提示词 6 行降到 3 行
- 润色入口、参考图计数与取消 / 生成两个按钮收进同一行动作:原先它们各占一行把内容顶到
  几何上界之外,面板因此出现滚动条;重排后面板高度回落到上界以内(overflow 仅作兜底)
- 新增画布卡片基类 token(.game-project-workbench 上的 --game-canvas-card-*),取值照抄
  网页端美术画布的面板;占位卡与生成浮层/弹窗从此共用一套圆角、描边、底色与投影,各卡只表达差异
- 用例补一条结构回归:动作行同时装下润色 / 参考计数 / 两个动作,比例与尺寸同处一格
This commit is contained in:
2026-09-21 01:24:03 +08:00
parent 2a2e4c1cea
commit 329dd749eb
4 changed files with 177 additions and 32 deletions
@@ -414,7 +414,7 @@ export function ResourceCanvasAssetGenerationPanelView({
选择框(客户端验收现场那条)。两边的可访问名都由控件自身的 `aria-label` 提供(引用输入区
的 `ariaLabel` 与 `PlatformTextField` 的 `aria-label`),不依赖 label 关联。
*/}
<div>
<div className="resource-canvas-asset-generation-prompt-field">
<span></span>
{referenceEnabled ? (
/*
@@ -433,7 +433,7 @@ export function ResourceCanvasAssetGenerationPanelView({
versions={versions}
activeVersionId={activeVersionId}
multiline
rows={6}
rows={3}
placeholder={`${action.promptPlaceholder}(可用 @ 选择参考图)`}
showPolishAction={false}
/>
@@ -442,7 +442,7 @@ export function ResourceCanvasAssetGenerationPanelView({
<PlatformTextField
variant="textarea"
aria-label="生成提示词"
rows={6}
rows={3}
autoFocus
maxLength={promptMaxLength}
placeholder={action.promptPlaceholder}
@@ -488,22 +488,6 @@ export function ResourceCanvasAssetGenerationPanelView({
{resolveEditorImageSizeLabel({ aspectRatio, imageSize })}
</span>
)}
<ResourcePromptPolishSlot
subject={`素材生成提示词(${action.label}`}
editKind="image-reference"
prompt={prompt}
applyPrompt={setPrompt}
/>
{referenceEnabled && referenceLimit > 0 ? (
<p
className="resource-canvas-asset-generation-reference-hint"
data-resource-canvas-generation-reference-count={
referenceAssetIds.length
}
>
{`参考图 ${referenceAssetIds.length}/${referenceLimit}`}
</p>
) : null}
{referenceProblemNotice ? (
<p
className="game-resource-generation-error"
@@ -525,18 +509,43 @@ export function ResourceCanvasAssetGenerationPanelView({
{shownError}
</p>
) : null}
{/*
动作行收口:润色入口、参考图计数与两个按钮挤在同一行。
原先「润色一行、参考图计数一行、按钮一行」把面板顶到必须滚动(验收现场截图里那条
滚动条),而这三块内容都没有独占一行的必要:润色作用在提示词上、计数是提示词的从属
信息、按钮是收尾动作。放一行之后面板高度回落到几何上界以内,滚动条物理上不再出现。
*/}
<div className="game-resource-generation-actions">
<PlatformActionButton
type="button"
tone="secondary"
onClick={closeWithDraft}
>
</PlatformActionButton>
<PlatformActionButton type="submit" disabled={!canSubmit}>
<Sparkles size={15} aria-hidden="true" />
{action.label}
</PlatformActionButton>
<ResourcePromptPolishSlot
subject={`素材生成提示词(${action.label}`}
editKind="image-reference"
prompt={prompt}
applyPrompt={setPrompt}
/>
{referenceEnabled && referenceLimit > 0 ? (
<p
className="resource-canvas-asset-generation-reference-hint"
data-resource-canvas-generation-reference-count={
referenceAssetIds.length
}
>
{`参考图 ${referenceAssetIds.length}/${referenceLimit}`}
</p>
) : null}
<div className="game-resource-generation-actions-buttons">
<PlatformActionButton
type="button"
tone="secondary"
onClick={closeWithDraft}
>
</PlatformActionButton>
<PlatformActionButton type="submit" disabled={!canSubmit}>
<Sparkles size={15} aria-hidden="true" />
{action.label}
</PlatformActionButton>
</div>
</div>
</form>
</>
@@ -14,8 +14,9 @@
align-content: center;
gap: 4px;
padding: 8px;
/* 差异只留「虚线 + 更深的描边」(表示还没落地);圆角与浮层卡共用基类 token。 */
border: 1px dashed #c9a493;
border-radius: 14px;
border-radius: var(--game-canvas-card-radius-inner, 14px);
background: rgb(255 250 247 / 88%);
color: #8a6a5c;
text-align: center;
@@ -80,14 +81,70 @@
/* 锚点给的是占位卡中心:不居中就会整体右偏半个面板宽(真实浏览器 x287 vs 卡中心 286 复现过)。 */
transform: translateX(-50%);
width: min(560px, calc(100% - 24px));
/* 外形走基类 token(= 网页端画布面板那一套),三块浮层因此长得一样。 */
border: 1px solid var(--game-canvas-card-border, #e4c8ba);
border-radius: var(--game-canvas-card-radius, 18px);
background: var(--game-canvas-card-fill, #fffaf7);
box-shadow: var(--game-canvas-card-shadow, 0 24px 64px rgb(62 37 27 / 24%));
padding: var(--game-canvas-card-padding, 18px);
overflow-y: auto;
overflow-x: hidden;
overscroll-behavior: contain;
pointer-events: auto;
/* 内联 `maxHeight` 按真实画布底边算;这条只是拿不到几何时的兜底上界。 */
/*
* 内联 `maxHeight` 按真实画布底边算;这条只是拿不到几何时的兜底上界。
*
* 面板内容已经压到「一行提示词 + 一行参数 + 一行动作」的紧凑版(见下面那组规则),正常几何下
* 根本到不了这里;`overflow` 与这条上界保留为极端窗口下的兜底,而不是日常出现的滚动条。
*/
max-height: min(560px, calc(100dvh - 160px));
}
/*
* 紧凑版:字段行两列(标签在左、控件在右)、比例与尺寸并排、动作用一行收口。
*
* 验收现场那张图里面板要滚动,是因为「标签各占一行 + 提示词 6 行 + 比例一行 + 尺寸一行 + 润色
* 一行 + 参考计数一行」把内容顶到几何上界之外。这里按信息层级重新排:从属信息(标签、计数、
* 润色)让位给主体(提示词、参数、动作),面板高度回落到上界以内,滚动条物理上不再出现。
*/
.game-resource-generation-form {
gap: 10px;
}
.game-resource-generation-form > label,
.game-resource-generation-form
> .resource-canvas-asset-generation-prompt-field {
display: grid;
grid-template-columns: auto minmax(0, 1fr);
align-items: center;
gap: 4px 10px;
}
.resource-canvas-asset-generation-prompt-field > span,
.game-resource-generation-form > label > span {
white-space: nowrap;
}
/* 比例(5 项)与尺寸(3 项)并排:两组都很短,各占半行足够点。 */
.resource-canvas-asset-generation-dimensions {
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
gap: 8px;
}
/* 动作行:润色与参考计数贴左,两个按钮贴右,同一行收口。 */
.game-approval-dialog.resource-canvas-generation-floating-panel
.game-resource-generation-actions {
align-items: center;
gap: 10px;
padding-top: 2px;
}
.game-resource-generation-actions-buttons {
display: flex;
margin-left: auto;
gap: 8px;
}
/*
* 提交行固定在浮层底部。
*
@@ -113,4 +170,5 @@
margin: 0;
color: #9a7d70;
font-size: 11px;
white-space: nowrap;
}
+20
View File
@@ -9546,6 +9546,26 @@ iframe.preview-frame {
box-shadow: 0 24px 64px rgb(62 37 27 / 24%);
}
/*
* 画布卡片基类 token
*
* 取值**照抄网页端美术画布的面板**`src/index.css` `.image-canvas-editor__generation-composer`
* 一族占位卡生成浮层 / 弹窗资源信息浮层从此共用同一组圆角 / 描边 / 底色 / 投影各卡
* 自己的规则只表达差异占位卡虚线描边浮层的定位与宽度信息浮层的窄宽
*
* 两块从网页端整站表逐条照抄下来的浮层快速编辑 / 生成动画本身不在这里改它们的取值由
* `tests/resourceCanvasCharacterAnimationPanelStyle.test.tsx` 逐条比对改了会直接把守卫打红
* 它们本来就是这套取值的来源
*/
.game-project-workbench {
--game-canvas-card-radius: 1.1rem;
--game-canvas-card-radius-inner: 0.85rem;
--game-canvas-card-border: rgba(148, 163, 184, 0.36);
--game-canvas-card-fill: rgba(255, 255, 255, 0.96);
--game-canvas-card-shadow: 0 22px 48px rgba(15, 23, 42, 0.22);
--game-canvas-card-padding: 0.76rem;
}
.game-approval-dialog > header {
display: flex;
align-items: flex-start;
@@ -330,6 +330,64 @@ describe('生成面板的参考接线', () => {
).not.toBeNull();
});
test('紧凑版排布:动作行同时装下润色 / 参考计数 / 两个动作,参数与提示词各占一行', () => {
const imageAsset = asset('asset-a', 'image/png', 'assets/素材-a.png');
render(
<ResourceCanvasAssetGenerationPanelView
action={imageAction}
assets={[imageAsset]}
projectPath="/tmp/project"
draft={{
prompt: '',
assetName: '猫',
aspectRatio: '1:1',
imageSize: '1K',
references: [],
}}
onSubmit={vi.fn()}
onClose={() => undefined}
/>,
);
const panel = screen.getByRole('dialog', { name: '生成图片' });
/*
验收现场那张图里面板要滚动:标签各占一行、提示词 6 行、比例与尺寸各占一行、润色与参考
计数又各占一行。这里钉住重排后的形状——动作行一行收口、参数两栏并排、提示词三行,
面板高度因此回落到几何上界以内(滚动条不该再出现)。
*/
const actions = panel.querySelector('.game-resource-generation-actions');
expect(actions).not.toBeNull();
expect(
within(actions as HTMLElement).getByRole('button', { name: 'AI 润色' }),
).not.toBeNull();
expect(
within(actions as HTMLElement).getByText('参考图 0/5'),
).not.toBeNull();
expect(
within(actions as HTMLElement).getByRole('button', { name: '取消' }),
).not.toBeNull();
expect(
within(actions as HTMLElement).getByRole('button', { name: '生成图片' }),
).not.toBeNull();
// 比例与尺寸同处一格(CSS 里排成两栏),不再各占一行。
const dimensions = panel.querySelectorAll(
'.resource-canvas-asset-generation-dimensions',
);
expect(dimensions).toHaveLength(1);
// 两组选择器(比例 5 项、尺寸 3 项)同处这一格,CSS 里排成两栏。
expect(
within(dimensions[0] as HTMLElement).getByRole('button', {
name: '生成图片比例 1:1',
}),
).not.toBeNull();
expect(
within(dimensions[0] as HTMLElement).getByRole('button', {
name: '生成图片尺寸 1K',
}),
).not.toBeNull();
});
test('超限时提交被挡住并给出原因', async () => {
const user = userEvent.setup();
const onSubmit =