WuYongJie f646b71813
Some checks failed
CI Check / check (push) Has been cancelled
chore: 初始化本地仓库并同步最近改动
2025-11-18 17:50:16 +08:00

194 lines
5.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 })
}
}