修复作品附件上传和显示功能
1. 后端 DTO 添加 attachments 字段 2. 后端 submit 方法使用事务创建作品和附件记录 3. 前端 SubmitWorkForm 添加 attachments 类型 4. 前端上传时将附件信息单独传递(不再合并到 files 中) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
1010c764cc
commit
9f22a20a2a
@ -1,4 +1,21 @@
|
||||
import { IsString, IsInt, IsOptional, IsObject, IsArray } from 'class-validator';
|
||||
import { IsString, IsInt, IsOptional, IsObject, IsArray, ValidateNested } from 'class-validator';
|
||||
import { Type } from 'class-transformer';
|
||||
|
||||
export class AttachmentDto {
|
||||
@IsString()
|
||||
fileName: string;
|
||||
|
||||
@IsString()
|
||||
fileUrl: string;
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
fileType?: string;
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
size?: string;
|
||||
}
|
||||
|
||||
export class SubmitWorkDto {
|
||||
@IsInt()
|
||||
@ -28,5 +45,11 @@ export class SubmitWorkDto {
|
||||
@IsObject()
|
||||
@IsOptional()
|
||||
aiModelMeta?: any;
|
||||
|
||||
@IsArray()
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => AttachmentDto)
|
||||
@IsOptional()
|
||||
attachments?: AttachmentDto[];
|
||||
}
|
||||
|
||||
|
||||
@ -120,8 +120,33 @@ export class WorksService {
|
||||
creator: submitterUserId,
|
||||
};
|
||||
|
||||
return this.prisma.contestWork.create({
|
||||
// 使用事务创建作品和附件
|
||||
return this.prisma.$transaction(async (tx) => {
|
||||
const work = await tx.contestWork.create({
|
||||
data,
|
||||
});
|
||||
|
||||
// 创建附件记录
|
||||
if (submitWorkDto.attachments && submitWorkDto.attachments.length > 0) {
|
||||
for (const attachment of submitWorkDto.attachments) {
|
||||
await tx.contestWorkAttachment.create({
|
||||
data: {
|
||||
tenantId,
|
||||
contestId: registration.contestId,
|
||||
workId: work.id,
|
||||
fileName: attachment.fileName,
|
||||
fileUrl: attachment.fileUrl,
|
||||
fileType: attachment.fileType,
|
||||
size: attachment.size,
|
||||
creator: submitterUserId,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 返回完整的作品信息
|
||||
return tx.contestWork.findUnique({
|
||||
where: { id: work.id },
|
||||
include: {
|
||||
contest: {
|
||||
select: {
|
||||
@ -143,6 +168,7 @@ export class WorksService {
|
||||
attachments: true,
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -367,6 +367,13 @@ export interface ContestWorkAttachment {
|
||||
modifyTime?: string;
|
||||
}
|
||||
|
||||
export interface SubmitWorkAttachment {
|
||||
fileName: string;
|
||||
fileUrl: string;
|
||||
fileType?: string;
|
||||
size?: string;
|
||||
}
|
||||
|
||||
export interface SubmitWorkForm {
|
||||
registrationId: number;
|
||||
title: string;
|
||||
@ -375,6 +382,7 @@ export interface SubmitWorkForm {
|
||||
previewUrl?: string;
|
||||
previewUrls?: string[];
|
||||
aiModelMeta?: any;
|
||||
attachments?: SubmitWorkAttachment[];
|
||||
}
|
||||
|
||||
export interface QueryWorkParams extends PaginationParams {
|
||||
|
||||
@ -553,7 +553,6 @@ const handleSubmit = async () => {
|
||||
let modelFiles: string[] = []
|
||||
let previewUrl = ""
|
||||
let previewUrlsList: string[] = []
|
||||
const attachmentUrls: string[] = []
|
||||
|
||||
if (uploadMode.value === "history") {
|
||||
// 从创作历史选择模式
|
||||
@ -611,11 +610,22 @@ const handleSubmit = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
// 上传附件
|
||||
// 上传附件并收集附件信息
|
||||
const attachments: Array<{
|
||||
fileName: string
|
||||
fileUrl: string
|
||||
fileType?: string
|
||||
size?: string
|
||||
}> = []
|
||||
for (const file of form.attachmentFiles) {
|
||||
try {
|
||||
const url = await uploadFile(file)
|
||||
attachmentUrls.push(url)
|
||||
attachments.push({
|
||||
fileName: file.name,
|
||||
fileUrl: url,
|
||||
fileType: file.type || undefined,
|
||||
size: String(file.size),
|
||||
})
|
||||
} catch (error: any) {
|
||||
console.error("附件上传失败:", error)
|
||||
}
|
||||
@ -625,9 +635,10 @@ const handleSubmit = async () => {
|
||||
registrationId: registrationIdRef.value,
|
||||
title: form.title,
|
||||
description: form.description,
|
||||
files: [...modelFiles, ...attachmentUrls],
|
||||
files: modelFiles, // 只包含模型文件,不包含附件
|
||||
previewUrl: previewUrl,
|
||||
previewUrls: previewUrlsList.length > 0 ? previewUrlsList : undefined,
|
||||
attachments: attachments.length > 0 ? attachments : undefined,
|
||||
}
|
||||
|
||||
await worksApi.submit(submitData)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user