WuYongJie d1c6efc79d
Some checks failed
CI Check / check (push) Has been cancelled
feat: NAS 部署与 Harbor 推送流程
2025-12-03 14:39:06 +08:00

164 lines
5.2 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'
import { Prisma } from '@prisma/client'
import { syncFieldPoolFromTemplates } from '@/lib/field-pool'
const baseSelect = {
id: true,
name: true,
description: true,
status: true,
materialType: true,
materialKind: true,
version: true,
fieldGroups: true,
displayConfig: true,
createdAt: true,
updatedAt: true,
fields: {
orderBy: { orderIndex: 'asc' },
select: {
id: true,
key: true,
label: true,
type: true,
required: true,
orderIndex: true,
layoutWidth: true,
validations: true,
optionsSource: true,
optionsStatic: true,
allowedExtensions: true,
visibleOnHomeFilter: true,
isSearchable: true,
isReadOnly: true,
addToCategory: true,
conditions: true,
createdAt: true,
updatedAt: true,
},
},
} as const
export async function GET() {
try {
const session = await getServerSession(authOptions)
if (!session || (session.user as any)?.role !== 'ADMIN') {
return NextResponse.json({ error: '无权限' }, { status: 403 })
}
const templates = await prisma.uploadTemplate.findMany({
orderBy: { updatedAt: 'desc' },
select: baseSelect,
})
return NextResponse.json(templates)
} catch (error) {
console.error('List upload templates error:', error)
return NextResponse.json({ error: '获取上传模板失败' }, { status: 500 })
}
}
export async function POST(req: NextRequest) {
let body: any = null
try {
const session = await getServerSession(authOptions)
if (!session || (session.user as any)?.role !== 'ADMIN') {
return NextResponse.json({ error: '无权限' }, { status: 403 })
}
body = await req.json()
const {
name,
description,
status = 'draft',
materialType,
materialKind,
fieldGroups,
displayConfig,
fields = [],
} = body || {}
if (!name) {
return NextResponse.json({ error: '模板名称不能为空' }, { status: 400 })
}
const finalMaterialType = typeof materialType === 'string' && materialType.trim() ? materialType.trim() : '其他'
// 仅允许 IMAGE / VIDEO / OTHER,避免脏数据
const rawKind = typeof materialKind === 'string' && materialKind.trim() ? materialKind.trim().toUpperCase() : 'IMAGE'
const allowedKinds = ['IMAGE', 'VIDEO', 'OTHER'] as const
const finalMaterialKind = (allowedKinds as readonly string[]).includes(rawKind) ? rawKind : 'IMAGE'
const formattedFields = Array.isArray(fields)
? fields.map((field: any, index: number) => ({
key: String(field.key || '').trim(),
label: String(field.label || '').trim() || `字段${index + 1}`,
type: String(field.type || 'text'),
required: !!field.required,
orderIndex: field.orderIndex ?? index,
layoutWidth: field.layoutWidth || 'full',
validations: field.validations ?? null,
optionsSource: field.optionsSource ?? null,
// optionsStatic 需要是字符串或 null,如果是数组则转换为 JSON 字符串
optionsStatic: field.optionsStatic !== null && field.optionsStatic !== undefined
? (Array.isArray(field.optionsStatic) ? JSON.stringify(field.optionsStatic) : String(field.optionsStatic))
: null,
allowedExtensions: field.allowedExtensions ?? null,
visibleOnHomeFilter: !!field.visibleOnHomeFilter,
isSearchable: !!field.isSearchable,
isReadOnly: !!field.isReadOnly,
addToCategory: !!field.addToCategory,
conditions: field.conditions ?? null,
}))
: []
const createData = {
name,
description: description ?? null,
status,
materialType: finalMaterialType,
materialKind: finalMaterialKind,
fieldGroups: fieldGroups ?? null,
displayConfig: displayConfig ?? null,
fields: formattedFields.length
? { createMany: { data: formattedFields } }
: undefined,
} as Prisma.UploadTemplateCreateInput
const template = await prisma.uploadTemplate.create({
data: createData,
select: baseSelect,
})
await syncFieldPoolFromTemplates()
return NextResponse.json(template, { status: 201 })
} catch (error: any) {
console.error('Create upload template error:', error)
console.error('Error details:', {
message: error?.message,
code: error?.code,
meta: error?.meta,
stack: error?.stack,
body: body,
})
// 如果是 Prisma 错误,返回更详细的错误信息
if (error?.code) {
if (error.code === 'P2002') {
return NextResponse.json({ error: '模板名称已存在,请使用其他名称' }, { status: 400 })
}
if (error.code === 'P2003') {
return NextResponse.json({ error: '关联数据不存在' }, { status: 400 })
}
}
// 返回更详细的错误信息
const errorMessage = error?.message || '创建上传模板失败'
return NextResponse.json({ error: errorMessage }, { status: 500 })
}
}