/** * 分类字段配置工具方法 * 用于读取/写入系统设置中「哪些字段需要同步到分类管理」的配置 */ import { prisma } from '@/lib/prisma' import { STANDARD_FIELDS } from './upload-template-presets' import { ensureSystemSettingsOptionalColumns } from './system-settings-columns' export const DEFAULT_MANAGED_CATEGORY_FIELDS = [ 'categoryName', 'sceneName', 'platformName', 'renderer', ] as const type CategorySettingsRow = { id: string categoryManagedFields: string | null } type CategoryFieldOption = { key: string label: string type: string source: 'standard' | 'custom' } const dedupeKeys = (keys: string[]) => Array.from(new Set(keys.filter(Boolean))) function parseStoredFields(value?: string | null): string[] | null { if (!value) return null try { const parsed = JSON.parse(value) if (Array.isArray(parsed)) { return dedupeKeys(parsed.map((item) => (typeof item === 'string' ? item : '')).filter(Boolean)) } } catch { return null } return null } async function ensureSystemSettingsId(): Promise { const existing = (await prisma.systemSettings.findFirst()) as unknown as CategorySettingsRow | null if (existing) { return existing } const created = (await prisma.systemSettings.create({ data: {} })) as unknown as CategorySettingsRow return created } export async function getManagedCategoryFields(): Promise { await ensureSystemSettingsOptionalColumns() const settings = (await prisma.systemSettings.findFirst()) as unknown as CategorySettingsRow | null const availableKeys = new Set((await getAvailableCategoryFields()).map(field => field.key)) const coerceToAvailable = (keys: string[] | null | undefined) => { if (!keys) return null const filtered = keys.filter((key) => availableKeys.has(key)) return filtered } const parsed = parseStoredFields(settings?.categoryManagedFields) const filteredParsed = coerceToAvailable(parsed) if (filteredParsed && filteredParsed.length > 0) { if (!parsed || filteredParsed.length !== parsed.length) { await saveManagedCategoryFields(filteredParsed) } return filteredParsed } const filteredDefaults = DEFAULT_MANAGED_CATEGORY_FIELDS.filter((key) => availableKeys.has(key)) await saveManagedCategoryFields(filteredDefaults) return filteredDefaults } export async function saveManagedCategoryFields(fieldKeys: string[]) { await ensureSystemSettingsOptionalColumns() const unique = dedupeKeys(fieldKeys) const payload = JSON.stringify(unique) const settings = await ensureSystemSettingsId() await prisma.systemSettings.update({ where: { id: settings.id }, // Prisma 类型缓存未及时刷新,临时使用 any 以避免阻塞,可在下一次 generate 后移除 data: { categoryManagedFields: payload } as any, }) return unique } export async function getAvailableCategoryFields(): Promise { await ensureSystemSettingsOptionalColumns() const fieldMap = new Map() Object.values(STANDARD_FIELDS).forEach((field) => { if (field.type === 'select') { fieldMap.set(field.key, { key: field.key, label: field.label, type: field.type, source: 'standard', }) } }) const customFields = await prisma.uploadField.findMany({ where: { type: 'select' }, select: { key: true, label: true }, distinct: ['key'], orderBy: { key: 'asc' }, }) customFields.forEach((field) => { if (!field.key) return if (!fieldMap.has(field.key)) { fieldMap.set(field.key, { key: field.key, label: field.label || field.key, type: 'select', source: 'custom', }) } }) return Array.from(fieldMap.values()).sort((a, b) => a.key.localeCompare(b.key)) }