109 lines
3.7 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server'
import { getServerSession } from 'next-auth'
import { authOptions } from '@/lib/auth'
import { prisma } from '@/lib/prisma'
import { isCurrentSuperAdmin } from '@/lib/admin-permissions'
import { canUseSystemSettings } from '@/lib/license'
export const dynamic = 'force-dynamic'
const REQUIRED_CONFIRM_PHRASE = '执行字段迁移'
export async function POST(req: NextRequest) {
try {
const session = await getServerSession(authOptions)
if (!session || !(await isCurrentSuperAdmin(session))) {
return NextResponse.json(
{ error: '仅最高权限账号可执行素材字段迁移' },
{ status: 403 }
)
}
if (!(await canUseSystemSettings())) {
return NextResponse.json(
{ error: '当前许可证未包含系统设置功能,请联系管理员处理授权' },
{ status: 403 }
)
}
const body = await req.json().catch(() => ({}))
if (body?.confirmPhrase !== REQUIRED_CONFIRM_PHRASE) {
return NextResponse.json(
{
error: '素材字段迁移是高风险操作,请输入确认短语后再执行',
requiredConfirmPhrase: REQUIRED_CONFIRM_PHRASE,
},
{ status: 400 }
)
}
// 执行 SQL 迁移 - 需要分开执行每个命令
const commands = [
`ALTER TABLE "materials" ADD COLUMN IF NOT EXISTS "brandName" TEXT`,
`ALTER TABLE "materials" ADD COLUMN IF NOT EXISTS "seriesName" TEXT`,
`ALTER TABLE "materials" ADD COLUMN IF NOT EXISTS "skuCode" TEXT`,
`ALTER TABLE "materials" ADD COLUMN IF NOT EXISTS "materialTexture" TEXT`,
`ALTER TABLE "materials" ADD COLUMN IF NOT EXISTS "renderTime" TEXT`,
`ALTER TABLE "materials" ADD COLUMN IF NOT EXISTS "imageResolution" TEXT`,
`ALTER TABLE "materials" ADD COLUMN IF NOT EXISTS "colorMode" TEXT`,
`ALTER TABLE "materials" ADD COLUMN IF NOT EXISTS "displayImages" TEXT NOT NULL DEFAULT ''`,
`ALTER TABLE "materials" ADD COLUMN IF NOT EXISTS "platformName" TEXT NOT NULL DEFAULT ''`,
`ALTER TABLE "materials" ADD COLUMN IF NOT EXISTS "previewUrls" TEXT`,
`ALTER TABLE "materials" ADD COLUMN IF NOT EXISTS "metadata" TEXT`,
`ALTER TABLE "materials" ADD COLUMN IF NOT EXISTS "templateId" TEXT`,
`CREATE INDEX IF NOT EXISTS "materials_platformName_idx" ON "materials"("platformName")`,
]
// 执行每个 ALTER TABLE 和 CREATE INDEX 命令
for (const cmd of commands) {
try {
await prisma.$executeRawUnsafe(cmd)
} catch (error: any) {
// 如果列已存在,忽略错误
if (error?.message?.includes('already exists')) {
// 忽略
} else {
throw error
}
}
}
// 执行外键约束(使用 $queryRawUnsafe 因为包含 DO 块)
const fkCommand = `
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM pg_constraint
WHERE conname = 'materials_templateId_fkey'
) THEN
ALTER TABLE "materials" ADD CONSTRAINT "materials_templateId_fkey" FOREIGN KEY ("templateId") REFERENCES "UploadTemplate"("id") ON DELETE SET NULL ON UPDATE CASCADE;
END IF;
END $$;
`
try {
await prisma.$queryRawUnsafe(fkCommand)
} catch (error: any) {
// 忽略外键已存在的错误
if (!error?.message?.includes('already exists')) {
throw error
}
}
return NextResponse.json({
message: '迁移成功',
success: true
})
} catch (error) {
console.error('[Migrate] Error:', error)
return NextResponse.json(
{
error: '迁移失败',
details: error instanceof Error ? error.message : '未知错误'
},
{ status: 500 }
)
}
}