assetUrl.js 3.32 KB
import { ref } from 'vue'
import Taro from '@tarojs/taro'

const IMAGE_CDN_PREFIX = 'https://cdn.ipadbiz.cn/jls_weapp/images/'
const ASSET_VERSION_URL = 'https://cdn.ipadbiz.cn/jls_weapp/version.json'
const ASSET_VERSION_STORAGE_KEY = 'jls_weapp_image_asset_version'
const ASSET_VERSION_FIELD = 'image_version'

const normalizeValue = (value) => String(value || '').trim()

const getStoredAssetVersion = () => {
  try {
    return normalizeValue(Taro.getStorageSync(ASSET_VERSION_STORAGE_KEY))
  } catch (error) {
    console.error('读取图片版本缓存失败:', error)
    return ''
  }
}

export const imageAssetVersion = ref(getStoredAssetVersion())

let assetVersionRequestPromise = null

const saveAssetVersion = (version) => {
  const normalizedVersion = normalizeValue(version)
  imageAssetVersion.value = normalizedVersion

  try {
    if (normalizedVersion) {
      Taro.setStorageSync(ASSET_VERSION_STORAGE_KEY, normalizedVersion)
      return
    }

    Taro.removeStorageSync(ASSET_VERSION_STORAGE_KEY)
  } catch (error) {
    console.error('缓存图片版本失败:', error)
  }
}

const parseAssetVersionResponse = (data) => {
  if (typeof data === 'string') {
    try {
      const parsedData = JSON.parse(data)
      return normalizeValue(parsedData?.[ASSET_VERSION_FIELD])
    } catch (error) {
      return ''
    }
  }

  return normalizeValue(data?.[ASSET_VERSION_FIELD])
}

const appendOrReplaceQueryParam = (url, key, value) => {
  if (!value) {
    return url
  }

  const hashIndex = url.indexOf('#')
  const hash = hashIndex >= 0 ? url.slice(hashIndex) : ''
  const baseUrl = hashIndex >= 0 ? url.slice(0, hashIndex) : url
  const queryPattern = new RegExp(`([?&])${key}=[^&#]*`)

  if (queryPattern.test(baseUrl)) {
    return `${baseUrl.replace(queryPattern, `$1${key}=${encodeURIComponent(value)}`)}${hash}`
  }

  const joiner = baseUrl.includes('?') ? '&' : '?'
  return `${baseUrl}${joiner}${key}=${encodeURIComponent(value)}${hash}`
}

export const buildImageCdnUrl = (fileName = '') => `${IMAGE_CDN_PREFIX}${normalizeValue(fileName)}`

export const shouldUseVersionedImageAsset = (url) => normalizeValue(url).startsWith(IMAGE_CDN_PREFIX)

export const getVersionedImageAssetUrl = (url) => {
  const normalizedUrl = normalizeValue(url)
  if (!shouldUseVersionedImageAsset(normalizedUrl)) {
    return normalizedUrl
  }

  const version = normalizeValue(imageAssetVersion.value)
  if (!version) {
    return normalizedUrl
  }

  return appendOrReplaceQueryParam(normalizedUrl, 'v', version)
}

export const getVersionedImageAssetByName = (fileName = '') => (
  getVersionedImageAssetUrl(buildImageCdnUrl(fileName))
)

export const preloadImageAssetVersion = async (force = false) => {
  if (!force && assetVersionRequestPromise) {
    return assetVersionRequestPromise
  }

  assetVersionRequestPromise = Taro.request({
    url: appendOrReplaceQueryParam(ASSET_VERSION_URL, '_t', String(Date.now())),
    method: 'GET',
    enableCache: false,
  })
    .then((response) => {
      const version = parseAssetVersionResponse(response?.data)
      if (version) {
        saveAssetVersion(version)
      }

      return version
    })
    .catch((error) => {
      console.error('加载图片版本配置失败:', error)
      return imageAssetVersion.value
    })
    .finally(() => {
      assetVersionRequestPromise = null
    })

  return assetVersionRequestPromise
}