hookehuyr

fix(file): 修复文件扩展名解析逻辑

- 修复 JPEG 等图片文件显示为 "DOC" 标签的问题
- 优化 extractExtensionFromFile 函数的 fallback 逻辑
- 移除首页、搜索页、周热门资料页的错误扩展名提取逻辑

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
## [2026-02-14] - 修复文件扩展名解析逻辑
### 修复
- 修复 JPEG 等图片文件显示为 "DOC" 标签的问题
- 优化 `extractExtensionFromFile` 函数的 fallback 逻辑
- 移除首页、搜索页、周热门资料页的错误扩展名提取逻辑
---
**详细信息**
- **影响文件**: src/utils/documentIcons.js, src/pages/index/index.vue, src/pages/search/index.vue, src/pages/week-hot-material/index.vue
- **技术栈**: Vue 3, Taro 4, 文件处理
- **测试状态**: 待测试
- **备注**:
- 问题根因:`fileName.split('.').pop()` 对 "IMG_6395大" 返回文件名本身而非扩展名
- 解决方案:让组件内部使用 `extractExtensionFromFile` 自动从 downloadUrl 解析扩展名
- 优先级:extension 字段 > fileName > src > downloadUrl
- 涉及页面:首页周热门资料、搜索页文件结果
---
## [2026-02-13] - 收藏页空名称处理
### 修复
......
......@@ -361,19 +361,15 @@ const fetchHotMaterials = async () => {
if (res.code === 1 && res.data && res.data.list) {
// 转换 API 数据格式为组件所需格式
hotMaterials.value = res.data.list.map(item => {
// 提取文件扩展名
const fileName = item.name || '未命名文件'
const extension = item.extension || fileName.split('.').pop()?.toLowerCase() || ''
return {
id: item.meta_id,
title: item.name || '未命名资料',
fileName: fileName,
fileName: item.name || '未命名文件',
downloadUrl: item.src,
fileSize: item.size,
extension: extension,
// 不在这里提取扩展名,让 MaterialCard 内部使用 extractExtensionFromFile 自动从 URL 解析
learners: `${item.read_people_count}人学习`,
readPeoplePercent: item.read_people_percent, // 学习人数比例
readPeoplePercent: item.read_people_percent,
collected: item.is_favorite
}
});
......
......@@ -275,17 +275,13 @@ const performSearch = async (keyword, type, page = 0, limit = pageSize, isLoadMo
// 映射资料列表(进行字段映射,与首页保持一致)
const newFiles = (res.data.files.list || []).map(item => {
// 提取文件扩展名
const fileName = item.name || '未命名文件'
const extension = item.extension || fileName.split('.').pop()?.toLowerCase() || ''
return {
id: item.meta_id || item.id,
title: item.name,
fileName: fileName,
fileName: item.name || '未命名文件',
fileSize: item.size || item.file_size,
downloadUrl: item.src || item.value,
extension: extension,
// 不手动提取 extension,让 MaterialCard 内部使用 extractExtensionFromFile 自动从 URL 解析
learners: item.read_people_count ? `${item.read_people_count }人学习` : '',
readPeoplePercent: item.read_people_percent,
is_favorite: item.is_favorite, // 保留原始字段
......
......@@ -134,15 +134,13 @@ const fetchWeekHotList = async (params = {}, isLoadMore = false) => {
// 处理列表数据
if (res.data.list?.length) {
// 直接映射为 MaterialCard 需要的格式
// 注意:extension 字段可以让 extractExtensionFromFile 函数自动从 URL 解析
// 不手动提取 extension,让 MaterialCard 内部使用 extractExtensionFromFile 自动从 URL 解析
const listData = res.data.list.map(item => {
return {
meta_id: item.meta_id,
name: item.name || '未命名文件',
size: item.size || '',
downloadUrl: item.src,
// extension 可以为空,MaterialCard 会使用 extractExtensionFromFile 从 src 解析
extension: item.extension || '',
collected: item.is_favorite === '1' || item.is_favorite === 1 || item.is_favorite === true,
read_people_count: item.read_people_count,
read_people_percent: item.read_people_percent
......
......@@ -138,6 +138,7 @@ export function getDocumentIcon(fileNameOrItem) {
* 从文件名或文件对象中提取扩展名(统一工具函数)
*
* @description 支持传入文件名或包含 extension 字段的对象,优先使用 extension 字段。
* 如果 extension 为空,会依次从 fileName、src、downloadUrl 解析,直到找到扩展名。
* 这是项目中所有文件类型判断的核心工具函数。
* @param {string|Object} fileNameOrItem - 文件名(如:document.pdf)或文件对象(包含 extension 字段)
* @param {string} [fileNameOrItem.fileName] - 文件名
......@@ -152,6 +153,7 @@ export function getDocumentIcon(fileNameOrItem) {
* extractExtensionFromFile({ fileName: 'document.DOC' }) // 'doc'(从文件名解析)
* extractExtensionFromFile({ extension: 'pdf', fileName: 'backup.doc' }) // 'pdf'(优先使用 extension)
* extractExtensionFromFile({ src: 'https://example.com/file.png' }) // 'png'(从 URL 解析)
* extractExtensionFromFile({ fileName: '无扩展名文件', src: 'https://cdn.com/file.jpeg' }) // 'jpeg'(src 补位)
* extractExtensionFromFile({ downloadUrl: 'https://cdn.com/file.jpg' }) // 'jpg'(从 URL 解析)
*/
export function extractExtensionFromFile(fileNameOrItem) {
......@@ -167,12 +169,14 @@ export function extractExtensionFromFile(fileNameOrItem) {
if (fileNameOrItem.fileName) {
extension = extractExtensionFromString(fileNameOrItem.fileName);
}
// 如果 fileName 没有扩展名,尝试从 src 解析
else if (fileNameOrItem.src) {
// 如果 fileName 没有扩展名(extension 仍为空),继续尝试其他字段
if (!extension && fileNameOrItem.src) {
extension = extractExtensionFromString(fileNameOrItem.src);
}
// 如果 src 也没有,尝试从 downloadUrl 解析
else if (fileNameOrItem.downloadUrl) {
// 如果 src 也没有扩展名,继续尝试 downloadUrl
if (!extension && fileNameOrItem.downloadUrl) {
extension = extractExtensionFromString(fileNameOrItem.downloadUrl);
}
}
......