feat(api): 添加安全上传 Skill 和 COS 图片归一化
This commit is contained in:
@@ -4,7 +4,7 @@ import { notesRepository } from '../repositories/notesRepository.js';
|
||||
import { imagesRepository } from '../repositories/imagesRepository.js';
|
||||
import { annotationsRepository } from '../repositories/annotationsRepository.js';
|
||||
import { database, databaseDialect, withTransaction, type QueryContext } from '../database.js';
|
||||
import { storeUploadedFile } from '../storage.js';
|
||||
import { storeExternalImageUrl, storeUploadedFile } from '../storage.js';
|
||||
import { recalculateCollectionStatus } from './collectionsService.js';
|
||||
import { ensureProjectCompatibilityCollection, recalculateProjectReviewStatus } from './projectsService.js';
|
||||
|
||||
@@ -24,8 +24,10 @@ async function prepareFiles(files: UploadedFile[]): Promise<StoredImage[]> {
|
||||
return Promise.all(files.map(async (file) => ({ ...(await readImageSize(file.path)), ...(await storeUploadedFile(file)) })));
|
||||
}
|
||||
|
||||
function externalImages(images: string[]): StoredImage[] {
|
||||
return images.map((url) => ({ url, width: 0, height: 0, storageProvider: 'external', storageKey: '' }));
|
||||
async function prepareExternalImages(images: string[]): Promise<StoredImage[]> {
|
||||
const prepared: StoredImage[] = [];
|
||||
for (const image of images) prepared.push(await storeExternalImageUrl(image));
|
||||
return prepared;
|
||||
}
|
||||
|
||||
async function createRoundInTransaction(
|
||||
@@ -138,10 +140,11 @@ export const notesService = {
|
||||
},
|
||||
|
||||
async createInProjectFromUrls(projectId: number, title: string, description: string, imageUrls: string[], tags: string[], externalId: string | null = null): Promise<Note> {
|
||||
const prepared = await prepareExternalImages(imageUrls);
|
||||
return withTransaction(async (tx) => {
|
||||
const collectionId = await ensureProjectCompatibilityCollection(projectId, tx);
|
||||
const id = await tx.insertId("INSERT INTO notes (project_id, collection_id, external_id, title, description, tags, review_status) VALUES (?, ?, ?, ?, ?, ?, 'pending')", [projectId, collectionId, externalId, title, description, JSON.stringify(tags)]);
|
||||
await createRoundInTransaction(tx, id, projectId, collectionId, { title, description, tags, images: externalImages(imageUrls) }, undefined, 'draft');
|
||||
await createRoundInTransaction(tx, id, projectId, collectionId, { title, description, tags, images: prepared }, undefined, 'draft');
|
||||
return (await notesRepository.findById(id))!;
|
||||
});
|
||||
},
|
||||
@@ -162,9 +165,10 @@ export const notesService = {
|
||||
const collection = await database.one<{ project_id: number }>('SELECT project_id FROM collections WHERE id = ?', [collectionId]);
|
||||
if (!collection) throw new Error('作品交付集不存在');
|
||||
const projectId = Number(collection.project_id);
|
||||
const prepared = await prepareExternalImages(imageUrls);
|
||||
return withTransaction(async (tx) => {
|
||||
const id = await tx.insertId("INSERT INTO notes (project_id, collection_id, external_id, title, description, tags, review_status) VALUES (?, ?, ?, ?, ?, ?, 'pending')", [projectId, collectionId, externalId, title, description, JSON.stringify(tags)]);
|
||||
await createRoundInTransaction(tx, id, projectId, collectionId, { title, description, tags, images: externalImages(imageUrls) }, undefined, 'draft');
|
||||
await createRoundInTransaction(tx, id, projectId, collectionId, { title, description, tags, images: prepared }, undefined, 'draft');
|
||||
return (await notesRepository.findById(id))!;
|
||||
});
|
||||
},
|
||||
@@ -183,7 +187,7 @@ export const notesService = {
|
||||
async createRoundFromUrls(id: number, round: UrlRound, createdBy?: number): Promise<Note> {
|
||||
const current = await notesRepository.findById(id);
|
||||
if (!current) throw new Error('作品不存在');
|
||||
const prepared = { ...round, images: externalImages(round.images) };
|
||||
const prepared = { ...round, images: await prepareExternalImages(round.images) };
|
||||
await withTransaction((tx) => createRoundInTransaction(tx, id, current.project_id, current.collection_id, prepared, createdBy, current.review_status));
|
||||
return (await notesRepository.findById(id))!;
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user