绿满眶商城微信小程序-uniapp
zxl
2025-07-17 b303b6945a139153688e86635346a621fe0c29b3
pages/video/video-play.vue
@@ -18,7 +18,7 @@
      @touchmove="handleSwiperMove"
      @touchend="handleSwiperEnd(item)"
       >
         <view style="width: 100%;height: 100%;" v-if="item.videoContentType === 'video'">
         <view :style="{width: '100%', height: windowHeight - marginBottom + 'px'}" v-if="item.videoContentType === 'video'">
              <!-- 播放按钮(仅当视频暂停时显示) -->
              <view 
               class="play-icon" 
@@ -35,7 +35,7 @@
               :autoplay="index === currentIndex"
               :controls="false"
               :loop="true"
               :object-fit="item.objectFit"
               :object-fit="item.videoFit"
               :enable-progress-gesture="false"
            :show-center-play-btn="false"
               class="video-item"
@@ -127,31 +127,35 @@
           </view>
          </view>
          
          <!-- 右侧互动按钮 -->
         <view class="action-buttons">
            <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">&#xe629;</text>
               </view>
            </view>
            <view class="action-item" @click="toggleCollect(item, index)">
            <text class="iconfont" v-if="item.collected">&#xe605;</text>
            <text class="iconfont" v-else>&#xe601;</text>
            <text style="font-size: 10px;font-weight: lighter;">{{item.collectNum}}</text>
            </view>
           <view class="action-item" @click="showComments(item)">
              <text class="iconfont">&#xe7f7;</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">&#xe602;</text>
                  </button>
           </view>
          </view>
        <!-- 右侧互动按钮 -->
        <view class="action-buttons">
         <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">&#xe629;</text>
            </view>
         </view>
           <view class="action-item" @click="toggleThumbsUp(item, index)">
                 <text class="iconfont" v-if="item.thumbsUp">&#xe605;</text>
                 <text class="iconfont" v-else>&#xe601;</text>
                 <text style="font-size: 10px;font-weight: lighter;">{{item.thumbsUpNum}}</text>
           </view>
          <view class="action-item" @click="showComments(item)">
             <text class="iconfont">&#xe7f7;</text>
             <text style="font-size: 10px;font-weight: lighter;">{{item.commentNum}}</text>
           </view>
           <view class="action-item" @click="toggleCollect(item, index)">
             <text class="iconfont" v-if="item.collected">&#xeb9d;</text>
             <text class="iconfont" v-else>&#xe603;</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">&#xe602;</text>
              </button>
           </view>
         </view>
         
        </swiper-item>
      </swiper>
@@ -239,7 +243,17 @@
</template>
<script>
import { getRecommendVideos, savePlayRecord, subscribe, getVideoComments, addVideoComment, thubmsUpComment, cancelThubmsUpComment } from "@/api/video.js";
import {
   getRecommendVideos,
   savePlayRecord,
   subscribe,
   getVideoComments,
   addVideoComment,
   thubmsUpComment,
   cancelThubmsUpComment,
   changeThumbsUp,
   getGoodsSimilarlyVideos
} from "@/api/video.js";
import { changeCollect } from "@/api/collect.js";
import { saveShare } from "@/api/share.js";
import storage from "@/utils/storage.js";
@@ -318,8 +332,22 @@
         pageNumber: 1,
         pageSize: 10,
         authorId: '',
         videoFrom: ''
      }
         videoFrom: '',
         keyword: ''
      },
      goodsSimilarlyQuery: { // 相似视频查询
         pageNumber: 1,
         pageSize: 10,
         videoFrom: 'goodsSimilarly',
         goodsIds: [],
         currentVideoId: ''
      },
      similarlyVideoList: [], // 相似视频
      similarlyNomore: false, // 是否还有更多相似视频
      similaryVideoIndex: 0, // 相似视频的播放位置
      similarlyLoading: false, // 相似视频加载
      marginBottom: 0, // 底部安全区域
      windowHeight: 0 // 可使用屏幕高度
    }
  },
  onShow() {
@@ -335,16 +363,19 @@
  },
  onUnload() {
     uni.removeStorageSync("playInfo");
     uni.removeStorageSync("searchPlayInfo");
  },
  onReady() {
     
  },
  onLoad(option) {
     const playInfo = uni.getStorageSync("playInfo", playInfo);
     this.marginBottom = uni.getSystemInfoSync().safeAreaInsets.bottom
     this.windowHeight = uni.getSystemInfoSync().windowHeight
     const playInfo = uni.getStorageSync("playInfo");
     const searchPlayInfo = uni.getStorageSync("searchPlayInfo");
     if(playInfo) {
        this.currentIndex = playInfo.playIndex;
        this.videoList = playInfo.videoList;
        console.log("拿到数据了",playInfo);
        this.videoQuery.pageNumber = playInfo.pageNumber;
        this.videoNoMore = playInfo.nomore;
        this.videoQuery.authorId = option.authorId;
@@ -353,6 +384,18 @@
        this.$nextTick(() => {
           const videoContext = uni.createVideoContext(`video${this.currentIndex}`, this);
           videoContext.play()
        })
     } else if (searchPlayInfo) { // 搜索页跳转过来的数据略有不同
        this.currentIndex = searchPlayInfo.playIndex;
        this.videoList = searchPlayInfo.videoList;
        this.videoQuery.pageNumber = searchPlayInfo.pageNumber;
        this.videoNoMore = searchPlayInfo.nomore;
        this.videoQuery.keyword = searchPlayInfo.keyword;
        this.videoQuery.videoFrom = option.videoFrom;
        this.currentVideoIsPlaying = true;
        this.$nextTick(() => {
                   const videoContext = uni.createVideoContext(`video${this.currentIndex}`, this);
                   videoContext.play()
        })
     } else {
        this.videoQuery.videoFrom = 'recommend';
@@ -380,6 +423,35 @@
     }
  },
  methods: {
     // 查询当前视频的关联视频(挂了同一商品的)
     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++;
                })
             }
     },
     // 点击商品跳转
     jumpToPay(videoId) {
           uni.navigateTo({
@@ -649,18 +721,25 @@
      this.loading = true;
      
     getRecommendVideos(this.videoQuery).then(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;
        }
@@ -694,6 +773,23 @@
       // 播放当前视频
       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()
@@ -711,7 +807,7 @@
       this.touchXY.endY = e.touches[0].pageY
   },
   // 结束触摸
   handleSwiperEnd(item) {
   async handleSwiperEnd(item) {
      // 防止滑动滚动条也触发跳转
      if (this.showProcess) {
         return
@@ -724,11 +820,37 @@
       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);
          }
         }
       }
       // 重置坐标
@@ -823,6 +945,28 @@
        }
     })
    },
   // 点赞/取消点赞
   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);
@@ -951,7 +1095,7 @@
   .video-info {
     width: 70%;
     position: absolute;
     bottom: 20px;
     bottom: 40px;
     left: 20px;
     color: #f8f8f8;
     z-index: 10;
@@ -1294,7 +1438,7 @@
     flex-direction: column;
     align-items: center;
     position: absolute;
     bottom: 0;
     bottom: 20px;
     width: 100%;
   }
   
@@ -1323,7 +1467,7 @@
   .progress-text {
     margin-top: 10px;
     font-size: 14px;
     color: #666;
     color: #fff;
   }
   .swiper-box {
     width: 100%;