documentIcons.js 11.2 KB
/**
 * @description 文档图标工具函数
 * @module utils/documentIcons
 * @author Claude Code
 * @created 2026-01-31
 */

// 导入所有 SVG 图标资源
import docIcon from '@/assets/images/icon/doc/doc.svg'
import pdfIcon from '@/assets/images/icon/doc/pdf.svg'
import wordIcon from '@/assets/images/icon/doc/word.svg'
import xlsIcon from '@/assets/images/icon/doc/xls.svg'
import pptIcon from '@/assets/images/icon/doc/ppt.svg'
import jpegIcon from '@/assets/images/icon/doc/jpeg.svg'
import pngIcon from '@/assets/images/icon/doc/png.svg'
import mp4Icon from '@/assets/images/icon/doc/mp4.svg'
import svgIcon from '@/assets/images/icon/doc/svg.svg'
import txtIcon from '@/assets/images/icon/doc/txt.svg'
import defaultIcon from '@/assets/images/icon/doc/其他文件.svg'

/**
 * 文件扩展名到图标的映射
 * @type {Object.<string, string>}
 */
const EXTENSION_ICON_MAP = {
  // 文档类
  'pdf': pdfIcon,
  'doc': wordIcon,
  'docx': wordIcon,

  // 表格类
  'xls': xlsIcon,
  'xlsx': xlsIcon,

  // 演示文稿类
  'ppt': pptIcon,
  'pptx': pptIcon,

  // 图片类
  'jpg': jpegIcon,
  'jpeg': jpegIcon,
  'png': pngIcon,
  'gif': pngIcon,
  'webp': pngIcon,

  // 视频类
  'mp4': mp4Icon,
  'mov': mp4Icon,
  'avi': mp4Icon,
  'mkv': mp4Icon,

  // 矢量图类
  'svg': svgIcon,

  // 文本类
  'txt': txtIcon,
  'md': txtIcon,

  // 其他
  'zip': defaultIcon,
  'rar': defaultIcon,
  '7z': defaultIcon,
};

/**
 * 默认图标(未知文件类型)
 * @type {string}
 */
const DEFAULT_ICON = defaultIcon;

/**
 * 文件扩展名到显示标签的映射
 * @type {Object.<string, string>}
 */
const EXTENSION_LABEL_MAP = {
  'pdf': 'PDF',
  'doc': 'Word',
  'docx': 'Word',
  'xls': 'Excel',
  'xlsx': 'Excel',
  'ppt': 'PPT',
  'pptx': 'PPT',
  'jpg': 'JPG',
  'jpeg': 'JPEG',
  'png': 'PNG',
  'gif': 'GIF',
  'webp': 'WebP',
  'mp4': 'MP4',
  'mov': 'MOV',
  'avi': 'AVI',
  'mkv': 'MKV',
  'svg': 'SVG',
  'txt': 'TXT',
  'md': 'MD',
  'zip': 'ZIP',
  'rar': 'RAR',
  '7z': '7Z',
};

/**
 * 默认文件类型标签
 * @type {string}
 */
const DEFAULT_LABEL = 'DOC';

/**
 * 根据文件名或扩展名获取文档图标路径
 *
 * @description 支持传入文件名或包含 extension 字段的对象,优先使用 extension 字段。
 *              如果没有 extension,会尝试从 fileName、src、downloadUrl 等字段解析。
 * @param {string|Object} fileNameOrItem - 文件名(如:document.pdf)或文件对象
 * @param {string} [fileNameOrItem.fileName] - 文件名
 * @param {string} [fileNameOrItem.extension] - 文件扩展名(优先使用)
 * @param {string} [fileNameOrItem.src] - 文件 URL(用于提取扩展名)
 * @param {string} [fileNameOrItem.downloadUrl] - 下载 URL(用于提取扩展名)
 * @returns {string} 图标路径
 *
 * @example
 * getDocumentIcon('报告.pdf') // 返回 PDF 图标
 * getDocumentIcon({ extension: 'pdf' }) // 返回 PDF 图标(优先使用 extension)
 * getDocumentIcon({ fileName: '报告.pdf' }) // 返回 PDF 图标
 * getDocumentIcon({ src: 'https://example.com/file.png' }) // 返回 PNG 图标(从 URL 解析)
 * getDocumentIcon('数据.xlsx') // 返回 Excel 图标
 * getDocumentIcon('图片.png') // 返回 PNG 图标
 */
