拆分图片画布生成图层模型
新增生成结果图层模型和单测 主视图改为复用生成图层模型创建普通生图、快速编辑和图标图层 更新图片画布前端拆分文档和 TRACKING 回归记录
This commit is contained in:
@@ -0,0 +1,225 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import type {
|
||||
CanvasGenerationInputs,
|
||||
CanvasLayer,
|
||||
} from './ImageCanvasEditorTypes';
|
||||
import {
|
||||
createGeneratedResultLayer,
|
||||
createIconSpritesheetResultLayers,
|
||||
createQuickEditResultLayer,
|
||||
} from './ImageCanvasGenerationLayerModel';
|
||||
|
||||
function createGenerated(overrides = {}) {
|
||||
return {
|
||||
imageSrc: 'data:image/png;base64,generated',
|
||||
width: 1024,
|
||||
height: 1024,
|
||||
sourceType: 'generated' as const,
|
||||
prompt: '生成提示词',
|
||||
actualPrompt: '实际提示词',
|
||||
model: 'gpt-image-2',
|
||||
provider: 'VectorEngine',
|
||||
taskId: 'task-generated',
|
||||
objectKey: 'generated/object.png',
|
||||
assetObjectId: 'asset-object-generated',
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function createSourceLayer(overrides: Partial<CanvasLayer> = {}): CanvasLayer {
|
||||
return {
|
||||
id: 'layer-source',
|
||||
resourceId: 'resource-source',
|
||||
title: '源图',
|
||||
src: 'data:image/png;base64,source',
|
||||
x: 120,
|
||||
y: 140,
|
||||
width: 320,
|
||||
height: 240,
|
||||
originalWidth: 1536,
|
||||
originalHeight: 1024,
|
||||
zIndex: 2,
|
||||
sourceType: 'generated',
|
||||
groupId: 'group-a',
|
||||
assetKind: 'spec',
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function createGenerationInputs(): CanvasGenerationInputs {
|
||||
return {
|
||||
fields: [{ title: '生成提示词', value: '生成提示词' }],
|
||||
references: [],
|
||||
};
|
||||
}
|
||||
|
||||
describe('ImageCanvasGenerationLayerModel', () => {
|
||||
it('creates generated result layers centered on the active placeholder', () => {
|
||||
const layer = createGeneratedResultLayer({
|
||||
generated: createGenerated({ width: 2048, height: 1152 }),
|
||||
generatedIndex: 7,
|
||||
canvasSize: { width: 900, height: 640 },
|
||||
viewport: { x: 10, y: 20, scale: 2 },
|
||||
frame: {
|
||||
x: 80,
|
||||
y: 60,
|
||||
width: 560,
|
||||
height: 315,
|
||||
originalWidth: 2048,
|
||||
originalHeight: 1152,
|
||||
},
|
||||
assetKind: 'spec',
|
||||
title: 'UI素材规范 7',
|
||||
generationInputs: createGenerationInputs(),
|
||||
});
|
||||
|
||||
expect(layer).toMatchObject({
|
||||
id: 'layer-generated-7',
|
||||
resourceId: 'local-resource-generated-7',
|
||||
title: 'UI素材规范 7',
|
||||
x: -664,
|
||||
y: -358.5,
|
||||
width: 2048,
|
||||
height: 1152,
|
||||
originalWidth: 2048,
|
||||
originalHeight: 1152,
|
||||
zIndex: 17,
|
||||
sourceType: 'generated',
|
||||
assetKind: 'spec',
|
||||
prompt: '生成提示词',
|
||||
actualPrompt: '实际提示词',
|
||||
objectKey: 'generated/object.png',
|
||||
assetObjectId: 'asset-object-generated',
|
||||
});
|
||||
expect(layer.generationInputs?.fields[0]?.value).toBe('生成提示词');
|
||||
});
|
||||
|
||||
it('creates edit result layers beside the source image', () => {
|
||||
const sourceLayer = createSourceLayer();
|
||||
const layer = createGeneratedResultLayer({
|
||||
generated: createGenerated({ prompt: '修改要求' }),
|
||||
generatedIndex: 8,
|
||||
canvasSize: { width: 900, height: 640 },
|
||||
viewport: { x: 0, y: 0, scale: 1 },
|
||||
sourceLayer,
|
||||
generationInputs: createGenerationInputs(),
|
||||
});
|
||||
|
||||
expect(layer).toMatchObject({
|
||||
id: 'layer-edit-8',
|
||||
resourceId: 'local-resource-edit-8',
|
||||
title: '源图 修改结果',
|
||||
x: 472,
|
||||
y: 140,
|
||||
width: 1024,
|
||||
height: 1024,
|
||||
sourceResourceId: 'resource-source',
|
||||
prompt: '修改要求',
|
||||
});
|
||||
});
|
||||
|
||||
it('creates quick edit layers with source group and asset kind preserved', () => {
|
||||
const sourceLayer = createSourceLayer();
|
||||
const layer = createQuickEditResultLayer({
|
||||
generated: createGenerated({ width: 1536, height: 1024 }),
|
||||
generatedIndex: 9,
|
||||
sourceLayer,
|
||||
generationInputs: createGenerationInputs(),
|
||||
});
|
||||
|
||||
expect(layer).toMatchObject({
|
||||
id: 'layer-quick-edit-9',
|
||||
resourceId: 'local-resource-quick-edit-9',
|
||||
title: '源图 快速编辑',
|
||||
x: 472,
|
||||
y: 140,
|
||||
width: 1536,
|
||||
height: 1024,
|
||||
originalWidth: 1536,
|
||||
originalHeight: 1024,
|
||||
sourceResourceId: 'resource-source',
|
||||
groupId: 'group-a',
|
||||
assetKind: 'spec',
|
||||
});
|
||||
});
|
||||
|
||||
it('creates wrapped icon layers with icon metadata', () => {
|
||||
const layers = createIconSpritesheetResultLayers({
|
||||
generated: {
|
||||
spritesheetImageSrc: 'data:image/png;base64,sheet',
|
||||
spritesheetWidth: 512,
|
||||
spritesheetHeight: 512,
|
||||
iconImageSrcs: [],
|
||||
prompt: '图标 prompt',
|
||||
actualPrompt: '图标 actual prompt',
|
||||
model: 'gpt-image-2',
|
||||
provider: 'VectorEngine',
|
||||
taskId: 'task-icons',
|
||||
},
|
||||
iconResults: [
|
||||
{
|
||||
name: '返回按钮',
|
||||
imageSrc: 'data:image/png;base64,back',
|
||||
width: 256,
|
||||
height: 256,
|
||||
},
|
||||
{
|
||||
name: '设置按钮',
|
||||
imageSrc: 'data:image/png;base64,settings',
|
||||
width: 512,
|
||||
height: 256,
|
||||
},
|
||||
{
|
||||
name: '提示按钮',
|
||||
imageSrc: 'data:image/png;base64,hint',
|
||||
width: 128,
|
||||
height: 128,
|
||||
},
|
||||
],
|
||||
startIndex: 11,
|
||||
canvasSize: { width: 900, height: 640 },
|
||||
viewport: { x: 0, y: 0, scale: 1 },
|
||||
frame: {
|
||||
x: 200,
|
||||
y: 100,
|
||||
width: 360,
|
||||
height: 360,
|
||||
originalWidth: 512,
|
||||
originalHeight: 512,
|
||||
},
|
||||
generationInputs: createGenerationInputs(),
|
||||
});
|
||||
|
||||
expect(layers).toHaveLength(3);
|
||||
expect(layers[0]).toMatchObject({
|
||||
id: 'layer-icon-11',
|
||||
title: '返回按钮',
|
||||
x: 200,
|
||||
y: 100,
|
||||
width: 256,
|
||||
height: 256,
|
||||
assetKind: 'icon',
|
||||
prompt: '图标 prompt',
|
||||
actualPrompt: '图标 actual prompt',
|
||||
});
|
||||
expect(layers[1]).toMatchObject({
|
||||
id: 'layer-icon-12',
|
||||
title: '设置按钮',
|
||||
x: 200,
|
||||
y: 380,
|
||||
width: 512,
|
||||
height: 256,
|
||||
assetKind: 'icon',
|
||||
});
|
||||
expect(layers[2]).toMatchObject({
|
||||
id: 'layer-icon-13',
|
||||
title: '提示按钮',
|
||||
x: 200,
|
||||
y: 660,
|
||||
width: 128,
|
||||
height: 128,
|
||||
assetKind: 'icon',
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user