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

225 lines
5.4 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 { 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<Array<{
categoryName: string
count: bigint
}>>`
SELECT
"categoryName" as "categoryName",
COUNT(*)::bigint as count
FROM "materials"
WHERE "categoryName" IS NOT NULL AND "categoryName" != ''
GROUP BY "categoryName"
`
const countMap = new Map<string, number>()
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 }
)
}
}