You need to sign in or sign up before continuing.
utils.js 3.59 KB
/**
 * @Description: 文档预览工具函数
 * @Date: 2025-01-30
 */

/**
 * 从 URL 中检测文件类型
 * @param {string} url - 文档 URL
 * @returns {string} 文件类型(小写)
 */
export function detectFileType(url) {
  if (!url) return ''

  // 从 URL 中提取扩展名
  const match = url.match(/\.([a-z0-9]+)(?:\?|#|$)/i)

  if (match && match[1]) {
    const ext = match[1].toLowerCase()

    // 映射常见扩展名到统一类型
    const typeMap = {
      pdf: 'pdf',
      doc: 'doc',
      docx: 'docx',
      xls: 'xls',
      xlsx: 'xlsx',
      ppt: 'ppt',
      pptx: 'pptx'
    }

    return typeMap[ext] || ext
  }

  // 如果无法从 URL 判断,尝试从 Content-Type 头(需要后端支持)
  return ''
}

/**
 * 获取文件大小(通过 HEAD 请求)
 * @param {string} url - 文档 URL
 * @returns {Promise<number>} 文件大小(字节)
 */
export async function getFileSize(url) {
  // 检测运行环境
  const isWeapp = typeof wx !== 'undefined' || typeof my !== 'undefined'

  // 小程序环境:使用 Taro.request
  if (isWeapp) {
    try {
      const Taro = (await import('@tarojs/taro')).default
      const res = await Taro.request({
        url: url,
        method: 'HEAD'
      })

      const contentLength = res.header['Content-Length'] || res.header['content-length']
      if (contentLength) {
        return parseInt(contentLength, 10)
      }
    } catch (err) {
      console.error('获取文件大小失败:', err)
    }
    return 0
  }

  // H5 环境:使用 fetch
  try {
    const response = await fetch(url, { method: 'HEAD' })
    const contentLength = response.headers.get('Content-Length')
    if (contentLength) {
      return parseInt(contentLength, 10)
    }
  } catch (err) {
    console.error('获取文件大小失败:', err)
  }

  // 无法获取大小,返回 0(将使用 web-view)
  return 0
}

/**
 * 格式化文件大小显示
 * @param {number} bytes - 文件大小(字节)
 * @returns {string} 格式化后的字符串
 */
export function formatFileSize(bytes) {
  if (!bytes || bytes === 0) return '未知大小'

  const units = ['B', 'KB', 'MB', 'GB']
  let size = bytes
  let unitIndex = 0

  while (size >= 1024 && unitIndex < units.length - 1) {
    size /= 1024
    unitIndex++
  }

  // 保留两位小数
  const formatted = size.toFixed(2).replace(/\.00$/, '')

  return `${formatted} ${units[unitIndex]}`
}

/**
 * 判断是否为支持的文档类型
 * @param {string} fileType - 文件类型
 * @returns {boolean}
 */
export function isSupportedDocumentType(fileType) {
  const supportedTypes = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx']
  return supportedTypes.includes(fileType?.toLowerCase())
}

/**
 * 获取文件图标名称
 * @param {string} fileType - 文件类型
 * @returns {string} 图标名称
 */
export function getFileIconName(fileType) {
  const iconMap = {
    pdf: 'pdf',
    doc: 'word',
    docx: 'word',
    xls: 'excel',
    xlsx: 'excel',
    ppt: 'ppt',
    pptx: 'ppt'
  }
  return iconMap[fileType?.toLowerCase()] || 'file'
}

/**
 * 生成腾讯文档预览 URL
 * @param {string} url - 原始文档 URL
 * @returns {string} 腾讯文档预览 URL
 */
export function getTencentPreviewUrl(url) {
  const encodedUrl = encodeURIComponent(url)
  return `https://view.officeapps.live.com/op/view.aspx?src=${encodedUrl}`
}

/**
 * 生成微软在线预览 URL
 * @param {string} url - 原始文档 URL
 * @returns {string} 微软预览 URL
 */
export function getMicrosoftPreviewUrl(url) {
  const encodedUrl = encodeURIComponent(url)
  return `https://view.officeapps.live.com/op/embed.aspx?src=${encodedUrl}`
}