// utils/file-validator.ts /** * 获取文件类型(多平台兼容) */ const getFileType = (file: any): any => { // 通过文件名后缀判断 const path = file.path || file.name || '' const extension = path.split('.').pop().toLowerCase() // 图片类型 const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'] if (imageExtensions.includes(extension)) return 'image' // 视频类型 const videoExtensions = ['mp4', 'avi', 'mov', 'wmv', 'flv', 'mkv', 'webm'] if (videoExtensions.includes(extension)) return 'video' // 音频类型 const audioExtensions = ['mp3', 'wav', 'aac', 'ogg', 'flac', 'm4a'] if (audioExtensions.includes(extension)) return 'audio' // 文档类型 const documentExtensions = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt'] if (documentExtensions.includes(extension)) return 'document' return 'other' } /** * 统一文件类型映射(将自定义类型映射到平台支持的类型) */ const mapAcceptTypeToPlatform = (accept: string, platform: string): any => { const typeMap = { image: { wx: ['image'], uni: ['image'], alipay: ['image'] }, video: { wx: ['video'], uni: ['video'], alipay: ['video'] }, audio: { wx: ['file'], uni: [], alipay: [] }, all: { wx: ['all'], uni: ['all'], alipay: ['all'] }, file: { wx: ['file'], uni: ['file'], alipay: ['file'] } } return typeMap[accept]?.[platform] || [accept] } /** * 检查文件类型是否被接受(多平台兼容) * @param {File|Object} file - 文件对象 * @param {string|Array} accept - 接受的文件类型 * @returns {boolean} */ export const isFileTypeAccepted = (file: any, accept: any = 'image'): boolean => { if (!file) return false // 如果 accept 是数组,转换为字符串处理 const acceptType = Array.isArray(accept) ? accept.join(',') : accept // 获取文件类型 const fileType = getFileType(file) // 处理 accept 字符串 const acceptTypes = acceptType.split(',').map((type: any) => type.trim()) // 特殊类型处理 if (acceptTypes.includes('*') || acceptTypes.includes('all')) return true // 检查文件类型 for (const accepted of acceptTypes) { // 精确匹配 if (accepted === fileType) return true // MIME 类型匹配 if (file.type && accepted.includes('/')) { if (file.type.includes(accepted)) return true } // 扩展名匹配 const extension = (file.path || file.name || '').split('.').pop().toLowerCase() if (accepted.startsWith('.') && `.${extension}` === accepted) { return true } // 通用类型匹配 const genericTypes: any = { 'image': ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'], 'video': ['mp4', 'avi', 'mov', 'wmv'], 'audio': ['mp3', 'wav', 'ogg', 'm4a'], 'document': ['pdf', 'doc', 'docx', 'xlsx'] } if (genericTypes[accepted] && genericTypes[accepted].includes(extension)) { return true } } return false } /** * 获取平台特定的文件选择配置 */ export const getPlatformFileConfig = (options: any = {}): any => { const { accept = 'image', count = 1 } = options // #ifdef MP-WEIXIN if (accept === 'image' || accept.includes('image')) { return { api: 'chooseImage', config: { count, sizeType: ['original', 'compressed'], sourceType: ['album', 'camera'] } } } else if (accept === 'video' || accept.includes('video')) { return { api: 'chooseVideo', config: { sourceType: ['album', 'camera'], compressed: true, maxDuration: 60 } } } else { return { api: 'chooseMessageFile', config: { count, type: 'file', extension: getWeChatExtensions(accept) } } } // #endif // #ifdef H5 || APP-PLUS return { api: 'chooseFile', config: { count, type: mapAcceptTypeToPlatform(accept, 'uni')[0] } } // #endif // #ifdef MP-ALIPAY if (accept === 'image' || accept.includes('image')) { return { api: 'chooseImage', config: { count, sizeType: ['original', 'compressed'], sourceType: ['album', 'camera'] } } } else { return { api: 'chooseFile', config: { count } } } // #endif return null } /** * 获取微信小程序支持的扩展名 */ const getWeChatExtensions = (accept: any): any => { const extensions: any = [] if (accept.includes('image')) { extensions.push('.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp') } if (accept.includes('video')) { extensions.push('.mp4', '.avi', '.mov', '.wmv') } if (accept.includes('.pdf')) { extensions.push('.pdf') } if (accept.includes('.doc') || accept.includes('.docx')) { extensions.push('.doc', '.docx') } if (accept.includes('.xls') || accept.includes('.xlsx')) { extensions.push('.xls', '.xlsx') } if (accept.includes('.ppt') || accept.includes('.pptx')) { extensions.push('.ppt', '.pptx') } return extensions }