Some checks failed
CI Check / check (push) Has been cancelled
- 创建统一的Modal组件,采用Apple风格设计 - 实现毛玻璃效果、圆角、动画和细边框描边 - 修复弹窗打开时背景滚动问题 - 修复分类管理中重复卡片和数组字符串显示问题 - 优化选项解析逻辑,添加去重和过滤机制
193 lines
6.5 KiB
TypeScript
193 lines
6.5 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server'
|
||
import { getServerSession } from 'next-auth'
|
||
import { authOptions } from '@/lib/auth'
|
||
import { prisma } from '@/lib/prisma'
|
||
import { defaultLogos, featureFlags } from '@/lib/config'
|
||
import { cache } from '@/lib/cache'
|
||
import { ensureSystemSettingsOptionalColumns } from '@/lib/system-settings-columns'
|
||
|
||
const CACHE_KEY = 'system-settings'
|
||
const CACHE_TTL = 60000 // 1分钟缓存
|
||
|
||
// GET - 获取系统设置(带缓存)
|
||
export async function GET() {
|
||
try {
|
||
await ensureSystemSettingsOptionalColumns()
|
||
// 先尝试从缓存获取
|
||
const cachedSettings = cache.get(CACHE_KEY)
|
||
if (cachedSettings) {
|
||
return NextResponse.json(cachedSettings)
|
||
}
|
||
|
||
// 获取或创建系统设置
|
||
// 使用 select 来避免查询不存在的字段
|
||
let settings = await prisma.systemSettings.findFirst({
|
||
select: {
|
||
id: true,
|
||
headerBgColor: true,
|
||
siteName: true,
|
||
updatedAt: true,
|
||
createdAt: true,
|
||
headerLogoUrl: true,
|
||
loginLogoUrl: true,
|
||
s3AccessKey: true,
|
||
s3Bucket: true,
|
||
s3Endpoint: true,
|
||
s3PublicUrl: true,
|
||
s3Region: true,
|
||
s3SecretKey: true,
|
||
enableRegistration: true,
|
||
enableUserActivation: true,
|
||
enableAiImageEdit: true,
|
||
enableTunnelService: true,
|
||
// enabledBuiltinTemplates 可能不存在,先不查询
|
||
},
|
||
}) as any
|
||
|
||
// 如果字段存在,尝试查询它
|
||
try {
|
||
const fullSettings = await prisma.$queryRaw<Array<{ enabledBuiltinTemplates?: string | null }>>`
|
||
SELECT "enabledBuiltinTemplates" FROM "system_settings" LIMIT 1
|
||
`
|
||
if (fullSettings[0] && settings) {
|
||
settings.enabledBuiltinTemplates = fullSettings[0].enabledBuiltinTemplates
|
||
}
|
||
} catch {
|
||
// 字段不存在,设置为 null(表示全部启用)
|
||
if (settings) {
|
||
settings.enabledBuiltinTemplates = null
|
||
}
|
||
}
|
||
|
||
if (!settings) {
|
||
// 如果不存在,创建默认设置
|
||
settings = await prisma.systemSettings.create({
|
||
data: {
|
||
headerBgColor: '#1f2937',
|
||
headerLogoUrl: defaultLogos.header,
|
||
loginLogoUrl: defaultLogos.login,
|
||
siteName: '由壹点3D素材',
|
||
enableUserActivation: false,
|
||
enableRegistration: true,
|
||
enableAiImageEdit: featureFlags.aiEditEnabled,
|
||
enableTunnelService: featureFlags.tunnelEnabled,
|
||
},
|
||
})
|
||
}
|
||
|
||
// 存入缓存
|
||
cache.set(CACHE_KEY, settings, CACHE_TTL)
|
||
|
||
return NextResponse.json(settings)
|
||
} catch (error) {
|
||
console.error('[SystemSettings] Get error:', error)
|
||
return NextResponse.json(
|
||
{ error: '获取系统设置失败' },
|
||
{ status: 500 }
|
||
)
|
||
}
|
||
}
|
||
|
||
// PUT - 更新系统设置(仅管理员)
|
||
export async function PUT(request: NextRequest) {
|
||
try {
|
||
await ensureSystemSettingsOptionalColumns()
|
||
const session = await getServerSession(authOptions)
|
||
|
||
const isSuperAdmin = (session?.user as any)?.isSuperAdmin
|
||
if (!session || session.user.role !== 'ADMIN') {
|
||
return NextResponse.json(
|
||
{ error: '无权限' },
|
||
{ status: 403 }
|
||
)
|
||
}
|
||
|
||
const body = await request.json()
|
||
const {
|
||
headerBgColor,
|
||
siteName,
|
||
headerLogoUrl,
|
||
loginLogoUrl,
|
||
s3Endpoint,
|
||
s3AccessKey,
|
||
s3SecretKey,
|
||
s3Bucket,
|
||
s3Region,
|
||
s3PublicUrl,
|
||
enableUserActivation,
|
||
enableRegistration,
|
||
enableAiImageEdit,
|
||
enableTunnelService,
|
||
enabledBuiltinTemplates,
|
||
} = body
|
||
|
||
// 只有最高权限账号可以修改 enableUserActivation
|
||
if (
|
||
(enableUserActivation !== undefined ||
|
||
enableAiImageEdit !== undefined ||
|
||
enableTunnelService !== undefined) &&
|
||
!isSuperAdmin
|
||
) {
|
||
return NextResponse.json(
|
||
{ error: '只有最高权限账号可以修改受保护的功能开关' },
|
||
{ status: 403 }
|
||
)
|
||
}
|
||
|
||
// 获取或创建系统设置
|
||
let settings = await prisma.systemSettings.findFirst()
|
||
|
||
if (!settings) {
|
||
// 创建
|
||
settings = await prisma.systemSettings.create({
|
||
data: {
|
||
headerBgColor: headerBgColor || '#1f2937',
|
||
headerLogoUrl: headerLogoUrl ?? defaultLogos.header,
|
||
loginLogoUrl: loginLogoUrl ?? defaultLogos.login,
|
||
siteName: siteName || '由壹点3D素材',
|
||
enableUserActivation: enableUserActivation !== undefined ? enableUserActivation : false,
|
||
enableRegistration: enableRegistration !== undefined ? enableRegistration : true,
|
||
enableAiImageEdit:
|
||
enableAiImageEdit !== undefined ? enableAiImageEdit : featureFlags.aiEditEnabled,
|
||
enableTunnelService:
|
||
enableTunnelService !== undefined ? enableTunnelService : featureFlags.tunnelEnabled,
|
||
}
|
||
})
|
||
} else {
|
||
// 更新
|
||
const updateData: any = {}
|
||
if (headerBgColor !== undefined) updateData.headerBgColor = headerBgColor
|
||
if (siteName !== undefined) updateData.siteName = siteName
|
||
if (headerLogoUrl !== undefined) updateData.headerLogoUrl = headerLogoUrl
|
||
if (loginLogoUrl !== undefined) updateData.loginLogoUrl = loginLogoUrl
|
||
if (s3Endpoint !== undefined) updateData.s3Endpoint = s3Endpoint
|
||
if (s3AccessKey !== undefined) updateData.s3AccessKey = s3AccessKey
|
||
if (s3SecretKey !== undefined) updateData.s3SecretKey = s3SecretKey
|
||
if (s3Bucket !== undefined) updateData.s3Bucket = s3Bucket
|
||
if (s3Region !== undefined) updateData.s3Region = s3Region
|
||
if (s3PublicUrl !== undefined) updateData.s3PublicUrl = s3PublicUrl
|
||
if (enableUserActivation !== undefined) updateData.enableUserActivation = enableUserActivation
|
||
if (enableRegistration !== undefined) updateData.enableRegistration = enableRegistration
|
||
if (enableAiImageEdit !== undefined) updateData.enableAiImageEdit = enableAiImageEdit
|
||
if (enableTunnelService !== undefined) updateData.enableTunnelService = enableTunnelService
|
||
if (enabledBuiltinTemplates !== undefined) updateData.enabledBuiltinTemplates = enabledBuiltinTemplates
|
||
|
||
settings = await prisma.systemSettings.update({
|
||
where: { id: settings.id },
|
||
data: updateData,
|
||
})
|
||
}
|
||
|
||
// 清除缓存,强制下次重新加载
|
||
cache.delete(CACHE_KEY)
|
||
|
||
return NextResponse.json(settings)
|
||
} catch (error) {
|
||
console.error('Update system settings error:', error)
|
||
return NextResponse.json(
|
||
{ error: '更新系统设置失败' },
|
||
{ status: 500 }
|
||
)
|
||
}
|
||
}
|