绿满眶商城微信小程序-uniapp
peng
2025-07-02 be80b22a4a0fcd33e1b17ebdb86eba91cc7de4d2
pages/kitchen/KitchenVideo.vue
@@ -2,7 +2,7 @@
  <view class="video-container">
    <!-- 视频加载 -->
    <zero-loading v-show="videoLoading" type="circle" color="#0ebd57" text=""></zero-loading>
    <view class="showLeft" @click="showDrawer('showLeft')" v-if="!showLeft">
    <view class="showLeft" @click="showDrawer('showLeft')" v-if="!showLeft" :style="{top: buttonHeight+'px'}">
      <uni-icons type="right" size="30"></uni-icons>
    </view>
    <!-- 视频列表 -->
@@ -56,6 +56,7 @@
              @touchstart.stop="handleTouchStart"
              @touchmove.stop="handleTouchMove"
              @touchend.stop="handleTouchEnd"
           :style="{bottom: marginBottom + 'px'}"
              class="container">
            <!-- 进度条 - 整个区域可拖动 -->
            <view class="process-warp" :style="{ opacity: showProcess ? 1 : 0 }">
@@ -121,7 +122,7 @@
        <!-- 视频信息层 -->
        <view class="video-info">
        <view class="video-info" :style="{bottom: marginBottom + 20 + 'px'}">
          <view>
            <text class="video-author">@{{item.authorName}}</text>
          </view>
@@ -133,29 +134,33 @@
        <!-- 右侧互动按钮 -->
        <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">&#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="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="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">
            <button open-type="share" class="custom-share-btn" :data-obj="item">
              <text class="iconfont">&#xe602;</text>
            </button>
          </view>
        </view>
             <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>
@@ -238,7 +243,7 @@
      </view>
    </uni-popup>
    <uni-drawer ref="showLeft" mode="left" width="120" :cus-style="true" height="80vh"
                @change="change($event,'showLeft')" class="navigationLeft">
                @change="change($event,'showLeft')" class="navigationLeft" :drawerTop="buttonHeight">
      <scroll-view class="typeNavigation" :scroll-y="true" :show-scrollbar="false">
        <view class="typeNavigationItem" :class="{typeNavigationItemCheck:currentCategort ==item.id}"
              @click="chooseCategory(item.id)" v-for="item in categoryList" :key="item.id">
@@ -247,7 +252,7 @@
      </scroll-view>
    </uni-drawer>
    <view v-if="videoList.length===0"  style="display: flex;align-items: center;justify-content: center;background-color: #fff;height: 100%">当前没有可以查看的视频</view>
   <custom-tabbar bgColor="#ffffff" selected="kitchen"></custom-tabbar>
  </view>
</template>
@@ -261,7 +266,8 @@
  getVideoComments,
  addVideoComment,
  thubmsUpComment,
  cancelThubmsUpComment
  cancelThubmsUpComment,
  changeThumbsUp
} from "@/api/video.js";
import {
  changeCollect
@@ -274,6 +280,7 @@
  },
  data() {
    return {
     buttonHeight:0,
      showLeft:false,
      currentCategort: '',
      categoryList: [],
@@ -340,15 +347,14 @@
        startY: 0,
        endY: 0
      },
      videoContexts: [], // 视频上下文对象集合
      loading: false, // 是否正在加载
      videoQuery: {
        pageNumber: 1,
        pageSize: 6,
        videoFrom: 'recommend',
        videoType: 'cook'
      }
      },
     marginBottom: 0 // 底部安全区域
    }
  },
  onShow() {
@@ -364,12 +370,12 @@
    this.startHidenTime = Date.now()
  },
  onLoad() {
    this.getKitchenTypeList();
    this.loadVideos();
  },
  onReady() {
    // 初始化视频上下文
    this.initVideoContexts();
   this.marginBottom = uni.getSystemInfoSync().safeAreaInsets.bottom
   // 获取状态栏高度
   const systemInfo = uni.getSystemInfoSync();
   this.buttonHeight = systemInfo.statusBarHeight;
   this.getKitchenTypeList();
   this.loadVideos();
  },
  methods: {
    async chooseCategory(id) {
@@ -379,7 +385,7 @@
          this.videoQuery.kitchenTypeId = id;
      this.videoLoading = false;
     this.currentIndex = 0;
      await this.loadVideos()
    },
    getKitchenTypeList() {
@@ -651,14 +657,6 @@
        }
      })
    },
    // 初始化视频上下文
    initVideoContexts() {
      this.videoContexts = this.videoList.map((_, index) => {
        let videoContent = uni.createVideoContext(`video${index}`, this);
        return videoContent;
      });
    },
    // 加载视频数据
    async loadVideos() {
      console.log(this.loading, this.videoNoMore,this.videoQuery)
@@ -679,9 +677,6 @@
            ),
          ];
        }
        this.$nextTick(() => {
          this.initVideoContexts();
        });
        this.loading = false;
        if (res.data.data.length < this.videoQuery.pageSize) {
          this.videoNoMore = true;
@@ -694,29 +689,75 @@
    // 滑动切换视频
    onSwiperChange(e) {
      this.videoLoading = false
      // 如果视频处于暂停状态往下刷视频,那么需要再计算一次暂停时间
      if (!this.currentVideoIsPlaying) {
        if (this.startPauseTime !== 0) {
          const duration = Date.now() - this.startPauseTime
          this.totalPauseTime += duration
        }
      if(!this.currentVideoIsPlaying) {
         if(this.startPauseTime !== 0) {
            const duration = Date.now() - this.startPauseTime
            this.totalPauseTime += duration
         }
      }
      // 保存上一个视频的播放记录
      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();
      }
      const videoContext1 = uni.createVideoContext(`video${this.currentIndex}`, this);
      videoContext1.play()
     // 如果剩余视频不足,触发请求获取更多视频
     if (this.videoList.length - 1 < this.currentIndex + this.videoLiveOffset) {
        this.loadVideos()
     }
    },
   // 开始触摸
   handleSwiperStart(e) {
      console.log("开始触摸", e);
       this.touchXY.startX = e.touches[0].pageX
       this.touchXY.startY = e.touches[0].pageY
   },
   // 触摸中
   handleSwiperMove(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
       // 判断是否是横向滑动(X轴变化大于Y轴变化)
       if (Math.abs(diffX) > Math.abs(diffY)) {
         if (diffX > 0) {
           console.log('右滑')
         if (item.goodsList && item.goodsList.length > 0) {
            this.jumpToPay(item.id)
         }
         } else {
           console.log('左滑')
         }
       }
       // 重置坐标
       this.touchXY = {
         startX: 0,
         endX: 0,
         startY: 0,
         endY: 0
      }
   },
    // 收藏/取消收藏
    toggleCollect(item, index) {
@@ -740,6 +781,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);
@@ -797,7 +860,7 @@
    onTimeUpdate(e) {
      this.videoLoading = false
      this.playRecord.playAt = e.detail.currentTime;
      this.currentTime = e.detail.currentTime;
      this.progress = (e.detail.currentTime / this.duration) * 100
    },
@@ -808,53 +871,15 @@
      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);
    },
    // 开始触摸
    handleSwiperStart(e) {
      console.log("开始触摸", e);
      this.touchXY.startX = e.touches[0].pageX
      this.touchXY.startY = e.touches[0].pageY
    },
    // 触摸中
    handleSwiperMove(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
      // 判断是否是横向滑动(X轴变化大于Y轴变化)
      if (Math.abs(diffX) > Math.abs(diffY)) {
        if (diffX > 0) {
          console.log('右滑')
          if (item.goodsList && item.goodsList.length > 0) {
            this.jumpToPay(item.id)
          }
        } else {
          console.log('左滑')
        }
      }
      // 重置坐标
      this.touchXY = {
        startX: 0,
        endX: 0,
        startY: 0,
        endY: 0
      }
    },
    // 触摸移动
    handleTouchMove(e) {
      if (!this.isDragging || !this.barWidth) return;
      clearTimeout(this.processHidenTimer)
      this.videoContexts[this.currentIndex].pause()
      this.updateProgress(e);
    },
