flnxi-Wu/lib/category-fields.ts
WuYongJie 8705b9846a
Some checks failed
CI Check / check (push) Has been cancelled
feat: 统一弹窗样式系统与分类管理优化
- 创建统一的Modal组件,采用Apple风格设计
- 实现毛玻璃效果、圆角、动画和细边框描边
- 修复弹窗打开时背景滚动问题
- 修复分类管理中重复卡片和数组字符串显示问题
- 优化选项解析逻辑,添加去重和过滤机制
2025-11-25 09:37:00 +08:00

128 lines
3.8 KiB
TypeScript

/**
* 分类字段配置工具方法
* 用于读取/写入系统设置中「哪些字段需要同步到分类管理」的配置
*/
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<CategorySettingsRow> {
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<string[]> {
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<CategoryFieldOption[]> {
await ensureSystemSettingsOptionalColumns()
const fieldMap = new Map<string, CategoryFieldOption>()
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))
}