Kaynağa Gözat

直播间真人直播使用 腾讯云原生直播

yuhongqi 1 gün önce
ebeveyn
işleme
035b0d9957

+ 2 - 1
src/views/live/components/productOrder.vue

@@ -598,7 +598,8 @@ export default {
         {key: "EMS", label: "邮政", value: "EMS"},
         {key: "ZTO", label: "中通", value: "ZTO"},
         {key: "JD", label: "京东", value: "JD"},
-        {key: "DBL", label: "德邦", value: "DBL"}
+        {key: "DBL", label: "德邦", value: "DBL"},
+        {key: "YD", label: "韵达", value: "YD"}
       ],
       editForm: {
         orderType: null,

+ 101 - 34
src/views/live/liveConsole/index.vue

@@ -81,14 +81,13 @@
         </div>
         <div style="border-radius: 5px; overflow: hidden;" v-else-if="liveType == 1">
           <video
-            controls
+            id="live-tcplayer-container"
             ref="livingPlayer"
-            autoplay
-            width="100%"
-            @click.prevent
-            @contextmenu.prevent
-            class="custom-video"
-            style="display: block; background: #000; height: 45vh;"
+            preload="auto"
+            playsinline
+            webkit-playsinline
+            class="custom-video tcplayer-live"
+            style="display: block; background: #000; height: 45vh; width: 100%;"
           ></video>
           <!-- 时间显示(可选) -->
           <div ref="liveElapsedTime" class="time-display">
@@ -323,6 +322,8 @@ export default {
       },
       livingUrl:"",
       videoUrl: "",
+      tcPlayer: null,
+      tcPlayerSdkReady: false,
       status: 0,
       loadMsgMaxPage: 2,
       liveVideo: {},
@@ -473,6 +474,7 @@ export default {
   // 使用 deactivated 和 activated 钩子替代 beforeDestroy 和 destroyed
   deactivated() {
     this.saveChatScrollPosition();
+    this.destroyTcPlayer();
   },
 
   activated() {
@@ -480,11 +482,15 @@ export default {
       this.restoreChatScrollPosition();
     });
     this.$nextTick(() => {
-      const video = this.$refs.videoPlayer;
-      if (video != null) {
-        this.initVideoPlayer(this.liveInfo.startTime)
+      if (this.liveType === 1 && this.livingUrl) {
+        this.initPlayer();
+      } else {
+        const video = this.$refs.videoPlayer;
+        if (video != null) {
+          this.initVideoPlayer(this.liveInfo.startTime);
+        }
       }
-    })
+    });
   },
   methods: {
     deleteMsg(m){
@@ -745,8 +751,9 @@ export default {
               return
             }
             if (res.data.liveType == 1) {
+              this.liveType = 1
               this.livingUrl = res.data.flvHlsUrl
-              this.livingUrl = this.livingUrl.replace("flv","m3u8")
+              // this.livingUrl = this.livingUrl.replace("flv","m3u8")
               this.$nextTick(() => {
                 this.initPlayer()
               })
@@ -792,32 +799,85 @@ export default {
         }
       })
     },