export function getDocumentIcon(fileNameOrItem) {
  const extension = extractExtensionFromFile(fileNameOrItem);

  if (!extension) {
    return DEFAULT_ICON;
  }

  // 返回对应图标,找不到则返回默认图标
  return EXTENSION_ICON_MAP[extension.toLowerCase()] || DEFAULT_ICON;
}

/**
 * 从文件名或文件对象中提取扩展名(统一工具函数)
 *
 * @description 支持传入文件名或包含 extension 字段的对象,优先使用 extension 字段。
 *              这是项目中所有文件类型判断的核心工具函数。
 * @param {string|Object} fileNameOrItem - 文件名(如:document.pdf)或文件对象(包含 extension 字段)
 * @param {string} [fileNameOrItem.fileName] - 文件名
 * @param {string} [fileNameOrItem.extension] - 文件扩展名(优先使用)
 * @param {string} [fileNameOrItem.src] - 文件 URL(用于提取扩展名)
 * @param {string} [fileNameOrItem.downloadUrl] - 下载 URL(用于提取扩展名)
 * @returns {string} 扩展名(小写),空字符串表示无法提取
 *
 * @example
 * extractExtensionFromFile('document.pdf') // 'pdf'
 * extractExtensionFromFile({ extension: 'PDF' }) // 'pdf'(自动转小写)
 * extractExtensionFromFile({ fileName: 'document.DOC' }) // 'doc'(从文件名解析)
 * extractExtensionFromFile({ extension: 'pdf', fileName: 'backup.doc' }) // 'pdf'(优先使用 extension)
 * extractExtensionFromFile({ src: 'https://example.com/file.png' }) // 'png'(从 URL 解析)
 * extractExtensionFromFile({ downloadUrl: 'https://cdn.com/file.jpg' }) // 'jpg'(从 URL 解析)
 */
export function extractExtensionFromFile(fileNameOrItem) {
  let extension = '';

  // 支持对象格式(优先使用 extension 字段)
  if (typeof fileNameOrItem === 'object' && fileNameOrItem !== null) {
    extension = fileNameOrItem.extension || '';

    // 如果没有 extension 字段,尝试从其他字段解析
    if (!extension) {
      // 优先从 fileName 解析
      if (fileNameOrItem.fileName) {
        extension = extractExtensionFromString(fileNameOrItem.fileName);
      }
      // 如果 fileName 没有扩展名,尝试从 src 解析
      else if (fileNameOrItem.src) {
        extension = extractExtensionFromString(fileNameOrItem.src);
      }
      // 如果 src 也没有,尝试从 downloadUrl 解析
      else if (fileNameOrItem.downloadUrl) {
        extension = extractExtensionFromString(fileNameOrItem.downloadUrl);
      }
    }
  } else if (typeof fileNameOrItem === 'string') {
    // 兼容字符串格式,从文件名解析
    extension = extractExtensionFromString(fileNameOrItem);
  }

  return extension.toLowerCase();
}

/**
 * 从文件名字符串中提取扩展名
 *
 * @description 内部辅助函数,从文件名字符串中提取扩展名
 * @param {string} fileName - 文件名
 * @returns {string} 扩展名(小写)
 * @private
 */
function extractExtensionFromString(fileName) {
  if (!fileName || typeof fileName !== 'string') {
    return '';
  }

  // 提取文件扩展名
  const lastDotIndex = fileName.lastIndexOf('.');

  // 没有扩展名或以点结尾(如 "file.")
  if (lastDotIndex === -1 || lastDotIndex === fileName.length - 1) {
    return '';
  }

  return fileName.slice(lastDotIndex + 1).toLowerCase();
}

/**
 * 根据文件名或扩展名获取文件类型标签
 *
 * @description 支持传入文件名或包含 extension 字段的对象,优先使用 extension 字段。
 *              如果没有 extension,会尝试从 fileName、src、downloadUrl 等字段解析。
 * @param {string|Object} fileNameOrItem - 文件名(如:document.pdf)或文件对象
 * @param {string} [fileNameOrItem.fileName] - 文件名
 * @param {string} [fileNameOrItem.extension] - 文件扩展名(优先使用)
 * @param {string} [fileNameOrItem.src] - 文件 URL(用于提取扩展名)
 * @param {string} [fileNameOrItem.downloadUrl] - 下载 URL(用于提取扩展名)
 * @returns {string} 文件类型标签(如:PDF、Word、Excel)
 *
 * @example
 * getDocumentLabel('报告.pdf') // 'PDF'
 * getDocumentLabel({ extension: 'pdf' }) // 'PDF'(优先使用 extension)
 * getDocumentLabel({ fileName: '报告.pdf' }) // 'PDF'
 * getDocumentLabel({ src: 'https://example.com/file.png' }) // 'PNG'(从 URL 解析)
 * getDocumentLabel('数据.xlsx') // 'Excel'
 * getDocumentLabel('图片.png') // 'PNG'
 */
