| | |
| | | @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" |
| | |
| | | :object-fit="item.videoFit" |
| | | :enable-progress-gesture="false" |
| | | :show-center-play-btn="false" |
| | | :show-progress="true" |
| | | :show-fullscreen-btn="true" |
| | | class="video-item" |
| | | @play="onPlay(item.id, index)" |
| | | @pause="onPause(index)" |
| | |
| | | :style="{bottom: marginBottom + 'px'}" |
| | | class="container"> |
| | | <!-- 进度条 - 整个区域可拖动 --> |
| | | <view class="process-warp" :style="{ opacity: showProcess ? 1 : 0 }"> |
| | | <!-- <view class="process-warp" :style="{ opacity: showProcess ? 1 : 0 }"> --> |
| | | <view class="process-warp"> |
| | | <!-- 显示当前进度 --> |
| | | <view class="progress-text">{{ hasPlayTime }}/{{formartDuration}}</view> |
| | | <view v-show="isTouch" class="progress-text">{{ hasPlayTime }}/{{formartDuration}}</view> |
| | | <view |
| | | class="progress-bar" |
| | | id="progressBar" |
| | |
| | | <view style="display: flex;"> |
| | | <image class="comment-avatar" :src="comment.userAvatar || '/static/default-avatar.png'"></image> |
| | | <view class="comment-content"> |
| | | <text class="nickname">{{comment.userNickname}}</text> |
| | | <text class="nickname">{{comment.userNickname}} <text v-if="userId===comment.userId">(我)</text> </text> |
| | | <text class="content">{{comment.commentContent}}</text> |
| | | <view style="position: relative;"> |
| | | <text class="time">{{formatTime(comment.createTime)}}</text> |
| | |
| | | <view class="reply-content"> |
| | | <view style="display: flex;"> |
| | | <image class="comment-reply-avatar" :src="reply.replyUserAvatar || '/static/default-avatar.png'"></image> |
| | | <text class="nickname">{{reply.userNickname}}</text> |
| | | <text v-if="reply.replyUserId && reply.masterCommentId !== reply.replyId" class="reply-to"><text style="margin-right: 10rpx;font-size: 28rpx;" class="iconfont"></text>{{reply.replyUserNickname}}</text> |
| | | <text class="nickname">{{reply.userNickname}}<text v-if="userId===comment.userId">(我)</text></text> |
| | | <text v-if="reply.replyUserId && reply.masterCommentId !== reply.replyId" class="reply-to"><text style="margin-right: 10rpx;font-size: 28rpx;" class="iconfont"></text>{{reply.replyUserNickname}}<text v-if="userId===comment.userId">(我)</text></text> |
| | | </view> |
| | | <text class="content">{{reply.commentContent}}</text> |
| | | <view class="reply-footer"> |
| | |
| | | }, |
| | | data() { |
| | | return { |
| | | isTouch:false, |
| | | userId :'', |
| | | currentImgIndex: 0, // 播放到第几张图--索引 |
| | | currentGoodsIndex: 0, // 播放到第几个商品--索引 |
| | | currentTime: 0, |
| | |
| | | barWidth: 0, // 进度条宽度 |
| | | isDragging: false, // 是否正在拖动 |
| | | processHidenTimer: null, // 进度条隐藏定时器 |
| | | showProcess: false, // 是否显示进度条 |
| | | showProcess: true, // 是否显示进度条 |
| | | videoNoMore: false, // 是否还有更多视频 |
| | | commentNoMore: false, // 是否还有更多评论 |
| | | commentQuery: { |
| | |
| | | } |
| | | }, |
| | | onShow() { |
| | | if(!this.userId){ |
| | | this.getUserId() |
| | | } |
| | | // const token = storage.getAccessToken(); |
| | | // if (! token) { |
| | | // this.wxSilentLogin(() => { |
| | |
| | | // this.loadVideos(); |
| | | // } |
| | | if (this.videoList.length < 1) { |
| | | this.loading = false; |
| | | this.videoNoMore = false; |
| | | console.log('触发数据加载') |
| | | this.loadVideos(); |
| | | } |
| | | // 如果视频按下暂停后切换页面再回到页面时,只算暂停时间(因为暂停时间和离开页面时间是重复的,只算一个) |
| | |
| | | this.startHidenTime = Date.now() |
| | | }, |
| | | onLoad(option) { |
| | | |
| | | console.log('-----------分享出的数据---------->',option) |
| | | //处理扫码出来的视频 |
| | | this.marginBottom = uni.getSystemInfoSync().safeAreaInsets.bottom |
| | | // 检查是否存在q参数 |
| | | 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; |
| | | queryParam.videoId = videoId |
| | | console.log('解析参数:', { shareType, videoId }); |
| | | } |
| | | const token = storage.getAccessToken(); |
| | | if (! token) { |
| | | this.wxSilentLogin(() => { |
| | | this.loadVideos(); |
| | | // 判断是不是点击分享链接进来的 |
| | | if (option.userId && option.videoId) { |
| | | queryParam.videoId = option.videoId |
| | | // 保存分享点击记录 |
| | | saveShareClickRecord({refId: option.videoId, shareUserId: option.userId}) |
| | | } |
| | | console.log('------------------------>',queryParam) |
| | | this.loadVideos(queryParam); |
| | | }) |
| | | } else { |
| | | this.loadVideos(); |
| | | if (option.userId && option.videoId) { |
| | | queryParam.videoId = option.videoId |
| | | // 保存分享点击记录 |
| | | saveShareClickRecord({refId: option.videoId, shareUserId: option.userId}) |
| | | } |
| | | console.log('------------------------2>',queryParam) |
| | | this.loadVideos(queryParam); |
| | | } |
| | | }, |
| | | onShareAppMessage(e) { |
| | |
| | | return { |
| | | title: videoInfo.title, |
| | | path: `/pages/tabbar/index/home?videoId=${videoInfo.id}&userId=${userInfo.id}`, |
| | | imageUrl: videoInfo.coverUrl |
| | | } |
| | | }, |
| | | methods: { |
| | | methods: { |
| | | getUserId(){ |
| | | const {id} = uni.getStorageSync('user_info_obj_dev') |
| | | this.userId = id; |
| | | }, |
| | | // 解析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();; |
| | |
| | | getVideoComments(this.commentQuery).then(res => { |
| | | this.commentsTotal = res.data.total; |
| | | this.comments = res.data.data; |
| | | console.log('------------------------>',this.comments) |
| | | this.commentQuery.pageNumber += 2; |
| | | this.commentQuery.pageSize /= 2; |
| | | }).catch(() => { |
| | |
| | | }, |
| | | |
| | | // 加载视频数据 |
| | | async loadVideos() { |
| | | async loadVideos(param) { |
| | | if (this.loading || this.videoNoMore) return; |
| | | this.loading = true; |
| | | |
| | | if(param){ |
| | | getRecommendVideos(param).then(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(res.data.data.length < this.videoQuery.pageSize) { |
| | | this.videoNoMore = true; |
| | | return; |
| | | } |
| | | this.videoQuery.pageNumber++; |
| | | |
| | | }) |
| | | }else{ |
| | | getRecommendVideos(this.videoQuery).then(res => { |
| | | // 新增一个字段用于循环时的key |
| | | const data = res.data.data.map(item => { |
| | |
| | | this.videoQuery.pageNumber++; |
| | | |
| | | }) |
| | | } |
| | | }, |
| | | |
| | | // 滑动切换视频 |
| | |
| | | handleTouchStart(e) { |
| | | this.isDragging = true; |
| | | this.showProcess = true; |
| | | this.isTouch = true; |
| | | this.startProgress = this.progress; // 记录开始时的进度 |
| | | this.startX = e.touches[0].pageX; |
| | | console.log("记录开始时的进度", this.startProgress); |
| | |
| | | videoContext.seek(this.duration * this.progress / 100) |
| | | videoContext.play() |
| | | this.processHidenTimer = setTimeout(() => { |
| | | this.showProcess = false; |
| | | // this.showProcess = true; |
| | | this.isTouch = false; |
| | | }, 1000); |
| | | }, |
| | | |
| | |
| | | .progress-bar { |
| | | position: relative; |
| | | width: 100%; |
| | | height: 16px; |
| | | background-color: #eee; |
| | | height: 5px; |
| | | background-color: rgba(255, 255, 255, 0.2); /* 半透明背景 */ |
| | | overflow: hidden; |
| | | border-radius: 1.5px; |
| | | cursor: pointer; |
| | | transition: height 0.2s; |
| | | } |
| | | |
| | | .progress-fill { |
| | | |
| | | position: absolute; |
| | | left: 0; |
| | | top: 0; |
| | | height: 100%; |
| | | border-radius: 2px; |
| | | background-color: lightgray; |
| | | transition: width 0.1s; |
| | | } |