| | |
| | | @click="togglePlay(index)" |
| | | v-show="!currentVideoIsPlaying" |
| | | > |
| | | <image src="/static/video/play.png" style="width: 45px;height: 45px" mode="aspectFit"></image> |
| | | <image src="/pages/subComponents/static/video/play.png" style="width: 45px;height: 45px" mode="aspectFit"></image> |
| | | </view> |
| | | <video |
| | | v-if="index >= currentIndex - videoLiveOffset && index <= currentIndex + videoLiveOffset" |
| | |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 右侧互动按钮 --> |
| | | <!-- 右侧互动按钮 --> |
| | | <view class="action-buttons" v-if="false"> |
| | | <view class="avatar-container"> |
| | | <image class="avatar" @click="jumpToHomePage(item.authorId)" :src="item.authorAvatar" mode="aspectFill"></image> |
| | | <!-- 关注图标 - 使用绝对定位 --> |
| | | <view v-if="!item.subscribeThisAuthor" class="follow-icon" @click="subscribeAuth(index, item.authorId)"> |
| | | <text class="iconfont"></text> |
| | | </view> |
| | | </view> |
| | | <view class="action-item" @click="toggleCollect(item, index)"> |
| | | <text class="iconfont" v-if="item.collected"></text> |
| | | <text class="iconfont" v-else></text> |
| | | <text style="font-size: 10px;font-weight: lighter;">{{item.collectNum}}</text> |
| | | <view class="avatar-container"> |
| | | <image class="avatar" @click="jumpToHomePage(item.authorId)" @touchend.stop :src="item.authorAvatar" mode="aspectFill"></image> |
| | | <!-- 关注图标 - 使用绝对定位 --> |
| | | <view v-if="!item.subscribeThisAuthor" class="follow-icon" @touchend.stop @click="subscribeAuth(index, item.authorId)"> |
| | | <text class="iconfont"></text> |
| | | </view> |
| | | </view> |
| | | <view class="action-item" @click="toggleThumbsUp(item, index)"> |
| | | <text class="iconfont" v-if="item.thumbsUp"></text> |
| | | <text class="iconfont" v-else></text> |
| | | <text style="font-size: 10px;font-weight: lighter;">{{item.thumbsUpNum}}</text> |
| | | </view> |
| | | <view class="action-item" @click="showComments(item)"> |
| | | <text class="iconfont"></text> |
| | | <text style="font-size: 10px;font-weight: lighter;">{{item.commentNum}}</text> |
| | | </view> |
| | | <view class="action-item"> |
| | | <button open-type="share" class="custom-share-btn" :data-obj="item"> |
| | | <text class="iconfont"></text> |
| | | </button> |
| | | |
| | | </view> |
| | | <view class="action-item" @click="toggleCollect(item, index)"> |
| | | <text class="iconfont" v-if="item.collected"></text> |
| | | <text class="iconfont" v-else></text> |
| | | <text style="font-size: 10px;font-weight: lighter;">{{item.collectNum}}</text> |
| | | </view> |
| | | <view class="action-item"> |
| | | <button open-type="share" class="custom-share-btn" :data-obj="item"> |
| | | <text class="iconfont"></text> |
| | | </button> |
| | | </view> |
| | | </view> |
| | | |
| | | </swiper-item> |
| | |
| | | |
| | | <script> |
| | | import TopBar from "@/components/TopBar.vue"; |
| | | import { getHealthRecommendVideos, savePlayRecord, subscribe, getVideoComments, addVideoComment, thubmsUpComment, cancelThubmsUpComment } from "@/api/video.js"; |
| | | import { |
| | | getHealthRecommendVideos, |
| | | savePlayRecord, |
| | | subscribe, |
| | | getVideoComments, |
| | | addVideoComment, |
| | | thubmsUpComment, |
| | | cancelThubmsUpComment, |
| | | changeThumbsUp, |
| | | getGoodsSimilarlyVideos |
| | | } from "@/api/video.js"; |
| | | import { changeCollect } from "@/api/collect.js"; |
| | | import { saveShare, saveShareClickRecord } from "@/api/share.js"; |
| | | import { silentLogin } from "@/api/connect.js"; |
| | | import { getUserInfo } from "@/api/members"; |
| | | import storage from "@/utils/storage.js"; |
| | | import { getSessionId, userAction } from "@/api/userAction.js"; |
| | | export default { |
| | | components: {TopBar}, |
| | | computed: { |
| | |
| | | }, |
| | | loading: false, // 是否正在加载 |
| | | videoQuery: { |
| | | source:'system', |
| | | pageNumber: 1, |
| | | pageSize: 10, |
| | | videoFrom: 'recommend' |
| | | }, |
| | | marginBottom: 0 // 底部安全区域 |
| | | goodsSimilarlyQuery: { // 相似视频查询 |
| | | pageNumber: 1, |
| | | pageSize: 10, |
| | | videoFrom: 'goodsSimilarly', |
| | | goodsIds: [], |
| | | currentVideoId: '' |
| | | }, |
| | | similarlyVideoList: [], // 相似视频 |
| | | similarlyNomore: false, // 是否还有更多相似视频 |
| | | similaryVideoIndex: 0, // 相似视频的播放位置 |
| | | similarlyLoading: false, // 相似视频加载 |
| | | marginBottom: 0 ,// 底部安全区域 |
| | | pageSessionNo:"", |
| | | actionParam:{ |
| | | sessionId:'', |
| | | actionType:"PAGE", |
| | | joinType:"SELF", |
| | | pageCode:"HEALTH_VIDEO", |
| | | pageParams:"{}", |
| | | pageStatus:"JOIN", |
| | | pageType:"DETAIL" |
| | | } |
| | | } |
| | | }, |
| | | onShow() { |
| | | getSessionId().then(res=>{ |
| | | this.pageSessionNo = res.data.data |
| | | if(this.pageSessionNo){ |
| | | let param = this.actionParam; |
| | | param.sessionId = this.pageSessionNo |
| | | userAction(param) |
| | | } |
| | | }) |
| | | // const token = storage.getAccessToken(); |
| | | // if (! token) { |
| | | // this.wxSilentLogin(() => { |
| | |
| | | this.totalHidenTime += duration |
| | | } |
| | | }, |
| | | onUnload() { |
| | | let param = this.actionParam; |
| | | if (this.sendOnShow)return |
| | | param.pageStatus = "LEAVE" |
| | | userAction(param) |
| | | }, |
| | | onHide() { |
| | | this.startHidenTime = Date.now() |
| | | this.startHidenTime = Date.now() |
| | | let param = this.actionParam; |
| | | this.sendOnShow = true; |
| | | param.pageStatus = "LEAVE" |
| | | userAction(param) |
| | | }, |
| | | onLoad(option) { |
| | | this.marginBottom = uni.getSystemInfoSync().safeAreaInsets.bottom |
| | | let queryParam = this.videoQuery; |
| | | if (option.q) { |
| | | // 双重解码:微信对URL进行了两次编码 |
| | | const decodedUrl = decodeURIComponent(decodeURIComponent(option.q)); |
| | | console.log('原始URL:', decodedUrl); |
| | | |
| | | // 解析URL中的查询参数 |
| | | const params = this.parseUrlParams(decodedUrl); |
| | | const shareType = params.shareType; |
| | | const videoId = params.videoId; |
| | | const source = params.source |
| | | |
| | | queryParam.videoId = videoId |
| | | queryParam.shareType = shareType |
| | | queryParam.source = source |
| | | console.log('解析参数:', { shareType, videoId,source }); |
| | | this.actionParam.pageParams = JSON.stringify(params) |
| | | this.actionParam.joinType = 'SHARE' |
| | | } |
| | | const token = storage.getAccessToken(); |
| | | if (! token) { |
| | | this.wxSilentLogin(() => { |
| | | this.loadVideos(); |
| | | // 判断是不是点击分享链接进来的 |
| | | if (option.userId && option.videoId) { |
| | | this.actionParam.pageParams = JSON.stringify(option) |
| | | this.actionParam.joinType = 'SCAN' |
| | | queryParam.videoId = option.videoId |
| | | // 保存分享点击记录 |
| | | saveShareClickRecord({refId: option.videoId, shareUserId: option.userId}) |
| | | } |
| | | this.loadVideos(queryParam); |
| | | }) |
| | | } else { |
| | | this.loadVideos(); |
| | | if (option.userId && option.videoId) { |
| | | queryParam.videoId = option.videoId |
| | | // 保存分享点击记录 |
| | | saveShareClickRecord({refId: option.videoId, shareUserId: option.userId}) |
| | | } |
| | | this.loadVideos(queryParam); |
| | | } |
| | | }, |
| | | onShareAppMessage(e) { |
| | |
| | | } |
| | | }, |
| | | methods: { |
| | | // 解析URL参数 |
| | | parseUrlParams(url) { |
| | | const params = {}; |
| | | // 处理可能存在的hash(如果有的话) |
| | | const cleanUrl = url.split('#')[0]; |
| | | const queryStr = cleanUrl.split('?')[1] || ''; |
| | | |
| | | queryStr.split('&').forEach(pair => { |
| | | const [key, value] = pair.split('='); |
| | | if (key) { |
| | | // 如果值存在,则解码,否则设为空字符串 |
| | | params[key] = value ? decodeURIComponent(value) : ''; |
| | | } |
| | | }); |
| | | |
| | | return params; |
| | | }, |
| | | // 查询当前视频的关联视频(挂了同一商品的) |
| | | async getGoodsSimilarly() { |
| | | if (this.similarlyLoading || this.similarlyNomore) return Promise.resolve();; |
| | | const video = this.videoList[this.currentIndex]; |
| | | if (video.goodsList && video.goodsList.length > 0) { |
| | | this.goodsSimilarlyQuery.goodsIds = video.goodsList.map(goods => goods.goodsId); |
| | | this.goodsSimilarlyQuery.currentVideoId = video.id; |
| | | if (this.similarlyVideoList.length < 1) { |
| | | this.similarlyVideoList.push(video); // 确保原视频是横向视频的第一个元素 |
| | | } |
| | | this.similarlyLoading = true; |
| | | return getGoodsSimilarlyVideos(this.goodsSimilarlyQuery).then(res => { |
| | | |
| | | this.similarlyVideoList = [ |
| | | ...this.similarlyVideoList, |
| | | ...res.data.data.filter( |
| | | (newItem) => !this.similarlyVideoList.some((oldItem) => oldItem.id === newItem.id) |
| | | ), |
| | | ]; |
| | | |
| | | this.similarlyLoading = false; |
| | | if(res.data.data.length < this.goodsSimilarlyQuery.pageSize) { |
| | | this.similarlyNomore = true; |
| | | return; |
| | | } |
| | | this.goodsSimilarlyQuery.pageNumber++; |
| | | }) |
| | | } |
| | | }, |
| | | topBarChange(titleObj) { |
| | | if (titleObj.index === 'home') { |
| | | uni.switchTab({ |
| | |
| | | }, |
| | | |
| | | // 加载视频数据 |
| | | async loadVideos() { |
| | | async loadVideos(param) { |
| | | if (this.loading || this.videoNoMore) return; |
| | | this.loading = true; |
| | | |
| | | if(param){ |
| | | console.log("二维码扫码数据执行在此处1") |
| | | console.log(this.videoQuery) |
| | | getHealthRecommendVideos(this.videoQuery).then(res => { |
| | | console.log(res) |
| | | // 新增一个字段用于循环时的key |
| | | const data = res.data.data.map(item => { |
| | | return { |
| | | ...item, |
| | | updateKey: item.id |
| | | } |
| | | }) |
| | | if (this.videoQuery.pageNumber === 1) { |
| | | this.videoList = data; |
| | | } else { |
| | | this.videoList = [ |
| | | ...this.videoList, |
| | | ...data.filter( |
| | | (newItem) => !this.videoList.some((oldItem) => oldItem.id === newItem.id) |
| | | ), |
| | | ]; |
| | | } |
| | | this.loading = false; |
| | | if(data.length < this.videoQuery.pageSize) { |
| | | this.videoNoMore = true; |
| | | return; |
| | | } |
| | | this.videoQuery.pageNumber++; |
| | | |
| | | }) |
| | | }else{ |
| | | console.log("二维码扫码数据执行在此处2") |
| | | console.log(this.videoQuery) |
| | | getHealthRecommendVideos(this.videoQuery).then(res => { |
| | | console.log(res, "视频数据"); |
| | | console.log(res) |
| | | // 新增一个字段用于循环时的key |
| | | const data = res.data.data.map(item => { |
| | | return { |
| | | ...item, |
| | | updateKey: item.id |
| | | } |
| | | }) |
| | | if (this.videoQuery.pageNumber === 1) { |
| | | this.videoList = res.data.data; |
| | | this.videoList = data; |
| | | } else { |
| | | this.videoList = [ |
| | | ...this.videoList, |
| | | ...res.data.data.filter( |
| | | ...data.filter( |
| | | (newItem) => !this.videoList.some((oldItem) => oldItem.id === newItem.id) |
| | | ), |
| | | ]; |
| | | } |
| | | this.loading = false; |
| | | if(res.data.data.length < this.videoQuery.pageSize) { |
| | | if(data.length < this.videoQuery.pageSize) { |
| | | this.videoNoMore = true; |
| | | return; |
| | | } |
| | | this.videoQuery.pageNumber++; |
| | | |
| | | }) |
| | | })} |
| | | }, |
| | | |
| | | // 滑动切换视频 |
| | |
| | | // 播放当前视频 |
| | | const videoContext1 = uni.createVideoContext(`video${this.currentIndex}`, this); |
| | | videoContext1.play() |
| | | |
| | | // 下滑时,需要将上一个视频重置为原始视频(如果横向滑动了相关视频) |
| | | if (this.similaryVideoIndex !== 0) { |
| | | this.videoList[oldIndex] = this.similarlyVideoList[0] |
| | | } |
| | | this.similarlyVideoList = []; |
| | | this.similaryVideoIndex = 0; |
| | | this.similarlyNomore = false; |
| | | this.similarlyLoading = false; |
| | | this.goodsSimilarlyQuery = { |
| | | pageNumber: 1, |
| | | pageSize: 6, |
| | | videoFrom: 'goodsSimilarly', |
| | | goodsIds: [], |
| | | currentVideoId: '' |
| | | } |
| | | |
| | | // 如果剩余视频不足,触发请求获取更多视频 |
| | | if (this.videoList.length - 1 < this.currentIndex + this.videoLiveOffset) { |
| | | this.loadVideos() |
| | |
| | | this.touchXY.endY = e.touches[0].pageY |
| | | }, |
| | | // 结束触摸 |
| | | handleSwiperEnd(item) { |
| | | async handleSwiperEnd(item) { |
| | | // 防止滑动滚动条也触发跳转 |
| | | if (this.showProcess) { |
| | | return |
| | |
| | | if (Math.abs(diffX) > Math.abs(diffY)) { |
| | | if (diffX > 0) { |
| | | console.log('右滑') |
| | | if (item.goodsList && item.goodsList.length > 0) { |
| | | this.jumpToPay(item.id) |
| | | } |
| | | if (this.similaryVideoIndex !== 0) { |
| | | // 如果滑动了横向视频,那么右滑就做视频切换而不是跳转商品页 |
| | | // 切换下一个视频 |
| | | const oldIndex = this.similaryVideoIndex; |
| | | this.similaryVideoIndex = Math.max(this.similaryVideoIndex - 1, 0); |
| | | if (this.similaryVideoIndex < oldIndex) { |
| | | // 把竖向视频的当前播放位置替换为横向视频的当前索引元素 |
| | | const video = this.similarlyVideoList[this.similaryVideoIndex]; |
| | | video["updateKey"] = video.id + this.similaryVideoIndex |
| | | this.videoList.splice(this.currentIndex, 1, video); |
| | | // this.videoList[this.currentIndex] = video |
| | | } |
| | | } |
| | | else if (item.goodsList && item.goodsList.length > 0) { |
| | | this.jumpToPay(item.id) |
| | | } |
| | | } else { |
| | | console.log('左滑') |
| | | if (this.similarlyVideoList.length < 1 || this.similarlyVideoList.length - this.similaryVideoIndex - 1 <= 3) { |
| | | // 相关视频为空或者剩余视频不足,触发加载相关视频 |
| | | await this.getGoodsSimilarly() |
| | | } |
| | | // 切换下一个视频 |
| | | const oldIndex = this.similaryVideoIndex; |
| | | this.similaryVideoIndex = Math.min(this.similaryVideoIndex + 1, this.similarlyVideoList.length - 1); |
| | | if (this.similaryVideoIndex > oldIndex) { |
| | | // 把竖向视频的当前播放位置替换为横向视频的当前索引元素 |
| | | const video = this.similarlyVideoList[this.similaryVideoIndex]; |
| | | video["updateKey"] = video.id + this.similaryVideoIndex |
| | | this.videoList.splice(this.currentIndex, 1, video); |
| | | } |
| | | } |
| | | } |
| | | // 重置坐标 |
| | |
| | | } |
| | | }) |
| | | }, |
| | | // 点赞/取消点赞 |
| | | toggleThumbsUp(item, index) { |
| | | let data = { |
| | | refId: item.id, |
| | | thumbsUpType: 'video' |
| | | } |
| | | const beforeThumbsUp = item.thumbsUp |
| | | const beforeThumbsUpNum = item.thumbsUpNum |
| | | if(item.thumbsUp) { |
| | | this.videoList[index].thumbsUp = false |
| | | this.videoList[index].thumbsUpNum -= 1 |
| | | } else { |
| | | this.videoList[index].thumbsUp = true |
| | | this.videoList[index].thumbsUpNum += 1 |
| | | } |
| | | changeThumbsUp(data).then(res => { |
| | | if(res.data.code !== 200) { |
| | | this.videoList[index].thumbsUp = beforeThumbsUp |
| | | this.videoList[index].thumbsUpNum = beforeThumbsUpNum |
| | | } |
| | | }) |
| | | }, |
| | | // 单击屏幕:暂停或继续播放 |
| | | togglePlay(index) { |
| | | console.log("单击视频", index); |