Prechádzať zdrojové kódy

销售直播代码 直播间

yuhongqi 2 mesiacov pred
rodič
commit
475f39aeb0

+ 14 - 2
src/views/live/liveConfig/goods.vue

@@ -182,7 +182,8 @@ export default {
         pageNum: 1,
         pageSize: 10,
         productName: null,
-        liveId: null
+        liveId: null,
+        storeId: null
       },
       goodsLiveList: [],
       goodsLiveTotal: 0,
@@ -308,7 +309,14 @@ export default {
         liveId: this.liveId,
         productsId: this.selectedGoods.map(item => item.productId).join(',')
       }).then(response => {
-        this.goodsDialogVisible = false
+        if (response.code !== 200) {
+          this.$message({
+            message: response.msg,
+            type: 'warning'
+          });
+          return;
+        }
+        this.goodsDialogVisible = false;
         this.getLiveGoodsList()
       })
     },
@@ -338,6 +346,10 @@ export default {
     },
     getStoreProductLists() {
       this.queryGoodParams.liveId = this.liveId
+      console.log(this.goodsLiveList)
+      if(this.goodsLiveList.length > 0){
+        this.queryGoodParams.storeId = this.goodsLiveList[0].storeId
+      }
       listStoreProduct(this.queryGoodParams).then(response => {
         this.goodsList = response.rows
         this.goodsTotal = response.total

+ 169 - 26
src/views/live/liveConsole/index.vue

@@ -85,17 +85,28 @@
             loop
             autoplay
             width="100%"
-            :src="videoUrl"
+            muted
+            playsinline
             @click.prevent
             @contextmenu.prevent
             class="custom-video"
-            style="display: block; background: #000; height: 45vh;"
-          ></video>
+            style="display: block; background: #000; height: 40vh;"
+          >
+            <source :src="videoUrl" type="video/mp4">
+          </video>
+          <!-- 自定义进度条容器 -->
+          <div ref="progressBar" class="progress-container">
+            <div id="progressBar" class="progress-bar"></div>
+          </div>
+
+          <!-- 时间显示(可选) -->
+          <div ref="elapsedTime" class="time-display">
+            已播放:<span id="elapsedTime">00:00:00</span>
+          </div>
         </div>
         <div style="border-radius: 5px; overflow: hidden;" v-else>
           <img :src="require('@/assets/images/videoNotStart.png')" style="width: 100%; height: 45vh;">
         </div>
-
       </div>
       <!-- 底部导航栏 -->
       <div style="display: flex; justify-content: space-around; padding: 15px 0; background: #fff; border-top: 1px solid #f0f0f0;">
@@ -280,6 +291,11 @@ export default {
         {value:'30',label:'30分钟',key:'30'},
         {value:'60',label:'1小时',key:'60'},
       ],
+      videoDuration: 0,
+      startTime: null,
+      processInterval: null,
+      // ... 其他数据
+      chatScrollTop: 0 // 保存聊天滚动位置
     }
   },
   created() {
@@ -328,40 +344,61 @@ export default {
     }
   },
   mounted() {
+    this.$nextTick(() => {
+      this.restoreChatScrollPosition();
+    });
     this.getEchartsTables();
-    if (this.videoUrl.length > 0) {
-      const video = this.$refs.videoPlayer;
-      video.play()
-    }
+    // 添加滚动事件监听器
+    this.$nextTick(() => {
+      if (this.$refs.manageRightRef && this.$refs.manageRightRef.wrap) {
+        this.$refs.manageRightRef.wrap.addEventListener('scroll', this.saveChatScrollPosition);
+      }
+    });
+  },
+  // 使用 deactivated 和 activated 钩子替代 beforeDestroy 和 destroyed
+  deactivated() {
+    this.saveChatScrollPosition();
+  },
 
+  activated() {
+    this.$nextTick(() => {
+      this.restoreChatScrollPosition();
+    });
+    this.$nextTick(() => {
+      const video = this.$refs.videoPlayer;
+      if (video != null) {
+        video.play();
+        this.initVideoPlayer(this.liveInfo.startTime)
+      }
+    })
   },
   methods: {
-    // 切换音量状态
-    toggleVolume() {
-      const video = this.$refs.videoPlayer;
-      if (video.volume > 0) {
-        // 保存当前音量并静音
-        this.lastVolume = video.volume;
-        video.volume = 0;
-        this.isMuted = true;
-      } else {
-        // 恢复之前的音量
-        video.volume = this.lastVolume || this.initialVolume;
-        this.isMuted = false;
+    // 保存聊天滚动位置
+    saveChatScrollPosition() {
+      if (this.$refs.manageRightRef && this.$refs.manageRightRef.wrap) {
+        this.chatScrollTop = this.$refs.manageRightRef.wrap.scrollHeight - this.$refs.manageRightRef.wrap.clientHeight;
+      }
+    },
+
+    // 恢复聊天滚动位置
+    restoreChatScrollPosition() {
+      if (this.$refs.manageRightRef && this.$refs.manageRightRef.wrap) {
+        this.$refs.manageRightRef.wrap.scrollTop = this.chatScrollTop;
       }
     },
     getLive(){
       getLive(this.liveId).then(res => {
-        this.loading = false
         if (res.code == 200) {
           if (res.data.isAudit != 1) {
             this.$message.error("当前直播间未经审核");
+            this.loading = false
             return
           }
           this.isAudit = true
           this.status = res.data.status
           if (res.data.status != 2) {
             this.$message.error("当前直播间未直播");
+            this.loading = false
             return
           }
           if (res.data.liveType == 1) {
@@ -372,13 +409,91 @@ export default {
           } else {
             this.liveType = 2
             this.videoUrl = res.data.videoUrl;
+            this.$nextTick(() => {
+              const video = this.$refs.videoPlayer;
+              video.play()
+              this.initVideoPlayer(res.data.startTime)
+            })
           }
+          this.loading = false
         } else {
           this.$message.error(res.msg)
+          this.loading = false
         }
         this.liveInfo = res.data
       })
     },
+    initVideoPlayer: function (startTime) {
+      const video = this.$refs.videoPlayer;
+
+
+      // 1. 初始化开播时间
+      startTime = new Date(startTime).getTime();
+      this.startTime = startTime;
+      // 2. 监听视频元数据加载完成(获取视频时长)
+      video.addEventListener('loadedmetadata', () => {
+        this.videoDuration = video.duration; // 获取视频时长(秒)
+
+        // 初始化视频播放位置
+        this.updateVideoPosition(video);
+
+        // 启动实时进度更新(每秒刷新一次)
+        this.processInterval = setInterval(this.updateProgress, 1000);
+      });
+
+    },
+    updateVideoPosition(video){
+      const currentTime = new Date().getTime(); // 当前时间戳(毫秒)
+      const elapsedTime = currentTime - this.startTime; // 已流逝时间(毫秒)
+
+      if (elapsedTime < 0) {
+        // 未开播:视频停在初始位置
+        video.currentTime = 0;
+        return;
+      }
+
+      // 已开播:计算视频循环后的位置(流逝时间 % 视频时长)
+      const elapsedSeconds = elapsedTime / 1000; // 转换为秒
+      const videoPosition = elapsedSeconds % this.videoDuration; // 视频内的播放位置(秒)
+
+      // 设置视频播放位置
+      video.currentTime = videoPosition;
+    },
+    updateProgress() {
+      const progressBar = this.$refs.progressBar;
+      const elapsedTimeEl = this.$refs.elapsedTime;
+      if (!this.videoDuration) return; // 视频时长未加载时不更新
+
+      const currentTime = new Date().getTime();
+      const elapsedTime = currentTime - this.startTime; // 总流逝时间(毫秒)
+
+      if (elapsedTime < 0) {
+        // 未开播状态
+        progressBar.style.width = '0%';
+        elapsedTimeEl.textContent = '00:00:00';
+        return;
+      }
+
+      // 计算进度百分比(基于视频循环)
+      const elapsedSeconds = elapsedTime / 1000;
+      const videoPosition = elapsedSeconds % this.videoDuration; // 当前在视频中的位置
+      const progressPercent = (videoPosition / this.videoDuration) * 100; // 进度百分比
+
+      // 更新进度条宽度
+      progressBar.style.width = `${progressPercent}%`;
+
+      // 格式化总流逝时间为“时:分:秒”并显示
+      elapsedTimeEl.textContent = this.formatTime(elapsedTime);
+    },
+    formatTime(ms) {
+      const totalSeconds = Math.floor(ms / 1000);
+      const hours = Math.floor(totalSeconds / 3600);
+      const minutes = Math.floor((totalSeconds % 3600) / 60);
+      const seconds = totalSeconds % 60;
+
+      // 补零处理(确保两位数)
+      return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
+    },
     // ... 其他方法 ...
     timeChange(val) {
       this.searchQuery.timeOptions = val
@@ -469,7 +584,6 @@ export default {
       }
     },
     handleClick(tab) {
-
     },
     getList() {
       this.resetParams()
@@ -564,10 +678,7 @@ export default {
       })
     },
     manageRightScroll() {
-      let max = this.$refs.manageRightRef.wrap.scrollHeight - this.$refs.manageRightRef.wrap.clientHeight
-      let current = this.$refs.manageRightRef.wrap.scrollTop
-      console.log("manageRightMax", max);
-      console.log("manageRight", current)
+      this.saveChatScrollPosition();
     },
     changeUserState(u) {
       // 修改状态
@@ -668,6 +779,7 @@ export default {
       liveId: this.liveId,
       userId: this.userId
     })
+    clearInterval(this.processInterval)
   }
 }
 </script>
@@ -738,6 +850,37 @@ export default {
 }
 .custom-video {
   pointer-events: none !important; /* 完全禁止鼠标交互,避免悬停时显示工具栏 */
+  outline: none !important; /* 移除焦点轮廓 */
+}
+/* 额外的兼容性隐藏 */
+.custom-video::-webkit-media-controls {
+  display: none !important;
 }
 
+.custom-video::-webkit-media-controls-panel {
+  display: none !important;
+}
+/* 进度条容器 */
+.progress-container {
+  width: 100%;
+  height: 6px;
+  background: #eee;
+  border-radius: 3px;
+  margin: 10px 0;
+  cursor: pointer;
+}
+
+/* 进度条填充部分 */
+.progress-bar {
+  height: 100%;
+  background: #42b983;  /* Vue 绿色主题示例 */
+  border-radius: 3px;
+  width: 0%;  /* 初始进度为 0 */
+}
+
+/* 时间显示样式 */
+.time-display {
+  color: #333;
+  font-size: 14px;
+}
 </style>

+ 3 - 2
src/views/live/liveOrder/liveOrderDetails.vue

@@ -790,8 +790,9 @@ export default {
     getlistOrderitem(orderId){
       listOrderitem(orderId).then(response => {
         this.prod = response.rows;
-        console.log(this.prod)
-        this.showProd=[this.prod[0]]
+        if (this.prod.length > 0) {
+          this.showProd=[this.prod[0]];
+        }
       });
     },
     // getlogList(orderId){