import { NextRequest, NextResponse } from 'next/server' import { getServerSession } from 'next-auth' import { authOptions } from '@/lib/auth' import { prisma } from '@/lib/prisma' // 获取所有使用店铺 export async function GET() { try { const categories = await prisma.category.findMany({ orderBy: { name: 'asc', }, }) // 优化:使用SQL聚合查询,避免N+1问题 const counts = await prisma.$queryRaw>` SELECT "categoryName" as "categoryName", COUNT(*)::bigint as count FROM "materials" WHERE "categoryName" IS NOT NULL AND "categoryName" != '' GROUP BY "categoryName" ` const countMap = new Map() counts.forEach(item => { countMap.set(item.categoryName, Number(item.count)) }) const categoriesWithCount = categories.map(category => ({ ...category, count: countMap.get(category.name) || 0, })) return NextResponse.json(categoriesWithCount) } catch (error) { console.error('Error fetching categories:', error) return NextResponse.json( { error: '获取店铺列表失败' }, { status: 500 } ) } } // 添加新的使用店铺 export async function POST(req: NextRequest) { try { const session = await getServerSession(authOptions) if (!session) { return NextResponse.json( { error: '请先登录' }, { status: 401 } ) } const { name } = await req.json() if (!name || !name.trim()) { return NextResponse.json( { error: '店铺名称不能为空' }, { status: 400 } ) } // 检查店铺是否已存在 const existing = await prisma.category.findUnique({ where: { name: name.trim() }, }) if (existing) { return NextResponse.json( { error: '该店铺已存在' }, { status: 400 } ) } // 创建新店铺 const category = await prisma.category.create({ data: { name: name.trim(), }, }) return NextResponse.json(category, { status: 201 }) } catch (error) { console.error('Error creating category:', error) return NextResponse.json( { error: '创建店铺失败' }, { status: 500 } ) } } // 更新店铺名称 export async function PATCH(req: NextRequest) { try { const session = await getServerSession(authOptions) if (!session || (session.user as any)?.role !== 'ADMIN') { return NextResponse.json( { error: '权限不足' }, { status: 403 } ) } const { id, name, options } = await req.json() if (!id || !name || !name.trim()) { return NextResponse.json( { error: '参数错误' }, { status: 400 } ) } // 检查新名称是否已存在(排除当前店铺) const existing = await prisma.category.findFirst({ where: { name: name.trim(), NOT: { id }, }, }) if (existing) { return NextResponse.json( { error: '该店铺名称已存在' }, { status: 400 } ) } // 获取旧名称 const oldCategory = await prisma.category.findUnique({ where: { id }, }) if (!oldCategory) { 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 category = await prisma.category.update({ where: { id }, data: { name: name.trim(), options: optionsValue, }, }) // 同步更新所有使用该分类的素材 await prisma.material.updateMany({ where: { categoryName: oldCategory.name }, data: { categoryName: name.trim() }, }) return NextResponse.json(category) } catch (error) { console.error('Error updating category:', error) return NextResponse.json( { error: '更新失败' }, { status: 500 } ) } } // 删除店铺 export async function DELETE(req: NextRequest) { try { const session = await getServerSession(authOptions) if (!session || (session.user as any)?.role !== 'ADMIN') { return NextResponse.json( { error: '权限不足' }, { status: 403 } ) } const { searchParams } = new URL(req.url) const id = searchParams.get('id') if (!id) { return NextResponse.json( { error: '缺少ID参数' }, { status: 400 } ) } // 删除店铺 await prisma.category.delete({ where: { id }, }) return NextResponse.json({ success: true }) } catch (error) { console.error('Error deleting category:', error) return NextResponse.json( { error: '删除失败' }, { status: 500 } ) } }