@@ -862,31 +887,31 @@
    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);
         this.showProcess = false;
       }, 1000);
    },
    // 更新进度
    updateProgress(e) {
      // 获取当前触摸点X坐标
      const currentX = e.touches[0].pageX;
       // 获取当前触摸点X坐标
       const currentX = e.touches[0].pageX;
      // 计算滑动距离(像素)
      const deltaX = currentX - this.startX;
       // 计算滑动距离(像素)
       const deltaX = currentX - this.startX;
      // 将像素距离转换为进度增量
      const deltaProgress = (deltaX / this.barWidth) * 100;
      console.log("进度增量", deltaProgress);
      // 计算新进度 = 开始时的进度 + 滑动增量
      let newProgress = this.startProgress + deltaProgress;
       // 将像素距离转换为进度增量
       const deltaProgress = (deltaX / this.barWidth) * 100;
       // 计算新进度 = 开始时的进度 + 滑动增量
       let newProgress = this.startProgress + deltaProgress;
      // 限制范围在0-100之间
      newProgress = Math.max(0, Math.min(100, newProgress));
       // 限制范围在0-100之间
       newProgress = Math.max(0, Math.min(100, newProgress));
      this.progress = newProgress;
       this.progress = newProgress;
    },
    // 视频缓冲
    videoWaiting(index) {
@@ -897,9 +922,9 @@
    },
    // 获取视频总时长
    onLoadedMetadata(e) {
      this.duration = e.detail.duration;
      this.formartDuration.push(this.sliderFormatTime(this.duration));
      console.log("视频总时长", this.duration);
      // this.duration = e.detail.duration;
      // this.formartDuration.push(this.sliderFormatTime(this.duration));
      // console.log("视频总时长", this.duration);
    },
    // 保存播放记录
    async savePlayRecord() {
@@ -939,7 +964,6 @@
.showLeft {
  display: flex;
  top: 50rpx;
  left: 0;
  align-items: center;
  justify-content: flex-start;
@@ -960,7 +984,6 @@
.video-item {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.play-icon {
@@ -1380,7 +1403,7 @@
.progress-text {
  margin-top: 10px;
  font-size: 14px;
  color: #666;
  color: #fff;
}
.swiper-box {
@@ -1407,18 +1430,18 @@
}
.typeNavigationItem {
  padding: 24rpx;
  font-size: 28rpx;
  color: black;
  margin-top: 10rpx;
  border-radius: 12rpx;
  border: 1rpx solid gray;
   padding: 24rpx;
   font-size: 28rpx;
   color: black;
   margin-top: 10rpx;
}
.typeNavigationItemCheck {
  background-color: #42b993;
  color: #fff;
  border: 0;
   color: #ef321e;
   font-size: 32rpx;
   font-weight: bold;
   border: 0;
}
.container ::v-deep .navigationLeft .uni-drawer__content {
@@ -1427,4 +1450,16 @@
  background-color: lightpink !important;
}
</style>
.custom-share-btn {
  font-size: unset;
  background: none;
  padding: 0;
  margin: 0;
  line-height: normal;
  border: none;
}
.custom-share-btn::after {
  border: none;
}
</style>