fix(file): 修复文件扩展名解析逻辑
- 修复 JPEG 等图片文件显示为 "DOC" 标签的问题 - 优化 extractExtensionFromFile 函数的 fallback 逻辑 - 移除首页、搜索页、周热门资料页的错误扩展名提取逻辑 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Showing
5 changed files
with
35 additions
and
20 deletions
| 1 | +## [2026-02-14] - 修复文件扩展名解析逻辑 | ||
| 2 | + | ||
| 3 | +### 修复 | ||
| 4 | +- 修复 JPEG 等图片文件显示为 "DOC" 标签的问题 | ||
| 5 | +- 优化 `extractExtensionFromFile` 函数的 fallback 逻辑 | ||
| 6 | +- 移除首页、搜索页、周热门资料页的错误扩展名提取逻辑 | ||
| 7 | + | ||
| 8 | +--- | ||
| 9 | + | ||
| 10 | +**详细信息**: | ||
| 11 | +- **影响文件**: src/utils/documentIcons.js, src/pages/index/index.vue, src/pages/search/index.vue, src/pages/week-hot-material/index.vue | ||
| 12 | +- **技术栈**: Vue 3, Taro 4, 文件处理 | ||
| 13 | +- **测试状态**: 待测试 | ||
| 14 | +- **备注**: | ||
| 15 | + - 问题根因:`fileName.split('.').pop()` 对 "IMG_6395大" 返回文件名本身而非扩展名 | ||
| 16 | + - 解决方案:让组件内部使用 `extractExtensionFromFile` 自动从 downloadUrl 解析扩展名 | ||
| 17 | + - 优先级:extension 字段 > fileName > src > downloadUrl | ||
| 18 | + - 涉及页面:首页周热门资料、搜索页文件结果 | ||
| 19 | + | ||
| 20 | +--- | ||
| 21 | + | ||
| 1 | ## [2026-02-13] - 收藏页空名称处理 | 22 | ## [2026-02-13] - 收藏页空名称处理 |
| 2 | 23 | ||
| 3 | ### 修复 | 24 | ### 修复 | ... | ... |
| ... | @@ -361,19 +361,15 @@ const fetchHotMaterials = async () => { | ... | @@ -361,19 +361,15 @@ const fetchHotMaterials = async () => { |
| 361 | if (res.code === 1 && res.data && res.data.list) { | 361 | if (res.code === 1 && res.data && res.data.list) { |
| 362 | // 转换 API 数据格式为组件所需格式 | 362 | // 转换 API 数据格式为组件所需格式 |
| 363 | hotMaterials.value = res.data.list.map(item => { | 363 | hotMaterials.value = res.data.list.map(item => { |
| 364 | - // 提取文件扩展名 | ||
| 365 | - const fileName = item.name || '未命名文件' | ||
| 366 | - const extension = item.extension || fileName.split('.').pop()?.toLowerCase() || '' | ||
| 367 | - | ||
| 368 | return { | 364 | return { |
| 369 | id: item.meta_id, | 365 | id: item.meta_id, |
| 370 | title: item.name || '未命名资料', | 366 | title: item.name || '未命名资料', |
| 371 | - fileName: fileName, | 367 | + fileName: item.name || '未命名文件', |
| 372 | downloadUrl: item.src, | 368 | downloadUrl: item.src, |
| 373 | fileSize: item.size, | 369 | fileSize: item.size, |
| 374 | - extension: extension, | 370 | + // 不在这里提取扩展名,让 MaterialCard 内部使用 extractExtensionFromFile 自动从 URL 解析 |
| 375 | learners: `${item.read_people_count}人学习`, | 371 | learners: `${item.read_people_count}人学习`, |
| 376 | - readPeoplePercent: item.read_people_percent, // 学习人数比例 | 372 | + readPeoplePercent: item.read_people_percent, |
| 377 | collected: item.is_favorite | 373 | collected: item.is_favorite |
| 378 | } | 374 | } |
| 379 | }); | 375 | }); | ... | ... |
| ... | @@ -275,17 +275,13 @@ const performSearch = async (keyword, type, page = 0, limit = pageSize, isLoadMo | ... | @@ -275,17 +275,13 @@ const performSearch = async (keyword, type, page = 0, limit = pageSize, isLoadMo |
| 275 | 275 | ||
| 276 | // 映射资料列表(进行字段映射,与首页保持一致) | 276 | // 映射资料列表(进行字段映射,与首页保持一致) |
| 277 | const newFiles = (res.data.files.list || []).map(item => { | 277 | const newFiles = (res.data.files.list || []).map(item => { |
| 278 | - // 提取文件扩展名 | ||
| 279 | - const fileName = item.name || '未命名文件' | ||
| 280 | - const extension = item.extension || fileName.split('.').pop()?.toLowerCase() || '' | ||
| 281 | - | ||
| 282 | return { | 278 | return { |
| 283 | id: item.meta_id || item.id, | 279 | id: item.meta_id || item.id, |
| 284 | title: item.name, | 280 | title: item.name, |
| 285 | - fileName: fileName, | 281 | + fileName: item.name || '未命名文件', |
| 286 | fileSize: item.size || item.file_size, | 282 | fileSize: item.size || item.file_size, |
| 287 | downloadUrl: item.src || item.value, | 283 | downloadUrl: item.src || item.value, |
| 288 | - extension: extension, | 284 | + // 不手动提取 extension,让 MaterialCard 内部使用 extractExtensionFromFile 自动从 URL 解析 |
| 289 | learners: item.read_people_count ? `${item.read_people_count }人学习` : '', | 285 | learners: item.read_people_count ? `${item.read_people_count }人学习` : '', |
| 290 | readPeoplePercent: item.read_people_percent, | 286 | readPeoplePercent: item.read_people_percent, |
| 291 | is_favorite: item.is_favorite, // 保留原始字段 | 287 | is_favorite: item.is_favorite, // 保留原始字段 | ... | ... |
| ... | @@ -134,15 +134,13 @@ const fetchWeekHotList = async (params = {}, isLoadMore = false) => { | ... | @@ -134,15 +134,13 @@ const fetchWeekHotList = async (params = {}, isLoadMore = false) => { |
| 134 | // 处理列表数据 | 134 | // 处理列表数据 |
| 135 | if (res.data.list?.length) { | 135 | if (res.data.list?.length) { |
| 136 | // 直接映射为 MaterialCard 需要的格式 | 136 | // 直接映射为 MaterialCard 需要的格式 |
| 137 | - // 注意:extension 字段可以让 extractExtensionFromFile 函数自动从 URL 解析 | 137 | + // 不手动提取 extension,让 MaterialCard 内部使用 extractExtensionFromFile 自动从 URL 解析 |
| 138 | const listData = res.data.list.map(item => { | 138 | const listData = res.data.list.map(item => { |
| 139 | return { | 139 | return { |
| 140 | meta_id: item.meta_id, | 140 | meta_id: item.meta_id, |
| 141 | name: item.name || '未命名文件', | 141 | name: item.name || '未命名文件', |
| 142 | size: item.size || '', | 142 | size: item.size || '', |
| 143 | downloadUrl: item.src, | 143 | downloadUrl: item.src, |
| 144 | - // extension 可以为空,MaterialCard 会使用 extractExtensionFromFile 从 src 解析 | ||
| 145 | - extension: item.extension || '', | ||
| 146 | collected: item.is_favorite === '1' || item.is_favorite === 1 || item.is_favorite === true, | 144 | collected: item.is_favorite === '1' || item.is_favorite === 1 || item.is_favorite === true, |
| 147 | read_people_count: item.read_people_count, | 145 | read_people_count: item.read_people_count, |
| 148 | read_people_percent: item.read_people_percent | 146 | read_people_percent: item.read_people_percent | ... | ... |
| ... | @@ -138,6 +138,7 @@ export function getDocumentIcon(fileNameOrItem) { | ... | @@ -138,6 +138,7 @@ export function getDocumentIcon(fileNameOrItem) { |
| 138 | * 从文件名或文件对象中提取扩展名(统一工具函数) | 138 | * 从文件名或文件对象中提取扩展名(统一工具函数) |
| 139 | * | 139 | * |
| 140 | * @description 支持传入文件名或包含 extension 字段的对象,优先使用 extension 字段。 | 140 | * @description 支持传入文件名或包含 extension 字段的对象,优先使用 extension 字段。 |
| 141 | + * 如果 extension 为空,会依次从 fileName、src、downloadUrl 解析,直到找到扩展名。 | ||
| 141 | * 这是项目中所有文件类型判断的核心工具函数。 | 142 | * 这是项目中所有文件类型判断的核心工具函数。 |
| 142 | * @param {string|Object} fileNameOrItem - 文件名(如:document.pdf)或文件对象(包含 extension 字段) | 143 | * @param {string|Object} fileNameOrItem - 文件名(如:document.pdf)或文件对象(包含 extension 字段) |
| 143 | * @param {string} [fileNameOrItem.fileName] - 文件名 | 144 | * @param {string} [fileNameOrItem.fileName] - 文件名 |
| ... | @@ -152,6 +153,7 @@ export function getDocumentIcon(fileNameOrItem) { | ... | @@ -152,6 +153,7 @@ export function getDocumentIcon(fileNameOrItem) { |
| 152 | * extractExtensionFromFile({ fileName: 'document.DOC' }) // 'doc'(从文件名解析) | 153 | * extractExtensionFromFile({ fileName: 'document.DOC' }) // 'doc'(从文件名解析) |
| 153 | * extractExtensionFromFile({ extension: 'pdf', fileName: 'backup.doc' }) // 'pdf'(优先使用 extension) | 154 | * extractExtensionFromFile({ extension: 'pdf', fileName: 'backup.doc' }) // 'pdf'(优先使用 extension) |
| 154 | * extractExtensionFromFile({ src: 'https://example.com/file.png' }) // 'png'(从 URL 解析) | 155 | * extractExtensionFromFile({ src: 'https://example.com/file.png' }) // 'png'(从 URL 解析) |
| 156 | + * extractExtensionFromFile({ fileName: '无扩展名文件', src: 'https://cdn.com/file.jpeg' }) // 'jpeg'(src 补位) | ||
| 155 | * extractExtensionFromFile({ downloadUrl: 'https://cdn.com/file.jpg' }) // 'jpg'(从 URL 解析) | 157 | * extractExtensionFromFile({ downloadUrl: 'https://cdn.com/file.jpg' }) // 'jpg'(从 URL 解析) |
| 156 | */ | 158 | */ |
| 157 | export function extractExtensionFromFile(fileNameOrItem) { | 159 | export function extractExtensionFromFile(fileNameOrItem) { |
| ... | @@ -167,12 +169,14 @@ export function extractExtensionFromFile(fileNameOrItem) { | ... | @@ -167,12 +169,14 @@ export function extractExtensionFromFile(fileNameOrItem) { |
| 167 | if (fileNameOrItem.fileName) { | 169 | if (fileNameOrItem.fileName) { |
| 168 | extension = extractExtensionFromString(fileNameOrItem.fileName); | 170 | extension = extractExtensionFromString(fileNameOrItem.fileName); |
| 169 | } | 171 | } |
| 170 | - // 如果 fileName 没有扩展名,尝试从 src 解析 | 172 | + |
| 171 | - else if (fileNameOrItem.src) { | 173 | + // 如果 fileName 没有扩展名(extension 仍为空),继续尝试其他字段 |
| 174 | + if (!extension && fileNameOrItem.src) { | ||
| 172 | extension = extractExtensionFromString(fileNameOrItem.src); | 175 | extension = extractExtensionFromString(fileNameOrItem.src); |
| 173 | } | 176 | } |
| 174 | - // 如果 src 也没有,尝试从 downloadUrl 解析 | 177 | + |
| 175 | - else if (fileNameOrItem.downloadUrl) { | 178 | + // 如果 src 也没有扩展名,继续尝试 downloadUrl |
| 179 | + if (!extension && fileNameOrItem.downloadUrl) { | ||
| 176 | extension = extractExtensionFromString(fileNameOrItem.downloadUrl); | 180 | extension = extractExtensionFromString(fileNameOrItem.downloadUrl); |
| 177 | } | 181 | } |
| 178 | } | 182 | } | ... | ... |
-
Please register or login to post a comment