绿满眶商城微信小程序-uniapp
peng
2025-06-25 28167c45044ddb9ceff22b44e48a7ab496b8839a
pages/tabbar/index/home.vue
@@ -1,11 +1,14 @@
<template>
  <view class="video-container">
   <!-- 视频加载 -->
   <zero-loading v-show="videoLoading" type="circle" color="#0ebd57" text=""></zero-loading>
    <!-- 视频列表 -->
    <swiper
      class="video-swiper"
      vertical
      :current="currentIndex"
      @change="onSwiperChange"
     :duration="250"
     easing-function="linear"
    >
      <swiper-item
@@ -25,14 +28,16 @@
            <image src="/static/video/play.png" style="width: 45px;height: 45px" mode="aspectFit"></image>
           </view>
           <video
            v-if="index >= currentIndex - videoLiveOffset && index <= currentIndex + videoLiveOffset"
            :id="'video'+index"
            :ref="'video'+index"
            :src="item.videoUrl"
            :autoplay="false"
            :autoplay="index === currentIndex"
            :controls="false"
            :loop="true"
            :object-fit="item.objectFit"
            :enable-progress-gesture="false"
            :show-center-play-btn="false"
            class="video-item"
            @play="onPlay(item.id, index)"
            @pause="onPause(index)"
@@ -40,12 +45,13 @@
            @click="togglePlay(index)"
            @timeupdate="onTimeUpdate($event)"
            @loadedmetadata="onLoadedMetadata($event)"
            @waiting="videoWaiting(index)"
           ></video>
           <!-- 自定义控制条 -->
           <view
            @touchstart="handleTouchStart"
            @touchmove="handleTouchMove"
            @touchend="handleTouchEnd"
            @touchstart.stop="handleTouchStart"
            @touchmove.stop="handleTouchMove"
            @touchend.stop="handleTouchEnd"
            class="container">
            <!-- 进度条 - 整个区域可拖动 -->
            <view class="process-warp" :style="{ opacity: showProcess ? 1 : 0 }">
