117 lines
3.2 KiB
TypeScript
117 lines
3.2 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server'
|
||
import { getServerSession } from 'next-auth'
|
||
import { authOptions } from '@/lib/auth'
|
||
import { prisma } from '@/lib/prisma'
|
||
import { uploadToS3, deleteFromS3 } from '@/lib/s3'
|
||
import { processImage, getProcessedFileName } from '@/lib/image-processor'
|
||
|
||
export async function PUT(req: NextRequest) {
|
||
try {
|
||
const session = await getServerSession(authOptions)
|
||
|
||
if (!session || (session.user as any).role !== 'ADMIN') {
|
||
return NextResponse.json(
|
||
{ error: '无权限' },
|
||
{ status: 403 }
|
||
)
|
||
}
|
||
|
||
const formData = await req.formData()
|
||
|
||
const id = formData.get('id') as string
|
||
const productModel = formData.get('productModel') as string
|
||
const categoryName = formData.get('categoryName') as string
|
||
const sceneName = formData.get('sceneName') as string
|
||
const renderer = (formData.get('renderer') as string) || 'CR'
|
||
const authorName = formData.get('authorName') as string
|
||
const previewImage = formData.get('previewImage') as File | null
|
||
|
||
// Validation
|
||
if (!id || !productModel || !categoryName || !sceneName || !renderer || !authorName) {
|
||
return NextResponse.json(
|
||
{ error: '所有字段都是必填的' },
|
||
{ status: 400 }
|
||
)
|
||
}
|
||
|
||
// Get existing material
|
||
const existingMaterial = await prisma.material.findUnique({
|
||
where: { id },
|
||
})
|
||
|
||
if (!existingMaterial) {
|
||
return NextResponse.json(
|
||
{ error: '素材不存在' },
|
||
{ status: 404 }
|
||
)
|
||
}
|
||
|
||
let previewUrl = existingMaterial.previewUrl
|
||
|
||
// If new preview image is uploaded
|
||
if (previewImage && previewImage.size > 0) {
|
||
// Delete old preview image from S3
|
||
try {
|
||
await deleteFromS3(existingMaterial.previewUrl)
|
||
} catch (error) {
|
||
console.error('Error deleting old preview:', error)
|
||
}
|
||
|
||
// 处理预览图:压缩到300KB以内,转换为webP,缩放到600px
|
||
const originalBuffer = Buffer.from(await previewImage.arrayBuffer())
|
||
const processedBuffer = await processImage(originalBuffer, {
|
||
maxSizeKB: 300,
|
||
maxWidth: 600,
|
||
format: 'webp',
|
||
})
|
||
|
||
// Upload processed preview image to S3
|
||
const processedFileName = getProcessedFileName(previewImage.name)
|
||
const previewFileName = `preview-${Date.now()}-${processedFileName}`
|
||
previewUrl = await uploadToS3(
|
||
processedBuffer,
|
||
previewFileName,
|
||
'image/webp'
|
||
)
|
||
}
|
||
|
||
// Update material record
|
||
const material = await prisma.material.update({
|
||
where: { id },
|
||
data: {
|
||
previewUrl,
|
||
productModel,
|
||
categoryName,
|
||
sceneName,
|
||
renderer,
|
||
authorName,
|
||
},
|
||
include: {
|
||
user: {
|
||
select: {
|
||
username: true,
|
||
},
|
||
},
|
||
},
|
||
})
|
||
|
||
// 转换BigInt为字符串
|
||
const materialData = {
|
||
...material,
|
||
zipFileSize: material.zipFileSize.toString()
|
||
}
|
||
|
||
return NextResponse.json(
|
||
{ message: '更新成功', material: materialData },
|
||
{ status: 200 }
|
||
)
|
||
} catch (error) {
|
||
console.error('Update error:', error)
|
||
return NextResponse.json(
|
||
{ error: '更新失败,请稍后再试' },
|
||
{ status: 500 }
|
||
)
|
||
}
|
||
}
|
||
|