121 lines
3.6 KiB
TypeScript
121 lines
3.6 KiB
TypeScript
// 上传相关的工具函数
|
||
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
|
||
}
|