完善快速编辑参考图与生成占位

- 快速编辑支持最多8张额外参考图,并将原图自动作为最后一张参考图提交

- 快速编辑尺寸和模型沿用原图配置,按禁用态参数胶囊展示

- 快速编辑提交前同步改写原图引用为实际图序号

- 快速编辑生成改为创建独立画布生成占位,并支持键盘删除生成中对象

- 对齐生成类面板参考图图标、规范类固定参数和相关文档测试
This commit is contained in:
2026-06-18 22:39:03 +08:00
parent b04b6cee2b
commit ea29887d9c
65 changed files with 2819 additions and 531 deletions
@@ -97,6 +97,7 @@ export const SEEDANCE_VIDEO_REFERENCE_LIMITS = {
audio: 3,
requestBytes: 64 * 1024 * 1024,
} as const;
export const QUICK_EDIT_REFERENCE_LIMIT = 8;
export const CHARACTER_ANIMATION_ACTION_PROMPTS = [
{ label: '待机', text: '待机动作,轻微呼吸起伏。' },
{ label: '行走', text: '循环行走动作,步伐稳定。' },
@@ -176,9 +177,9 @@ export const DEFAULT_SPEC_FORM_VALUES: Record<
};
export const SPEC_TYPE_LABEL: Record<SpecGenerationType, string> = {
character: '角色形象规范',
ui: 'UI素材规范',
icon: '图标素材规范',
character: '角色规范',
ui: '图标规范',
icon: '图标规范',
custom: '自定义规范',
};
@@ -316,7 +317,7 @@ export function formatLayerImageType(layer: CanvasLayer) {
return '图标素材图片';
}
if (layer.assetKind === 'icon-spec') {
return '图标素材规范图片';
return '图标规范图片';
}
if (layer.assetKind === 'ui-design') {
return 'UI设计图';
@@ -377,6 +378,30 @@ export function createCanvasLayerReference(
};
}
export function appendLimitedQuickEditReferences(
references: CharacterReferenceImage[] | undefined,
nextReferences: CharacterReferenceImage[],
) {
const imageReferences = nextReferences.filter(
(reference) => (reference.mediaType ?? 'image') === 'image',
);
return [
...(references ?? []),
...imageReferences,
].slice(0, QUICK_EDIT_REFERENCE_LIMIT);
}
export function normalizeQuickEditPromptSourceReference(
prompt: string,
sourceReferenceIndex: number,
) {
const normalizedIndex = Math.max(1, sourceReferenceIndex);
const sourceReferenceLabel = `图${normalizedIndex}`;
return prompt
.replace(/原图|当前图片|当前图/gu, sourceReferenceLabel)
.replace(/图\s*1(?!\d)/gu, sourceReferenceLabel);
}
export function createGenerationInputField(
title: string,
value: string | null | undefined,
@@ -499,7 +524,7 @@ export function buildCharacterGenerationInputs(
...(specReference
? [
{
title: '角色形象规范',
title: '角色规范',
label: specReference.label,
src: specReference.src,
},
@@ -523,7 +548,7 @@ export function buildUiDesignGenerationInputs(
references: specReference
? [
{
title: '图标素材规范',
title: '图标规范',
label: specReference.label,
src: specReference.src,
},
@@ -545,7 +570,7 @@ export function buildIconGenerationInputs(
],
references: [
{
title: '图标素材规范',
title: '图标规范',
label: specReference.label,
src: specReference.src,
},
@@ -570,6 +595,33 @@ export function buildEditGenerationInputs(
};
}
export function buildQuickEditGenerationInputs(
title: '快速编辑提示词' | '重绘提示词',
prompt: string,
sourceLayer: CanvasLayer,
references: CharacterReferenceImage[] | undefined,
): CanvasGenerationInputs {
const limitedReferences = (references ?? []).slice(
0,
QUICK_EDIT_REFERENCE_LIMIT,
);
return {
fields: createGenerationInputField(title, prompt),
references: [
...limitedReferences.map((reference, index) => ({
title: `参考图 ${index + 1}`,
label: reference.label,
src: reference.src,
})),
{
title: `参考图 ${limitedReferences.length + 1}`,
label: sourceLayer.title,
src: sourceLayer.objectKey?.trim() || sourceLayer.src,
},
],
};
}
export function isCanvasGenerationDialog(
dialog: GenerateDialogState | null,
): dialog is CanvasGenerationDialogState {
@@ -580,6 +632,7 @@ export function isCanvasGenerationDialog(
dialog.mode === 'character' ||
dialog.mode === 'icon' ||
dialog.mode === 'ui-design' ||
dialog.mode === 'quick-edit' ||
dialog.mode === 'character-animation' ||
dialog.mode === 'video' ||
dialog.mode === 'audio-sound-effect' ||
@@ -602,6 +655,9 @@ export function getGenerationFrameAriaLabel(
if (dialog.mode === 'ui-design') {
return 'UI设计图生成占位图';
}
if (dialog.mode === 'quick-edit') {
return '快速编辑生成占位图';
}
if (dialog.mode === 'video') {
return '视频生成占位图';
}
@@ -630,6 +686,9 @@ export function getGenerationFrameLabel(dialog: CanvasGenerationDialogState) {
if (dialog.mode === 'ui-design') {
return 'UI Design Generator';
}
if (dialog.mode === 'quick-edit') {
return 'Quick Edit Generator';
}
if (dialog.mode === 'video') {
return 'Video Generator';
}