// 上传相关的工具函数 import { isVideoMaterialType } from '@/lib/video-material-types' import { extractPlausibleSpuFromFileName } from '@/lib/product-model' import { formatHumanBytes, formatHumanSpeed, formatRemainingTime, formatTransferProgressSummary, } from '@/lib/human-readable-transfer' /** * 格式化文件大小 */ export function formatBytes(bytes: number): string { return formatHumanBytes(bytes) } /** * 格式化上传速度(字节/秒 -> 用户友好单位) * 使用字节单位(B/s、KB/s、MB/s),而非比特单位 */ export function formatSpeed(bytesPerSecond: number): string { return formatHumanSpeed(bytesPerSecond) } /** * 计算剩余时间 */ export function calculateRemainingTime(remainingBytes: number, speed: number): string { return formatRemainingTime(remainingBytes, speed).replace(/^剩余\s*/, '') } export function formatTransferProgress( speedBytesPerSecond: number, loadedBytes?: number, totalBytes?: number, ): string { return formatTransferProgressSummary({ speedBytesPerSecond, loadedBytes, totalBytes, }) } /** * 获取文件扩展名 */ 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 { return extractPlausibleSpuFromFileName(filename) } /** * 将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 }