194 lines
5.9 KiB
TypeScript
194 lines
5.9 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server'
|
||
import { prisma } from '@/lib/prisma'
|
||
import { getServerSession } from 'next-auth'
|
||
import { authOptions } from '@/lib/auth'
|
||
|
||
// GET - 获取所有平台分类(包含数量统计)
|
||
export async function GET(request: NextRequest) {
|
||
try {
|
||
const platforms = await prisma.platform.findMany({
|
||
orderBy: { createdAt: 'asc' }
|
||
})
|
||
|
||
// 优化:使用SQL聚合查询,避免N+1问题
|
||
const counts = await prisma.$queryRaw<Array<{
|
||
platformName: string
|
||
count: bigint
|
||
}>>`
|
||
SELECT
|
||
"platformName" as "platformName",
|
||
COUNT(*)::bigint as count
|
||
FROM "materials"
|
||
WHERE "platformName" IS NOT NULL AND "platformName" != ''
|
||
GROUP BY "platformName"
|
||
`
|
||
|
||
const countMap = new Map<string, number>()
|
||
counts.forEach(item => {
|
||
countMap.set(item.platformName, Number(item.count))
|
||
})
|
||
|
||
const platformsWithCount = platforms.map(platform => ({
|
||
id: platform.id,
|
||
name: platform.name,
|
||
count: countMap.get(platform.name) || 0,
|
||
options: (platform as any).options,
|
||
}))
|
||
|
||
return NextResponse.json(platformsWithCount)
|
||
} catch (error) {
|
||
console.error('[Platforms] Get error:', error)
|
||
return NextResponse.json({ error: '获取平台分类失败' }, { status: 500 })
|
||
}
|
||
}
|
||
|
||
// POST - 创建新平台分类
|
||
export async function POST(request: NextRequest) {
|
||
try {
|
||
const session = await getServerSession(authOptions)
|
||
|
||
if (!session || session.user.role !== 'ADMIN') {
|
||
return NextResponse.json({ error: '需要管理员权限' }, { status: 403 })
|
||
}
|
||
|
||
const { name } = await request.json()
|
||
|
||
if (!name || !name.trim()) {
|
||
return NextResponse.json({ error: '平台分类名称不能为空' }, { status: 400 })
|
||
}
|
||
|
||
// 检查是否已存在
|
||
const existing = await prisma.platform.findUnique({
|
||
where: { name: name.trim() }
|
||
})
|
||
|
||
if (existing) {
|
||
return NextResponse.json({ error: '该平台分类已存在' }, { status: 400 })
|
||
}
|
||
|
||
const platform = await prisma.platform.create({
|
||
data: { name: name.trim() }
|
||
})
|
||
|
||
return NextResponse.json(platform, { status: 201 })
|
||
} catch (error) {
|
||
console.error('[Platforms] POST error:', error)
|
||
return NextResponse.json({ error: '创建平台分类失败' }, { status: 500 })
|
||
}
|
||
}
|
||
|
||
// PUT - 更新平台分类
|
||
export async function PUT(request: NextRequest) {
|
||
try {
|
||
const session = await getServerSession(authOptions)
|
||
|
||
if (!session || session.user.role !== 'ADMIN') {
|
||
return NextResponse.json({ error: '需要管理员权限' }, { status: 403 })
|
||
}
|
||
|
||
const { id, name, options } = await request.json()
|
||
|
||
if (!id || !name || !name.trim()) {
|
||
return NextResponse.json({ error: '平台分类ID和名称不能为空' }, { status: 400 })
|
||
}
|
||
|
||
// 检查是否存在其他同名平台
|
||
const existing = await prisma.platform.findFirst({
|
||
where: {
|
||
name: name.trim(),
|
||
NOT: { id }
|
||
}
|
||
})
|
||
|
||
if (existing) {
|
||
return NextResponse.json({ error: '该平台分类名称已被使用' }, { status: 400 })
|
||
}
|
||
|
||
// 获取旧名称
|
||
const oldPlatform = await prisma.platform.findUnique({ where: { id } })
|
||
if (!oldPlatform) {
|
||
return NextResponse.json({ error: '平台分类不存在' }, { status: 404 })
|
||
}
|
||
|
||
// 处理options:如果是数组,转换为JSON字符串;如果是字符串,直接使用
|
||
let optionsValue: string | null = null
|
||
if (options !== undefined && options !== null) {
|
||
if (Array.isArray(options)) {
|
||
optionsValue = JSON.stringify(options)
|
||
} else if (typeof options === 'string') {
|
||
// 支持每行一个选项的格式
|
||
const trimmed = options.trim()
|
||
if (trimmed && !trimmed.startsWith('[') && !trimmed.startsWith('{')) {
|
||
const lines = trimmed.split('\n').map(line => line.trim()).filter(Boolean)
|
||
optionsValue = lines.length > 0 ? JSON.stringify(lines) : null
|
||
} else {
|
||
optionsValue = trimmed || null
|
||
}
|
||
}
|
||
}
|
||
|
||
// 更新平台分类名称和选项
|
||
const platform = await prisma.platform.update({
|
||
where: { id },
|
||
data: {
|
||
name: name.trim(),
|
||
options: optionsValue,
|
||
} as any
|
||
})
|
||
|
||
// 更新所有使用该平台的素材
|
||
await prisma.material.updateMany({
|
||
where: { platformName: oldPlatform.name },
|
||
data: { platformName: name.trim() }
|
||
})
|
||
|
||
return NextResponse.json(platform)
|
||
} catch (error) {
|
||
console.error('[Platforms] PUT error:', error)
|
||
return NextResponse.json({ error: '更新平台分类失败' }, { status: 500 })
|
||
}
|
||
}
|
||
|
||
// DELETE - 删除平台分类
|
||
export async function DELETE(request: NextRequest) {
|
||
try {
|
||
const session = await getServerSession(authOptions)
|
||
|
||
if (!session || session.user.role !== 'ADMIN') {
|
||
return NextResponse.json({ error: '需要管理员权限' }, { status: 403 })
|
||
}
|
||
|
||
const { searchParams } = new URL(request.url)
|
||
const id = searchParams.get('id')
|
||
|
||
if (!id) {
|
||
return NextResponse.json({ error: '平台分类ID不能为空' }, { status: 400 })
|
||
}
|
||
|
||
// 检查是否有素材使用该平台
|
||
const platform = await prisma.platform.findUnique({ where: { id } })
|
||
if (!platform) {
|
||
return NextResponse.json({ error: '平台分类不存在' }, { status: 404 })
|
||
}
|
||
|
||
const materialCount = await prisma.material.count({
|
||
where: { platformName: platform.name }
|
||
})
|
||
|
||
if (materialCount > 0) {
|
||
return NextResponse.json({
|
||
error: `无法删除:有 ${materialCount} 个素材正在使用该平台分类`
|
||
}, { status: 400 })
|
||
}
|
||
|
||
// 删除平台分类
|
||
await prisma.platform.delete({ where: { id } })
|
||
|
||
return NextResponse.json({ message: '平台分类已删除' })
|
||
} catch (error) {
|
||
console.error('[Platforms] DELETE error:', error)
|
||
return NextResponse.json({ error: '删除平台分类失败' }, { status: 500 })
|
||
}
|
||
}
|
||
|