From fc8d0707420a9726c957c37cd81073a1b9e3f158 Mon Sep 17 00:00:00 2001 From: Trae AI Date: Sat, 10 Jan 2026 14:46:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E8=A7=86=E9=A2=91?= =?UTF-8?q?=E5=B8=A7=E6=8F=90=E5=8F=96=E5=8A=9F=E8=83=BD=EF=BC=8C=E8=A7=A3?= =?UTF-8?q?=E5=86=B3=E8=A7=86=E9=A2=91-only=E5=95=86=E5=93=81=E5=88=86?= =?UTF-8?q?=E4=BA=AB=E5=8D=A1=E7=89=87=E4=B8=BA=E7=A9=BA=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/goods-detail/goods-detail.js | 220 +++++++++++++++++++++++++-- pages/goods-detail/goods-detail.wxml | 20 +++ 2 files changed, 229 insertions(+), 11 deletions(-) diff --git a/pages/goods-detail/goods-detail.js b/pages/goods-detail/goods-detail.js index c193bbe..e1dc617 100644 --- a/pages/goods-detail/goods-detail.js +++ b/pages/goods-detail/goods-detail.js @@ -429,10 +429,36 @@ Page({ sharePath += `®ion=${regionParam}`; } + // 确定分享图片 + let imageUrl = '/images/你有好蛋.png'; // 默认值 + + // 检查是否为纯视频商品 + const mediaItems = goodsDetail.mediaItems || []; + const hasVideo = mediaItems.some(item => item.type === 'video'); + const hasImage = mediaItems.some(item => item.type === 'image'); + + if (hasVideo && !hasImage) { + // 纯视频商品:使用提取的封面或默认图片 + if (this.data.videoCoverUrl) { + imageUrl = this.data.videoCoverUrl; + console.log('使用提取的视频封面分享:', imageUrl); + } else { + console.log('视频封面尚未提取完成,使用默认图片'); + // 尝试立即提取视频封面 + const videoItems = mediaItems.filter(item => item.type === 'video'); + if (videoItems.length > 0) { + this.extractVideoFirstFrame(videoItems[0].url); + } + } + } else { + // 有图片的商品:使用原有的图片选择逻辑 + imageUrl = getShareImageUrl(goodsDetail); + } + return { title: title, path: sharePath, - imageUrl: getShareImageUrl(goodsDetail) + imageUrl: imageUrl } }, @@ -466,10 +492,34 @@ Page({ const contactQuery = queryParams.join('&'); + // 确定分享图片 + let imageUrl = '/images/你有好蛋.png'; + + const mediaItems = goodsDetail.mediaItems || []; + const hasVideo = mediaItems.some(item => item.type === 'video'); + const hasImage = mediaItems.some(item => item.type === 'image'); + + if (hasVideo && !hasImage) { + // 纯视频商品:使用提取的封面或默认图片 + if (this.data.videoCoverUrl) { + imageUrl = this.data.videoCoverUrl; + console.log('使用提取的视频封面分享:', imageUrl); + } else { + console.log('视频封面尚未提取完成,使用默认图片'); + // 尝试立即提取视频封面 + const videoItems = mediaItems.filter(item => item.type === 'video'); + if (videoItems.length > 0) { + this.extractVideoFirstFrame(videoItems[0].url); + } + } + } else { + imageUrl = getShareImageUrl(goodsDetail); + } + return { title: title, query: contactQuery, - imageUrl: getShareImageUrl(goodsDetail) + imageUrl: imageUrl } }, @@ -500,6 +550,11 @@ Page({ favoriteGoods: [], // 收藏商品数据 loadingHome: false, // 首页数据加载状态 loadingFavorite: false, // 收藏数据加载状态 + // 新增以下字段: + videoCoverUrl: null, // 视频封面图片URL + isExtractingCover: false, // 是否正在提取封面 + videoCoverCache: {}, // 视频封面缓存 {videoUrl: coverUrl} + videoSrcForSnapshot: '', // 用于截图的视频URL }, onLoad: function (options) { @@ -649,6 +704,143 @@ Page({ }); }, + // ========== 新增:视频封面提取相关方法 ========== + + /** + * 检查并提取视频封面 + */ + async checkAndExtractVideoCover() { + const goodsDetail = this.data.goodsDetail; + const mediaItems = goodsDetail.mediaItems || []; + + // 1. 检查是否为纯视频商品 + const hasVideo = mediaItems.some(item => item.type === 'video'); + const hasImage = mediaItems.some(item => item.type === 'image'); + + if (!hasVideo || hasImage) { + // 不是纯视频商品,不需要提取 + return; + } + + // 2. 获取第一个视频 + const videoItems = mediaItems.filter(item => item.type === 'video'); + if (videoItems.length === 0) return; + + const firstVideo = videoItems[0]; + const videoUrl = firstVideo.url; + + // 3. 检查缓存 + const cachedCover = this.data.videoCoverCache[videoUrl]; + if (cachedCover) { + console.log('使用缓存的视频封面'); + this.setData({ + videoCoverUrl: cachedCover + }); + return; + } + + // 4. 开始提取 + await this.extractVideoFirstFrame(videoUrl); + }, + + /** + * 提取视频第一帧 + */ + async extractVideoFirstFrame(videoUrl) { + if (!videoUrl || this.data.isExtractingCover) { + return null; + } + + console.log('开始提取视频封面:', videoUrl); + this.setData({ isExtractingCover: true }); + + try { + // 方法1:使用snapshot API(推荐) + const coverUrl = await this.captureVideoFrame(videoUrl); + + if (coverUrl && coverUrl !== '/images/你有好蛋.png') { + // 更新缓存 + const newCache = { ...this.data.videoCoverCache }; + newCache[videoUrl] = coverUrl; + + this.setData({ + videoCoverUrl: coverUrl, + videoCoverCache: newCache, + isExtractingCover: false + }); + + console.log('视频封面提取成功:', coverUrl); + return coverUrl; + } + } catch (error) { + console.error('提取视频封面失败:', error); + } + + // 降级到默认图片 + this.setData({ + videoCoverUrl: '/images/你有好蛋.png', + isExtractingCover: false + }); + + return '/images/你有好蛋.png'; + }, + + /** + * 捕获视频帧(从真实视频中提取帧) + */ + captureVideoFrame(videoUrl) { + return new Promise((resolve, reject) => { + console.log('尝试从视频中提取真实帧:', videoUrl); + + try { + // 检查当前环境是否为预览环境 + const isPreview = __wxConfig.envVersion === 'develop' || __wxConfig.envVersion === 'trial'; + console.log('当前环境:', isPreview ? '预览环境' : '生产环境'); + + // 检查视频URL是否来自阿里云OSS + // 如果是,可以使用阿里云OSS的视频处理参数来获取视频帧 + if (videoUrl.includes('aliyuncs.com')) { + console.log('检测到阿里云OSS视频,使用URL参数获取视频帧'); + + // 构建带参数的URL,用于获取视频第一帧 + // 添加阿里云OSS视频处理参数:x-oss-process=video/snapshot,t_0,f_jpg + // t_0表示获取第0秒的帧,f_jpg表示输出为jpg格式 + const frameUrl = videoUrl + (videoUrl.includes('?') ? '&' : '?') + 'x-oss-process=video/snapshot,t_0,f_jpg'; + console.log('构建的视频帧URL:', frameUrl); + + // 使用wx.downloadFile下载视频帧 + wx.downloadFile({ + url: frameUrl, + success: (res) => { + console.log('视频帧下载响应:', res); + if (res.statusCode === 200) { + console.log('视频帧下载成功:', res.tempFilePath); + resolve(res.tempFilePath); + } else { + console.error('视频帧下载失败,状态码:', res.statusCode); + // 降级方案:使用默认图片 + resolve('/images/你有好蛋.png'); + } + }, + fail: (err) => { + console.error('视频帧下载失败:', err); + // 降级方案:使用默认图片 + resolve('/images/你有好蛋.png'); + } + }); + } else { + // 如果不是阿里云OSS视频,使用默认图片 + console.log('非阿里云OSS视频,使用默认图片'); + resolve('/images/你有好蛋.png'); + } + } catch (error) { + console.error('提取视频帧异常:', error); + // 降级方案:使用默认图片 + resolve('/images/你有好蛋.png'); + } + }); + }, + loadGoodsDetail: function (productId, preloadedData = null, contactFromShare = null) { // 首先显示预加载的数据,确保UI快速响应 if (preloadedData) { @@ -982,15 +1174,21 @@ Page({ } this.setData({ - goodsDetail: formattedGoods, - displayRegion: displayRegion, - isFavorite: preloadedFavoriteStatus // 优先使用预加载数据中的收藏状态 - }); - - // 只有当没有预加载的收藏状态时,才从服务器加载 - if (!preloadedData || preloadedData.isFavorite === undefined) { - this.loadGoodsFavoriteStatus(productIdStr); - } + goodsDetail: formattedGoods, + displayRegion: displayRegion, + isFavorite: preloadedFavoriteStatus, // 优先使用预加载数据中的收藏状态 + videoCoverUrl: null // 重置封面URL + }); + + // 商品加载完成后检查并提取视频封面 + setTimeout(() => { + this.checkAndExtractVideoCover(); + }, 500); + + // 只有当没有预加载的收藏状态时,才从服务器加载 + if (!preloadedData || preloadedData.isFavorite === undefined) { + this.loadGoodsFavoriteStatus(productIdStr); + } } else { wx.showToast({ title: '获取商品详情失败', diff --git a/pages/goods-detail/goods-detail.wxml b/pages/goods-detail/goods-detail.wxml index 81cf119..1883c4d 100644 --- a/pages/goods-detail/goods-detail.wxml +++ b/pages/goods-detail/goods-detail.wxml @@ -1,5 +1,25 @@ + + + + + + +