utils.js 9.54 KB
import CryptoJS from 'crypto-js'
import config from '@/config.js'
export function szToHz(num) {
  const hzArr = ['〇', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十']
  return hzArr[parseInt(num)]
}

export function AESEncrypt(data) {
  const key = CryptoJS.enc.Utf8.parse('abcdefgabcdegf21')
  // 将数据转换为字符串
  const parseByte2HexStr = (wordArray) => {
    const hexStr = wordArray.ciphertext.toString(CryptoJS.enc.Hex)
    return hexStr
  }
  let dataStr
  if (typeof data === 'object') {
    dataStr = JSON.stringify(data)
  } else {
    dataStr = String(data)
  }
  // 加密
  const encrypted = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(dataStr), key, {
    mode: CryptoJS.mode.ECB,
    padding: CryptoJS.pad.Pkcs7
  })
  return parseByte2HexStr(encrypted)
}


export function AESDecrypt(str) {
  const key = CryptoJS.enc.Utf8.parse('abcdefgabcdegf21')
  const decrypt = CryptoJS.AES.decrypt(str, key, {
    mode: CryptoJS.mode.ECB,
    padding: CryptoJS.pad.Pkcs7
  })
  const aesStr = CryptoJS.enc.Utf8.stringify(decrypt).toString()
  try {
    return JSON.parse(aesStr)
  } catch (e) {
    return aesStr
  }
}

export function isDaoGuanRole() {
  const app = getApp()
  const deptType = app.globalData?.deptType
  const userType = app.globalData?.userType
  return deptType == null || deptType == 6 || deptType == '6' || userType == '4'
}

export function reLaunchHomeByRole() {
  uni.reLaunch({
    url: isDaoGuanRole() ? '/pages/index/daoGuanPerson' : '/pages/index/home'
  })
}

export function fillImgUrl(url, prefix) {
  if (!url) return ''
  const trimmedUrl = String(url).trim()
  if (!trimmedUrl) return ''
  if (trimmedUrl === 'null' || trimmedUrl === 'undefined') return ''
  if (trimmedUrl.startsWith('msr:')) {
    return `${trimBaseUrl(config.baseUrl_api)}/fileServer/download?file=${encodeURIComponent(trimmedUrl)}&downFlag=0`
  }
  if (/^(data:|https?:\/\/)/.test(trimmedUrl)) {
    return trimmedUrl
  }
  const baseUrl = prefix
    ? `${trimBaseUrl(config.baseUrl_api)}/${String(prefix).replace(/^\/+|\/+$/g, '')}`
    : trimBaseUrl(config.baseUrl_api)
  const path = trimmedUrl.startsWith('/') ? trimmedUrl : `/${trimmedUrl}`
  return baseUrl + path
}

export function isImageUrl(url) {
  const value = String(url || '').trim()
  if (!value) return false
  const decodedValue = safeDecodeURIComponent(value)
  return /\.(png|jpe?g|gif|webp|bmp|svg)(\?.*)?$/i.test(decodedValue) ||
    /[?&]file=[^&]*\.(png|jpe?g|gif|webp|bmp|svg)(&|$)/i.test(decodedValue)
}

export function getMemberPhotoValue(item = {}) {
  return [item.photo, item.perPhoto, item.photo2, item.perPhoto2].find(isValidUrlValue) || ''
}

export function fillMemberPhoto(item = {}, fallback = '') {
  const photo = getMemberPhotoValue(item)
  return photo ? fillImgUrl(photo) : fallback
}

export async function previewAttachment(file, options = {}) {
  const item = normalizeAttachment(file)
  const rawUrl = item.rawUrl || item.url
  const previewUrl = getAttachmentPreviewUrl(rawUrl, 0)
  if (!previewUrl) {
    uni.showToast({
      title: '暂无可预览附件',
      icon: 'none'
    })
    return
  }
  if (isAttachmentImage(item) || isImageUrl(rawUrl) || isImageUrl(previewUrl)) {
    const errorMsg = await checkAttachmentError(previewUrl)
    if (errorMsg) {
      uni.showToast({
        title: errorMsg,
        icon: 'none'
      })
      return
    }
    uni.previewImage({
      urls: [previewUrl],
      current: previewUrl,
      fail: () => {
        uni.showToast({
          title: '图片预览失败',
          icon: 'none'
        })
      }
    })
    return
  }
  if (getAttachmentExt(item) === 'zip') {
    uni.showToast({
      title: '压缩包暂不支持在线预览',
      icon: 'none'
    })
    return
  }
  openDocumentAttachment(item, getAttachmentPreviewUrl(rawUrl, 0), false, options)
}

export function normalizeAttachment(file) {
  if (Array.isArray(file)) return normalizeAttachment(file[0])
  if (typeof file === 'string') {
    const parsed = parseAttachmentJson(file)
    if (parsed !== file) return normalizeAttachment(parsed)
    return {
      rawUrl: file,
      url: file,
      name: ''
    }
  }
  if (file && typeof file === 'object') {
    const rawUrl = file.rawUrl || file.url || file.fileUrl || file.path || ''
    return {
      ...file,
      rawUrl,
      url: rawUrl
    }
  }
  return {}
}

export function parseAttachmentJson(value) {
  if (!value || typeof value !== 'string') return value
  try {
    return JSON.parse(value)
  } catch (e) {
    return value
  }
}

