import { NextRequest, NextResponse } from 'next/server' import { getServerSession } from 'next-auth' import { authOptions } from '@/lib/auth' import { prisma } from '@/lib/prisma' import path from 'path' import JSZip from 'jszip' import { ensureMaterialDownloadLogsTable } from '@/lib/material-download-log' // SKU批量下载API export async function POST( request: NextRequest, { params }: { params: { id: string } } ) { try { const session = await getServerSession(authOptions) if (!session?.user || !(session.user as any).id) { return NextResponse.json({ error: '请先登录' }, { status: 401 }) } const userId = (session.user as any).id const user = await prisma.user.findUnique({ where: { id: userId }, select: { canDownload: true }, }) if (!user?.canDownload) { return NextResponse.json({ error: '您没有下载权限,请联系管理员' }, { status: 403 }) } const materialId = params.id const body = await request.json() const { skuIds } = body if (!skuIds || !Array.isArray(skuIds) || skuIds.length === 0) { return NextResponse.json({ error: '请选择要下载的SKU' }, { status: 400 }) } // 检查素材是否存在(排除已删除的素材) const material = await prisma.material.findFirst({ where: { id: materialId, deletedAt: null }, select: { id: true, productModel: true, materialType: true } }) if (!material) { return NextResponse.json({ error: '素材不存在或已被删除' }, { status: 404 }) } if (material.materialType !== '标准模型') { return NextResponse.json({ error: '只有标准模型类型才支持SKU批量下载' }, { status: 400 }) } // 获取选中的SKU列表 const skus = await prisma.materialSku.findMany({ where: { id: { in: skuIds }, materialId, deletedAt: null // 只获取未删除的SKU }, select: { id: true, skuName: true, filePath: true, fileName: true } }) if (skus.length === 0) { return NextResponse.json({ error: '没有找到可下载的SKU' }, { status: 404 }) } // 创建ZIP文件 const zip = new JSZip() let addedCount = 0 const fs = await import('fs/promises') for (const sku of skus) { try { const filePath = path.join(process.cwd(), 'uploads', sku.filePath) // 检查文件是否存在 try { await fs.access(filePath) } catch { console.warn(`SKU文件不存在: ${filePath}`) continue } // 读取文件并添加到ZIP const fileBuffer = await fs.readFile(filePath) const fileName = sku.fileName || `${sku.skuName}.zip` zip.file(fileName, fileBuffer) addedCount++ } catch (error) { console.error(`添加SKU文件失败: ${sku.id}`, error) // 继续处理其他文件 } } if (addedCount === 0) { return NextResponse.json({ error: '没有可下载的文件' }, { status: 404 }) } // 生成ZIP文件 const zipBuffer = await zip.generateAsync({ type: 'nodebuffer', compression: 'DEFLATE', compressionOptions: { level: 6 } }) const filename = `${material.productModel}_SKU批量下载_${Date.now()}.zip` recordBatchDownloadLog(materialId, userId).catch((error) => { console.error('[SKU Batch Download] 记录下载日志失败:', error) }) return new NextResponse(zipBuffer as any, { headers: { 'Content-Type': 'application/zip', 'Content-Length': zipBuffer.length.toString(), 'Content-Disposition': `attachment; filename="${encodeURIComponent(filename)}"`, }, }) } catch (error) { console.error('SKU批量下载失败:', error) return NextResponse.json( { error: '下载失败: ' + (error instanceof Error ? error.message : '未知错误') }, { status: 500 } ) } } async function recordBatchDownloadLog(materialId: string, userId: string) { await ensureMaterialDownloadLogsTable() await Promise.all([ prisma.materialDownloadLog.create({ data: { materialId, userId, downloadedAt: new Date(), }, }), prisma.material.update({ where: { id: materialId }, data: { downloadCount: { increment: 1, }, }, }), ]) }