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 { buildDepartmentDescendants, isDepartmentWithinScope } from '@/lib/departments' export const dynamic = 'force-dynamic' export async function POST(req: NextRequest) { try { const session = await getServerSession(authOptions) if (!session || (session.user as any).role !== 'ADMIN') { return NextResponse.json({ error: '无操作权限' }, { status: 403 }) } const { materialId, isPremium } = await req.json() if (!materialId || typeof isPremium !== 'boolean') { return NextResponse.json({ error: '参数错误' }, { status: 400 }) } const operatorId = (session.user as any).id as string const operator = await prisma.user.findUnique({ where: { id: operatorId }, select: { id: true, role: true, isSuperAdmin: true, department: true, managedDepartment: true, }, }) if (!operator) { return NextResponse.json({ error: '未找到当前用户信息' }, { status: 403 }) } const targetMaterial = await prisma.material.findUnique({ where: { id: materialId }, select: { id: true, isPremium: true, user: { select: { id: true, department: true, }, }, }, }) if (!targetMaterial) { return NextResponse.json({ error: '素材不存在' }, { status: 404 }) } if (!operator.isSuperAdmin) { const operatorScope = (operator.managedDepartment || operator.department || '').trim() if (!operatorScope) { return NextResponse.json( { error: '尚未配置所属组织,无法设置精品' }, { status: 403 } ) } const targetDepartment = (targetMaterial.user?.department || '').trim() if (!targetDepartment) { return NextResponse.json( { error: '目标素材未设置所属组织,暂不支持跨组织加精' }, { status: 403 } ) } let hasAccess = targetDepartment === operatorScope || targetDepartment.startsWith(`${operatorScope}-`) if (!hasAccess) { const departments = await prisma.department.findMany({ select: { name: true } }) const descendantMap = buildDepartmentDescendants(departments) hasAccess = isDepartmentWithinScope(operatorScope, targetDepartment, descendantMap) } if (!hasAccess) { return NextResponse.json( { error: '只能为所属组织及下级组织的素材设置精品' }, { status: 403 } ) } } if (targetMaterial.isPremium === isPremium) { return NextResponse.json({ success: true, material: targetMaterial }) } if (isPremium) { const settings = await prisma.systemSettings.findFirst({ select: { premiumRatio: true }, }) const ratio = settings?.premiumRatio ?? 10 if (ratio <= 0) { return NextResponse.json( { error: '当前已禁用精品作品,请先在系统设置中开启' }, { status: 400 } ) } const [totalMaterials, currentPremiumCount] = await Promise.all([ prisma.material.count(), prisma.material.count({ where: { isPremium: true } }), ]) if (totalMaterials === 0) { return NextResponse.json( { error: '暂无素材,无法设置精品作品' }, { status: 400 } ) } const allowedCount = Math.max(1, Math.floor((totalMaterials * ratio) / 100)) if (currentPremiumCount >= allowedCount) { return NextResponse.json( { error: `精品作品已达上限(${allowedCount} 条),请调整比例或取消其他素材的精品状态`, }, { status: 400 } ) } } const updated = await prisma.material.update({ where: { id: materialId }, data: { isPremium }, select: { id: true, isPremium: true, }, }) // 记录切换精品状态日志 await createMaterialLog({ materialId, userId: operatorId, action: 'TOGGLE_PREMIUM', changes: { isPremium: { oldValue: targetMaterial.isPremium, newValue: isPremium, }, }, }) return NextResponse.json({ success: true, material: updated }) } catch (error) { console.error('[MaterialPremium] POST error:', error) return NextResponse.json({ error: '更新精品状态失败' }, { status: 500 }) } }