|
|
@@ -0,0 +1,99 @@
|
|
|
+// 统一给 OSS/MinIO/静态域资源追加版本参数(用于绕过长缓存)。
|
|
|
+// 约束:不要用 Date.now() 常态化破缓存;默认用“可控版本号”,需要强刷时只改版本号即可。
|
|
|
+
|
|
|
+let _cachedVersion = null
|
|
|
+
|
|
|
+// 作为兜底版本号来源(构建期静态注入)
|
|
|
+// eslint-disable-next-line import/no-unresolved
|
|
|
+import manifest from '@/manifest.json'
|
|
|
+
|
|
|
+function pickEnv(name) {
|
|
|
+ try {
|
|
|
+ if (typeof import.meta !== 'undefined' && import.meta.env && import.meta.env[name]) {
|
|
|
+ return String(import.meta.env[name]).trim()
|
|
|
+ }
|
|
|
+ } catch {
|
|
|
+ // ignore
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ if (typeof process !== 'undefined' && process.env && process.env[name]) {
|
|
|
+ return String(process.env[name]).trim()
|
|
|
+ }
|
|
|
+ } catch {
|
|
|
+ // ignore
|
|
|
+ }
|
|
|
+ return ''
|
|
|
+}
|
|
|
+
|
|
|
+function fallbackVersionFromManifest() {
|
|
|
+ try {
|
|
|
+ const vn = String(manifest?.versionName || '').trim()
|
|
|
+ const vc = String(manifest?.versionCode || '').trim()
|
|
|
+ return [vn, vc].filter(Boolean).join('.')
|
|
|
+ } catch {
|
|
|
+ // ignore
|
|
|
+ }
|
|
|
+ return ''
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 统一版本号:
|
|
|
+ * - 优先:`VITE_STATIC_ASSETS_VERSION` / `VUE_APP_STATIC_ASSETS_VERSION` / `UNI_APP_STATIC_ASSETS_VERSION`
|
|
|
+ * - 兜底:manifest.versionName/versionCode
|
|
|
+ * - 最终兜底:固定日期(需要强刷时可直接改这个值或用环境变量覆盖)
|
|
|
+ */
|
|
|
+export function getStaticAssetsVersion() {
|
|
|
+ if (_cachedVersion != null) return _cachedVersion
|
|
|
+ const v =
|
|
|
+ pickEnv('VITE_STATIC_ASSETS_VERSION') ||
|
|
|
+ pickEnv('VUE_APP_STATIC_ASSETS_VERSION') ||
|
|
|
+ pickEnv('UNI_APP_STATIC_ASSETS_VERSION') ||
|
|
|
+ fallbackVersionFromManifest() ||
|
|
|
+ '20260423'
|
|
|
+ _cachedVersion = String(v || '').trim()
|
|
|
+ return _cachedVersion
|
|
|
+}
|
|
|
+
|
|
|
+function hasSignedQuery(u) {
|
|
|
+ // 预签名/鉴权 URL:追加参数可能导致签名失效,必须跳过
|
|
|
+ return /(?:[?&](?:X-Amz-|x-amz-|OSSAccessKeyId|Signature|x-oss-|Expires)=)/.test(u)
|
|
|
+}
|
|
|
+
|
|
|
+function hasVersionParam(u) {
|
|
|
+ return /(?:[?&]v=)/i.test(u)
|
|
|
+}
|
|
|
+
|
|
|
+function looksLikeOurObjectStorage(u) {
|
|
|
+ // 只对我们自己的 OSS/MinIO/静态域处理,避免误伤第三方资源
|
|
|
+ return (
|
|
|
+ u.includes('/sqxp-static/') ||
|
|
|
+ u.includes('/sanqiang/') ||
|
|
|
+ u.includes('/minio/') ||
|
|
|
+ /:\/\/(?:www\.)?chengyantek\.cn\//i.test(u) ||
|
|
|
+ /:\/\/\d{1,3}(?:\.\d{1,3}){3}:20004\//.test(u)
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+function appendQueryParam(url, key, value) {
|
|
|
+ const sep = url.includes('?') ? '&' : '?'
|
|
|
+ return `${url}${sep}${encodeURIComponent(key)}=${encodeURIComponent(value)}`
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 给 OSS/MinIO/静态域 URL 追加 `v=<version>`,用于“内容更新但 URL 不变”时强制刷新。
|
|
|
+ *
|
|
|
+ * - 已带 `v=`:不重复追加
|
|
|
+ * - 预签名 URL:不追加(避免签名失效)
|
|
|
+ * - 非 http(s) / // / 非本站存储域:不处理
|
|
|
+ */
|
|
|
+export function withOssVersion(rawUrl, version = getStaticAssetsVersion()) {
|
|
|
+ const u = String(rawUrl || '').trim()
|
|
|
+ if (!u) return ''
|
|
|
+ if (!(u.startsWith('http://') || u.startsWith('https://') || u.startsWith('//'))) return u
|
|
|
+ if (!version) return u
|
|
|
+ if (!looksLikeOurObjectStorage(u)) return u
|
|
|
+ if (hasVersionParam(u)) return u
|
|
|
+ if (hasSignedQuery(u)) return u
|
|
|
+ return appendQueryParam(u, 'v', version)
|
|
|
+}
|
|
|
+
|