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

232 lines
7.6 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server'
import { getServerSession } from 'next-auth'
import { authOptions } from '@/lib/auth'
import { prisma } from '@/lib/prisma'
import { syncFieldPoolFromTemplates } from '@/lib/field-pool'
const selectTemplate = {
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
async function ensureAdmin() {
const session = await getServerSession(authOptions)
if (!session || (session.user as any)?.role !== 'ADMIN') {
return null
}
return session
}
export async function GET(_: NextRequest, { params }: { params: { id: string } }) {
try {
const session = await ensureAdmin()
if (!session) return NextResponse.json({ error: '无权限' }, { status: 403 })
const template = await prisma.uploadTemplate.findUnique({
where: { id: params.id },
select: selectTemplate,
})
if (!template) return NextResponse.json({ error: '模板不存在' }, { status: 404 })
return NextResponse.json(template)
} catch (error) {
console.error('Get upload template error:', error)
return NextResponse.json({ error: '获取模板失败' }, { status: 500 })
}
}
export async function PUT(req: NextRequest, { params }: { params: { id: string } }) {
try {
const session = await ensureAdmin()
if (!session) return NextResponse.json({ error: '无权限' }, { status: 403 })
const { id } = params
const body = await req.json()
const {
name,
description,
status,
materialType,
materialKind,
fieldGroups,
displayConfig,
fields,
version,
} = body || {}
const existing = await prisma.uploadTemplate.findUnique({
where: { id },
select: { id: true, version: true },
})
if (!existing) return NextResponse.json({ error: '模板不存在' }, { status: 404 })
if (version !== undefined && version !== existing.version) {
return NextResponse.json({ error: '模板已被其他人修改,请刷新后重试' }, { status: 409 })
}
const updateData: any = {}
if (name !== undefined) updateData.name = name
if (description !== undefined) updateData.description = description
if (status !== undefined) updateData.status = status
if (fieldGroups !== undefined) updateData.fieldGroups = fieldGroups
if (displayConfig !== undefined) updateData.displayConfig = displayConfig
if (materialType !== undefined && typeof materialType === 'string') {
updateData.materialType = materialType.trim() || '其他'
}
if (materialKind !== undefined && typeof materialKind === 'string') {
const rawKind = materialKind.trim().toUpperCase()
const allowedKinds = ['IMAGE', 'VIDEO', 'OTHER'] as const
updateData.materialKind = (allowedKinds as readonly string[]).includes(rawKind) ? rawKind : 'IMAGE'
}
updateData.version = (existing.version || 1) + 1
const formattedFields = Array.isArray(fields)
? fields.map((field: any, index: number) => ({
id: field.id ?? null,
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: field.optionsStatic ?? null,
allowedExtensions: field.allowedExtensions ?? null,
visibleOnHomeFilter: !!field.visibleOnHomeFilter,
isSearchable: !!field.isSearchable,
isReadOnly: !!field.isReadOnly,
addToCategory: !!field.addToCategory,
conditions: field.conditions ?? null,
}))
: null
const result = await prisma.$transaction(async (tx) => {
const updated = await tx.uploadTemplate.update({
where: { id },
data: updateData,
select: { id: true },
})
if (formattedFields) {
const incomingIds = formattedFields.map((f) => f.id).filter(Boolean) as string[]
await tx.uploadField.deleteMany({
where: {
templateId: id,
id: { notIn: incomingIds.length ? incomingIds : [''] },
},
})
for (const field of formattedFields) {
if (field.id) {
await tx.uploadField.update({
where: { id: field.id },
data: {
key: field.key,
label: field.label,
type: field.type,
required: field.required,
orderIndex: field.orderIndex,
layoutWidth: field.layoutWidth,
validations: field.validations,
optionsSource: field.optionsSource,
optionsStatic: field.optionsStatic,
allowedExtensions: field.allowedExtensions,
visibleOnHomeFilter: field.visibleOnHomeFilter,
isSearchable: field.isSearchable,
isReadOnly: field.isReadOnly,
addToCategory: field.addToCategory,
conditions: field.conditions,
},
})
} else {
await tx.uploadField.create({
data: {
templateId: id,
key: field.key,
label: field.label,
type: field.type,
required: field.required,
orderIndex: field.orderIndex,
layoutWidth: field.layoutWidth,
validations: field.validations,
optionsSource: field.optionsSource,
optionsStatic: field.optionsStatic,
allowedExtensions: field.allowedExtensions,
visibleOnHomeFilter: field.visibleOnHomeFilter,
isSearchable: field.isSearchable,
isReadOnly: field.isReadOnly,
addToCategory: field.addToCategory,
conditions: field.conditions,
},
})
}
}
}
return updated.id
})
const template = await prisma.uploadTemplate.findUnique({
where: { id: result },
select: selectTemplate,
})
await syncFieldPoolFromTemplates()
return NextResponse.json(template)
} catch (error) {
console.error('Update upload template error:', error)
return NextResponse.json({ error: '更新模板失败' }, { status: 500 })
}
}
export async function DELETE(_: NextRequest, { params }: { params: { id: string } }) {
try {
const session = await ensureAdmin()
if (!session) return NextResponse.json({ error: '无权限' }, { status: 403 })
await prisma.uploadTemplate.delete({ where: { id: params.id } })
await syncFieldPoolFromTemplates()
return NextResponse.json({ success: true })
} catch (error) {
console.error('Delete upload template error:', error)
return NextResponse.json({ error: '删除模板失败' }, { status: 500 })
}
}