Files
wordcloud/frontend/src/lib/templateLibrary.ts
T

113 lines
4.7 KiB
TypeScript

import { BackendAsset, CanvasDocument, CanvasTemplate } from '../types';
import { apiUrl, ensureOk } from './api';
import { cloneDocument, normalizeDocument } from './canvasDocument';
export function templateId(template: CanvasTemplate) {
return template.template_id || template.id || '';
}
export function templateCreatedAt(template: CanvasTemplate) {
return template.created_at || template.createdAt || '';
}
export function templateUpdatedAt(template: CanvasTemplate) {
return template.updated_at || template.updatedAt || '';
}
export function templateReferenceIds(template: CanvasTemplate) {
return template.reference_asset_ids || template.referenceAssetIds || [];
}
export function templateCoverId(template: CanvasTemplate) {
return template.cover_asset_id || template.coverAssetId || templateReferenceIds(template)[0] || '';
}
export async function listDesignTemplates(): Promise<CanvasTemplate[]> {
const res = await ensureOk(await fetch(apiUrl('/api/design-templates')), '读取模板库失败');
const items = (await res.json()) as CanvasTemplate[];
return items.map(item => ({ ...item, document: normalizeDocument(item.document) }));
}
export async function createCanvasTemplate(input: {
name: string;
description: string;
document: CanvasDocument;
referenceAssetIds?: string[];
coverAssetId?: string;
}): Promise<CanvasTemplate> {
const fd = new FormData();
fd.append('name', input.name.trim() || '未命名模板');
fd.append('description', input.description.trim());
fd.append('document', JSON.stringify(normalizeDocument(input.document)));
fd.append('reference_asset_ids', JSON.stringify(input.referenceAssetIds || []));
fd.append('cover_asset_id', input.coverAssetId || input.referenceAssetIds?.[0] || '');
const res = await ensureOk(await fetch(apiUrl('/api/design-templates'), { method: 'POST', body: fd }), '保存模板失败');
const template = (await res.json()) as CanvasTemplate;
return { ...template, document: normalizeDocument(template.document) };
}
export async function importCanvasTemplate(
file: File,
name = '',
description = '',
): Promise<CanvasTemplate> {
const fd = new FormData();
fd.append('file', file);
if (name) fd.append('name', name.trim());
if (description) fd.append('description', description.trim());
const res = await ensureOk(await fetch(apiUrl('/api/design-templates/import'), { method: 'POST', body: fd }), '导入设计包失败');
const template = (await res.json()) as CanvasTemplate;
return { ...template, document: normalizeDocument(template.document) };
}
export async function updateCanvasTemplate(
id: string,
partial: {
name?: string;
description?: string;
document?: CanvasDocument;
referenceAssetIds?: string[];
coverAssetId?: string;
},
): Promise<CanvasTemplate> {
const fd = new FormData();
if (partial.name !== undefined) fd.append('name', partial.name.trim() || '未命名模板');
if (partial.description !== undefined) fd.append('description', partial.description.trim());
if (partial.document) fd.append('document', JSON.stringify(normalizeDocument(partial.document)));
if (partial.referenceAssetIds) fd.append('reference_asset_ids', JSON.stringify(partial.referenceAssetIds));
if (partial.coverAssetId !== undefined) fd.append('cover_asset_id', partial.coverAssetId);
const res = await ensureOk(await fetch(apiUrl(`/api/design-templates/${id}`), { method: 'PATCH', body: fd }), '更新模板失败');
const template = (await res.json()) as CanvasTemplate;
return { ...template, document: normalizeDocument(template.document) };
}
export async function deleteCanvasTemplate(id: string) {
await ensureOk(await fetch(apiUrl(`/api/design-templates/${id}`), { method: 'DELETE' }), '删除模板失败');
}
export async function listAssets(type = ''): Promise<BackendAsset[]> {
const query = type ? `?type=${encodeURIComponent(type)}` : '';
const res = await ensureOk(await fetch(apiUrl(`/api/assets${query}`)), '读取素材失败');
return (await res.json()) as BackendAsset[];
}
export async function uploadAsset(file: File, type = 'reference'): Promise<BackendAsset> {
const fd = new FormData();
fd.append('file', file);
fd.append('name', file.name.replace(/\.(svg|png|jpe?g)$/i, ''));
fd.append('type', type);
const res = await ensureOk(await fetch(apiUrl('/api/assets'), { method: 'POST', body: fd }), '上传参考图失败');
return (await res.json()) as BackendAsset;
}
export function assetUrl(assetOrPath?: BackendAsset | string) {
if (!assetOrPath) return '';
const raw = typeof assetOrPath === 'string' ? assetOrPath : assetOrPath.file_url;
if (!raw) return '';
return apiUrl(raw);
}
export function duplicateDocument(document: CanvasDocument): CanvasDocument {
return cloneDocument(document);
}