改为行引用保存画布参考图元数据

生成输入参考图只保存 refType/refId 行引用
生成器布局快照只保存参考图行指针并在加载时恢复临时源
上传参考图优先创建项目资源行并回写 resourceId
元数据弹窗改为展示参考图行引用信息
更新图片画布技术文档和项目决策记录
This commit is contained in:
2026-06-21 17:27:23 +08:00
parent 29d9c9ff5b
commit de9eaef28f
19 changed files with 822 additions and 264 deletions
@@ -7,6 +7,7 @@ import { isGeneratedLayer } from './ImageCanvasEditorModel';
import type {
CanvasGenerationDialogState,
CanvasGenerationInputField,
CanvasGenerationInputReference,
CanvasGenerationInputs,
CanvasLayer,
CharacterReferenceImage,
@@ -543,13 +544,7 @@ export function buildCharacterAnimationGenerationInputs(
): CanvasGenerationInputs {
return {
fields: createGenerationInputField('动作描述', promptText),
references: [
{
title: '角色图片',
label: sourceLayer.title,
src: sourceLayer.objectKey?.trim() || sourceLayer.src,
},
],
references: createLayerGenerationInputReference('角色图片', sourceLayer),
};
}
@@ -710,9 +705,57 @@ export function createCanvasLayerReference(
...(mediaType ? { mediaType } : {}),
objectKey: layer.objectKey ?? undefined,
assetObjectId: layer.assetObjectId ?? undefined,
resourceId: layer.resourceId,
sourceAssetId: layer.sourceAssetId ?? undefined,
};
}
export function createGenerationInputReference(
title: string,
reference: Pick<
CharacterReferenceImage,
'label' | 'resourceId' | 'sourceAssetId'
>,
): CanvasGenerationInputReference[] {
const resourceId = reference.resourceId?.trim();
if (
resourceId &&
!resourceId.startsWith('local-') &&
!resourceId.startsWith('generation-dialog:')
) {
return [
{
title,
label: reference.label,
refType: 'project-resource',
refId: resourceId,
},
];
}
const sourceAssetId = reference.sourceAssetId?.trim();
return sourceAssetId && !sourceAssetId.startsWith('upload-')
? [
{
title,
label: reference.label,
refType: 'asset',
refId: sourceAssetId,
},
]
: [];
}
export function createLayerGenerationInputReference(
title: string,
layer: CanvasLayer,
): CanvasGenerationInputReference[] {
return createGenerationInputReference(title, {
label: layer.title,
resourceId: layer.resourceId,
sourceAssetId: layer.sourceAssetId,
});
}
export function appendLimitedQuickEditReferences(
references: CharacterReferenceImage[] | undefined,
nextReferences: CharacterReferenceImage[],
@@ -751,11 +794,9 @@ export function buildImageGenerationInputs(
): CanvasGenerationInputs {
return {
fields: createGenerationInputField('生成提示词', prompt),
references: (references ?? []).map((reference, index) => ({
title: `参考图 ${index + 1}`,
label: reference.label,
src: reference.src,
})),
references: (references ?? []).flatMap((reference, index) =>
createGenerationInputReference(`参考图 ${index + 1}`, reference),
),
};
}
@@ -770,7 +811,7 @@ export function buildVideoGenerationInputs(
};
return {
fields: createGenerationInputField('视频描述', prompt),
references: (references ?? []).map((reference) => {
references: (references ?? []).flatMap((reference) => {
const mediaType = reference.mediaType ?? 'image';
mediaIndexes[mediaType] += 1;
const title =
@@ -779,11 +820,7 @@ export function buildVideoGenerationInputs(
: mediaType === 'audio'
? `参考音频 ${mediaIndexes.audio}`
: `参考图 ${mediaIndexes.image}`;
return {
title,
label: reference.label,
src: reference.src,
};
return createGenerationInputReference(title, reference);
}),
};
}
@@ -821,7 +858,7 @@ export function buildSpecGenerationInputs(
reference?: CharacterReferenceImage | null,
): CanvasGenerationInputs {
const references = reference
? [{ title: '参考图', label: reference.label, src: reference.src }]
? createGenerationInputReference('参考图', reference)
: [];
if (specType === 'custom') {
return {
@@ -855,19 +892,11 @@ export function buildCharacterGenerationInputs(
fields: createGenerationInputField('角色设定', prompt),
references: [
...(specReference
? [
{
title: '角色规范',
label: specReference.label,
src: specReference.src,
},
]
? createGenerationInputReference('角色规范', specReference)
: []),
...(references ?? []).map((reference, index) => ({
title: `常规参考图 ${index + 1}`,
label: reference.label,
src: reference.src,
})),
...(references ?? []).flatMap((reference, index) =>
createGenerationInputReference(`常规参考图 ${index + 1}`, reference),
),
],
};
}
@@ -879,13 +908,7 @@ export function buildUiDesignGenerationInputs(
return {
fields: createGenerationInputField('用户输入', prompt),
references: specReference
? [
{
title: '图标规范',
label: specReference.label,
src: specReference.src,
},
]
? createGenerationInputReference('图标规范', specReference)
: [],
};
}
@@ -947,11 +970,9 @@ export function buildPublicationMaterialsGenerationInputs(
normalizedGameInfo.gameDescription,
),
],
references: (references ?? []).map((reference, index) => ({
title: `宣发参考图 ${index + 1}`,
label: reference.label,
src: reference.src,
})),
references: (references ?? []).flatMap((reference, index) =>
createGenerationInputReference(`宣发参考图 ${index + 1}`, reference),
),
};
}
@@ -966,13 +987,7 @@ export function buildIconGenerationInputs(
value: iconDescriptions.join('\n'),
},
],
references: [
{
title: '图标规范',
label: specReference.label,
src: specReference.src,
},
],
references: createGenerationInputReference('图标规范', specReference),
};
}
@@ -984,13 +999,7 @@ export function buildUiDesignAssetExtractionGenerationInputs(
'提取提示词',
UI_DESIGN_ASSET_EXTRACTION_PROMPT,
),
references: [
{
title: 'UI设计图',
label: sourceLayer.title,
src: sourceLayer.objectKey?.trim() || sourceLayer.src,
},
],
references: createLayerGenerationInputReference('UI设计图', sourceLayer),
};
}
@@ -1001,13 +1010,7 @@ export function buildEditGenerationInputs(
): CanvasGenerationInputs {
return {
fields: createGenerationInputField(title, prompt),
references: [
{
title: '参考图',
label: sourceLayer.title,
src: sourceLayer.src,
},
],
references: createLayerGenerationInputReference('参考图', sourceLayer),
};
}
@@ -1024,16 +1027,13 @@ export function buildQuickEditGenerationInputs(
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,
},
...limitedReferences.flatMap((reference, index) =>
createGenerationInputReference(`参考图 ${index + 1}`, reference),
),
...createLayerGenerationInputReference(
`参考图 ${limitedReferences.length + 1}`,
sourceLayer,
),
],
};
}