export function getDocumentLabel(fileNameOrItem) {
  const extension = extractExtensionFromFile(fileNameOrItem);

  if (!extension) {
    return DEFAULT_LABEL;
  }

  // 返回对应标签,找不到则返回默认标签
  return EXTENSION_LABEL_MAP[extension.toLowerCase()] || DEFAULT_LABEL;
}

/**
 * 根据文件名或扩展名判断是否为 PDF 文件
 *
 * @description 支持传入文件名或包含 extension 字段的对象,优先使用 extension 字段。
 *              如果没有 extension,会尝试从 fileName、src、downloadUrl 等字段解析。
 * @param {string|Object} fileNameOrItem - 文件名或文件对象
 * @param {string} [fileNameOrItem.fileName] - 文件名
 * @param {string} [fileNameOrItem.extension] - 文件扩展名(优先使用)
 * @param {string} [fileNameOrItem.src] - 文件 URL(用于提取扩展名)
 * @param {string} [fileNameOrItem.downloadUrl] - 下载 URL(用于提取扩展名)
 * @returns {boolean} 是否为 PDF 文件
 *
 * @example
 * isPDF('document.pdf') // true
 * isPDF({ extension: 'pdf' }) // true(优先使用 extension)
 * isPDF({ fileName: 'document.pdf' }) // true
 * isPDF({ src: 'https://example.com/file.pdf' }) // true(从 URL 解析)
 * isPDF('document.docx') // false
 */
export function isPDF(fileNameOrItem) {
  const extension = extractExtensionFromFile(fileNameOrItem);
  return extension.toLowerCase() === 'pdf';
}

/**
 * 根据文件名或扩展名判断是否为图片文件
 *
 * @description 支持传入文件名或包含 extension 字段的对象,优先使用 extension 字段。
 *              如果没有 extension,会尝试从 fileName、src、downloadUrl 等字段解析。
 * @param {string|Object} fileNameOrItem - 文件名或文件对象
 * @param {string} [fileNameOrItem.fileName] - 文件名
 * @param {string} [fileNameOrItem.extension] - 文件扩展名(优先使用)
 * @param {string} [fileNameOrItem.src] - 文件 URL(用于提取扩展名)
 * @param {string} [fileNameOrItem.downloadUrl] - 下载 URL(用于提取扩展名)
 * @returns {boolean} 是否为图片文件
 *
 * @example
 * isImage('photo.jpg') // true
 * isImage({ extension: 'jpg' }) // true(优先使用 extension)
 * isImage({ src: 'https://example.com/file.png' }) // true(从 URL 解析)
 * isImage('document.pdf') // false
 */
export function isImage(fileNameOrItem) {
  const extension = extractExtensionFromFile(fileNameOrItem);

  if (!extension) return false;

  const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg'];
  return imageExtensions.includes(extension.toLowerCase());
}

/**
 * 根据文件名或扩展名判断是否为视频文件
 *
 * @description 支持传入文件名或包含 extension 字段的对象,优先使用 extension 字段。
 *              如果没有 extension,会尝试从 fileName、src、downloadUrl 等字段解析。
 * @param {string|Object} fileNameOrItem - 文件名或文件对象
 * @param {string} [fileNameOrItem.fileName] - 文件名
 * @param {string} [fileNameOrItem.extension] - 文件扩展名(优先使用)
 * @param {string} [fileNameOrItem.src] - 文件 URL(用于提取扩展名)
 * @param {string} [fileNameOrItem.downloadUrl] - 下载 URL(用于提取扩展名)
 * @returns {boolean} 是否为视频文件
 *
 * @example
 * isVideo('movie.mp4') // true
 * isVideo({ extension: 'mp4' }) // true(优先使用 extension)
 * isVideo({ src: 'https://example.com/file.mp4' }) // true(从 URL 解析)
 * isVideo('document.pdf') // false
 */
export function isVideo(fileNameOrItem) {
  const extension = extractExtensionFromFile(fileNameOrItem);

  if (!extension) return false;

  const videoExtensions = ['mp4', 'mov', 'avi', 'mkv'];
  return videoExtensions.includes(extension.toLowerCase());
}