@@ -300,13 +306,11 @@
         startPlayTime: 0 // 这个视频从什么时候开始播放的
      },
      currentVideoIsPlaying: true, // 当前视频是否正在播放
      isFullScreen: false,
      windowHeight: 0,
      currentIndex: 0, // 当前播放的视频索引
      videoLoading: false, // 视频缓冲中
      videoList: [],   // 视频列表数据
      videoContexts: [], // 视频上下文对象集合
      videoBufferOffset: 0.1 ,// 视频预加载参数
      videoLiveOffset: 5, // 保留当前视频前后各多少个视频上下文
      videoLiveOffset: 2, // 保留当前视频前后各多少个视频上下文
      touchXY: {  // 监听左滑右滑
         startX: 0,
         endX: 0,
@@ -662,56 +666,6 @@
         }
      })
     },
    // 初始化视频上下文
    initVideoContexts() {
     const start = Math.max(0, this.currentIndex - this.videoLiveOffset);
     const end = Math.min(this.currentIndex + this.videoLiveOffset, this.videoList.length - 1);
     let contextsLength = this.videoContexts.length;
     if (contextsLength === 0) {
        // 第一次初始化
        for (let i = 0; i < this.videoList.length; i++) {
         if (i < start || i > end) {
            this.videoContexts.push(null)
         } else {
            let videoContent = uni.createVideoContext(`video${i}`, this);
            videoContent.seek(this.videoBufferOffset);
            videoContent.pause();
            this.videoContexts.push(videoContent);
         }
        }
     } else {
       for (let i = 0; i < this.videoList.length; i++) {
          contextsLength = this.videoContexts.length
         if (contextsLength - 1 >= i) {
            // 如果已经是null了就不用管,因为视频加载只会在后面push,前面已经设置为null则无需处理
            if (this.videoContexts[i] == null) {
               continue
            }
            // 超出可视化范围的视频直接释放资源,并置为null
            if (i < start || i > end) {
               if (this.videoContexts[i]) {
                  this.videoContexts[i].stop();
                  this.videoContexts[i] = null
               }
            }
         } else {
            if (i < start || i > end) {
               this.videoContexts.push(null);
            } else {
               let videoContent = uni.createVideoContext(`video${i}`, this);
               videoContent.seek(this.videoBufferOffset);
               videoContent.pause();
               this.videoContexts.push(videoContent);
            }
         }
       }
     }
     // 将当前视频设置为播放
     if (this.videoContexts[this.currentIndex]) {
        this.videoContexts[this.currentIndex].play()
     }
    },
    // 加载视频数据
    async loadVideos() {
@@ -730,9 +684,6 @@
           ),
         ];
        }
        this.$nextTick(() => {
          this.initVideoContexts();
        });
        this.loading = false;
        if(res.data.data.length < this.videoQuery.pageSize) {
           this.videoNoMore = true;
@@ -745,6 +696,7 @@
    // 滑动切换视频
    onSwiperChange(e) {
      this.videoLoading = false
      // 如果视频处于暂停状态往下刷视频,那么需要再计算一次暂停时间
      if(!this.currentVideoIsPlaying) {
         if(this.startPauseTime !== 0) {
@@ -756,49 +708,23 @@
      this.savePlayRecord()
      const oldIndex = this.currentIndex;
      this.currentIndex = e.detail.current;
      const videoContext = uni.createVideoContext(`video${oldIndex}`, this);
      // 暂停上一个视频
      if (this.videoContexts[oldIndex]) {
         this.videoContexts[oldIndex].pause();
      }
      videoContext.pause();
      this.startPauseTime = 0;
      // 设置当前播放视频的总时长
      this.duration = this.videoList[this.currentIndex].videoDuration;
      this.formartDuration = this.sliderFormatTime(this.duration);
      // 播放当前视频
      if (this.videoContexts[this.currentIndex]) {
         this.videoContexts[this.currentIndex].play();
      }
      this.clearVideoContext()
    },
   // 清除超出视频可视化区域的视频上下文
    async clearVideoContext() {
      // 对超出可视化区域的视频上下文做销毁处理
      const start = Math.max(0, this.currentIndex - this.videoLiveOffset);
      const end = Math.min(this.currentIndex + this.videoLiveOffset, this.videoList.length - 1);
      for (let i = 0; i < this.videoContexts.length; i++) {
         if (i < start || i > end) {
            if (this.videoContexts[i]) {
               this.videoContexts[i].stop();
               this.videoContexts[i] = null
            }
         } else {
            if (this.videoContexts[i] == null) {
               let videoContent = uni.createVideoContext(`video${i}`, this);
               videoContent.seek(this.videoBufferOffset);
               videoContent.pause();
               this.videoContexts[i] = videoContent;
            }
         }
      }
      // 播放当前视频
      const videoContext1 = uni.createVideoContext(`video${this.currentIndex}`, this);
      videoContext1.play()
      // 如果剩余视频不足,触发请求获取更多视频
      if (this.videoList.length - 1 < this.currentIndex + this.videoLiveOffset) {
         this.loadVideos()
      }
   },
    },
   // 开始触摸
   handleSwiperStart(e) {
@@ -808,12 +734,15 @@
   },
   // 触摸中
   handleSwiperMove(e) {
      console.log("触摸中", e);
       this.touchXY.endX = e.touches[0].pageX
       this.touchXY.endY = e.touches[0].pageY
   },
   // 结束触摸
   handleSwiperEnd(item) {
      // 防止滑动滚动条也触发跳转
      if (this.showProcess) {
         return
      }
       const diffX = this.touchXY.endX - this.touchXY.startX
       const diffY = this.touchXY.endY - this.touchXY.startY
@@ -861,18 +790,16 @@
    },
    // 单击屏幕:暂停或继续播放
   togglePlay(index) {
      console.log("单击视频", index, this.videoContexts);
      console.log("单击视频", index);
      const videoContext = uni.createVideoContext(`video${index}`, this);
      if(this.currentVideoIsPlaying) {
         this.videoContexts[index].pause();
         videoContext.pause();
      } else {
         this.videoContexts[index].play();
         videoContext.play();
      }
   },
    // 视频播放事件
    onPlay(id, index) {
      this.getBarRect()
      this.progress = 0
      console.log(id, index, "触发播放");
      if(index === this.currentIndex) {
         this.currentVideoIsPlaying = true;
         if(! this.duration) {
@@ -881,9 +808,11 @@
            this.formartDuration = this.sliderFormatTime(this.duration);
         }
      } else {
         this.currentVideoIsPlaying = false;
         return
      }
      this.getBarRect()
      this.progress = 0
      console.log(id, index, "触发播放");
      this.playRecord.videoId = id;
      // 没初始化才赋值,因为一个视频重复播放onPlay会重复触发
      if(this.playRecord.startPlayTime === 0) {
@@ -893,7 +822,7 @@
         const duration = Date.now() - this.startPauseTime
         this.totalPauseTime += duration
      }
      this.videoLoading = false
    },
    // 视频暂停事件
@@ -901,11 +830,8 @@
      console.log(index, "触发暂停");
      if(index === this.currentIndex) {
         this.currentVideoIsPlaying = false;
      } else {
         this.currentVideoIsPlaying = true;
         return
         this.startPauseTime = Date.now()
      }
     this.startPauseTime = Date.now()
    },
    // 视频结束事件
    onEnded(index) {
@@ -914,6 +840,7 @@
   // 记录播放时长
   onTimeUpdate(e) {
      this.videoLoading = false
      this.playRecord.playAt = e.detail.currentTime;
      this.currentTime = e.detail.currentTime;
@@ -926,7 +853,8 @@
     this.startProgress = this.progress; // 记录开始时的进度
     this.startX = e.touches[0].pageX;
     console.log("记录开始时的进度", this.startProgress);
     this.videoContexts[this.currentIndex].pause()
     const videoContext = uni.createVideoContext(`video${this.currentIndex}`, this);
     videoContext.pause()
     // this.updateProgress(e);
   },
@@ -934,7 +862,6 @@
   handleTouchMove(e) {
     if (!this.isDragging || !this.barWidth) return;
     clearTimeout(this.processHidenTimer)
     this.videoContexts[this.currentIndex].pause()
     this.updateProgress(e);
   },
@@ -942,8 +869,9 @@
   handleTouchEnd() {
     this.isDragging = false;
     console.log("滑动结束", this.duration * this.progress);
     this.videoContexts[this.currentIndex].seek(this.duration * this.progress / 100)
     this.videoContexts[this.currentIndex].play()
     const videoContext = uni.createVideoContext(`video${this.currentIndex}`, this);
     videoContext.seek(this.duration * this.progress / 100)
     videoContext.play()
     this.processHidenTimer = setTimeout(() => {
        this.showProcess = false;
      }, 1000);
@@ -959,7 +887,6 @@
      // 将像素距离转换为进度增量
      const deltaProgress = (deltaX / this.barWidth) * 100;
      console.log("进度增量", deltaProgress);
      // 计算新进度 = 开始时的进度 + 滑动增量
      let newProgress = this.startProgress + deltaProgress;
@@ -967,6 +894,13 @@
      newProgress = Math.max(0, Math.min(100, newProgress));
      this.progress = newProgress;
   },
   // 视频缓冲
   videoWaiting(index) {
      if (index === this.currentIndex) {
         console.log("视频缓冲中。。。");
         this.videoLoading = true;
      }
   },
   // 获取视频总时长
   onLoadedMetadata(e) {
@@ -1015,7 +949,7 @@
   .video-item {
     width: 100%;
     height: 100%;
     object-fit: cover;
     /* object-fit: cover; */
   }
   .play-icon {
     position: absolute;