组件修改

This commit is contained in:
2025-12-08 17:36:20 +08:00
parent bc1ee71fc1
commit 19ff3e2a93
23 changed files with 4036 additions and 82 deletions

View File

@@ -0,0 +1,181 @@
/**
* 文件处理相关工具函数
*/
/**
* 验证文件类型
*/
export const isValidFileType = (file: File, accept: string): boolean => {
if (!accept || accept === '*/*') return true
const acceptTypes = accept.split(',').map(t => t.trim())
return acceptTypes.some(type => {
if (type.startsWith('.')) {
return file.name.toLowerCase().endsWith(type.toLowerCase())
} else if (type.endsWith('/*')) {
return file.type.startsWith(type.replace('/*', ''))
} else {
return file.type === type
}
})
}
/**
* 判断是否为图片文件
*/
export const isImageFile = (file: File): boolean => {
return file.type.startsWith('image/')
}
/**
* 判断是否为文本文件
*/
export const isTextFile = (file: File): boolean => {
return file.type.startsWith('text/')
}
/**
* 获取文件预览URL
*/
export const getFilePreviewUrl = (file: File): string => {
return URL.createObjectURL(file)
}
/**
* 格式化文件大小
*/
export const formatFileSize = (bytes: number): string => {
if (bytes === 0) return '0 B'
const k = 1024
const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
const i = Math.floor(Math.log(bytes) / Math.log(k))
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}
/**
* 获取文件类型图标
*/
export const getFileTypeIcon = (file: File): string => {
const extension = file.name.split('.').pop()?.toLowerCase()
const iconMap: Record<string, string> = {
// 文档类
'pdf': '📄',
'doc': '📝',
'docx': '📝',
'txt': '📄',
'md': '📄',
'rtf': '📄',
// 表格类
'xls': '📊',
'xlsx': '📊',
'csv': '📊',
// 演示文稿
'ppt': '📊',
'pptx': '📊',
// 压缩包
'zip': '📦',
'rar': '📦',
'7z': '📦',
'tar': '📦',
'gz': '📦',
// 视频
'mp4': '🎬',
'avi': '🎬',
'mov': '🎬',
'wmv': '🎬',
'flv': '🎬',
'mkv': '🎬',
// 音频
'mp3': '🎵',
'wav': '🎵',
'flac': '🎵',
'aac': '🎵',
// 图片
'jpg': '🖼️',
'jpeg': '🖼️',
'png': '🖼️',
'gif': '🖼️',
'bmp': '🖼️',
'svg': '🖼️',
'webp': '🖼️'
}
return iconMap[extension || ''] || '📄'
}
/**
* 验证文件大小
*/
export const validateFileSize = (file: File, maxSize: number): { valid: boolean; error?: string } => {
if (file.size > maxSize) {
const maxSizeMB = (maxSize / 1024 / 1024).toFixed(0)
return {
valid: false,
error: `文件 ${file.name} 大小超过 ${maxSizeMB}MB`
}
}
return { valid: true }
}
/**
* 验证文件类型
*/
export const validateFileType = (file: File, accept?: string): { valid: boolean; error?: string } => {
if (accept && !isValidFileType(file, accept)) {
return {
valid: false,
error: `文件 ${file.name} 类型不符合要求`
}
}
return { valid: true }
}
/**
* 检查文件是否重复
*/
export const checkFileDuplicate = (file: File, existingFiles: File[]): { valid: boolean; error?: string } => {
if (existingFiles.some(f => f.name === file.name && f.size === file.size)) {
return {
valid: false,
error: `文件 ${file.name} 已添加`
}
}
return { valid: true }
}
/**
* 综合验证文件
*/
export const validateFile = (
file: File,
options: {
maxSize?: number
accept?: string
existingFiles?: File[]
} = {}
): { valid: boolean; error?: string } => {
const { maxSize, accept, existingFiles = [] } = options
// 检查文件大小
if (maxSize) {
const sizeResult = validateFileSize(file, maxSize)
if (!sizeResult.valid) return sizeResult
}
// 检查文件类型
if (accept) {
const typeResult = validateFileType(file, accept)
if (!typeResult.valid) return typeResult
}
// 检查是否重复
const duplicateResult = checkFileDuplicate(file, existingFiles)
if (!duplicateResult.valid) return duplicateResult
return { valid: true }
}

View File

@@ -0,0 +1,5 @@
/**
* Utils 统一导出
*/
export * from './file'