拆分编辑器上传模型

抽出上传文件夹解析和画布落点计算

补充上传模型单测

更新 TRACKING.md 记录第三十六阶段验证
This commit is contained in:
2026-06-17 18:06:53 +08:00
parent 4abf00d007
commit b5707ac2b9
4 changed files with 335 additions and 71 deletions

View File

@@ -0,0 +1,151 @@
import { describe, expect, it } from 'vitest';
import type {
CanvasLayer,
EditorAssetFolder,
} from './ImageCanvasEditorTypes';
import {
createUploadCanvasLayer,
createUploadingAssetPlaceholder,
resizeUploadCanvasLayerToImage,
resolveUploadFolderId,
} from './ImageCanvasUploadModel';
function createFolder(
overrides: Partial<EditorAssetFolder> = {},
): EditorAssetFolder {
return {
id: 'project',
label: '项目素材',
collapsed: false,
systemDefault: true,
persisted: true,
...overrides,
};
}
function createLayer(overrides: Partial<CanvasLayer> = {}): CanvasLayer {
return {
id: 'layer-upload-1',
resourceId: 'local-resource-upload-1',
title: '上传图片',
src: 'data:image/png;base64,upload',
x: -160,
y: -107.5,
width: 420,
height: 315,
originalWidth: 420,
originalHeight: 315,
zIndex: 11,
sourceType: 'uploaded',
sourceAssetId: 'upload-1',
...overrides,
};
}
describe('ImageCanvasUploadModel', () => {
it('resolves upload folder ids with project fallback', () => {
const folders = [
createFolder(),
createFolder({ id: 'characters', label: '角色素材' }),
];
expect(
resolveUploadFolderId({
assetFolders: folders,
requestedFolderId: 'characters',
activeUploadFolderId: 'project',
}),
).toBe('characters');
expect(
resolveUploadFolderId({
assetFolders: folders,
requestedFolderId: 'missing',
activeUploadFolderId: 'characters',
}),
).toBe('project');
});
it('creates uploading asset placeholders', () => {
expect(
createUploadingAssetPlaceholder({
uploadIndex: 7,
fileName: 'hero.png',
folderId: 'characters',
}),
).toEqual({
id: 'upload-7',
label: 'hero.png',
src: '',
width: 420,
height: 315,
folderId: 'characters',
sourceKind: 'uploaded',
sourceType: 'uploaded',
persisted: false,
uploadStatus: 'uploading',
uploadProgress: 8,
uploadMessage: '准备上传',
});
});
it('creates upload canvas layers centered on the target canvas point', () => {
const layer = createUploadCanvasLayer({
uploadIndex: 1,
fileName: '画布素材.png',
imageSrc: 'data:image/png;base64,canvas',
canvasPoint: { x: 110, y: 120 },
canvasSize: { width: 900, height: 640 },
viewport: { x: 10, y: 20, scale: 2 },
});
expect(layer).toMatchObject({
id: 'layer-upload-1',
resourceId: 'local-resource-upload-1',
title: '画布素材.png',
x: -160,
y: -107.5,
width: 420,
height: 315,
originalWidth: 420,
originalHeight: 315,
zIndex: 11,
sourceAssetId: 'upload-1',
});
});
it('uses viewport center fallback for invalid upload points', () => {
const layer = createUploadCanvasLayer({
uploadIndex: 2,
fileName: '',
imageSrc: 'data:image/png;base64,canvas',
canvasPoint: { x: Number.NaN, y: Number.POSITIVE_INFINITY },
canvasSize: { width: 900, height: 640 },
viewport: { x: 10, y: 20, scale: 2 },
});
expect(layer.title).toBe('上传图片');
expect(layer.x).toBe(10);
expect(layer.y).toBe(-7.5);
});
it('resizes upload canvas layers around the same canvas point', () => {
const resizedLayer = resizeUploadCanvasLayerToImage({
layer: createLayer(),
originalWidth: 1536,
originalHeight: 1024,
canvasPoint: { x: 110, y: 120 },
canvasSize: { width: 900, height: 640 },
viewport: { x: 10, y: 20, scale: 2 },
});
expect(resizedLayer).toMatchObject({
width: 1536,
height: 1024,
originalWidth: 1536,
originalHeight: 1024,
x: -718,
y: -462,
});
});
});