+    loadTcPlayerSdk() {
+      if (this.tcPlayerSdkReady && window.TCPlayer) {
+        return Promise.resolve();
+      }
+      if (this._tcPlayerSdkPromise) {
+        return this._tcPlayerSdkPromise;
+      }
+      const loadScript = (src) => new Promise((resolve, reject) => {
+        if (document.querySelector(`script[src="${src}"]`)) {
+          resolve();
+          return;
+        }
+        const script = document.createElement('script');
+        script.src = src;
+        script.onload = () => resolve();
+        script.onerror = () => reject(new Error('Failed to load ' + src));
+        document.head.appendChild(script);
+      });
+      const loadCss = (href) => {
+        if (document.querySelector(`link[href="${href}"]`)) {
+          return;
+        }
+        const link = document.createElement('link');
+        link.rel = 'stylesheet';
+        link.href = href;
+        document.head.appendChild(link);
+      };
+      this._tcPlayerSdkPromise = Promise.resolve()
+        .then(() => {
+          loadCss('https://web.sdk.qcloud.com/player/tcplayer/release/v4.9.1/tcplayer.min.css');
+          return loadScript('https://video.sdk.qcloudecdn.com/web/TXLivePlayer-1.3.2.min.js');
+        })
+        .then(() => loadScript('https://web.sdk.qcloud.com/player/tcplayer/release/v4.9.1/tcplayer.v4.9.1.min.js'))
+        .then(() => {
+          this.tcPlayerSdkReady = true;
+        });
+      return this._tcPlayerSdkPromise;
+    },
+    destroyTcPlayer() {
+      if (this.tcPlayer) {
+        try {
+          this.tcPlayer.dispose();
+        } catch (e) {
+          console.error('销毁 TCPlayer 失败:', e);
+        }
+        this.tcPlayer = null;
+      }
+    },
     initPlayer(){
-      var isUrl = this.livingUrl === null || this.livingUrl.trim() === ''
+      const isUrl = this.livingUrl === null || this.livingUrl.trim() === '';
       if (isUrl) {
-        console.error('直播地址为空,无法初始化播放器')
-        return
+        console.error('直播地址为空,无法初始化播放器');
+        return;
       }
-      if (Hls.isSupported() && !isUrl) {
-        const videoElement = this.$refs.livingPlayer
-        if (!videoElement) {
-          console.error('找不到 video 元素')
-          return
-        }
-        this.hls = new Hls();
-        this.hls.attachMedia(videoElement);
-        this.hls.on(Hls.Events.MEDIA_ATTACHED, () => {
-          this.hls.loadSource(this.livingUrl);
-          this.hls.on(Hls.Events.STREAM_LOADED, (event, data) => {
-            videoElement.play();
+      this.loadTcPlayerSdk().then(() => {
+        this.destroyTcPlayer();
+        this.$nextTick(() => {
+          if (!this.$refs.livingPlayer || !window.TCPlayer) {
+            console.error('找不到 video 元素或 TCPlayer 未加载');
+            return;
+          }
+          this.tcPlayer = window.TCPlayer('live-tcplayer-container', {
+            sources: [this.livingUrl],
+            autoplay: true,
+            width: '100%',
+            height: '45vh',
+            live: true,
+            controls: true,
+            playsinline: true,
+            'webkit-playsinline': true,
+            x5_player: true,
+            x5_type: 'h5-page',
+            x5_fullscreen: false
           });
         });
-        this.hls.on(Hls.Events.ERROR, (event, data) => {
-          console.error('HLS 错误:', data);
-        });
-      } else {
-        console.error('浏览器不支持 HLS')
-      }
+      }).catch(err => {
+        console.error('TCPlayer SDK 加载失败:', err);
+        this.$message.error('直播播放器加载失败,请刷新页面重试');
+      });
     },
     handleClick(tab) {
       const tabName = tab.name;
@@ -1358,8 +1418,9 @@ export default {
     },
   },
   destroyed() {
+    this.destroyTcPlayer();
     this.hls?.destroy();
-    clearInterval(this.processInterval)
+    clearInterval(this.processInterval);
   }
 }
 </script>
@@ -1466,4 +1527,10 @@ export default {
     border: none !important;
     box-shadow: none !important;
   }
+  .tcplayer-live {
+    width: 100%;
+  }
+  ::v-deep .tcplayer {
+    margin: 0 auto;
+  }
 </style>

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

@@ -471,7 +471,8 @@ export default {
         {key: "EMS", label: "邮政", value: "EMS"},
         {key: "ZTO", label: "中通", value: "ZTO"},
         {key: "JD", label: "京东", value: "JD"},
-        {key: "DBL", label: "德邦", value: "DBL"}
+        {key: "DBL", label: "德邦", value: "DBL"},
+        {key: "YD", label: "韵达", value: "YD"}
       ],
       editDyForm:{
         id: null,

+ 2 - 1
src/views/store/components/productOrder.vue

@@ -593,7 +593,8 @@ export default {
         { key: "EMS", label: "邮政", value: "EMS" },
         { key: "ZTO", label: "中通", value: "ZTO" },
         { key: "JD", label: "京东", value: "JD" },
-        { key: "DBL", label: "德邦", value: "DBL" }
+        { key: "DBL", label: "德邦", value: "DBL" },
+        {key: "YD", label: "韵达", value: "YD"}
       ],
       editForm:{
         orderType:null,