export function getAttachmentPreviewUrl(url, downFlag = 0) {
  if (!url) return ''
  const value = String(url).trim()
  if (!value || value === 'null' || value === 'undefined') return ''
  if (value.startsWith('msr:')) {
    return `${trimBaseUrl(config.baseUrl_api)}/fileServer/download?file=${encodeURIComponent(value)}&downFlag=${downFlag}`
  }
  return fillImgUrl(value)
}

function openDocumentAttachment(item, url, retried = false, options = {}) {
  if (!url) {
    uni.showToast({
      title: '文件下载失败',
      icon: 'none'
    })
    return
  }
  uni.showLoading({
    title: '打开中',
    mask: true
  })
  uni.downloadFile({
    url,
    header: {
      Authorization: uni.getStorageSync('token')
    },
    success: res => {
      if (res.statusCode && res.statusCode !== 200) {
        if ((res.statusCode === 301 || res.statusCode === 302) && !retried) {
          const redirectUrl = getRedirectUrl(res.header)
          uni.hideLoading()
          if (redirectUrl) {
            openDocumentAttachment(item, redirectUrl, true, options)
          } else {
            uni.showToast({
              title: '文件下载失败',
              icon: 'none'
            })
          }
          return
        }
        showAttachmentFailToast(url, '文件下载失败')
        return
      }
      uni.openDocument({
        filePath: res.tempFilePath,
        fileType: getDocumentFileType(item),
        showMenu: true,
        fail: () => {
          uni.showToast({
            title: '文件暂不支持预览',
            icon: 'none'
          })
        }
      })
    },
    fail: () => {
      showAttachmentFailToast(url, '文件下载失败')
    },
    complete: () => {
      uni.hideLoading()
    }
  })
}

function openAttachmentWebView(url, title = '附件预览') {
  if (!url) {
    uni.showToast({
      title: '文件下载失败',
      icon: 'none'
    })
    return
  }
  uni.navigateTo({
    url: `/pages/webview/webview?title=${encodeURIComponent(title)}&url=${encodeURIComponent(url)}`,
    fail: () => {
      uni.showToast({
        title: '附件预览失败',
        icon: 'none'
      })
    }
  })
}

function getAttachmentExt(file) {
  const name = `${file?.extname || file?.name || file?.rawUrl || file?.url || file || ''}`
  const fileParam = getQueryParam(name, 'file')
  const cleanName = safeDecodeURIComponent(fileParam || name).split('?')[0].split('#')[0]
  const fileName = cleanName.split('/').pop() || cleanName
  const ext = fileName.includes('.') ? fileName.split('.').pop() : fileName
  return ext.toLowerCase()
}

function checkAttachmentError(url) {
  if (!isFileDownloadUrl(url)) return Promise.resolve('')
  return new Promise(resolve => {
    uni.request({
      url,
      method: 'GET',
      header: {
        Authorization: uni.getStorageSync('token') || ''
      },
      success: res => {
        const data = parseAttachmentResponse(res.data)
        if (res.statusCode >= 400 || (data && data.code && data.code !== 200)) {
          resolve(getAttachmentErrorMsg(data))
          return
        }
        resolve('')
      },
      fail: () => resolve('')
    })
  })
}

async function showAttachmentFailToast(url, fallback) {
  const errorMsg = await checkAttachmentError(url)
  uni.showToast({
    title: errorMsg || fallback,
    icon: 'none'
  })
}

function parseAttachmentResponse(data) {
  if (!data) return null
  if (typeof data === 'object') return data
  if (typeof data === 'string') {
    try {
      return JSON.parse(data)
    } catch (e) {
      return null
    }
  }
  return null
}

function getAttachmentErrorMsg(data) {
  const msg = data?.msg || data?.message || ''
  if (!msg) return '附件预览失败'
  if (msg.includes('Hostname') || msg.includes('certificate')) {
    return '附件服务证书异常,请稍后再试'
  }
  return msg.length > 40 ? msg.slice(0, 40) : msg
}

function isAttachmentImage(file) {
  return ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp', 'svg'].includes(getAttachmentExt(file))
}

function getDocumentFileType(file) {
  const ext = getAttachmentExt(file)
  const types = ['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'pdf']
  return types.includes(ext) ? ext : undefined
}

function getRedirectUrl(header = {}) {
  const location = header.Location || header.location
  if (!location) return ''
  if (/^https?:\/\//.test(location)) return location
  return `${trimBaseUrl(config.baseUrl_api)}/${String(location).replace(/^\/+/, '')}`
}

function isFileDownloadUrl(url) {
  const value = String(url || '')
  return value.includes('/fileServer/download') || value.startsWith('fileServer/download')
}

function getQueryParam(url, key) {
  const match = String(url || '').match(new RegExp(`[?&]${key}=([^&#]+)`))
  return match ? safeDecodeURIComponent(match[1]) : ''
}

function isValidUrlValue(value) {
  if (value === undefined || value === null) return false
  const url = String(value).trim()
  return url !== '' && url !== 'null' && url !== 'undefined'
}

function trimBaseUrl(url) {
  return String(url || '').replace(/\/+$/, '')
}

function safeDecodeURIComponent(value) {
  try {
    return decodeURIComponent(value)
  } catch (e) {
    return value
  }
}