diff --git a/src/components/itemCenter.vue b/src/components/itemCenter.vue index de35e44..bf5a74a 100644 --- a/src/components/itemCenter.vue +++ b/src/components/itemCenter.vue @@ -10,6 +10,7 @@ alt="" width="100%" style="display: block" + :crossorigin="isOSSImage ? 'anonymous' : undefined" />
{ return isVisible.value }) +// 判断是否为OSS图片 +const isOSSImage = computed(() => { + return props.imgUrl.startsWith('https://tkm-likei.oss-ap-southeast-1.aliyuncs.com/h5') +}) + // 创建交叉观察器 const createObserver = () => { if (!props.lazy || props.immediate) return diff --git a/src/config/imagePaths.js b/src/config/imagePaths.js index c1fd6d0..61d39a6 100644 --- a/src/config/imagePaths.js +++ b/src/config/imagePaths.js @@ -1,6 +1,8 @@ // src/config/imagePaths.js -export const OSS_BASE_URL = 'https://tkm-likei.oss-ap-southeast-1.aliyuncs.com/h5/' // 阿里云oss -// export const OMAN_NATIONAL_DAY_PATH = 'Activities/Oman/NationalDay/'// 文件路径 +export const OSS_BASE_URL = + process.env.NODE_ENV === 'development' + ? '/oss/h5/' // 开发环境使用代理 + : 'https://tkm-likei.oss-ap-southeast-1.aliyuncs.com/h5/' // 生产环境直接访问 // 组合使用示例 export const getPngUrl = (imagePath, filename) => { diff --git a/src/directives/smartImage.js b/src/directives/smartImage.js index 38ba326..de736c1 100644 --- a/src/directives/smartImage.js +++ b/src/directives/smartImage.js @@ -4,21 +4,37 @@ import { imageCacheManager } from '@/utils/imageCacheManager' export const smartImage = { async mounted(el, binding) { if (binding.value) { - // 对于外部链接,直接使用普通加载方式 - if (!imageCacheManager.isBuildAsset(binding.value)) { - el.src = binding.value - el.style.opacity = '1' - return - } - // 设置加载状态样式 el.style.opacity = '0' el.style.transition = 'opacity 0.3s ease-in-out' try { - await imageCacheManager.loadImage(binding.value) - el.src = binding.value - el.style.opacity = '1' + // 对于OSS图片使用特殊处理 + if (binding.value.startsWith('https://tkm-likei.oss-ap-southeast-1.aliyuncs.com/h5')) { + const img = new Image() + img.crossOrigin = 'anonymous' + img.onload = () => { + el.src = binding.value + el.style.opacity = '1' + } + img.onerror = (error) => { + console.warn(`图片加载失败: ${binding.value}`, error) + el.src = binding.value + el.style.opacity = '1' + } + img.src = binding.value + } else { + // 对于外部链接,直接使用普通加载方式 + if (!imageCacheManager.isBuildAsset(binding.value)) { + el.src = binding.value + el.style.opacity = '1' + return + } + + await imageCacheManager.loadImage(binding.value) + el.src = binding.value + el.style.opacity = '1' + } } catch (error) { console.warn(`图片加载失败: ${binding.value}`, error) el.src = binding.value @@ -29,17 +45,34 @@ export const smartImage = { async updated(el, binding) { if (binding.value !== binding.oldValue && binding.value) { - // 对于外部链接,直接使用普通加载方式 - if (!imageCacheManager.isBuildAsset(binding.value)) { - el.src = binding.value - return - } - el.style.opacity = '0' + try { - await imageCacheManager.loadImage(binding.value) - el.src = binding.value - el.style.opacity = '1' + // 对于OSS图片使用特殊处理 + if (binding.value.startsWith('https://tkm-likei.oss-ap-southeast-1.aliyuncs.com/h5')) { + const img = new Image() + img.crossOrigin = 'anonymous' + img.onload = () => { + el.src = binding.value + el.style.opacity = '1' + } + img.onerror = (error) => { + console.warn(`图片更新失败: ${binding.value}`, error) + el.src = binding.value + el.style.opacity = '1' + } + img.src = binding.value + } else { + // 对于外部链接,直接使用普通加载方式 + if (!imageCacheManager.isBuildAsset(binding.value)) { + el.src = binding.value + return + } + + await imageCacheManager.loadImage(binding.value) + el.src = binding.value + el.style.opacity = '1' + } } catch (error) { console.warn(`图片更新失败: ${binding.value}`, error) el.src = binding.value diff --git a/src/utils/imageCacheManager.js b/src/utils/imageCacheManager.js index b027c56..089ba85 100644 --- a/src/utils/imageCacheManager.js +++ b/src/utils/imageCacheManager.js @@ -4,8 +4,8 @@ class ImageCacheManager { this.cacheVersionKey = 'likei-image-cache-version' this.currentAppVersion = import.meta.env.VITE_APP_VERSION || '1.0.0' this.cacheName = `likei-images-v${this.currentAppVersion}` - this.maxCacheItems = 50 // 限制最多缓存50张图片(可根据需要调整) - this.maxCacheSize = 50 * 1024 * 1024 // 限制总大小50MB(可根据需要调整) + this.maxCacheItems = 100 // 限制最多缓存50张图片(可根据需要调整) + this.maxCacheSize = 100 * 1024 * 1024 // 限制总大小50MB(可根据需要调整) this.init() } @@ -119,7 +119,10 @@ class ImageCacheManager { // 先检查并清理超出限制的缓存 // await this.enforceCacheLimits(cache) - const response = await fetch(url) + const response = await fetch(url, { + mode: 'cors', + credentials: 'omit', + }) if (response.ok) { await cache.put(url, response.clone()) console.log(`图片已缓存: ${url}`) @@ -180,15 +183,42 @@ class ImageCacheManager { async loadImageFromNetwork(src, resolve, reject) { try { - const response = await fetch(src) + // 对于OSS资源,先尝试直接创建Image对象(绕过fetch的CORS问题) + if (src.startsWith('https://tkm-likei.oss-ap-southeast-1.aliyuncs.com/h5')) { + const img = new Image() + img.crossOrigin = 'anonymous' + img.onload = () => { + resolve(img) + // 对于OSS资源,仍然尝试缓存(如果支持) + if (this.isBuildAsset(src)) { + this.cacheImageFromImage(src, img) + } + } + img.onerror = (error) => { + console.warn('图片加载失败:', src, error) + reject(error) + } + img.src = src + return + } + + // 对于其他资源,使用fetch + const response = await fetch(src, { + mode: 'cors', + credentials: 'omit', + }) + if (response.ok) { const img = new Image() img.onload = async () => { resolve(img) // 缓存带有 ETag 的响应 if (this.isBuildAsset(src)) { - const cache = await caches.open(this.cacheName) - await cache.put(src, response.clone()) + try { + await this.cacheImage(src) // 使用原始的缓存方法 + } catch (cacheError) { + console.warn('缓存图片时出错:', cacheError) + } } } img.onerror = reject @@ -197,9 +227,43 @@ class ImageCacheManager { reject(new Error(`HTTP ${response.status}`)) } } catch (error) { + console.warn('网络加载图片失败:', src, error) reject(error) } } + + // 为OSS图片创建缓存的特殊处理 + async cacheImageFromImage(src, img) { + try { + if (!('caches' in window) || !this.isBuildAsset(src)) return + + const cache = await caches.open(this.cacheName) + const cachedResponse = await cache.match(src) + + if (!cachedResponse) { + // 创建一个模拟的响应来缓存 + const canvas = document.createElement('canvas') + canvas.width = img.width + canvas.height = img.height + const ctx = canvas.getContext('2d') + ctx.drawImage(img, 0, 0) + + canvas.toBlob(async (blob) => { + if (blob) { + const response = new Response(blob, { + headers: { + 'Content-Type': 'image/png', + }, + }) + await cache.put(src, response.clone()) + console.log(`OSS图片已缓存: ${src}`) + } + }) + } + } catch (error) { + console.warn('缓存OSS图片失败:', src, error) + } + } } // 导出单例 diff --git a/src/views/Activities/Game/index.vue b/src/views/Activities/Game/index.vue index 998bb4d..b1bb1c8 100644 --- a/src/views/Activities/Game/index.vue +++ b/src/views/Activities/Game/index.vue @@ -1,7 +1,7 @@ - +