refactor(utils): 提取统一的文件扩展名判断函数
- 新增 extractExtensionFromFile() 统一函数 - 优先使用 extension 字段 - 更新 documentIcons.js/tools.js/useFileOperation.js 使用统一函数 - 更新 API 类型定义和组件 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Showing
7 changed files
with
168 additions
and
70 deletions
| ... | @@ -40,6 +40,7 @@ const Api = { | ... | @@ -40,6 +40,7 @@ const Api = { |
| 40 | file_name: string; // 附件名 | 40 | file_name: string; // 附件名 |
| 41 | file_size: string; // 附件大小 | 41 | file_size: string; // 附件大小 |
| 42 | file_size_formatted: string; // 附件大小(转换过显示) | 42 | file_size_formatted: string; // 附件大小(转换过显示) |
| 43 | + extension?: string; // 文件扩展名(优先使用) | ||
| 43 | }>; | 44 | }>; |
| 44 | cover_image: string; // 产品封面图 | 45 | cover_image: string; // 产品封面图 |
| 45 | * }; | 46 | * }; | ... | ... |
| ... | @@ -129,18 +129,24 @@ const emit = defineEmits({ | ... | @@ -129,18 +129,24 @@ const emit = defineEmits({ |
| 129 | /** | 129 | /** |
| 130 | * 获取文档图标 URL | 130 | * 获取文档图标 URL |
| 131 | * | 131 | * |
| 132 | - * @description 根据文件名获取对应的文档类型图标 | 132 | + * @description 优先使用 extension 字段,其次从 fileName 解析 |
| 133 | * @returns {string} 图标 URL | 133 | * @returns {string} 图标 URL |
| 134 | */ | 134 | */ |
| 135 | -const iconUrl = props.fileName ? getDocumentIcon(props.fileName) : ''; | 135 | +const iconUrl = getDocumentIcon({ |
| 136 | + extension: props.extension, | ||
| 137 | + fileName: props.fileName | ||
| 138 | +}); | ||
| 136 | 139 | ||
| 137 | /** | 140 | /** |
| 138 | * 获取文档类型标签 | 141 | * 获取文档类型标签 |
| 139 | * | 142 | * |
| 140 | - * @description 根据文件名获取文档类型标签文本 | 143 | + * @description 优先使用 extension 字段,其次从 fileName 解析 |
| 141 | * @returns {string} 文档类型标签 | 144 | * @returns {string} 文档类型标签 |
| 142 | */ | 145 | */ |
| 143 | -const docTypeLabel = props.fileName ? getDocumentLabel(props.fileName) : ''; | 146 | +const docTypeLabel = getDocumentLabel({ |
| 147 | + extension: props.extension, | ||
| 148 | + fileName: props.fileName | ||
| 149 | +}); | ||
| 144 | 150 | ||
| 145 | /** | 151 | /** |
| 146 | * 使用收藏操作 composable | 152 | * 使用收藏操作 composable | ... | ... |
| ... | @@ -10,6 +10,7 @@ | ... | @@ -10,6 +10,7 @@ |
| 10 | 10 | ||
| 11 | import { showToast, showLoading, hideLoading, showModal, openDocument, downloadFile, previewImage } from '@tarojs/taro' | 11 | import { showToast, showLoading, hideLoading, showModal, openDocument, downloadFile, previewImage } from '@tarojs/taro' |
| 12 | import { isVideoFile } from '@/utils/tools' | 12 | import { isVideoFile } from '@/utils/tools' |
| 13 | +import { extractExtensionFromFile } from '@/utils/documentIcons' | ||
| 13 | 14 | ||
| 14 | /** | 15 | /** |
| 15 | * 文件操作 Hook | 16 | * 文件操作 Hook |
| ... | @@ -20,13 +21,18 @@ export function useFileOperation() { | ... | @@ -20,13 +21,18 @@ export function useFileOperation() { |
| 20 | /** | 21 | /** |
| 21 | * 判断是否为图片文件 | 22 | * 判断是否为图片文件 |
| 22 | * | 23 | * |
| 23 | - * @param {string} fileName - 文件名 | 24 | + * @description 支持传入文件名或包含 extension 字段的对象,优先使用 extension 字段 |
| 25 | + * @param {string|Object} fileNameOrItem - 文件名或文件对象 | ||
| 26 | + * @param {string} [fileNameOrItem.fileName] - 文件名 | ||
| 27 | + * @param {string} [fileNameOrItem.extension] - 文件扩展名(优先使用) | ||
| 24 | * @returns {boolean} 是否为图片文件 | 28 | * @returns {boolean} 是否为图片文件 |
| 25 | */ | 29 | */ |
| 26 | - const isImageFile = (fileName) => { | 30 | + const isImageFile = (fileNameOrItem) => { |
| 27 | - if (!fileName) return false | 31 | + const extension = extractExtensionFromFile(fileNameOrItem) |
| 32 | + | ||
| 33 | + if (!extension) return false | ||
| 34 | + | ||
| 28 | const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'svg'] | 35 | const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'svg'] |
| 29 | - const extension = fileName.split('.').pop()?.toLowerCase() || '' | ||
| 30 | return imageExtensions.includes(extension) | 36 | return imageExtensions.includes(extension) |
| 31 | } | 37 | } |
| 32 | /** | 38 | /** |
| ... | @@ -36,12 +42,14 @@ export function useFileOperation() { | ... | @@ -36,12 +42,14 @@ export function useFileOperation() { |
| 36 | * @async | 42 | * @async |
| 37 | * @param {string} filePath - 本地文件路径 | 43 | * @param {string} filePath - 本地文件路径 |
| 38 | * @param {Object} item - 文件信息对象 | 44 | * @param {Object} item - 文件信息对象 |
| 39 | - * @param {string} item.fileName - 文件名(用于判断文件类型) | 45 | + * @param {string} [item.fileName] - 文件名(用于判断文件类型) |
| 46 | + * @param {string} [item.extension] - 文件扩展名(优先使用) | ||
| 40 | * @returns {Promise<void>} | 47 | * @returns {Promise<void>} |
| 41 | * | 48 | * |
| 42 | * @example | 49 | * @example |
| 43 | * const { openFile } = useFileOperation() | 50 | * const { openFile } = useFileOperation() |
| 44 | * await openFile(tempFilePath, { fileName: 'document.pdf' }) | 51 | * await openFile(tempFilePath, { fileName: 'document.pdf' }) |
| 52 | + * await openFile(tempFilePath, { extension: 'pdf' }) // 优先使用 extension | ||
| 45 | */ | 53 | */ |
| 46 | const openFile = async (filePath, item) => { | 54 | const openFile = async (filePath, item) => { |
| 47 | try { | 55 | try { |
| ... | @@ -51,7 +59,8 @@ export function useFileOperation() { | ... | @@ -51,7 +59,8 @@ export function useFileOperation() { |
| 51 | success: () => { | 59 | success: () => { |
| 52 | console.log('文件打开成功') | 60 | console.log('文件打开成功') |
| 53 | // 文件打开后,延迟提示用户如果看不到内容该如何操作 | 61 | // 文件打开后,延迟提示用户如果看不到内容该如何操作 |
| 54 | - const fileExt = item.fileName.split('.').pop()?.toLowerCase() || '' | 62 | + // 使用统一的扩展名提取函数 |
| 63 | + const fileExt = extractExtensionFromFile(item) | ||
| 55 | const unsupportedFormats = ['docx', 'doc', 'pptx', 'ppt', 'xlsx', 'xls'] | 64 | const unsupportedFormats = ['docx', 'doc', 'pptx', 'ppt', 'xlsx', 'xls'] |
| 56 | 65 | ||
| 57 | if (unsupportedFormats.includes(fileExt)) { | 66 | if (unsupportedFormats.includes(fileExt)) { |
| ... | @@ -67,8 +76,8 @@ export function useFileOperation() { | ... | @@ -67,8 +76,8 @@ export function useFileOperation() { |
| 67 | fail: (err) => { | 76 | fail: (err) => { |
| 68 | console.error('打开文件失败:', err) | 77 | console.error('打开文件失败:', err) |
| 69 | 78 | ||
| 70 | - // 获取文件扩展名 | 79 | + // 获取文件扩展名(使用统一的扩展名提取函数) |
| 71 | - const fileExt = item.fileName.split('.').pop()?.toLowerCase() || '' | 80 | + const fileExt = extractExtensionFromFile(item) |
| 72 | 81 | ||
| 73 | // 根据文件类型给出提示 | 82 | // 根据文件类型给出提示 |
| 74 | let message = '文件打开失败' | 83 | let message = '文件打开失败' |
| ... | @@ -110,7 +119,8 @@ export function useFileOperation() { | ... | @@ -110,7 +119,8 @@ export function useFileOperation() { |
| 110 | * @async | 119 | * @async |
| 111 | * @param {Object} item - 文件信息对象 | 120 | * @param {Object} item - 文件信息对象 |
| 112 | * @param {string} item.downloadUrl - 文件下载地址 | 121 | * @param {string} item.downloadUrl - 文件下载地址 |
| 113 | - * @param {string} item.fileName - 文件名 | 122 | + * @param {string} [item.fileName] - 文件名 |
| 123 | + * @param {string} [item.extension] - 文件扩展名(优先使用) | ||
| 114 | * @returns {Promise<void>} | 124 | * @returns {Promise<void>} |
| 115 | * | 125 | * |
| 116 | * @example | 126 | * @example |
| ... | @@ -119,10 +129,14 @@ export function useFileOperation() { | ... | @@ -119,10 +129,14 @@ export function useFileOperation() { |
| 119 | * downloadUrl: 'https://example.com/file.pdf', | 129 | * downloadUrl: 'https://example.com/file.pdf', |
| 120 | * fileName: 'document.pdf' | 130 | * fileName: 'document.pdf' |
| 121 | * }) | 131 | * }) |
| 132 | + * await downloadAndOpenFile({ | ||
| 133 | + * downloadUrl: 'https://example.com/file.pdf', | ||
| 134 | + * extension: 'pdf' // 优先使用 extension | ||
| 135 | + * }) | ||
| 122 | */ | 136 | */ |
| 123 | const downloadAndOpenFile = async (item) => { | 137 | const downloadAndOpenFile = async (item) => { |
| 124 | try { | 138 | try { |
| 125 | - // 下载文件 | 139 | + //下载文件 |
| 126 | const downloadResult = await downloadFile({ | 140 | const downloadResult = await downloadFile({ |
| 127 | url: item.downloadUrl | 141 | url: item.downloadUrl |
| 128 | }) | 142 | }) |
| ... | @@ -139,8 +153,8 @@ export function useFileOperation() { | ... | @@ -139,8 +153,8 @@ export function useFileOperation() { |
| 139 | // 隐藏加载提示 | 153 | // 隐藏加载提示 |
| 140 | hideLoading() | 154 | hideLoading() |
| 141 | 155 | ||
| 142 | - // 获取文件扩展名 | 156 | + // 获取文件扩展名(使用统一的扩展名提取函数) |
| 143 | - const fileExt = item.fileName.split('.').pop()?.toLowerCase() || '' | 157 | + const fileExt = extractExtensionFromFile(item) |
| 144 | 158 | ||
| 145 | // 微信小程序对 Office 文档支持有限,提前提示用户 | 159 | // 微信小程序对 Office 文档支持有限,提前提示用户 |
| 146 | const unsupportedFormats = ['docx', 'doc', 'pptx', 'ppt', 'xlsx', 'xls'] | 160 | const unsupportedFormats = ['docx', 'doc', 'pptx', 'ppt', 'xlsx', 'xls'] |
| ... | @@ -194,7 +208,8 @@ export function useFileOperation() { | ... | @@ -194,7 +208,8 @@ export function useFileOperation() { |
| 194 | * @async | 208 | * @async |
| 195 | * @param {Object} item - 文件信息对象 | 209 | * @param {Object} item - 文件信息对象 |
| 196 | * @param {string} [item.downloadUrl] - 文件下载地址 | 210 | * @param {string} [item.downloadUrl] - 文件下载地址 |
| 197 | - * @param {string} item.fileName - 文件名 | 211 | + * @param {string} [item.fileName] - 文件名 |
| 212 | + * @param {string} [item.extension] - 文件扩展名(优先使用) | ||
| 198 | * @returns {Promise<void>} | 213 | * @returns {Promise<void>} |
| 199 | * | 214 | * |
| 200 | * @example | 215 | * @example |
| ... | @@ -203,6 +218,10 @@ export function useFileOperation() { | ... | @@ -203,6 +218,10 @@ export function useFileOperation() { |
| 203 | * downloadUrl: 'https://example.com/file.pdf', | 218 | * downloadUrl: 'https://example.com/file.pdf', |
| 204 | * fileName: 'document.pdf' | 219 | * fileName: 'document.pdf' |
| 205 | * }) | 220 | * }) |
| 221 | + * await viewFile({ | ||
| 222 | + * downloadUrl: 'https://example.com/file.pdf', | ||
| 223 | + * extension: 'pdf' // 优先使用 extension | ||
| 224 | + * }) | ||
| 206 | */ | 225 | */ |
| 207 | const viewFile = async (item) => { | 226 | const viewFile = async (item) => { |
| 208 | // 检查是否有下载地址 | 227 | // 检查是否有下载地址 |
| ... | @@ -215,8 +234,8 @@ export function useFileOperation() { | ... | @@ -215,8 +234,8 @@ export function useFileOperation() { |
| 215 | return | 234 | return |
| 216 | } | 235 | } |
| 217 | 236 | ||
| 218 | - // 判断是否为图片文件 | 237 | + // 判断是否为图片文件(优先使用 extension 字段) |
| 219 | - if (isImageFile(item.fileName)) { | 238 | + if (isImageFile(item)) { |
| 220 | // 图片文件:使用图片预览 | 239 | // 图片文件:使用图片预览 |
| 221 | console.log('[文件操作] 检测到图片文件,使用图片预览') | 240 | console.log('[文件操作] 检测到图片文件,使用图片预览') |
| 222 | try { | 241 | try { |
| ... | @@ -235,8 +254,8 @@ export function useFileOperation() { | ... | @@ -235,8 +254,8 @@ export function useFileOperation() { |
| 235 | return | 254 | return |
| 236 | } | 255 | } |
| 237 | 256 | ||
| 238 | - // 判断是否为视频文件 | 257 | + // 判断是否为视频文件(优先使用 extension 字段) |
| 239 | - if (isVideoFile(item.fileName)) { | 258 | + if (isVideoFile(item)) { |
| 240 | // 视频文件:跳转到视频播放页面 | 259 | // 视频文件:跳转到视频播放页面 |
| 241 | // 需要动态导入 navigateTo 以避免循环依赖 | 260 | // 需要动态导入 navigateTo 以避免循环依赖 |
| 242 | const Taro = await import('@tarojs/taro') | 261 | const Taro = await import('@tarojs/taro') | ... | ... |
| ... | @@ -28,7 +28,7 @@ | ... | @@ -28,7 +28,7 @@ |
| 28 | <view class="flex gap-[24rpx] mb-[12rpx]"> | 28 | <view class="flex gap-[24rpx] mb-[12rpx]"> |
| 29 | <!-- Document Icon --> | 29 | <!-- Document Icon --> |
| 30 | <view class="w-[88rpx] h-[88rpx] mr-[24rpx] flex-shrink-0 flex items-center justify-center bg-gradient-to-br from-blue-50 to-blue-100 rounded-[20rpx] shadow-inner self-start"> | 30 | <view class="w-[88rpx] h-[88rpx] mr-[24rpx] flex-shrink-0 flex items-center justify-center bg-gradient-to-br from-blue-50 to-blue-100 rounded-[20rpx] shadow-inner self-start"> |
| 31 | - <image :src="getDocumentIcon(item.name)" class="w-[48rpx] h-[48rpx]" mode="aspectFit" /> | 31 | + <image :src="getDocumentIcon({ extension: item.extension, fileName: item.name })" class="w-[48rpx] h-[48rpx]" mode="aspectFit" /> |
| 32 | </view> | 32 | </view> |
| 33 | 33 | ||
| 34 | <!-- Title --> | 34 | <!-- Title --> | ... | ... |
| ... | @@ -79,13 +79,13 @@ | ... | @@ -79,13 +79,13 @@ |
| 79 | <div class="flex items-center justify-between"> | 79 | <div class="flex items-center justify-between"> |
| 80 | <div class="flex items-center flex-1 mr-[24rpx]"> | 80 | <div class="flex items-center flex-1 mr-[24rpx]"> |
| 81 | <image | 81 | <image |
| 82 | - :src="getDocumentIcon(doc.file_name)" | 82 | + :src="getDocumentIcon({ extension: doc.extension, fileName: doc.file_name })" |
| 83 | class="w-[58rpx] h-[58rpx] mr-[24rpx]" | 83 | class="w-[58rpx] h-[58rpx] mr-[24rpx]" |
| 84 | mode="aspectFit" | 84 | mode="aspectFit" |
| 85 | /> | 85 | /> |
| 86 | <div class="flex flex-col"> | 86 | <div class="flex flex-col"> |
| 87 | <span class="text-[#1F2937] text-[28rpx] font-medium mb-[4rpx] line-clamp-2">{{ doc.file_name }}</span> | 87 | <span class="text-[#1F2937] text-[28rpx] font-medium mb-[4rpx] line-clamp-2">{{ doc.file_name }}</span> |
| 88 | - <span class="text-[#9CA3AF] text-[24rpx]">{{ getDocumentLabel(doc.file_name) }} · {{ doc.file_size_formatted }}</span> | 88 | + <span class="text-[#9CA3AF] text-[24rpx]">{{ getDocumentLabel({ extension: doc.extension, fileName: doc.file_name }) }} · {{ doc.file_size_formatted }}</span> |
| 89 | </div> | 89 | </div> |
| 90 | </div> | 90 | </div> |
| 91 | <IconFont name="eye" size="14" color="#2563EB" @tap="viewDocument(doc)" /> | 91 | <IconFont name="eye" size="14" color="#2563EB" @tap="viewDocument(doc)" /> | ... | ... |
| ... | @@ -104,110 +104,179 @@ const EXTENSION_LABEL_MAP = { | ... | @@ -104,110 +104,179 @@ const EXTENSION_LABEL_MAP = { |
| 104 | const DEFAULT_LABEL = 'DOC'; | 104 | const DEFAULT_LABEL = 'DOC'; |
| 105 | 105 | ||
| 106 | /** | 106 | /** |
| 107 | - * 根据文件名获取文档图标路径 | 107 | + * 根据文件名或扩展名获取文档图标路径 |
| 108 | * | 108 | * |
| 109 | - * @description 从文件名中提取扩展名,返回对应的图标路径 | 109 | + * @description 支持传入文件名或包含 extension 字段的对象,优先使用 extension 字段 |
| 110 | - * @param {string} fileName - 文件名(如:document.pdf) | 110 | + * @param {string|Object} fileNameOrItem - 文件名(如:document.pdf)或文件对象(包含 extension 字段) |
| 111 | + * @param {string} [fileNameOrItem.fileName] - 文件名 | ||
| 112 | + * @param {string} [fileNameOrItem.extension] - 文件扩展名(优先使用) | ||
| 111 | * @returns {string} 图标路径 | 113 | * @returns {string} 图标路径 |
| 112 | * | 114 | * |
| 113 | * @example | 115 | * @example |
| 114 | * getDocumentIcon('报告.pdf') // 返回 PDF 图标 | 116 | * getDocumentIcon('报告.pdf') // 返回 PDF 图标 |
| 117 | + * getDocumentIcon({ extension: 'pdf' }) // 返回 PDF 图标(优先使用 extension) | ||
| 118 | + * getDocumentIcon({ fileName: '报告.pdf' }) // 返回 PDF 图标 | ||
| 115 | * getDocumentIcon('数据.xlsx') // 返回 Excel 图标 | 119 | * getDocumentIcon('数据.xlsx') // 返回 Excel 图标 |
| 116 | * getDocumentIcon('图片.png') // 返回 PNG 图标 | 120 | * getDocumentIcon('图片.png') // 返回 PNG 图标 |
| 117 | */ | 121 | */ |
| 118 | -export function getDocumentIcon(fileName) { | 122 | +export function getDocumentIcon(fileNameOrItem) { |
| 119 | - if (!fileName || typeof fileName !== 'string') { | 123 | + const extension = extractExtensionFromFile(fileNameOrItem); |
| 124 | + | ||
| 125 | + if (!extension) { | ||
| 120 | return DEFAULT_ICON; | 126 | return DEFAULT_ICON; |
| 121 | } | 127 | } |
| 122 | 128 | ||
| 129 | + // 返回对应图标,找不到则返回默认图标 | ||
| 130 | + return EXTENSION_ICON_MAP[extension.toLowerCase()] || DEFAULT_ICON; | ||
| 131 | +} | ||
| 132 | + | ||
| 133 | +/** | ||
| 134 | + * 从文件名或文件对象中提取扩展名(统一工具函数) | ||
| 135 | + * | ||
| 136 | + * @description 支持传入文件名或包含 extension 字段的对象,优先使用 extension 字段。 | ||
| 137 | + * 这是项目中所有文件类型判断的核心工具函数。 | ||
| 138 | + * @param {string|Object} fileNameOrItem - 文件名(如:document.pdf)或文件对象(包含 extension 字段) | ||
| 139 | + * @param {string} [fileNameOrItem.fileName] - 文件名 | ||
| 140 | + * @param {string} [fileNameOrItem.extension] - 文件扩展名(优先使用) | ||
| 141 | + * @returns {string} 扩展名(小写),空字符串表示无法提取 | ||
| 142 | + * | ||
| 143 | + * @example | ||
| 144 | + * extractExtensionFromFile('document.pdf') // 'pdf' | ||
| 145 | + * extractExtensionFromFile({ extension: 'PDF' }) // 'pdf'(自动转小写) | ||
| 146 | + * extractExtensionFromFile({ fileName: 'document.DOC' }) // 'doc'(从文件名解析) | ||
| 147 | + * extractExtensionFromFile({ extension: 'pdf', fileName: 'backup.doc' }) // 'pdf'(优先使用 extension) | ||
| 148 | + */ | ||
| 149 | +export function extractExtensionFromFile(fileNameOrItem) { | ||
| 150 | + let extension = ''; | ||
| 151 | + | ||
| 152 | + // 支持对象格式(优先使用 extension 字段) | ||
| 153 | + if (typeof fileNameOrItem === 'object' && fileNameOrItem !== null) { | ||
| 154 | + extension = fileNameOrItem.extension || ''; | ||
| 155 | + // 如果没有 extension 字段,尝试从 fileName 解析 | ||
| 156 | + if (!extension && fileNameOrItem.fileName) { | ||
| 157 | + extension = extractExtensionFromString(fileNameOrItem.fileName); | ||
| 158 | + } | ||
| 159 | + } else if (typeof fileNameOrItem === 'string') { | ||
| 160 | + // 兼容字符串格式,从文件名解析 | ||
| 161 | + extension = extractExtensionFromString(fileNameOrItem); | ||
| 162 | + } | ||
| 163 | + | ||
| 164 | + return extension.toLowerCase(); | ||
| 165 | +} | ||
| 166 | + | ||
| 167 | +/** | ||
| 168 | + * 从文件名字符串中提取扩展名 | ||
| 169 | + * | ||
| 170 | + * @description 内部辅助函数,从文件名字符串中提取扩展名 | ||
| 171 | + * @param {string} fileName - 文件名 | ||
| 172 | + * @returns {string} 扩展名(小写) | ||
| 173 | + * @private | ||
| 174 | + */ | ||
| 175 | +function extractExtensionFromString(fileName) { | ||
| 176 | + if (!fileName || typeof fileName !== 'string') { | ||
| 177 | + return ''; | ||
| 178 | + } | ||
| 179 | + | ||
| 123 | // 提取文件扩展名 | 180 | // 提取文件扩展名 |
| 124 | const lastDotIndex = fileName.lastIndexOf('.'); | 181 | const lastDotIndex = fileName.lastIndexOf('.'); |
| 125 | 182 | ||
| 126 | // 没有扩展名或以点结尾(如 "file.") | 183 | // 没有扩展名或以点结尾(如 "file.") |
| 127 | if (lastDotIndex === -1 || lastDotIndex === fileName.length - 1) { | 184 | if (lastDotIndex === -1 || lastDotIndex === fileName.length - 1) { |
| 128 | - return DEFAULT_ICON; | 185 | + return ''; |
| 129 | } | 186 | } |
| 130 | 187 | ||
| 131 | - const extension = fileName.slice(lastDotIndex + 1).toLowerCase(); | 188 | + return fileName.slice(lastDotIndex + 1).toLowerCase(); |
| 132 | - | ||
| 133 | - // 返回对应图标,找不到则返回默认图标 | ||
| 134 | - return EXTENSION_ICON_MAP[extension] || DEFAULT_ICON; | ||
| 135 | } | 189 | } |
| 136 | 190 | ||
| 137 | /** | 191 | /** |
| 138 | - * 根据文件名获取文件类型标签 | 192 | + * 根据文件名或扩展名获取文件类型标签 |
| 139 | * | 193 | * |
| 140 | - * @description 从文件名中提取扩展名,返回对应的显示标签 | 194 | + * @description 支持传入文件名或包含 extension 字段的对象,优先使用 extension 字段 |
| 141 | - * @param {string} fileName - 文件名(如:document.pdf) | 195 | + * @param {string|Object} fileNameOrItem - 文件名(如:document.pdf)或文件对象(包含 extension 字段) |
| 196 | + * @param {string} [fileNameOrItem.fileName] - 文件名 | ||
| 197 | + * @param {string} [fileNameOrItem.extension] - 文件扩展名(优先使用) | ||
| 142 | * @returns {string} 文件类型标签(如:PDF、Word、Excel) | 198 | * @returns {string} 文件类型标签(如:PDF、Word、Excel) |
| 143 | * | 199 | * |
| 144 | * @example | 200 | * @example |
| 145 | * getDocumentLabel('报告.pdf') // 'PDF' | 201 | * getDocumentLabel('报告.pdf') // 'PDF' |
| 202 | + * getDocumentLabel({ extension: 'pdf' }) // 'PDF'(优先使用 extension) | ||
| 203 | + * getDocumentLabel({ fileName: '报告.pdf' }) // 'PDF' | ||
| 146 | * getDocumentLabel('数据.xlsx') // 'Excel' | 204 | * getDocumentLabel('数据.xlsx') // 'Excel' |
| 147 | * getDocumentLabel('图片.png') // 'PNG' | 205 | * getDocumentLabel('图片.png') // 'PNG' |
| 148 | */ | 206 | */ |
| 149 | -export function getDocumentLabel(fileName) { | 207 | +export function getDocumentLabel(fileNameOrItem) { |
| 150 | - if (!fileName || typeof fileName !== 'string') { | 208 | + const extension = extractExtensionFromFile(fileNameOrItem); |
| 151 | - return DEFAULT_LABEL; | ||
| 152 | - } | ||
| 153 | - | ||
| 154 | - // 提取文件扩展名 | ||
| 155 | - const lastDotIndex = fileName.lastIndexOf('.'); | ||
| 156 | 209 | ||
| 157 | - // 没有扩展名或以点结尾(如 "file.") | 210 | + if (!extension) { |
| 158 | - if (lastDotIndex === -1 || lastDotIndex === fileName.length - 1) { | ||
| 159 | return DEFAULT_LABEL; | 211 | return DEFAULT_LABEL; |
| 160 | } | 212 | } |
| 161 | 213 | ||
| 162 | - const extension = fileName.slice(lastDotIndex + 1).toLowerCase(); | ||
| 163 | - | ||
| 164 | // 返回对应标签,找不到则返回默认标签 | 214 | // 返回对应标签,找不到则返回默认标签 |
| 165 | - return EXTENSION_LABEL_MAP[extension] || DEFAULT_LABEL; | 215 | + return EXTENSION_LABEL_MAP[extension.toLowerCase()] || DEFAULT_LABEL; |
| 166 | } | 216 | } |
| 167 | 217 | ||
| 168 | /** | 218 | /** |
| 169 | - * 根据文件名判断是否为 PDF 文件 | 219 | + * 根据文件名或扩展名判断是否为 PDF 文件 |
| 170 | * | 220 | * |
| 171 | - * @param {string} fileName - 文件名 | 221 | + * @description 支持传入文件名或包含 extension 字段的对象,优先使用 extension 字段 |
| 222 | + * @param {string|Object} fileNameOrItem - 文件名或文件对象(包含 extension 字段) | ||
| 223 | + * @param {string} [fileNameOrItem.fileName] - 文件名 | ||
| 224 | + * @param {string} [fileNameOrItem.extension] - 文件扩展名(优先使用) | ||
| 172 | * @returns {boolean} 是否为 PDF 文件 | 225 | * @returns {boolean} 是否为 PDF 文件 |
| 173 | * | 226 | * |
| 174 | * @example | 227 | * @example |
| 175 | * isPDF('document.pdf') // true | 228 | * isPDF('document.pdf') // true |
| 229 | + * isPDF({ extension: 'pdf' }) // true(优先使用 extension) | ||
| 230 | + * isPDF({ fileName: 'document.pdf' }) // true | ||
| 176 | * isPDF('document.docx') // false | 231 | * isPDF('document.docx') // false |
| 177 | */ | 232 | */ |
| 178 | -export function isPDF(fileName) { | 233 | +export function isPDF(fileNameOrItem) { |
| 179 | - const extension = fileName?.split('.').pop()?.toLowerCase(); | 234 | + const extension = extractExtensionFromFile(fileNameOrItem); |
| 180 | - return extension === 'pdf'; | 235 | + return extension.toLowerCase() === 'pdf'; |
| 181 | } | 236 | } |
| 182 | 237 | ||
| 183 | /** | 238 | /** |
| 184 | - * 根据文件名判断是否为图片文件 | 239 | + * 根据文件名或扩展名判断是否为图片文件 |
| 185 | * | 240 | * |
| 186 | - * @param {string} fileName - 文件名 | 241 | + * @description 支持传入文件名或包含 extension 字段的对象,优先使用 extension 字段 |
| 242 | + * @param {string|Object} fileNameOrItem - 文件名或文件对象(包含 extension 字段) | ||
| 243 | + * @param {string} [fileNameOrItem.fileName] - 文件名 | ||
| 244 | + * @param {string} [fileNameOrItem.extension] - 文件扩展名(优先使用) | ||
| 187 | * @returns {boolean} 是否为图片文件 | 245 | * @returns {boolean} 是否为图片文件 |
| 188 | * | 246 | * |
| 189 | * @example | 247 | * @example |
| 190 | * isImage('photo.jpg') // true | 248 | * isImage('photo.jpg') // true |
| 249 | + * isImage({ extension: 'jpg' }) // true(优先使用 extension) | ||
| 191 | * isImage('document.pdf') // false | 250 | * isImage('document.pdf') // false |
| 192 | */ | 251 | */ |
| 193 | -export function isImage(fileName) { | 252 | +export function isImage(fileNameOrItem) { |
| 194 | - const extension = fileName?.split('.').pop()?.toLowerCase(); | 253 | + const extension = extractExtensionFromFile(fileNameOrItem); |
| 254 | + | ||
| 255 | + if (!extension) return false; | ||
| 256 | + | ||
| 195 | const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg']; | 257 | const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg']; |
| 196 | - return imageExtensions.includes(extension); | 258 | + return imageExtensions.includes(extension.toLowerCase()); |
| 197 | } | 259 | } |
| 198 | 260 | ||
| 199 | /** | 261 | /** |
| 200 | - * 根据文件名判断是否为视频文件 | 262 | + * 根据文件名或扩展名判断是否为视频文件 |
| 201 | * | 263 | * |
| 202 | - * @param {string} fileName - 文件名 | 264 | + * @description 支持传入文件名或包含 extension 字段的对象,优先使用 extension 字段 |
| 265 | + * @param {string|Object} fileNameOrItem - 文件名或文件对象(包含 extension 字段) | ||
| 266 | + * @param {string} [fileNameOrItem.fileName] - 文件名 | ||
| 267 | + * @param {string} [fileNameOrItem.extension] - 文件扩展名(优先使用) | ||
| 203 | * @returns {boolean} 是否为视频文件 | 268 | * @returns {boolean} 是否为视频文件 |
| 204 | * | 269 | * |
| 205 | * @example | 270 | * @example |
| 206 | * isVideo('movie.mp4') // true | 271 | * isVideo('movie.mp4') // true |
| 272 | + * isVideo({ extension: 'mp4' }) // true(优先使用 extension) | ||
| 207 | * isVideo('document.pdf') // false | 273 | * isVideo('document.pdf') // false |
| 208 | */ | 274 | */ |
| 209 | -export function isVideo(fileName) { | 275 | +export function isVideo(fileNameOrItem) { |
| 210 | - const extension = fileName?.split('.').pop()?.toLowerCase(); | 276 | + const extension = extractExtensionFromFile(fileNameOrItem); |
| 277 | + | ||
| 278 | + if (!extension) return false; | ||
| 279 | + | ||
| 211 | const videoExtensions = ['mp4', 'mov', 'avi', 'mkv']; | 280 | const videoExtensions = ['mp4', 'mov', 'avi', 'mkv']; |
| 212 | - return videoExtensions.includes(extension); | 281 | + return videoExtensions.includes(extension.toLowerCase()); |
| 213 | } | 282 | } | ... | ... |
| ... | @@ -8,6 +8,7 @@ | ... | @@ -8,6 +8,7 @@ |
| 8 | import dayjs from 'dayjs'; | 8 | import dayjs from 'dayjs'; |
| 9 | import Taro from '@tarojs/taro'; | 9 | import Taro from '@tarojs/taro'; |
| 10 | import BASE_URL, { REQUEST_DEFAULT_PARAMS } from './config' | 10 | import BASE_URL, { REQUEST_DEFAULT_PARAMS } from './config' |
| 11 | +import { extractExtensionFromFile } from './documentIcons' | ||
| 11 | 12 | ||
| 12 | /** | 13 | /** |
| 13 | * @description 格式化时间 | 14 | * @description 格式化时间 |
| ... | @@ -199,24 +200,26 @@ const buildApiUrl = (action, params = {}) => { | ... | @@ -199,24 +200,26 @@ const buildApiUrl = (action, params = {}) => { |
| 199 | 200 | ||
| 200 | /** | 201 | /** |
| 201 | * @description 判断文件是否为视频文件 | 202 | * @description 判断文件是否为视频文件 |
| 202 | - * @param {string} fileName 文件名 | 203 | + * @param {string|Object} fileNameOrItem 文件名或文件对象(支持 extension 字段) |
| 204 | + * @param {string} [fileNameOrItem.fileName] - 文件名 | ||
| 205 | + * @param {string} [fileNameOrItem.extension] - 文件扩展名(优先使用) | ||
| 203 | * @returns {boolean} true=是视频文件,false=不是视频文件 | 206 | * @returns {boolean} true=是视频文件,false=不是视频文件 |
| 204 | * | 207 | * |
| 205 | * @example | 208 | * @example |
| 206 | * isVideoFile('video.mp4') // true | 209 | * isVideoFile('video.mp4') // true |
| 210 | + * isVideoFile({ extension: 'mp4' }) // true (优先使用 extension) | ||
| 207 | * isVideoFile('document.pdf') // false | 211 | * isVideoFile('document.pdf') // false |
| 208 | * isVideoFile('presentation.mov') // true | 212 | * isVideoFile('presentation.mov') // true |
| 209 | */ | 213 | */ |
| 210 | -const isVideoFile = (fileName) => { | 214 | +const isVideoFile = (fileNameOrItem) => { |
| 211 | - if (!fileName || typeof fileName !== 'string') return false; | 215 | + const extension = extractExtensionFromFile(fileNameOrItem); |
| 212 | 216 | ||
| 213 | - // 提取文件扩展名 | 217 | + if (!extension) return false; |
| 214 | - const ext = fileName.split('.').pop()?.toLowerCase() || ''; | ||
| 215 | 218 | ||
| 216 | // 微信小程序支持的视频格式 | 219 | // 微信小程序支持的视频格式 |
| 217 | const videoExtensions = ['mp4', 'm4v', 'mov']; | 220 | const videoExtensions = ['mp4', 'm4v', 'mov']; |
| 218 | 221 | ||
| 219 | - return videoExtensions.includes(ext); | 222 | + return videoExtensions.includes(extension.toLowerCase()); |
| 220 | }; | 223 | }; |
| 221 | 224 | ||
| 222 | export { | 225 | export { | ... | ... |
-
Please register or login to post a comment