139 lines
4.0 KiB
TypeScript
139 lines
4.0 KiB
TypeScript
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 { canManageMaterial, getMaterialPermissionActor } from '@/lib/material-permissions'
|
|
|
|
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 actor = await getMaterialPermissionActor(session)
|
|
if (!actor) {
|
|
return NextResponse.json({ error: '未找到当前用户信息' }, { status: 403 })
|
|
}
|
|
const operatorId = actor.id
|
|
|
|
const targetMaterial = await prisma.material.findUnique({
|
|
where: { id: materialId },
|
|
select: {
|
|
id: true,
|
|
userId: true,
|
|
isPremium: true,
|
|
user: {
|
|
select: {
|
|
id: true,
|
|
department: true,
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
if (!targetMaterial) {
|
|
return NextResponse.json({ error: '素材不存在' }, { status: 404 })
|
|
}
|
|
|
|
if (!actor.isSuperAdmin) {
|
|
const operatorScope = (actor.managedDepartment || '').trim()
|
|
if (!operatorScope) {
|
|
return NextResponse.json(
|
|
{ error: '尚未配置管理组织,无法设置精品' },
|
|
{ status: 403 }
|
|
)
|
|
}
|
|
if (!(targetMaterial.user?.department || '').trim()) {
|
|
return NextResponse.json(
|
|
{ error: '目标素材未设置所属组织,暂不支持跨组织加精' },
|
|
{ status: 403 }
|
|
)
|
|
}
|
|
|
|
if (!(await canManageMaterial(targetMaterial, actor))) {
|
|
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 })
|
|
}
|
|
}
|