flnxi-Wu/lib/upload-template-presets.ts
2026-05-25 14:52:24 +08:00

263 lines
8.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

export type StandardFieldConfig = {
key: string
label: string
type: string
required: boolean
layoutWidth: string
visibleOnHomeFilter: boolean
isSearchable: boolean
addToCategory?: boolean
optionsStatic?: string
isReadOnly?: boolean
}
export const BUILTIN_TEMPLATE_KEYS = [
'3dmax-material',
'psd-material',
'audio-material',
'video-material',
'model-material',
'other-material',
] as const
export const BUILTIN_TEMPLATE_NAMES: Record<string, string> = {
'3dmax-material': '3DMAX 素材模板',
'psd-material': 'PSD 素材模板',
'audio-material': '音频素材模板',
'video-material': '视频素材模板',
'model-material': '模特素材模板',
'other-material': '其他素材模板',
}
export const BUILTIN_TEMPLATE_DESCRIPTIONS: Record<string, string> = {
'3dmax-material': '适用于 3D 模型类素材,覆盖渲染器、SKU 与品牌等核心字段。',
'psd-material': '针对平面设计 PSD 素材,包含品牌、颜色模式和输出分辨率。',
'audio-material': '适用于音频文件素材,支持 MP3、WAV、FLAC、AAC 等格式。',
'video-material': '适用于视频文件素材。',
'model-material': '用于模特/人像素材,关注拍摄场景与负责作者。',
'other-material': '适用于其他类型的素材。',
}
export const BUILTIN_TEMPLATE_TYPES: Record<string, string> = {
'3dmax-material': '3DMAX',
'psd-material': 'PSD',
'audio-material': '音频',
'video-material': '视频',
'model-material': '模特',
'other-material': '其他',
}
export const BUILTIN_TEMPLATE_KINDS: Record<string, 'IMAGE' | 'VIDEO' | 'AUDIO' | 'OTHER'> = {
'3dmax-material': 'IMAGE',
'psd-material': 'IMAGE',
'audio-material': 'AUDIO',
'video-material': 'VIDEO',
'model-material': 'IMAGE',
'other-material': 'OTHER',
}
// 注意:下拉选项字段的 optionsStatic 不再硬编码默认值
// 用户可以在后台分类管理中自由添加/删除选项
export const STANDARD_FIELDS: Record<string, StandardFieldConfig> = {
productModel: { key: 'productModel', label: 'SPU型号', type: 'text', required: true, layoutWidth: 'full', visibleOnHomeFilter: false, isSearchable: true },
categoryName: {
key: 'categoryName',
label: '使用店铺',
type: 'select',
required: false,
layoutWidth: 'full',
visibleOnHomeFilter: true,
isSearchable: true,
addToCategory: true,
},
sceneName: {
key: 'sceneName',
label: '场景类别',
type: 'select',
required: false,
layoutWidth: 'full',
visibleOnHomeFilter: true,
isSearchable: true,
addToCategory: true,
},
platformName: {
key: 'platformName',
label: '平台分类',
type: 'text',
required: false,
layoutWidth: 'half',
visibleOnHomeFilter: false,
isSearchable: true,
},
renderer: {
key: 'renderer',
label: '渲染器',
type: 'select',
required: false,
layoutWidth: 'full',
visibleOnHomeFilter: false,
isSearchable: true,
addToCategory: true,
},
brandName: {
key: 'brandName',
label: '品牌名称',
type: 'text',
required: false,
layoutWidth: 'half',
visibleOnHomeFilter: false,
isSearchable: true,
},
seriesName: {
key: 'seriesName',
label: '系列/产品线',
type: 'text',
required: false,
layoutWidth: 'half',
visibleOnHomeFilter: false,
isSearchable: true,
},
skuCode: { key: 'skuCode', label: 'SKU编码', type: 'text', required: false, layoutWidth: 'half', visibleOnHomeFilter: false, isSearchable: true },
materialTexture: {
key: 'materialTexture',
label: '材质/工艺',
type: 'text',
required: false,
layoutWidth: 'half',
visibleOnHomeFilter: false,
isSearchable: true,
},
renderTime: { key: 'renderTime', label: '渲染耗时', type: 'text', required: false, layoutWidth: 'half', visibleOnHomeFilter: false, isSearchable: false },
imageResolution: { key: 'imageResolution', label: '输出分辨率', type: 'text', required: false, layoutWidth: 'half', visibleOnHomeFilter: false, isSearchable: false },
colorMode: { key: 'colorMode', label: '颜色模式', type: 'text', required: false, layoutWidth: 'half', visibleOnHomeFilter: false, isSearchable: false },
authorName: { key: 'authorName', label: '作者', type: 'text', required: false, layoutWidth: 'half', visibleOnHomeFilter: false, isSearchable: true },
audioDuration: { key: 'audioDuration', label: '时长', type: 'text', required: false, layoutWidth: 'half', visibleOnHomeFilter: false, isSearchable: false, isReadOnly: true },
audioCategory: {
key: 'audioCategory',
label: '音频分类',
type: 'select',
required: true,
layoutWidth: 'full',
visibleOnHomeFilter: true,
isSearchable: true,
addToCategory: true,
},
audioScene: {
key: 'audioScene',
label: '音频使用场景',
type: 'select',
required: true,
layoutWidth: 'full',
visibleOnHomeFilter: true,
isSearchable: true,
addToCategory: true,
},
}
export const BASE_TEMPLATE_FIELDS = ['productModel', 'categoryName', 'sceneName'] as const
export const BUILTIN_TEMPLATE_FIELDS: Record<string, string[]> = {
'3dmax-material': ['productModel', 'categoryName', 'sceneName', 'renderer'],
'psd-material': [...BASE_TEMPLATE_FIELDS],
'audio-material': ['productModel', 'audioCategory', 'audioScene', 'authorName'],
'video-material': [...BASE_TEMPLATE_FIELDS],
'model-material': [...BASE_TEMPLATE_FIELDS],
'other-material': [...BASE_TEMPLATE_FIELDS],
}
export type BuiltinTemplateField = {
id: string
key: string
label: string
type: string
required: boolean
orderIndex: number
layoutWidth?: string | null
validations: null
optionsSource: null
optionsStatic: string | null
allowedExtensions: null
visibleOnHomeFilter: boolean
isSearchable: boolean
isReadOnly?: boolean
addToCategory?: boolean
conditions: null
}
export type BuiltinTemplate = {
id: string
name: string
description: string
status: 'active'
materialType: string
materialKind: 'IMAGE' | 'VIDEO' | 'AUDIO' | 'OTHER'
isBuiltin: true
fields: BuiltinTemplateField[]
}
export function createBuiltinTemplate(key: string): BuiltinTemplate {
const fields = BUILTIN_TEMPLATE_FIELDS[key] || []
const requireRenderer = key === '3dmax-material'
const isAudioTemplate = key === 'audio-material'
const overrides: Record<
string,
Partial<{
required: boolean
visibleOnHomeFilter: boolean
isSearchable: boolean
label: string
}>
> = {
productModel: { required: true, isSearchable: true },
categoryName: { required: true, visibleOnHomeFilter: true, isSearchable: true },
sceneName: { required: true, visibleOnHomeFilter: true, isSearchable: true },
}
if (requireRenderer) {
overrides.renderer = { required: true, isSearchable: true }
}
// 音频模板的字段标签覆盖
if (isAudioTemplate) {
overrides.productModel = { ...overrides.productModel, label: '音频名称' }
// audioCategory 和 audioScene 是独立字段,不需要覆盖
}
return {
id: `builtin-${key}`,
name: BUILTIN_TEMPLATE_NAMES[key] || key,
description: BUILTIN_TEMPLATE_DESCRIPTIONS[key] || '',
status: 'active',
materialType: BUILTIN_TEMPLATE_TYPES[key] || '其他',
materialKind: BUILTIN_TEMPLATE_KINDS[key] || 'IMAGE',
isBuiltin: true,
fields: fields
.map((fieldKey, index) => {
const fieldConfig = STANDARD_FIELDS[fieldKey]
if (!fieldConfig) return null
const override = overrides[fieldKey] || {}
return {
id: `builtin-${key}-${fieldKey}`,
key: fieldConfig.key,
label: override.label ?? fieldConfig.label,
type: fieldConfig.type,
required: override.required ?? fieldConfig.required,
orderIndex: index,
layoutWidth: fieldConfig.layoutWidth,
validations: null,
optionsSource: null,
optionsStatic: fieldConfig.optionsStatic || null,
allowedExtensions: null,
visibleOnHomeFilter: override.visibleOnHomeFilter ?? fieldConfig.visibleOnHomeFilter ?? false,
isSearchable: override.isSearchable ?? fieldConfig.isSearchable ?? false,
isReadOnly: fieldConfig.isReadOnly ?? false,
addToCategory: fieldConfig.addToCategory ?? false,
conditions: null,
}
})
.filter(Boolean) as BuiltinTemplateField[],
}
}