flnxi-Wu/lib/template-validator.ts
WuYongJie 542c7bcc49 feat: 优化自定义上传模板系统
- 修复内置模板验证问题(builtin-video-material等)
- 添加模板验证工具 lib/template-validator.ts
- 创建模板系统优化需求文档(30个详细需求)
- 优化上传API的模板验证逻辑
- 改进错误提示信息的清晰度
- 添加字段池和分类管理相关需求
- 完善自定义字段的创建、验证、存储逻辑
- 清理过期的 .specstory 和 .trae 文件
2025-12-13 14:26:43 +08:00

160 lines
4.1 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.

/**
* 模板验证工具
*
* 提供统一的模板验证逻辑,支持内置模板和自定义模板
*/
import { prisma } from '@/lib/prisma'
// 内置模板key列表
export const BUILTIN_TEMPLATE_KEYS = [
'3dmax-material',
'psd-material',
'ai-material',
'video-material',
'model-material',
'other-material',
] as const
export type BuiltinTemplateKey = typeof BUILTIN_TEMPLATE_KEYS[number]
/**
* 模板验证结果
*/
export type TemplateValidationResult = {
valid: boolean
isBuiltin: boolean
templateKey?: string
error?: string
}
/**
* 验证模板ID是否有效
*
* @param templateId - 模板ID(可以是内置模板或自定义模板)
* @returns 验证结果
*/
export async function validateTemplateId(
templateId: string | null | undefined
): Promise<TemplateValidationResult> {
// 如果没有提供 templateId,视为有效(向后兼容)
if (!templateId) {
return { valid: true, isBuiltin: false }
}
// 检查是否为内置模板(builtin-* 格式)
const isBuiltinTemplate = templateId.startsWith('builtin-')
if (isBuiltinTemplate) {
// 内置模板:验证模板key是否在预设列表中
const templateKey = templateId.replace('builtin-', '') as BuiltinTemplateKey
if (!BUILTIN_TEMPLATE_KEYS.includes(templateKey)) {
return {
valid: false,
isBuiltin: true,
templateKey,
error: `无效的内置模板:${templateId}。有效的内置模板包括:${BUILTIN_TEMPLATE_KEYS.map(k => `builtin-${k}`).join(', ')}`,
}
}
return {
valid: true,
isBuiltin: true,
templateKey,
}
}
// 自定义模板:从数据库验证
try {
const template = await prisma.uploadTemplate.findUnique({
where: { id: templateId },
select: {
id: true,
name: true,
status: true,
},
})
if (!template) {
return {
valid: false,
isBuiltin: false,
error: `自定义模板不存在:${templateId}。请检查模板是否已被删除或ID是否正确。`,
}
}
// 检查模板状态
if (template.status !== 'active') {
return {
valid: false,
isBuiltin: false,
error: `模板"${template.name}"当前状态为"${template.status}",无法使用。请联系管理员启用该模板。`,
}
}
return {
valid: true,
isBuiltin: false,
}
} catch (error) {
console.error('[TemplateValidator] Error checking custom template:', error)
return {
valid: false,
isBuiltin: false,
error: `验证模板时发生错误:${error instanceof Error ? error.message : '未知错误'}`,
}
}
}
/**
* 检查模板ID是否为内置模板
*
* @param templateId - 模板ID
* @returns 是否为内置模板
*/
export function isBuiltinTemplate(templateId: string | null | undefined): boolean {
if (!templateId) return false
return templateId.startsWith('builtin-')
}
/**
* 从内置模板ID提取模板key
*
* @param templateId - 内置模板ID(如 builtin-video-material)
* @returns 模板key(如 video-material)
*/
export function extractBuiltinTemplateKey(templateId: string): BuiltinTemplateKey | null {
if (!isBuiltinTemplate(templateId)) return null
const key = templateId.replace('builtin-', '')
return BUILTIN_TEMPLATE_KEYS.includes(key as BuiltinTemplateKey)
? (key as BuiltinTemplateKey)
: null
}
/**
* 获取模板的完整信息(包括字段)
*
* @param templateId - 模板ID
* @returns 模板信息,如果不存在返回 null
*/
export async function getTemplateWithFields(templateId: string) {
if (isBuiltinTemplate(templateId)) {
// 内置模板需要动态生成
const { createBuiltinTemplate } = await import('@/lib/upload-template-presets')
const templateKey = extractBuiltinTemplateKey(templateId)
if (!templateKey) return null
return createBuiltinTemplate(templateKey)
}
// 自定义模板从数据库读取
return prisma.uploadTemplate.findUnique({
where: { id: templateId },
include: {
fields: {
orderBy: { orderIndex: 'asc' },
},
},
})
}