// 上传相关的工具函数 import { isVideoMaterialType } from '@/lib/video-material-types' /** * 格式化文件大小 */ export function formatBytes(bytes: number): string { if (bytes === 0) return '0 B' const k = 1024 const sizes = ['B', 'KB', 'MB', 'GB'] const i = Math.floor(Math.log(bytes) / Math.log(k)) return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i] } /** * 格式化上传速度(字节/秒 -> 用户友好单位) * 使用字节单位(B/s、KB/s、MB/s),而非比特单位 */ export function formatSpeed(bytesPerSecond: number): string { if (bytesPerSecond < 1024) { return `${bytesPerSecond.toFixed(0)} B/s` } if (bytesPerSecond < 1024 * 1024) { return `${(bytesPerSecond / 1024).toFixed(2)} KB/s` } return `${(bytesPerSecond / 1024 / 1024).toFixed(2)} MB/s` } /** * 计算剩余时间 */ export function calculateRemainingTime(remainingBytes: number, speed: number): string { if (speed <= 0) return '计算中...' const seconds = Math.ceil(remainingBytes / speed) if (seconds < 60) return `${seconds}秒` const minutes = Math.floor(seconds / 60) const secs = seconds % 60 return `${minutes}分${secs}秒` } /** * 获取文件扩展名 */ export function getFileExtension(filename: string): string { const idx = filename.lastIndexOf('.') return idx >= 0 ? filename.slice(idx).toLowerCase() : '' } /** * 验证主文件类型是否有效 */ export function isValidMainFileType(file: File, materialType: string): boolean { const ext = getFileExtension(file.name) const archiveExts = ['.zip', '.rar', '.7z'] const videoExts = ['.mp4', '.mov', '.avi', '.mkv', '.mts', '.m4v'] const audioExts = ['.mp3', '.wav', '.flac', '.m4a', '.aac', '.ogg'] const psdExts = ['.psd', '.tif', '.tiff', '.psb'] // 详情模板支持 PSD、TIF、PSB // 音乐:只能是音频文件 if (materialType === '音乐') return audioExts.includes(ext) // 视频类:只能是视频文件 if (isVideoMaterialType(materialType)) return videoExts.includes(ext) // 品牌VI灵感:只能是 PDF,展示图在单独的展示图字段里上传 if (materialType === '品牌VI灵感') return ext === '.pdf' // 详情模板:支持直接上传 PSD/TIF/PSB 文件或压缩包 if (materialType === '详情模板') { return psdExts.includes(ext) || archiveExts.includes(ext) } // 其他类型(3D场景/模特等):仍然按旧逻辑走压缩包 return archiveExts.includes(ext) } /** * 获取主文件接受的类型 */ export function getMainFileAccept(materialType: string): string { if (materialType === '音乐') return '.mp3,.wav,.flac,.m4a,.aac,.ogg' if (isVideoMaterialType(materialType)) return '.mp4,.mov,.avi,.mkv,.mts,.m4v' if (materialType === '品牌VI灵感') return '.pdf' // 详情模板:支持直接上传 PSD/TIF/PSB 文件或压缩包 if (materialType === '详情模板') { return '.psd,.tif,.tiff,.psb,.zip,.rar,.7z' } return '.zip,.rar,.7z' } /** * 从文件名提取SPU(简单逻辑:提取文件名中的大写字母和数字组合) */ export function extractSpuFromFileName(filename: string): string { // 移除扩展名 const nameWithoutExt = filename.replace(/\.[^/.]+$/, '') // 尝试提取类似 "XY-2024-001" 的格式 const spuMatch = nameWithoutExt.match(/[A-Z]{2,}-?\d{4}-?\d{3,}/i) if (spuMatch) { return spuMatch[0].toUpperCase() } // 如果没有匹配到,返回文件名(去除扩展名和特殊字符) return nameWithoutExt.replace(/[^a-zA-Z0-9\-_]/g, '').toUpperCase() } /** * 将File转换为base64格式(用于批量上传中的预览图) */ export async function convertFileToBase64(file: File): Promise<{ name: string; data: number[]; type: string }> { const arrayBuffer = await file.arrayBuffer() return { name: file.name, data: Array.from(new Uint8Array(arrayBuffer)), type: file.type, } } /** * 检测素材类型(从文件名) */ export function detectMaterialType(filename: string): string | null { // 不再根据文件扩展名自动检测素材类型 // 用户需要手动选择素材类型 return null }