flnxi-Wu/scripts/fix-missing-templates.ts
WuYongJie 63ec6b7dfb fix: 修复排行榜按钮消失、tag排序和输入框浅色模式问题
1. 排行榜悬浮窗关闭后小按钮消失问题
   - 修复面板居中模式关闭时按钮位置错误
   - 保存并恢复按钮的居中状态

2. 首页tag按钮按素材数量排序
   - 添加按素材数量降序排序逻辑

3. 上传弹窗输入框浅色模式文字不可见
   - 添加 text-slate-900 确保浅色模式下文字可见
   - 添加 placeholder 样式确保占位符正确显示
2025-12-14 21:41:29 +08:00

225 lines
7.9 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.

/**
* 修复缺失的模板记录
*
* 问题:数据库中缺少内置模板记录(builtin-xxx),导致素材上传失败
* 解决:在数据库中创建所有内置模板记录
*
* 使用方法:
* npx ts-node scripts/fix-missing-templates.ts
*/
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
// 内置模板配置(直接定义,避免导入问题)
const BUILTIN_TEMPLATE_KEYS = [
'3dmax-material',
'psd-material',
'audio-material',
'video-material',
'model-material',
'other-material',
] as const
const BUILTIN_TEMPLATE_NAMES: Record<string, string> = {
'3dmax-material': '3DMAX 素材模板',
'psd-material': 'PSD 素材模板',
'audio-material': '音频素材模板',
'video-material': '视频素材模板',
'model-material': '模特素材模板',
'other-material': '其他素材模板',
}
const BUILTIN_TEMPLATE_DESCRIPTIONS: Record<string, string> = {
'3dmax-material': '适用于 3D 模型类素材',
'psd-material': '针对平面设计 PSD 素材',
'audio-material': '适用于音频文件素材,支持 MP3、WAV、FLAC、AAC 等格式',
'video-material': '适用于视频文件素材',
'model-material': '用于模特/人像素材',
'other-material': '适用于其他类型的素材',
}
const BUILTIN_TEMPLATE_TYPES: Record<string, string> = {
'3dmax-material': '3DMAX',
'psd-material': 'PSD',
'audio-material': '音频',
'video-material': '视频',
'model-material': '模特',
'other-material': '其他',
}
const BUILTIN_TEMPLATE_KINDS: Record<string, string> = {
'3dmax-material': 'IMAGE',
'psd-material': 'IMAGE',
'audio-material': 'AUDIO',
'video-material': 'VIDEO',
'model-material': 'IMAGE',
'other-material': 'OTHER',
}
const BUILTIN_TEMPLATE_FIELDS: Record<string, string[]> = {
'3dmax-material': ['productModel', 'categoryName', 'sceneName', 'renderer'],
'psd-material': ['productModel', 'categoryName', 'sceneName'],
'audio-material': ['productModel', 'audioCategory', 'audioScene', 'authorName'],
'video-material': ['productModel', 'categoryName', 'sceneName'],
'model-material': ['productModel', 'categoryName', 'sceneName'],
'other-material': ['productModel', 'categoryName', 'sceneName'],
}
const STANDARD_FIELDS: Record<string, any> = {
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 },
renderer: { key: 'renderer', label: '渲染器', type: 'select', required: false, layoutWidth: 'full', visibleOnHomeFilter: false, isSearchable: true, addToCategory: 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 },
authorName: { key: 'authorName', label: '作者', type: 'text', required: false, layoutWidth: 'half', visibleOnHomeFilter: false, isSearchable: true },
}
async function fixMissingTemplates() {
console.log('开始修复缺失的模板记录...\n')
try {
// 1. 检查哪些内置模板缺失
console.log('步骤 1: 检查内置模板...')
const existingTemplates = await prisma.uploadTemplate.findMany({
where: {
id: {
in: BUILTIN_TEMPLATE_KEYS.map(key => `builtin-${key}`)
}
},
select: { id: true, name: true }
})
const existingIds = new Set(existingTemplates.map(t => t.id))
console.log(`已存在的内置模板: ${existingTemplates.length}/${BUILTIN_TEMPLATE_KEYS.length}`)
existingTemplates.forEach(t => console.log(` ✓ ${t.id} - ${t.name}`))
const missingKeys = BUILTIN_TEMPLATE_KEYS.filter(
key => !existingIds.has(`builtin-${key}`)
)
if (missingKeys.length === 0) {
console.log('\n✓ 所有内置模板都已存在,无需修复')
return true
}
console.log(`\n缺失的内置模板: ${missingKeys.length}`)
missingKeys.forEach(key => console.log(` ✗ builtin-${key} - ${BUILTIN_TEMPLATE_NAMES[key]}`))
// 2. 创建缺失的内置模板
console.log('\n步骤 2: 创建缺失的内置模板...')
for (const key of missingKeys) {
const templateId = `builtin-${key}`
const name = BUILTIN_TEMPLATE_NAMES[key]
const description = BUILTIN_TEMPLATE_DESCRIPTIONS[key]
const materialType = BUILTIN_TEMPLATE_TYPES[key]
const materialKind = BUILTIN_TEMPLATE_KINDS[key]
const fieldKeys = BUILTIN_TEMPLATE_FIELDS[key] || []
console.log(`\n创建模板: ${name} (${templateId})`)
// 创建模板记录
const template = await prisma.uploadTemplate.create({
data: {
id: templateId,
name,
description,
status: 'active',
materialType,
materialKind,
version: 1,
},
})
console.log(` ✓ 模板记录已创建`)
// 创建字段记录
const requireRenderer = key === '3dmax-material'
const fieldOverrides: Record<string, Partial<{ required: boolean }>> = {
productModel: { required: true },
categoryName: { required: true },
sceneName: { required: true },
}
if (requireRenderer) {
fieldOverrides.renderer = { required: true }
}
for (let i = 0; i < fieldKeys.length; i++) {
const fieldKey = fieldKeys[i]
const fieldConfig = STANDARD_FIELDS[fieldKey]
if (!fieldConfig) {
console.warn(` ⚠ 字段配置不存在: ${fieldKey}`)
continue
}
const override = fieldOverrides[fieldKey] || {}
await prisma.uploadField.create({
data: {
templateId: template.id,
key: fieldConfig.key,
label: fieldConfig.label,
type: fieldConfig.type,
required: override.required ?? fieldConfig.required,
orderIndex: i,
layoutWidth: fieldConfig.layoutWidth,
validations: null,
optionsSource: null,
optionsStatic: fieldConfig.optionsStatic || null,
allowedExtensions: null,
visibleOnHomeFilter: fieldConfig.visibleOnHomeFilter,
isSearchable: fieldConfig.isSearchable,
addToCategory: fieldConfig.addToCategory || false,
conditions: null,
},
})
}
console.log(` ✓ ${fieldKeys.length} 个字段已创建`)
}
// 3. 验证修复结果
console.log('\n步骤 3: 验证修复结果...')
const allTemplates = await prisma.uploadTemplate.findMany({
where: {
id: {
in: BUILTIN_TEMPLATE_KEYS.map(key => `builtin-${key}`)
}
},
select: { id: true, name: true, status: true }
})
console.log(`\n内置模板总数: ${allTemplates.length}/${BUILTIN_TEMPLATE_KEYS.length}`)
allTemplates.forEach(t => console.log(` ✓ ${t.id} - ${t.name} (${t.status})`))
if (allTemplates.length === BUILTIN_TEMPLATE_KEYS.length) {
console.log('\n✓ 所有内置模板修复完成!')
return true
} else {
console.warn('\n⚠ 部分模板修复失败,请检查日志')
return false
}
} catch (error) {
console.error('\n✗ 修复失败:', error)
throw error
} finally {
await prisma.$disconnect()
}
}
// 执行脚本
fixMissingTemplates()
.then((success) => {
process.exit(success ? 0 : 1)
})
.catch((error) => {
console.error('脚本执行失败:', error)
process.exit(1)
})