Merge branch 'codex/editor-asset-metadata-migration' into codex/editor-asset-library
# Conflicts: # docs/project-memory/shared-memory/decision-log.md # server-rs/crates/api-server/src/editor_project.rs # src/components/image-editor/ImageCanvasEditorModel.ts # src/components/image-editor/ImageCanvasEditorView.test-utils.ts # src/components/image-editor/ImageCanvasEditorView.tsx # src/components/image-editor/useImageCanvasGenerationSubmissionWorkflow.ts # src/services/image-editor/editorProjectClient.test.ts
This commit is contained in:
@@ -279,6 +279,11 @@ describe('editorProjectClient', () => {
|
||||
prompt: 'dragon knight',
|
||||
model: 'gpt-image-2',
|
||||
sourceResourceId: 'resource-source',
|
||||
assetKind: 'character',
|
||||
generationInputs: {
|
||||
fields: [{ title: '角色设定', value: 'dragon knight' }],
|
||||
references: [],
|
||||
},
|
||||
});
|
||||
|
||||
expect(requestJsonMock).toHaveBeenCalledWith(
|
||||
@@ -295,6 +300,11 @@ describe('editorProjectClient', () => {
|
||||
prompt: 'dragon knight',
|
||||
model: 'gpt-image-2',
|
||||
sourceResourceId: 'resource-source',
|
||||
assetKind: 'character',
|
||||
generationInputs: {
|
||||
fields: [{ title: '角色设定', value: 'dragon knight' }],
|
||||
references: [],
|
||||
},
|
||||
}),
|
||||
}),
|
||||
'创建图片画布资源失败',
|
||||
@@ -425,6 +435,11 @@ describe('editorProjectClient', () => {
|
||||
width: 640,
|
||||
height: 480,
|
||||
sourceType: 'uploaded',
|
||||
assetKind: 'icon',
|
||||
generationInputs: {
|
||||
fields: [{ title: '素材描述', value: '返回按钮' }],
|
||||
references: [],
|
||||
},
|
||||
});
|
||||
await updateEditorAsset('asset-1', {
|
||||
label: '角色主视觉.png',
|
||||
@@ -444,6 +459,11 @@ describe('editorProjectClient', () => {
|
||||
width: 640,
|
||||
height: 480,
|
||||
sourceType: 'uploaded',
|
||||
assetKind: 'icon',
|
||||
generationInputs: {
|
||||
fields: [{ title: '素材描述', value: '返回按钮' }],
|
||||
references: [],
|
||||
},
|
||||
}),
|
||||
}),
|
||||
'创建图片画布素材失败',
|
||||
@@ -551,6 +571,15 @@ describe('editorProjectClient', () => {
|
||||
model: 'gpt-image-2',
|
||||
aspectRatio: '2:3',
|
||||
imageSize: '1K',
|
||||
projectId: 'editor-project-1',
|
||||
assetKind: 'character',
|
||||
assetFolderId: 'project',
|
||||
assetLabel: '角色形象',
|
||||
sourceResourceId: 'resource-spec-1',
|
||||
generationInputs: {
|
||||
fields: [{ title: '角色设定', value: '角色设定' }],
|
||||
references: [],
|
||||
},
|
||||
});
|
||||
|
||||
expect(requestJsonMock).toHaveBeenCalledWith(
|
||||
@@ -564,6 +593,15 @@ describe('editorProjectClient', () => {
|
||||
model: 'gpt-image-2',
|
||||
aspectRatio: '2:3',
|
||||
imageSize: '1K',
|
||||
projectId: 'editor-project-1',
|
||||
assetKind: 'character',
|
||||
generationInputs: {
|
||||
fields: [{ title: '角色设定', value: '角色设定' }],
|
||||
references: [],
|
||||
},
|
||||
assetFolderId: 'project',
|
||||
assetLabel: '角色形象',
|
||||
sourceResourceId: 'resource-spec-1',
|
||||
}),
|
||||
}),
|
||||
'生成图片失败',
|
||||
@@ -643,6 +681,12 @@ describe('editorProjectClient', () => {
|
||||
aspectRatio: '1:1',
|
||||
imageSize: '2K',
|
||||
priceMudPoints: 20,
|
||||
projectId: 'editor-project-1',
|
||||
assetFolderId: 'project',
|
||||
generationInputs: {
|
||||
fields: [{ title: '素材描述', value: '返回按钮' }],
|
||||
references: [],
|
||||
},
|
||||
});
|
||||
|
||||
expect(requestJsonMock).toHaveBeenCalledWith(
|
||||
@@ -657,6 +701,12 @@ describe('editorProjectClient', () => {
|
||||
aspectRatio: '1:1',
|
||||
imageSize: '2K',
|
||||
priceMudPoints: 20,
|
||||
projectId: 'editor-project-1',
|
||||
generationInputs: {
|
||||
fields: [{ title: '素材描述', value: '返回按钮' }],
|
||||
references: [],
|
||||
},
|
||||
assetFolderId: 'project',
|
||||
}),
|
||||
}),
|
||||
'生成图标素材失败',
|
||||
@@ -690,6 +740,13 @@ describe('editorProjectClient', () => {
|
||||
|
||||
const result = await extractEditorUiDesignAssets({
|
||||
sourceImageSrc: 'data:image/png;base64,ui-design',
|
||||
projectId: 'editor-project-1',
|
||||
assetFolderId: 'project',
|
||||
spritesheetLabel: '战斗UI设计图 素材图集',
|
||||
generationInputs: {
|
||||
fields: [{ title: '来源', value: '战斗UI设计图' }],
|
||||
references: [],
|
||||
},
|
||||
});
|
||||
|
||||
expect(result.taskId).toBe('ui-asset-extraction-1');
|
||||
@@ -700,6 +757,13 @@ describe('editorProjectClient', () => {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
sourceImageSrc: 'data:image/png;base64,ui-design',
|
||||
projectId: 'editor-project-1',
|
||||
generationInputs: {
|
||||
fields: [{ title: '来源', value: '战斗UI设计图' }],
|
||||
references: [],
|
||||
},
|
||||
assetFolderId: 'project',
|
||||
spritesheetLabel: '战斗UI设计图 素材图集',
|
||||
}),
|
||||
}),
|
||||
'提取UI设计图素材失败',
|
||||
@@ -1108,6 +1172,15 @@ describe('editorProjectClient', () => {
|
||||
sourceImageSrc: 'data:image/png;base64,source',
|
||||
size: '1024x1024',
|
||||
model: 'gpt-image-2',
|
||||
projectId: 'editor-project-1',
|
||||
assetKind: 'character',
|
||||
assetFolderId: 'project',
|
||||
assetLabel: '角色形象 修改结果',
|
||||
sourceResourceId: 'resource-character-1',
|
||||
generationInputs: {
|
||||
fields: [{ title: '修改提示词', value: '把画面改成黄昏光线' }],
|
||||
references: [],
|
||||
},
|
||||
});
|
||||
|
||||
expect(result.taskId).toBe('vector-edit-1');
|
||||
@@ -1121,6 +1194,15 @@ describe('editorProjectClient', () => {
|
||||
sourceImageSrc: 'data:image/png;base64,source',
|
||||
size: '1024x1024',
|
||||
model: 'gpt-image-2',
|
||||
projectId: 'editor-project-1',
|
||||
assetKind: 'character',
|
||||
generationInputs: {
|
||||
fields: [{ title: '修改提示词', value: '把画面改成黄昏光线' }],
|
||||
references: [],
|
||||
},
|
||||
assetFolderId: 'project',
|
||||
assetLabel: '角色形象 修改结果',
|
||||
sourceResourceId: 'resource-character-1',
|
||||
}),
|
||||
}),
|
||||
'修改图片失败',
|
||||
|
||||
@@ -29,6 +29,22 @@ export type EditorProjectLayerSnapshot = Record<string, unknown> & {
|
||||
resourceId: string;
|
||||
};
|
||||
|
||||
export type EditorAssetGenerationInputField = {
|
||||
title: string;
|
||||
value: string;
|
||||
};
|
||||
|
||||
export type EditorAssetGenerationInputReference = {
|
||||
title: string;
|
||||
label: string;
|
||||
src: string;
|
||||
};
|
||||
|
||||
export type EditorAssetGenerationInputs = {
|
||||
fields: EditorAssetGenerationInputField[];
|
||||
references: EditorAssetGenerationInputReference[];
|
||||
};
|
||||
|
||||
export type EditorProjectResourceSourceType =
|
||||
| 'uploaded'
|
||||
| 'generated'
|
||||
@@ -50,6 +66,8 @@ export type EditorProjectResourceSnapshot = {
|
||||
taskId?: string | null;
|
||||
durationSeconds?: number | null;
|
||||
sourceResourceId?: string | null;
|
||||
assetKind?: string | null;
|
||||
generationInputs?: EditorAssetGenerationInputs | null;
|
||||
createdAt?: string;
|
||||
updatedAt?: string;
|
||||
};
|
||||
@@ -80,6 +98,8 @@ export type EditorAssetSnapshot = {
|
||||
provider?: string | null;
|
||||
taskId?: string | null;
|
||||
durationSeconds?: number | null;
|
||||
assetKind?: string | null;
|
||||
generationInputs?: EditorAssetGenerationInputs | null;
|
||||
createdAt?: string;
|
||||
updatedAt?: string;
|
||||
};
|
||||
@@ -102,6 +122,12 @@ export type EditorImageGenerationInput = {
|
||||
aspectRatio?: string;
|
||||
imageSize?: string;
|
||||
referenceImageSrcs?: string[];
|
||||
projectId?: string | null;
|
||||
assetKind?: string | null;
|
||||
generationInputs?: EditorAssetGenerationInputs | null;
|
||||
assetFolderId?: string | null;
|
||||
assetLabel?: string | null;
|
||||
sourceResourceId?: string | null;
|
||||
};
|
||||
|
||||
export type EditorIconSpritesheetGenerationInput = {
|
||||
@@ -111,10 +137,17 @@ export type EditorIconSpritesheetGenerationInput = {
|
||||
aspectRatio?: string;
|
||||
imageSize?: string;
|
||||
priceMudPoints: number;
|
||||
projectId?: string | null;
|
||||
generationInputs?: EditorAssetGenerationInputs | null;
|
||||
assetFolderId?: string | null;
|
||||
};
|
||||
|
||||
export type EditorUiDesignAssetExtractionInput = {
|
||||
sourceImageSrc: string;
|
||||
projectId?: string | null;
|
||||
generationInputs?: EditorAssetGenerationInputs | null;
|
||||
assetFolderId?: string | null;
|
||||
spritesheetLabel?: string | null;
|
||||
};
|
||||
|
||||
export type EditorImageEditInput = {
|
||||
@@ -122,6 +155,12 @@ export type EditorImageEditInput = {
|
||||
sourceImageSrc: string;
|
||||
size?: string;
|
||||
model?: string;
|
||||
projectId?: string | null;
|
||||
assetKind?: string | null;
|
||||
generationInputs?: EditorAssetGenerationInputs | null;
|
||||
assetFolderId?: string | null;
|
||||
assetLabel?: string | null;
|
||||
sourceResourceId?: string | null;
|
||||
};
|
||||
|
||||
export type EditorImageGenerationResult = {
|
||||
@@ -136,6 +175,8 @@ export type EditorImageGenerationResult = {
|
||||
model: string;
|
||||
provider: string;
|
||||
taskId: string;
|
||||
resource?: EditorProjectResourceSnapshot | null;
|
||||
asset?: EditorAssetSnapshot | null;
|
||||
};
|
||||
|
||||
export type EditorIconSpritesheetIconResult = {
|
||||
@@ -143,6 +184,8 @@ export type EditorIconSpritesheetIconResult = {
|
||||
imageSrc: string;
|
||||
width: number;
|
||||
height: number;
|
||||
resource?: EditorProjectResourceSnapshot | null;
|
||||
asset?: EditorAssetSnapshot | null;
|
||||
};
|
||||
|
||||
export type EditorIconSpritesheetGenerationResult = {
|
||||
@@ -156,6 +199,8 @@ export type EditorIconSpritesheetGenerationResult = {
|
||||
provider: string;
|
||||
taskId: string;
|
||||
priceMudPoints: number;
|
||||
spritesheetResource?: EditorProjectResourceSnapshot | null;
|
||||
spritesheetAsset?: EditorAssetSnapshot | null;
|
||||
};
|
||||
|
||||
export type EditorCharacterAnimationResolution = '480p' | '720p';
|
||||
@@ -315,6 +360,8 @@ export type EditorProjectResourceCreateInput = {
|
||||
taskId?: string | null;
|
||||
durationSeconds?: number | null;
|
||||
sourceResourceId?: string | null;
|
||||
assetKind?: string | null;
|
||||
generationInputs?: EditorAssetGenerationInputs | null;
|
||||
};
|
||||
|
||||
export type EditorAssetCreateInput = {
|
||||
@@ -332,6 +379,8 @@ export type EditorAssetCreateInput = {
|
||||
provider?: string | null;
|
||||
taskId?: string | null;
|
||||
durationSeconds?: number | null;
|
||||
assetKind?: string | null;
|
||||
generationInputs?: EditorAssetGenerationInputs | null;
|
||||
};
|
||||
|
||||
export type EditorAssetUpdateInput = {
|
||||
@@ -558,6 +607,16 @@ export async function generateEditorImage(input: EditorImageGenerationInput) {
|
||||
...(input.referenceImageSrcs?.length
|
||||
? { referenceImageSrcs: input.referenceImageSrcs }
|
||||
: {}),
|
||||
...(input.projectId ? { projectId: input.projectId } : {}),
|
||||
...(input.assetKind ? { assetKind: input.assetKind } : {}),
|
||||
...(input.generationInputs
|
||||
? { generationInputs: input.generationInputs }
|
||||
: {}),
|
||||
...(input.assetFolderId ? { assetFolderId: input.assetFolderId } : {}),
|
||||
...(input.assetLabel ? { assetLabel: input.assetLabel } : {}),
|
||||
...(input.sourceResourceId
|
||||
? { sourceResourceId: input.sourceResourceId }
|
||||
: {}),
|
||||
}),
|
||||
'生成图片失败',
|
||||
{
|
||||
@@ -581,6 +640,11 @@ export async function generateEditorIconSpritesheet(
|
||||
...(input.aspectRatio ? { aspectRatio: input.aspectRatio } : {}),
|
||||
...(input.imageSize ? { imageSize: input.imageSize } : {}),
|
||||
priceMudPoints: input.priceMudPoints,
|
||||
...(input.projectId ? { projectId: input.projectId } : {}),
|
||||
...(input.generationInputs
|
||||
? { generationInputs: input.generationInputs }
|
||||
: {}),
|
||||
...(input.assetFolderId ? { assetFolderId: input.assetFolderId } : {}),
|
||||
}),
|
||||
'生成图标素材失败',
|
||||
{
|
||||
@@ -599,6 +663,14 @@ export async function extractEditorUiDesignAssets(
|
||||
EDITOR_UI_DESIGN_ASSET_EXTRACTION_API,
|
||||
jsonRequest('POST', {
|
||||
sourceImageSrc: input.sourceImageSrc,
|
||||
...(input.projectId ? { projectId: input.projectId } : {}),
|
||||
...(input.generationInputs
|
||||
? { generationInputs: input.generationInputs }
|
||||
: {}),
|
||||
...(input.assetFolderId ? { assetFolderId: input.assetFolderId } : {}),
|
||||
...(input.spritesheetLabel
|
||||
? { spritesheetLabel: input.spritesheetLabel }
|
||||
: {}),
|
||||
}),
|
||||
'提取UI设计图素材失败',
|
||||
{
|
||||
@@ -618,6 +690,16 @@ export async function editEditorImage(input: EditorImageEditInput) {
|
||||
sourceImageSrc: input.sourceImageSrc,
|
||||
...(input.size ? { size: input.size } : {}),
|
||||
...(input.model ? { model: input.model } : {}),
|
||||
...(input.projectId ? { projectId: input.projectId } : {}),
|
||||
...(input.assetKind ? { assetKind: input.assetKind } : {}),
|
||||
...(input.generationInputs
|
||||
? { generationInputs: input.generationInputs }
|
||||
: {}),
|
||||
...(input.assetFolderId ? { assetFolderId: input.assetFolderId } : {}),
|
||||
...(input.assetLabel ? { assetLabel: input.assetLabel } : {}),
|
||||
...(input.sourceResourceId
|
||||
? { sourceResourceId: input.sourceResourceId }
|
||||
: {}),
|
||||
}),
|
||||
'修改图片失败',
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user