import { NextRequest, NextResponse } from 'next/server'; import { getServerSession } from 'next-auth'; import { authOptions } from '@/lib/auth'; import { prisma } from '@/lib/prisma'; import { createMaterialLog } from '@/lib/material-log'; import { getOriginalTaskNo } from '@/lib/product-package'; // POST /api/materials/restore - 恢复已删除的素材 export async function POST(request: NextRequest) { try { const session = await getServerSession(authOptions); if (!session?.user || !(session.user as any).id) { return NextResponse.json({ error: '未登录' }, { status: 401 }); } const userRole = (session.user as any).role; if (userRole !== 'ADMIN') { return NextResponse.json({ error: '无权限' }, { status: 403 }); } const { id } = await request.json(); if (!id) { return NextResponse.json({ error: '缺少素材ID' }, { status: 400 }); } // 检查素材是否存在 const material = await prisma.material.findUnique({ where: { id }, }); if (!material) { return NextResponse.json({ error: '素材不存在' }, { status: 404 }); } const restoredTaskNo = getOriginalTaskNo((material as any).taskNo); if (restoredTaskNo && restoredTaskNo !== (material as any).taskNo) { const existingMaterial = await prisma.material.findFirst({ where: { taskNo: restoredTaskNo, deletedAt: null, NOT: { id }, } as any, select: { id: true, productModel: true, materialType: true, }, }); if (existingMaterial) { return NextResponse.json( { error: `恢复失败:原任务号 ${restoredTaskNo} 已被素材 ${existingMaterial.productModel}(${existingMaterial.materialType})占用` }, { status: 409 } ); } } if (material.materialType === '标准模型') { const materialSkus = await prisma.materialSku.findMany({ where: { materialId: id }, select: { skuName: true, }, }); const skuNames = Array.from( new Set( materialSkus .map((sku) => String(sku.skuName || '').trim().toUpperCase()) .filter(Boolean) ) ); if (skuNames.length > 0) { const conflictingSkus = await prisma.materialSku.findMany({ where: { deletedAt: null, skuName: { in: skuNames, mode: 'insensitive', }, materialId: { not: id, }, material: { is: { materialType: '标准模型', deletedAt: null, }, }, }, select: { skuName: true, material: { select: { productModel: true, }, }, }, take: 5, }); if (conflictingSkus.length > 0) { const conflictSummary = conflictingSkus .map((item) => `${item.skuName}(${item.material.productModel})`) .join('、'); return NextResponse.json( { error: `恢复失败:以下 SKU 已被其他标准模型占用:${conflictSummary}` }, { status: 409 } ); } } } // 恢复素材(将 deletedAt 设为 null) await prisma.$transaction([ prisma.material.update({ where: { id }, data: { deletedAt: null, ...(restoredTaskNo && restoredTaskNo !== (material as any).taskNo ? { taskNo: restoredTaskNo } : {}), }, }), prisma.materialSku.updateMany({ where: { materialId: id, }, data: { deletedAt: null, }, }), ]); // 记录操作日志 const userId = (session.user as any).id; await createMaterialLog({ materialId: id, userId, action: 'RESTORE', changes: { deletedAt: { oldValue: material.deletedAt?.toISOString() || null, newValue: null, }, ...(restoredTaskNo && restoredTaskNo !== (material as any).taskNo ? { taskNo: { oldValue: (material as any).taskNo || null, newValue: restoredTaskNo, }, } : {}), }, }); return NextResponse.json({ message: '恢复成功' }); } catch (error: any) { // 兼容旧版本数据库(没有 deletedAt 字段) if (error?.meta?.column?.includes('deletedAt')) { return NextResponse.json({ error: '恢复功能需要先运行数据库迁移' }, { status: 400 }); } console.error('[Materials] RESTORE error:', error); return NextResponse.json({ error: '恢复失败' }, { status: 500 }); } }