合并图标规范与图集生成优化

合入 PR 137 的图标规范生成、稳定引用与图集提示词链路
保留主分支现行音效提交、Prompt 模块与结果压缩逻辑
解决 External Worker、生成提交和客户端测试冲突
This commit is contained in:
2026-08-08 21:44:15 +08:00
76 changed files with 7690 additions and 3063 deletions
@@ -6,6 +6,7 @@ import {
import type {
EditorBackgroundMusicGenerationInput,
EditorCharacterAnimationGenerationInput,
EditorIconSpecGenerationInput,
EditorIconSpritesheetGenerationInput,
EditorImageEditInput,
EditorImageGenerationInput,
@@ -13,6 +14,7 @@ import type {
EditorSoundEffectGenerationInput,
EditorVideoGenerationInput,
} from '../../services/image-editor/editorProjectClient';
import { EDITOR_ICON_DESCRIPTION_MAX_CHARS } from '../../services/image-editor/editorProjectClient';
import type {
CanvasGenerationInputs,
CanvasLayer,
@@ -101,6 +103,25 @@ export function resolveImageReferenceSubmissionSource(reference: {
return reference.objectKey?.trim() || reference.src;
}
export function resolveRegisteredEditorReferenceId(reference: {
resourceId?: string | null;
sourceAssetId?: string | null;
}) {
const resourceId = reference.resourceId?.trim();
if (
resourceId &&
!resourceId.startsWith('local-resource-') &&
!resourceId.startsWith('generation-dialog:')
) {
return resourceId;
}
const assetId = reference.sourceAssetId?.trim();
if (assetId) {
return assetId;
}
throw new Error('参考图尚未登记为项目资源或素材,请重新选择或上传后再试');
}
function buildSeedanceVideoReferenceInput(
references: NonNullable<GenerateDialogState['generationReferences']>,
) {
@@ -198,6 +219,16 @@ export type ImageGenerationSubmissionPlan =
};
rememberImageModel?: string;
}
| {
kind: 'icon-spec';
normalizedPrompt: string;
input: EditorIconSpecGenerationInput;
result: {
assetKind: 'icon-spec';
title: string;
generationInputs: CanvasGenerationInputs;
};
}
| {
kind: 'quick-edit';
normalizedPrompt: string;
@@ -419,6 +450,37 @@ export function buildImageGenerationSubmissionPlan({
if (dialog.mode === 'spec') {
const specType = dialog.specType ?? 'custom';
const specValues = dialog.specValues ?? DEFAULT_SPEC_FORM_VALUES[specType];
if (specType === 'icon') {
const generationInputs = buildSpecGenerationInputs(
specType,
specValues,
dialog.specReference,
);
return {
kind: 'icon-spec',
normalizedPrompt,
input: {
playSetting: specValues.playSetting.trim(),
artStyle: specValues.artStyle.trim(),
...(dialog.specReference?.src
? {
referenceId: resolveRegisteredEditorReferenceId(
dialog.specReference,
),
}
: {}),
generationInputs,
},
result: {
assetKind: 'icon-spec',
title: resolveGenerationAssetLabel(
dialog.assetLabel,
`${SPEC_TYPE_LABEL[specType]} ${nextGeneratedIndex}`,
),
generationInputs,
},
};
}
return {
kind: 'image',
normalizedPrompt,
@@ -442,9 +504,7 @@ export function buildImageGenerationSubmissionPlan({
: {}),
},
result: {
// 中文注释:生成规范菜单里的“图标规范”沿用历史 ui specType,但产物语义应作为图标规范供图标素材引用。
assetKind:
specType === 'ui' || specType === 'icon' ? 'icon-spec' : 'spec',
assetKind: 'spec',
title: resolveGenerationAssetLabel(
dialog.assetLabel,
`${SPEC_TYPE_LABEL[specType]} ${nextGeneratedIndex}`,
@@ -728,6 +788,24 @@ export function buildIconSpritesheetGenerationSubmissionPlan(
errorMessage: '请填写素材描述',
};
}
if (Array.from(normalizedPrompt).length > EDITOR_ICON_DESCRIPTION_MAX_CHARS) {
return {
ok: false,
errorMessage: `素材描述不能超过 ${EDITOR_ICON_DESCRIPTION_MAX_CHARS} 个字符`,
};
}
let referenceId: string;
try {
referenceId = resolveRegisteredEditorReferenceId(dialog.iconSpecReference);
} catch (error) {
return {
ok: false,
errorMessage:
error instanceof Error && error.message.trim()
? error.message
: '图标规范尚未完成资源登记,请重新选择或上传后再试',
};
}
const rememberImageModel = normalizeEditorImageModel(dialog.imageModel);
const screenColor = DEFAULT_EDITOR_GENERATION_BACKGROUND_COLOR;
@@ -736,9 +814,7 @@ export function buildIconSpritesheetGenerationSubmissionPlan(
ok: true,
iconDescriptions,
input: {
referenceImageSrc: resolveImageReferenceSubmissionSource(
dialog.iconSpecReference,
),
referenceId,
...(dialog.generationReferences?.length
? {
referenceImageSrcs: dialog.generationReferences.map((reference) =>