lex-xin 3 年之前
父节点
当前提交
92721e18e4

文件差异内容过多而无法显示
+ 1 - 0
dist/assets/index-legacy.0958e411.js


文件差异内容过多而无法显示
+ 1 - 0
dist/assets/index-legacy.162818bd.js


文件差异内容过多而无法显示
+ 0 - 0
dist/assets/index-legacy.61803a48.js


文件差异内容过多而无法显示
+ 0 - 0
dist/assets/index-legacy.c26659c5.js


文件差异内容过多而无法显示
+ 0 - 0
dist/assets/index-legacy.ee5eabf0.js


+ 1 - 1
dist/assets/index.48a3b026.js → dist/assets/index.0da1cc3f.js

@@ -1 +1 @@
-import{d as i,a as s,l as t}from"./vendor.9c266e46.js";const e="_wscnHttp404Container_1v1ex_1",c="_wscnHttp404_1v1ex_1",u="_pic404_1v1ex_13",n="_pic404__parent_1v1ex_19",o="_pic404__child_1v1ex_22",a="_left_1v1ex_25",d="_cloudLeft_1v1ex_1",r="_mid_1v1ex_36",h="_cloudMid_1v1ex_1",p="_right_1v1ex_47",v="_cloudRight_1v1ex_1",b="_bullshit_1v1ex_124",x="_bullshit__oops_1v1ex_132",m="_slideUp_1v1ex_1",g="_bullshit__headline_1v1ex_143",f="_bullshit__info_1v1ex_155",H="_bullshit__returnHome_1v1ex_166";var _={wscnHttp404Container:e,wscnHttp404:c,pic404:u,pic404__parent:n,pic404__child:o,left:a,cloudLeft:d,mid:r,cloudMid:h,right:p,cloudRight:v,bullshit:b,bullshit__oops:x,slideUp:m,bullshit__headline:g,bullshit__info:f,bullshit__returnHome:H},F="./assets/404.538aa4d7.png",l="./assets/404_cloud.98e7ac66.png",w=i({name:"Page404",data(){return{message:"\u5F88\u62B1\u6B49\uFF0C\u4F60\u8BBF\u95EE\u7684\u9875\u9762\u4E0D\u5B58\u5728"}},render(){return s("div",{class:_.wscnHttp404Container},[s("div",{class:_.wscnHttp404},[s("div",{class:_.pic404},[s("img",{class:_.pic404__parent,src:F,alt:"404"},null),s("img",{class:[_.pic404__child,_.left],src:l,alt:"404"},null),s("img",{class:[_.pic404__child,_.mid],src:l,alt:"404"},null),s("img",{class:[_.pic404__child,_.right],src:l,alt:"404"},null)]),s("div",{class:_.bullshit},[s("div",{class:_.bullshit__oops},[t("OOPS!")]),s("div",{class:_.bullshit__headline},[this.message]),s("div",{class:_.bullshit__info},[t("\u8BF7\u68C0\u67E5\u60A8\u8F93\u5165\u7684\u7F51\u5740\u662F\u5426\u6B63\u786E\uFF0C\u6216\u8005\u70B9\u51FB\u94FE\u63A5\u7EE7\u7EED\u6D4F\u89C8")]),s("a",{href:"",class:_.bullshit__returnHome},[t("\u8FD4\u56DE\u9996\u9875")])])])])}});export{w as default};
+import{d as i,a as t,t as s}from"./vendor.8df6bc42.js";const e="_wscnHttp404Container_1v1ex_1",c="_wscnHttp404_1v1ex_1",u="_pic404_1v1ex_13",n="_pic404__parent_1v1ex_19",o="_pic404__child_1v1ex_22",a="_left_1v1ex_25",d="_cloudLeft_1v1ex_1",r="_mid_1v1ex_36",h="_cloudMid_1v1ex_1",p="_right_1v1ex_47",v="_cloudRight_1v1ex_1",b="_bullshit_1v1ex_124",x="_bullshit__oops_1v1ex_132",m="_slideUp_1v1ex_1",g="_bullshit__headline_1v1ex_143",f="_bullshit__info_1v1ex_155",H="_bullshit__returnHome_1v1ex_166";var _={wscnHttp404Container:e,wscnHttp404:c,pic404:u,pic404__parent:n,pic404__child:o,left:a,cloudLeft:d,mid:r,cloudMid:h,right:p,cloudRight:v,bullshit:b,bullshit__oops:x,slideUp:m,bullshit__headline:g,bullshit__info:f,bullshit__returnHome:H},F="./assets/404.538aa4d7.png",l="./assets/404_cloud.98e7ac66.png",w=i({name:"Page404",data(){return{message:"\u5F88\u62B1\u6B49\uFF0C\u4F60\u8BBF\u95EE\u7684\u9875\u9762\u4E0D\u5B58\u5728"}},render(){return t("div",{class:_.wscnHttp404Container},[t("div",{class:_.wscnHttp404},[t("div",{class:_.pic404},[t("img",{class:_.pic404__parent,src:F,alt:"404"},null),t("img",{class:[_.pic404__child,_.left],src:l,alt:"404"},null),t("img",{class:[_.pic404__child,_.mid],src:l,alt:"404"},null),t("img",{class:[_.pic404__child,_.right],src:l,alt:"404"},null)]),t("div",{class:_.bullshit},[t("div",{class:_.bullshit__oops},[s("OOPS!")]),t("div",{class:_.bullshit__headline},[this.message]),t("div",{class:_.bullshit__info},[s("\u8BF7\u68C0\u67E5\u60A8\u8F93\u5165\u7684\u7F51\u5740\u662F\u5426\u6B63\u786E\uFF0C\u6216\u8005\u70B9\u51FB\u94FE\u63A5\u7EE7\u7EED\u6D4F\u89C8")]),t("a",{href:"",class:_.bullshit__returnHome},[s("\u8FD4\u56DE\u9996\u9875")])])])])}});export{w as default};

文件差异内容过多而无法显示
+ 0 - 0
dist/assets/index.416453c6.js


文件差异内容过多而无法显示
+ 0 - 0
dist/assets/index.cd9189f2.css


文件差异内容过多而无法显示
+ 0 - 0
dist/assets/index.d538a524.js


文件差异内容过多而无法显示
+ 0 - 0
dist/assets/index.d85298aa.js


文件差异内容过多而无法显示
+ 0 - 0
dist/assets/index.fb6968e4.css


文件差异内容过多而无法显示
+ 0 - 0
dist/assets/polyfills-legacy.7f3fc881.js


文件差异内容过多而无法显示
+ 0 - 0
dist/assets/vendor-legacy.834fd8a8.js


文件差异内容过多而无法显示
+ 0 - 0
dist/assets/vendor.8df6bc42.js


+ 127 - 0
dist/index.html

@@ -5,16 +5,143 @@
     <link rel="icon" href="./favicon.ico" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     <title>管乐迷</title>
+<<<<<<< HEAD
     <script type="module" crossorigin src="./assets/index.c91f90b6.js"></script>
     <link rel="modulepreload" href="./assets/vendor.9c266e46.js">
     <link rel="stylesheet" href="./assets/index.fb6968e4.css">
+=======
+    
+    <script type="module" crossorigin src="./assets/index.d538a524.js"></script>
+    <link rel="modulepreload" href="./assets/vendor.8df6bc42.js">
+    <link rel="stylesheet" href="./assets/index.cd9189f2.css">
+>>>>>>> master
     <script type="module">!function(){try{new Function("m","return import(m)")}catch(o){console.warn("vite: loading legacy build because dynamic import is unsupported, syntax error above should be ignored");var e=document.getElementById("vite-legacy-polyfill"),n=document.createElement("script");n.src=e.src,n.onload=function(){System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))},document.body.appendChild(n)}}();</script>
   </head>
   <body>
     <div id="app"></div>
     
+
+    <div id="notification_1" class="el-notification right hide" role="alert" style="top: 16px; z-index: 2011;"><i class="el-icon el-notification__icon el-notification--info"><svg class="icon" width="200" height="200" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" d="M512 64a448 448 0 110 896.064A448 448 0 01512 64zm67.2 275.072c33.28 0 60.288-23.104 60.288-57.344s-27.072-57.344-60.288-57.344c-33.28 0-60.16 23.104-60.16 57.344s26.88 57.344 60.16 57.344zM590.912 699.2c0-6.848 2.368-24.64 1.024-34.752l-52.608 60.544c-10.88 11.456-24.512 19.392-30.912 17.28a12.992 12.992 0 01-8.256-14.72l87.68-276.992c7.168-35.136-12.544-67.2-54.336-71.296-44.096 0-108.992 44.736-148.48 101.504 0 6.784-1.28 23.68.064 33.792l52.544-60.608c10.88-11.328 23.552-19.328 29.952-17.152a12.8 12.8 0 017.808 16.128L388.48 728.576c-10.048 32.256 8.96 63.872 55.04 71.04 67.84 0 107.904-43.648 147.456-100.416z"></path></svg></i><div class="el-notification__group"><h2 class="el-notification__title">提示</h2><div class="el-notification__content"><p>为了保障更好的直播体验,建议使用chrome浏览器</p></div><i id="noClose" class="el-icon el-notification__closeBtn"><svg class="icon" width="200" height="200" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" d="M764.288 214.592L512 466.88 259.712 214.592a31.936 31.936 0 00-45.12 45.12L466.752 512 214.528 764.224a31.936 31.936 0 1045.12 45.184L512 557.184l252.288 252.288a31.936 31.936 0 0045.12-45.12L557.12 512.064l252.288-252.352a31.936 31.936 0 10-45.12-45.184z"></path></svg></i></div></div>
+
+    <script>
+      var win = window;
+      var nav = win.navigator;
+      var doc = win.document;
+      var ieAX = win.ActiveXObject;
+      var ieMode = doc.documentMode;
+      var REG_APPLE = /^Apple/;
+      // var ieVer = _getIeVersion() || ieMode || 0;
+      var isIe = ieAX || ieMode;
+      // var chromiumType = _getChromiumType();
+      /**
+       * 检测 external 是否包含该字段
+       * @param reg 正则
+       * @param type 检测类型,0为键,1为值
+       * @returns {boolean}
+       * @private
+       */
+      function _testExternal(reg, type) {
+          var external = win.external || {};
+
+          for (var i in external) {
+              if (reg.test(type ? external[i] : i)) {
+                  return true;
+              }
+          }
+
+          return false;
+      }
+      /**
+       * 获取 Chromium 内核浏览器类型
+       * @link http://www.adtchrome.com/js/help.js
+       * @link https://ext.chrome.360.cn/webstore
+       * @link https://ext.se.360.cn
+       * @return {String}
+       *         360ee 360极速浏览器
+       *         360se 360安全浏览器
+       *         sougou 搜狗浏览器
+       *         liebao 猎豹浏览器
+       *         chrome 谷歌浏览器
+       *         ''    无法判断
+       * @version 1.0
+       */
+      function _getChromiumType() {
+        if (isIe || typeof win.scrollMaxX !== 'undefined' || REG_APPLE.test(nav.vendor || '')) {
+            return '';
+        }
+
+        var _track = 'track' in document.createElement('track');
+        var webstoreKeysLength = win.chrome && win.chrome.webstore ? Object.keys(win.chrome.webstore).length : 0;
+        console.log(webstoreKeysLength)
+        // 搜狗浏览器
+        if (_testExternal(/^sogou/i, 0)) {
+            return 'sogou';
+        }
+
+        // 猎豹浏览器
+        if (_testExternal(/^liebao/i, 0)) {
+            return 'liebao';
+        }
+
+        // chrome 由于360极速浏览器 内核也是 chrome,所以先判断360极速浏览器
+        if (win.clientInformation && win.clientInformation.permissions) {
+            return 'chrome';
+        }
+
+        if (_track) {
+            // 360极速浏览器
+            // 360安全浏览器
+            return webstoreKeysLength > 1 ? '360ee' : '360se';
+        }
+
+        return '';
+      }
+      // 获得ie浏览器版本
+      function _getIeVersion() {
+          var v = 3,
+              p = document.createElement('p'),
+              all = p.getElementsByTagName('i');
+
+          while (
+              p.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
+                  all[0]);
+
+          return v > 4 ? v : 0;
+      }
+
+      function getBrowserInfo() {
+        const userAgent = navigator.userAgent.toLocaleLowerCase();
+        if (userAgent.match(/chrome/) != null) {
+          if (userAgent.match(/wow64/) != null) {
+              return false
+            } else {
+              return true
+            }
+        }
+      }
+      var isChrome = getBrowserInfo()
+      var isCloseBrowser = sessionStorage.getItem('isCloseBrowser')
+      console.log(isChrome, isCloseBrowser)
+      // 如果不是360浏览器会提示
+      if((!isChrome) && !isCloseBrowser) {
+        console.log(document.getElementById('notification_1').className)
+        document.getElementById('notification_1').className = 'el-notification right'
+        // document.getElementById('notification_1').classList.remove('hide')
+        sessionStorage.removeItem('isCloseBrowser')
+      }
+      document.getElementById('noClose').onclick = function() {
+        // document.getElementById('notification_1').classList.add('hide')
+        document.getElementById('notification_1').className = 'el-notification right hide'
+        sessionStorage.setItem('isCloseBrowser', 1)
+      }
+    </script>
     <script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script>
+<<<<<<< HEAD
     <script nomodule id="vite-legacy-polyfill" src="./assets/polyfills-legacy.d7e0e383.js"></script>
     <script nomodule id="vite-legacy-entry" data-src="./assets/index-legacy.f71896e7.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
+=======
+    <script nomodule id="vite-legacy-polyfill" src="./assets/polyfills-legacy.7f3fc881.js"></script>
+    <script nomodule id="vite-legacy-entry" data-src="./assets/index-legacy.61803a48.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
+>>>>>>> master
   </body>
 </html>

+ 193 - 0
index.html

@@ -5,9 +5,202 @@
     <link rel="icon" href="/favicon.ico" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     <title>管乐迷</title>
+    <style>
+      .hide {
+        display: none !important;
+      }
+      .el-notification {
+        display: flex;
+        width: 330px;
+        padding: 14px 26px 14px 13px;
+        border-radius: 8px;
+        box-sizing: border-box;
+        border: 1px solid #ebeef5;
+        position: fixed;
+        background-color: #fff;
+        box-shadow:0 2px 12px 0 rgba(0, 0, 0, 0.1);
+        transition: opacity 0.3s,transform 0.3s,left 0.3s,right 0.3s,top .4s,bottom 0.3s;
+        overflow-wrap: anywhere;
+        overflow: hidden;
+        z-index: 9999;
+        top: 16px;
+        z-index: 2011;
+        right: 16px;
+      }
+      .el-icon {
+        --color: inherit;
+        height: 1em;
+        width: 1em;
+        line-height: 1em;
+        display: inline-flex;
+        justify-content: center;
+        align-items: center;
+        position: relative;
+        fill: currentColor;
+        color: var(--color);
+        font-size: inherit;
+      }
+      .el-notification .el-notification--info {
+          color: #909399;
+      }
+      .el-notification .el-notification__icon {
+          height: 24px;
+          width: 24px;
+          font-size: 24px;
+      }
+      .el-icon svg {
+          height: 1em;
+          width: 1em;
+      }
+
+      .el-notification__group {
+          margin-left: 13px;
+          margin-right: 8px;
+      }
+      .el-notification__title {
+        font-weight: 700;
+        font-size: 16px;
+        line-height: 24px;
+        color: #303133;
+        margin: 0;
+      }
+      .el-notification__content {
+          font-size: 14px;
+          line-height: 24px;
+          margin: 6px 0 0 0;
+          color: #606266;
+          text-align: justify;
+      }
+      .el-notification__content p {
+          margin: 0;
+      }
+      .el-notification .el-notification__closeBtn {
+          position: absolute;
+          top: 18px;
+          right: 15px;
+          cursor: pointer;
+          color: #909399;
+          font-size: 16px;
+      }
+    </style>
   </head>
   <body>
     <div id="app"></div>
     <script type="module" src="/src/main.ts"></script>
+
+    <div id="notification_1" class="el-notification right hide" role="alert" style="top: 16px; z-index: 2011;"><i class="el-icon el-notification__icon el-notification--info"><svg class="icon" width="200" height="200" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" d="M512 64a448 448 0 110 896.064A448 448 0 01512 64zm67.2 275.072c33.28 0 60.288-23.104 60.288-57.344s-27.072-57.344-60.288-57.344c-33.28 0-60.16 23.104-60.16 57.344s26.88 57.344 60.16 57.344zM590.912 699.2c0-6.848 2.368-24.64 1.024-34.752l-52.608 60.544c-10.88 11.456-24.512 19.392-30.912 17.28a12.992 12.992 0 01-8.256-14.72l87.68-276.992c7.168-35.136-12.544-67.2-54.336-71.296-44.096 0-108.992 44.736-148.48 101.504 0 6.784-1.28 23.68.064 33.792l52.544-60.608c10.88-11.328 23.552-19.328 29.952-17.152a12.8 12.8 0 017.808 16.128L388.48 728.576c-10.048 32.256 8.96 63.872 55.04 71.04 67.84 0 107.904-43.648 147.456-100.416z"></path></svg></i><div class="el-notification__group"><h2 class="el-notification__title">提示</h2><div class="el-notification__content"><p>为了保障更好的直播体验,建议使用chrome浏览器</p></div><i id="noClose" class="el-icon el-notification__closeBtn"><svg class="icon" width="200" height="200" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" d="M764.288 214.592L512 466.88 259.712 214.592a31.936 31.936 0 00-45.12 45.12L466.752 512 214.528 764.224a31.936 31.936 0 1045.12 45.184L512 557.184l252.288 252.288a31.936 31.936 0 0045.12-45.12L557.12 512.064l252.288-252.352a31.936 31.936 0 10-45.12-45.184z"></path></svg></i></div></div>
+
+    <script>
+      var win = window;
+      var nav = win.navigator;
+      var doc = win.document;
+      var ieAX = win.ActiveXObject;
+      var ieMode = doc.documentMode;
+      var REG_APPLE = /^Apple/;
+      // var ieVer = _getIeVersion() || ieMode || 0;
+      var isIe = ieAX || ieMode;
+      // var chromiumType = _getChromiumType();
+      /**
+       * 检测 external 是否包含该字段
+       * @param reg 正则
+       * @param type 检测类型,0为键,1为值
+       * @returns {boolean}
+       * @private
+       */
+      function _testExternal(reg, type) {
+          var external = win.external || {};
+
+          for (var i in external) {
+              if (reg.test(type ? external[i] : i)) {
+                  return true;
+              }
+          }
+
+          return false;
+      }
+      /**
+       * 获取 Chromium 内核浏览器类型
+       * @link http://www.adtchrome.com/js/help.js
+       * @link https://ext.chrome.360.cn/webstore
+       * @link https://ext.se.360.cn
+       * @return {String}
+       *         360ee 360极速浏览器
+       *         360se 360安全浏览器
+       *         sougou 搜狗浏览器
+       *         liebao 猎豹浏览器
+       *         chrome 谷歌浏览器
+       *         ''    无法判断
+       * @version 1.0
+       */
+      function _getChromiumType() {
+        if (isIe || typeof win.scrollMaxX !== 'undefined' || REG_APPLE.test(nav.vendor || '')) {
+            return '';
+        }
+
+        var _track = 'track' in document.createElement('track');
+        var webstoreKeysLength = win.chrome && win.chrome.webstore ? Object.keys(win.chrome.webstore).length : 0;
+        console.log(webstoreKeysLength)
+        // 搜狗浏览器
+        if (_testExternal(/^sogou/i, 0)) {
+            return 'sogou';
+        }
+
+        // 猎豹浏览器
+        if (_testExternal(/^liebao/i, 0)) {
+            return 'liebao';
+        }
+
+        // chrome 由于360极速浏览器 内核也是 chrome,所以先判断360极速浏览器
+        if (win.clientInformation && win.clientInformation.permissions) {
+            return 'chrome';
+        }
+
+        if (_track) {
+            // 360极速浏览器
+            // 360安全浏览器
+            return webstoreKeysLength > 1 ? '360ee' : '360se';
+        }
+
+        return '';
+      }
+      // 获得ie浏览器版本
+      function _getIeVersion() {
+          var v = 3,
+              p = document.createElement('p'),
+              all = p.getElementsByTagName('i');
+
+          while (
+              p.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
+                  all[0]);
+
+          return v > 4 ? v : 0;
+      }
+
+      function getBrowserInfo() {
+        const userAgent = navigator.userAgent.toLocaleLowerCase();
+        if (userAgent.match(/chrome/) != null) {
+          if (userAgent.match(/wow64/) != null) {
+              return false
+            } else {
+              return true
+            }
+        }
+      }
+      var isChrome = getBrowserInfo()
+      var isCloseBrowser = sessionStorage.getItem('isCloseBrowser')
+      console.log(isChrome, isCloseBrowser)
+      // 如果不是360浏览器会提示
+      if((!isChrome) && !isCloseBrowser) {
+        console.log(document.getElementById('notification_1').className)
+        document.getElementById('notification_1').className = 'el-notification right'
+        // document.getElementById('notification_1').classList.remove('hide')
+        sessionStorage.removeItem('isCloseBrowser')
+      }
+      document.getElementById('noClose').onclick = function() {
+        // document.getElementById('notification_1').classList.add('hide')
+        document.getElementById('notification_1').className = 'el-notification right hide'
+        sessionStorage.setItem('isCloseBrowser', 1)
+      }
+    </script>
   </body>
 </html>

+ 1 - 0
src/components/live-broadcast/event.ts

@@ -15,6 +15,7 @@ export const LIVE_EVENT_MESSAGE = {
   'RC:Chatroom:Leave': 'Leave',
   'RC:ForcedOffline': 'ForcedOffline',
   'RC:LookerLoginOut': 'LookerLoginOut',
+  'RC:Chatroom:downSeat': 'DownSeat',
 }
 
 export default mitt()

+ 175 - 175
src/components/live-broadcast/index.tsx

@@ -1,175 +1,175 @@
-import { defineComponent, ref } from 'vue'
-import * as RTC from '@rongcloud/plugin-rtc'
-import Header from './header'
-import ActionBar, { state as ActionBarRuntime} from './action-bar'
-import VideoStatus from './video-status'
-import { state } from '/src/state'
-import event, { LIVE_EVENT_MESSAGE } from './event'
-import runtime, * as RuntimeUtils from './runtime'
-import Chronography from './chronography'
-// import { removeMedia } from './helpers'
-import styles from './index.module.less'
-
-const videoRef = ref<HTMLVideoElement | null>(null)
-
-let microphoneAudioTrack: RTC.RCLocalTrack
-let cameraVideoTrack: RTC.RCLocalTrack
-
-export default defineComponent({
-  name: 'LiveBroadcast',
-  data() {
-    return {
-      headerStatus: false
-    }
-  },
-  computed: {
-    isLive() {
-      console.log(runtime.videoStatus)
-      if(runtime.videoStatus === 'liveing') {
-        setTimeout(() => {
-          this.headerStatus = true
-        }, 3000);
-      } else {
-        this.headerStatus = false
-      }
-      return runtime.videoStatus === 'liveing'
-    }
-  },
-  async mounted() {
-    this.initializeRoom()
-    RuntimeUtils.loopSyncLike()
-    event.on(LIVE_EVENT_MESSAGE['RC:Chatroom:Like'], this.onLikeMessage)
-    window.onbeforeunload = this.beforeunload
-  },
-  beforeUnmount() {
-    event.off(LIVE_EVENT_MESSAGE['RC:Chatroom:Like'], this.onLikeMessage)
-    window.onbeforeunload = null
-  },
-  methods: {
-    beforeunload() {
-      if (runtime.videoStatus === 'liveing') {
-        return '当前正在直播中是否确认关闭页面?'
-      }
-    },
-    onLikeMessage(msg: any) {
-      runtime.likeCount += msg.counts
-    },
-    getDeviceByDeviceType(type: RuntimeUtils.TrackType) {
-      const videoDeviceId = localStorage.getItem(RuntimeUtils.VIDEO_DEVICE_ID)
-      const audioDeviceId = localStorage.getItem(RuntimeUtils.AUDIO_DEVICE_ID)
-      if (type === 'camera') {
-        if (videoDeviceId) {
-          return runtime.cameras.find(camera => camera.deviceId === videoDeviceId) || runtime.cameras[0]
-        }
-        return runtime.cameras[0]
-      }
-      if (audioDeviceId) {
-        return runtime.microphones.find(microphone => microphone.deviceId === audioDeviceId) || runtime.microphones[0]
-      }
-      return runtime.microphones[0]
-    },
-    async initializeRoom () {
-      if (!state.user) throw Error('请先登录')
-      try {
-        runtime.likeCount = state.user?.likeNum || 0
-        runtime.lookCount = state.user?.lookNum || 0
-        const isLiveing = sessionStorage.getItem(RuntimeUtils.START_LIVE_STATUS) === 'liveing'
-        // IM连接
-        await RuntimeUtils.connectIM(state.user?.imToken)
-        runtime.videoRef = videoRef.value
-        // 获取设备
-        await RuntimeUtils.getMicrophones()
-        await RuntimeUtils.getCameras()
-        // 设置播放设备
-        RuntimeUtils.setSelectCamera(this.getDeviceByDeviceType('camera'))
-        RuntimeUtils.setSelectMicrophone(this.getDeviceByDeviceType('microphone'))
-        cameraVideoTrack = await RuntimeUtils.getTrack('camera')
-        runtime.videoRef && cameraVideoTrack.play(runtime.videoRef)
-        // await RuntimeUtils.setTrack([cameraVideoTrack], 'camera', isLiveing)
-        // await RuntimeUtils.getTrack('microphone')
-        microphoneAudioTrack = await RuntimeUtils.getTrack('microphone')
-        // microphoneAudioTrack.play()
-        // console.log(microphoneAudioTrack)
-        // console.log(runtime.deviceStatus)
-        runtime.videoStatus = 'stream'
-        const join = await RuntimeUtils.joinRoom(state.user?.roomUid, RTC.RCLivingType.VIDEO, {
-          onMessageReceive(name, content) {
-            console.log(name, content)
-          },
-          onKickOff(byServer: boolean) {
-            console.log(byServer)
-          },
-          async onTrackPublish (tracks: RTC.RCRemoteTrack[]) {
-            const subscribeRes = await join?.room?.subscribe(tracks)
-            console.log(subscribeRes)
-            if (subscribeRes?.code && subscribeRes.code !== RTC.RCRTCCode.SUCCESS) {
-              console.log('资源订阅失败 ->', subscribeRes.code)
-            }
-          },
-          onTrackUnpublish(tracks: RTC.RCRemoteTrack[]) {
-            console.log(tracks)
-            event.emit(LIVE_EVENT_MESSAGE['RM:RTC:TrackUnpublish'], tracks)
-          },
-          onSwitchRole(userId: string, role: RTC.RCRTCLiveRole) {
-            event.emit(LIVE_EVENT_MESSAGE['RM:RTC:SwitchRole'], {
-              userId,
-              role,
-            })
-          },
-          onTrackReady (track: RTC.RCRemoteTrack) {
-            if (track.isAudioTrack()) {
-              // 音轨不需要传递播放控件
-              track.play()
-            }
-          },
-          onUserJoin (userIds: string[]) {
-            console.log('onUserJoin', userIds)
-          },
-          onUserLeave (userIds: string[]) {
-            event.emit(LIVE_EVENT_MESSAGE['RM:RTC:UserLeave'], userIds)
-            console.log('onUserLeave', userIds)
-          },
-        })
-        if (join.room && join.code === RTC.RCRTCCode.SUCCESS) {
-          runtime.joinedRoom = join.room
-        }
-        if (isLiveing) {
-          await RuntimeUtils.startLive(false)
-          runtime.videoStatus = 'liveing'
-        } else {
-          await RuntimeUtils.setTrack([cameraVideoTrack], 'camera', false)
-          await RuntimeUtils.setTrack([microphoneAudioTrack], 'microphone', false)
-        }
-        const volume =localStorage.getItem(RuntimeUtils.AUDIO_DEVICE_VOLUME)
-        if (volume) {
-          ActionBarRuntime.volume = parseInt(volume)
-          RuntimeUtils.setVolume(parseInt(volume))
-        }
-      } catch (error) {
-        runtime.videoStatus = 'error'
-        console.log(error)
-      }
-    },
-    closeLive() {
-      // removeMedia(runtime.mediaStreams, runtime.mediaStreamTrack)
-      runtime.videoStatus = 'stream'
-    }
-  },
-  render() {
-    return (
-      <div class={styles.main}>
-        {this.isLive ? null : null}
-        <div class={[styles.headerSection]}>
-          <Header class={[styles.headerContent, this.headerStatus ? styles["header-top"] : null]} />
-        </div>
-        <div class={styles.video}>
-          <video ref={videoRef}></video>
-          {!runtime.screenShareStatus ? <VideoStatus/> : null}
-          {runtime.videoStatus === 'liveing' ? <Chronography/> : null}
-        </div>
-        <ActionBar/>
-        {/* <div>video: {runtime.videoStatus}, imStatus: {runtime.imConnectStatus}</div> */}
-      </div>
-    )
-  }
-})
+import { defineComponent, ref } from 'vue'
+import * as RTC from '@rongcloud/plugin-rtc'
+import Header from './header'
+import ActionBar, { state as ActionBarRuntime} from './action-bar'
+import VideoStatus from './video-status'
+import { state } from '/src/state'
+import event, { LIVE_EVENT_MESSAGE } from './event'
+import runtime, * as RuntimeUtils from './runtime'
+import Chronography from './chronography'
+// import { removeMedia } from './helpers'
+import styles from './index.module.less'
+
+const videoRef = ref<HTMLVideoElement | null>(null)
+
+let microphoneAudioTrack: RTC.RCLocalTrack
+let cameraVideoTrack: RTC.RCLocalTrack
+
+export default defineComponent({
+  name: 'LiveBroadcast',
+  data() {
+    return {
+      headerStatus: false
+    }
+  },
+  computed: {
+    isLive() {
+      console.log(runtime.videoStatus)
+      if(runtime.videoStatus === 'liveing') {
+        setTimeout(() => {
+          this.headerStatus = true
+        }, 3000);
+      } else {
+        this.headerStatus = false
+      }
+      return runtime.videoStatus === 'liveing'
+    }
+  },
+  async mounted() {
+    this.initializeRoom()
+    RuntimeUtils.loopSyncLike()
+    event.on(LIVE_EVENT_MESSAGE['RC:Chatroom:Like'], this.onLikeMessage)
+    window.onbeforeunload = this.beforeunload
+  },
+  beforeUnmount() {
+    event.off(LIVE_EVENT_MESSAGE['RC:Chatroom:Like'], this.onLikeMessage)
+    window.onbeforeunload = null
+  },
+  methods: {
+    beforeunload() {
+      if (runtime.videoStatus === 'liveing') {
+        return '当前正在直播中是否确认关闭页面?'
+      }
+    },
+    onLikeMessage(msg: any) {
+      runtime.likeCount += msg.counts
+    },
+    getDeviceByDeviceType(type: RuntimeUtils.TrackType) {
+      const videoDeviceId = localStorage.getItem(RuntimeUtils.VIDEO_DEVICE_ID)
+      const audioDeviceId = localStorage.getItem(RuntimeUtils.AUDIO_DEVICE_ID)
+      if (type === 'camera') {
+        if (videoDeviceId) {
+          return runtime.cameras.find(camera => camera.deviceId === videoDeviceId) || runtime.cameras[0]
+        }
+        return runtime.cameras[0]
+      }
+      if (audioDeviceId) {
+        return runtime.microphones.find(microphone => microphone.deviceId === audioDeviceId) || runtime.microphones[0]
+      }
+      return runtime.microphones[0]
+    },
+    async initializeRoom () {
+      if (!state.user) throw Error('请先登录')
+      try {
+        runtime.likeCount = state.user?.likeNum || 0
+        runtime.lookCount = state.user?.lookNum || 0
+        const isLiveing = sessionStorage.getItem(RuntimeUtils.START_LIVE_STATUS) === 'liveing'
+        // IM连接
+        await RuntimeUtils.connectIM(state.user?.imToken)
+        runtime.videoRef = videoRef.value
+        // 获取设备
+        await RuntimeUtils.getMicrophones()
+        await RuntimeUtils.getCameras()
+        // 设置播放设备
+        RuntimeUtils.setSelectCamera(this.getDeviceByDeviceType('camera'))
+        RuntimeUtils.setSelectMicrophone(this.getDeviceByDeviceType('microphone'))
+        cameraVideoTrack = await RuntimeUtils.getTrack('camera')
+        runtime.videoRef && cameraVideoTrack.play(runtime.videoRef)
+        // await RuntimeUtils.setTrack([cameraVideoTrack], 'camera', isLiveing)
+        // await RuntimeUtils.getTrack('microphone')
+        microphoneAudioTrack = await RuntimeUtils.getTrack('microphone')
+        // microphoneAudioTrack.play()
+        // console.log(microphoneAudioTrack)
+        // console.log(runtime.deviceStatus)
+        runtime.videoStatus = 'stream'
+        const join = await RuntimeUtils.joinRoom(state.user?.roomUid, RTC.RCLivingType.VIDEO, {
+          onMessageReceive(name, content) {
+            console.log(name, content)
+          },
+          onKickOff(byServer: boolean) {
+            console.log(byServer)
+          },
+          async onTrackPublish (tracks: RTC.RCRemoteTrack[]) {
+            const subscribeRes = await join?.room?.subscribe(tracks)
+            console.log(subscribeRes)
+            if (subscribeRes?.code && subscribeRes.code !== RTC.RCRTCCode.SUCCESS) {
+              console.log('资源订阅失败 ->', subscribeRes.code)
+            }
+          },
+          onTrackUnpublish(tracks: RTC.RCRemoteTrack[]) {
+            console.log(tracks)
+            event.emit(LIVE_EVENT_MESSAGE['RM:RTC:TrackUnpublish'], tracks)
+          },
+          onSwitchRole(userId: string, role: RTC.RCRTCLiveRole) {
+            event.emit(LIVE_EVENT_MESSAGE['RM:RTC:SwitchRole'], {
+              userId,
+              role,
+            })
+          },
+          onTrackReady (track: RTC.RCRemoteTrack) {
+            if (track.isAudioTrack()) {
+              // 音轨不需要传递播放控件
+              track.play()
+            }
+          },
+          onUserJoin (userIds: string[]) {
+            console.log('onUserJoin', userIds)
+          },
+          onUserLeave (userIds: string[]) {
+            event.emit(LIVE_EVENT_MESSAGE['RM:RTC:UserLeave'], userIds)
+            console.log('onUserLeave', userIds)
+          },
+        })
+        if (join.room && join.code === RTC.RCRTCCode.SUCCESS) {
+          runtime.joinedRoom = join.room
+        }
+        if (isLiveing) {
+          await RuntimeUtils.startLive(false)
+          runtime.videoStatus = 'liveing'
+        } else {
+          await RuntimeUtils.setTrack([cameraVideoTrack], 'camera', false)
+          await RuntimeUtils.setTrack([microphoneAudioTrack], 'microphone', false)
+        }
+        const volume =localStorage.getItem(RuntimeUtils.AUDIO_DEVICE_VOLUME)
+        if (volume) {
+          ActionBarRuntime.volume = parseInt(volume)
+          RuntimeUtils.setVolume(parseInt(volume))
+        }
+      } catch (error) {
+        runtime.videoStatus = 'error'
+        console.log(error)
+      }
+    },
+    closeLive() {
+      // removeMedia(runtime.mediaStreams, runtime.mediaStreamTrack)
+      runtime.videoStatus = 'stream'
+    }
+  },
+  render() {
+    return (
+      <div class={styles.main}>
+        {this.isLive ? null : null}
+        <div class={[styles.headerSection]}>
+          <Header class={[styles.headerContent, this.headerStatus ? styles["header-top"] : null]} />
+        </div>
+        <div class={styles.video}>
+          <video ref={videoRef}></video>
+          {!runtime.screenShareStatus ? <VideoStatus/> : null}
+          {runtime.videoStatus === 'liveing' ? <Chronography/> : null}
+        </div>
+        <ActionBar/>
+        {/* <div>video: {runtime.videoStatus}, imStatus: {runtime.imConnectStatus}</div> */}
+      </div>
+    )
+  }
+})

+ 17 - 5
src/components/live-broadcast/runtime.ts

@@ -76,7 +76,8 @@ const runtime = reactive({
     microphone: 'init',
     camera: 'init',
     screen: 'init'
-  } as DeviceStatus
+  } as DeviceStatus,
+  syncLikeTimer: null as any
 })
 
 export default runtime
@@ -109,6 +110,9 @@ const MessageMemberCount = RongIMLib.registerMessageType('RC:Chatroom:MemberCoun
 // 当前连麦人员同步
 const MessageSeatMember = RongIMLib.registerMessageType('RC:Chatroom:SeatMember', true, true)
 
+// 当前点赞数量同步
+const MessageLikeCount = RongIMLib.registerMessageType('RC:Chatroom:LikeCount', true, true)
+
 
 type MessageProps = {
   messageType: 'RC:Chatroom:Welcome' | 'RC:TxtMsg' | 'RC:Chatroom:Barrage' | 'RC:Chatroom:Like' | 'RC:Chatroom:SeatsCtrl' | 'RC:Chatroom:ChatBan' | 'RC:Chatroom:SeatApply',
@@ -511,7 +515,8 @@ export const closeLive = async (remove = false) => {
  * 同步点赞数量
  */
 export const loopSyncLike = async () => {
-  if ((runtime.likeCount !== runtime.lastLikeCount || runtime.likeCount === 0) && state.user) {
+  // (runtime.likeCount !== runtime.lastLikeCount || runtime.likeCount === 0) &&
+  if (state.user) {
     try {
       await request.get('/api-web/imLiveBroadcastRoom/syncLike', {
         hideLoading: true,
@@ -522,14 +527,15 @@ export const loopSyncLike = async () => {
         }
       })
       runtime.lastLikeCount = runtime.likeCount
+      sendMessage({ count: runtime.likeCount }, 'LikeCount')
     } catch (error) {}
   }
-  setTimeout(() => {
+  runtime.syncLikeTimer = setTimeout(() => {
     loopSyncLike()
-  }, 1000 * 30)
+  }, 1000 * 10)
 }
 
-type SendMessageType = 'text' | 'image' | 'audio' | 'video' | 'file' | 'SeatsCtrl' | 'ChatBan' | 'SeatApply' | 'SeatResponse' | 'MemberCount' | 'SeatMember'
+type SendMessageType = 'text' | 'image' | 'audio' | 'video' | 'file' | 'SeatsCtrl' | 'ChatBan' | 'SeatApply' | 'SeatResponse' | 'MemberCount' | 'SeatMember' | 'LikeCount'
 
 export const getSendMessageUser = () => {
   return {
@@ -570,6 +576,8 @@ export const sendMessage = async (msg: any, type: SendMessageType = 'text') => {
     message = new MessageMemberCount(msg)
   } else if(type === 'SeatMember') {
     message = new MessageSeatMember(msg)
+  } else if(type === 'LikeCount') {
+    message = new MessageLikeCount(msg)
   }
   if (!message) return
   console.log(message)
@@ -621,6 +629,10 @@ export const toggleDevice = async (trackType: TrackType) => {
 
 export const leaveIMRoom = async () => {
   await closeLive(true)
+  leaveIMRoomAndClear()
+}
+
+export const leaveIMRoomAndClear = async () => {
   if (runtime.joinedRoom) {
     // @ts-ignore
     await runtime.rtcClient?.leaveRoom(runtime.joinedRoom)

+ 14 - 8
src/components/live-message/model/join-model.tsx

@@ -43,6 +43,7 @@ export default defineComponent({
     event.on(LIVE_EVENT_MESSAGE['RC:Chatroom:SeatApply'], this.onSeatApply);
     event.on(LIVE_EVENT_MESSAGE['RC:Chatroom:SeatResponse'], this.onSeatApply);
     event.on(LIVE_EVENT_MESSAGE['RM:RTC:UserLeave'], this.onSeatApply);
+    event.on(LIVE_EVENT_MESSAGE['RC:Chatroom:downSeat'], this.onDownSeat);
     event.on(LIVE_EVENT_MESSAGE['RM:RTC:SwitchRole'], this.onSwitchRole);
     event.on(LIVE_EVENT_MESSAGE['RC:Chatroom:Leave'], this.onLeave); // 移动端接收的消息
     event.on(LIVE_EVENT_MESSAGE['RC:LookerLoginOut'], this.onLeave); // 后台接收的消息
@@ -170,24 +171,29 @@ export default defineComponent({
         this.downStatus = false
       }, 300);
     },
-    onSwitchRole(evt: any) {
-      console.log(evt, 'onSwitchRole')
-      if (runtimeModel.joinList[evt.userId] && evt.role === 2) {
-        const user = runtimeModel.joinList[evt.userId]
+    onDownSeat(evt: any) {
+      console.log(evt, 'onDownSeat')
+      if (runtimeModel.joinList[evt.audienceId]) {
+        const users = runtimeModel.joinList[evt.audienceId]
         const sendTime = dayjs(new Date()).format('HH:mm:ss')
+        console.log(evt.$EventMessage.senderUserId, state.user?.speakerId, 'onDownSeat')
+        let message = users.type == 5 ? '被报下麦' : '取消了连麦申请'
         let tempObj = {
-          name: user.audienceName,
-          id: user.audienceId,
+          name: evt.audienceName,
+          id: evt.audienceId,
           system: 1,
           isSelf: false,
-          content: '发起了连麦申请',
+          content: message,
           sendTime
         }
         RuntimeModelUtils.addMessage(tempObj);
         event.emit('MESSAGE:Change')
 
-        RuntimeModelUtils.removeJoin(evt.userId)
+        RuntimeModelUtils.removeJoin(evt.audienceId)
       }
+    },
+    onSwitchRole(evt: any) {
+      console.log(evt, 'onSwitchRole')
       if (runtimeModel.lookList[evt.userId] && evt.role === 2) {
         let userLook = runtimeModel.lookList[evt.userId]
         userLook.userRoomType = 1

+ 1 - 0
src/components/live-message/model/message-model.tsx

@@ -43,6 +43,7 @@ export default defineComponent({
         await request.post('/api-auth/exit', { data: {} });
         RuntimeUtilCast.closeDevice('camera')
         RuntimeUtilCast.closeDevice('microphone')
+        runtimeCast.syncLikeTimer && clearTimeout(runtimeCast.syncLikeTimer)
         state.user = null
         removeToken();
         (this as any).$router.push({

+ 107 - 98
src/helpers/request.ts

@@ -1,98 +1,107 @@
-import { getToken, removeToken } from './../utils/auth';
-import { extend } from 'umi-request'
-import { ElMessage } from 'element-plus'
-import cleanDeep from 'clean-deep'
-import router from '../router';
-import { showLoading, hideLoading } from '../utils/loading'
-// import { setLogout } from 'src/actions/users'
-// import store from 'src/store'
-
-export interface SearchInitParams {
-  rows?: string | number;
-  page?: string | number;
-}
-
-export interface InitSearchRespones {
-  data: {
-    rows: any[],
-    [key: string]: any
-  },
-  [key: string]: any
-}
-
-const request = extend({
-  requestType: 'form',
-  timeout: 10000
-})
-
-request.interceptors.request.use((url, options: any) => {
-  let hideLoading = options.hideLoading || false
-  if(!hideLoading) {
-    showLoading()
-  }
-  const Authorization = getToken()
-  const tenantId = (localStorage.getItem('tenantId') || '')
-  const organId = (localStorage.getItem('organId') || '')
-  const authHeaders: any = {}
-  if (Authorization && !['/api-auth/usernameLogin', '/api-auth/smsLogin', '/api-auth/code/sendSms'].includes(url)) {
-    authHeaders.Authorization = Authorization
-  }
-  if (tenantId) {
-    authHeaders.tenantId = tenantId
-  }
-  if (organId) {
-    authHeaders.organId = organId
-  }
-  return {
-    url,
-    options: {
-      ...options,
-      params: cleanDeep(options.params),
-      headers: {
-        ...options.headers,
-        ...authHeaders
-      }
-    }
-  }
-})
-
-request.interceptors.response.use(async (res, options) => {
-  setTimeout(() => {
-    hideLoading()
-  }, 200)
-  let hideMessage = options.hideMessage || false
-  const url = new URL(res.url)
-  if (res.status > 299 || res.status < 200) {
-    const msg = '服务器错误,状态码' + res.status
-    if (!hideMessage) {
-      ElMessage.error(msg)
-    }
-    throw new Error(msg)
-  }
-  const data = await res.clone().json()
-  if (data.code !== 200 && data.errCode !== 0) {
-    const msg = data.msg || '处理失败,请重试'
-    if(data.code === 401 || data.code === 403) {
-      if(!hideMessage) {
-        ElMessage.error(`登录过期,请重新登录!`)
-      }
-      removeToken()
-      router.push(`/login`)
-    }
-    if(data.code === 404) {
-      if(!hideMessage) {
-        ElMessage.error(`请求资源不存在!`)
-      }
-      router.push('/404')
-    }
-    if (!(data.code === 403 || data.code === 401)) {
-      if (!hideMessage) {
-        ElMessage.error(msg)
-      }
-    }
-    throw new Error(msg)
-  }
-  return res
-})
-
-export default request
+import { getToken, removeToken } from './../utils/auth';
+import { extend } from 'umi-request'
+import { ElMessage } from 'element-plus'
+import cleanDeep from 'clean-deep'
+import router from '../router';
+import { showLoading, hideLoading } from '../utils/loading'
+import runtime, * as RuntimeUtils from '../components/live-broadcast/runtime';
+import { state } from '../state';
+// import { setLogout } from 'src/actions/users'
+// import store from 'src/store'
+
+export interface SearchInitParams {
+  rows?: string | number;
+  page?: string | number;
+}
+
+export interface InitSearchRespones {
+  data: {
+    rows: any[],
+    [key: string]: any
+  },
+  [key: string]: any
+}
+
+const request = extend({
+  requestType: 'form',
+  timeout: 10000
+})
+
+request.interceptors.request.use((url, options: any) => {
+  let hideLoading = options.hideLoading || false
+  if(!hideLoading) {
+    showLoading()
+  }
+  const Authorization = getToken()
+  const tenantId = (localStorage.getItem('tenantId') || '')
+  const organId = (localStorage.getItem('organId') || '')
+  const authHeaders: any = {}
+  if (Authorization && !['/api-auth/usernameLogin', '/api-auth/smsLogin', '/api-auth/code/sendSms'].includes(url)) {
+    authHeaders.Authorization = Authorization
+  }
+  if (tenantId) {
+    authHeaders.tenantId = tenantId
+  }
+  if (organId) {
+    authHeaders.organId = organId
+  }
+  return {
+    url,
+    options: {
+      ...options,
+      params: cleanDeep(options.params),
+      headers: {
+        ...options.headers,
+        ...authHeaders
+      }
+    }
+  }
+})
+
+request.interceptors.response.use(async (res, options) => {
+  setTimeout(() => {
+    hideLoading()
+  }, 200)
+  let hideMessage = options.hideMessage || false
+  const url = new URL(res.url)
+  if (res.status > 299 || res.status < 200) {
+    const msg = '服务器错误,状态码' + res.status
+    if (!hideMessage) {
+      ElMessage.error(msg)
+    }
+    throw new Error(msg)
+  }
+  const data = await res.clone().json()
+  if (data.code !== 200 && data.errCode !== 0) {
+    const msg = data.msg || '处理失败,请重试'
+    if(data.code === 401 || data.code === 403) {
+      if(!hideMessage) {
+        ElMessage.error(`登录过期,请重新登录!`)
+      }
+      try {
+        await RuntimeUtils.leaveIMRoomAndClear()
+        RuntimeUtils.closeDevice('camera')
+        RuntimeUtils.closeDevice('microphone')
+        state.user = null
+      } catch {}
+      runtime.syncLikeTimer && clearTimeout(runtime.syncLikeTimer)
+      removeToken()
+      router.push(`/login`)
+    }
+    if(data.code === 404) {
+      if(!hideMessage) {
+        ElMessage.error(`请求资源不存在!`)
+      }
+      router.push('/404')
+    }
+    if (!(data.code === 403 || data.code === 401)) {
+      if (!hideMessage) {
+        ElMessage.error(msg)
+      }
+    }
+    throw new Error(msg)
+  }
+  return res
+})
+
+export default request

+ 66 - 65
src/pages/home/header/index.tsx

@@ -1,65 +1,66 @@
-import { defineComponent } from "vue";
-import { ElDropdownMenu, ElDropdown, ElDropdownItem, ElMessage } from "element-plus";
-import router from "/src/router";
-import styles from './index.module.less';
-import request from '/src/helpers/request';
-import runtime, * as RuntimeUtils from "/src/components/live-broadcast/runtime";
-import { removeToken } from "/src/utils/auth";
-import { removeMedia } from '/src/components/live-broadcast/helpers'
-import { state } from '/src/state'
-import userLogo from '/src/assets/home/placehorder-icon.png'
-
-export default defineComponent({
-  methods: {
-    async loginOut() {
-      try {
-        await RuntimeUtils.leaveIMRoom()
-        await request.post('/api-auth/exit', { data: {} });
-        RuntimeUtils.closeDevice('camera')
-        RuntimeUtils.closeDevice('microphone')
-        state.user = null
-        ElMessage.success('退出成功');
-        removeToken();
-        (this as any).$router.push({
-          path: '/login',
-          query: {
-            ...this.$route.query
-          }
-        });
-      } catch(e) {
-        // TODO: handle error
-      }
-    }
-  },
-  render() {
-    return (
-      <div class={styles.liveHeader}>
-        <div class={styles.liveHeaderLeft}>
-          <div class={styles.liveHeaderLeftIcon}>
-            <img class={styles.liveLogo} src={state.user?.tenantLogo} alt=""/>
-            {state.user?.tenantName}
-          </div>
-          <div class={styles.liveHeaderLeftText}>
-            《{state.user?.roomTitle}》
-          </div>
-        </div>
-        <ElDropdown trigger={'hover'}
-          // @ts-ignore
-          vSlots={{
-            dropdown: () => (
-              <ElDropdownMenu>
-                <ElDropdownItem command="1" onClick={this.loginOut}>
-                  <span>安全退出</span>
-                </ElDropdownItem>
-              </ElDropdownMenu>
-            )
-          }}>
-          <div class={styles.avatarWrapper}>
-            {state.user?.speakerPic ? <img class={styles.userAvatar} src={state.user?.speakerPic} /> : <img class={styles.userAvatar} src={userLogo} />}
-            <span>{ state.user?.speakerName }</span>
-          </div>
-        </ElDropdown>
-      </div>
-    )
-  }
-})
+import { defineComponent } from "vue";
+import { ElDropdownMenu, ElDropdown, ElDropdownItem, ElMessage } from "element-plus";
+import router from "/src/router";
+import styles from './index.module.less';
+import request from '/src/helpers/request';
+import runtime, * as RuntimeUtils from "/src/components/live-broadcast/runtime";
+import { removeToken } from "/src/utils/auth";
+import { removeMedia } from '/src/components/live-broadcast/helpers'
+import { state } from '/src/state'
+import userLogo from '/src/assets/home/placehorder-icon.png'
+
+export default defineComponent({
+  methods: {
+    async loginOut() {
+      try {
+        await RuntimeUtils.leaveIMRoom()
+        await request.post('/api-auth/exit', { data: {} });
+        RuntimeUtils.closeDevice('camera')
+        RuntimeUtils.closeDevice('microphone')
+        state.user = null
+        runtime.syncLikeTimer && clearTimeout(runtime.syncLikeTimer)
+        ElMessage.success('退出成功');
+        removeToken();
+        (this as any).$router.push({
+          path: '/login',
+          query: {
+            ...this.$route.query
+          }
+        });
+      } catch(e) {
+        // TODO: handle error
+      }
+    }
+  },
+  render() {
+    return (
+      <div class={styles.liveHeader}>
+        <div class={styles.liveHeaderLeft}>
+          <div class={styles.liveHeaderLeftIcon}>
+            <img class={styles.liveLogo} src={state.user?.tenantLogo} alt=""/>
+            {state.user?.tenantName}
+          </div>
+          <div class={styles.liveHeaderLeftText}>
+            《{state.user?.roomTitle}》
+          </div>
+        </div>
+        <ElDropdown trigger={'hover'}
+          // @ts-ignore
+          vSlots={{
+            dropdown: () => (
+              <ElDropdownMenu>
+                <ElDropdownItem command="1" onClick={this.loginOut}>
+                  <span>安全退出</span>
+                </ElDropdownItem>
+              </ElDropdownMenu>
+            )
+          }}>
+          <div class={styles.avatarWrapper}>
+            {state.user?.speakerPic ? <img class={styles.userAvatar} src={state.user?.speakerPic} /> : <img class={styles.userAvatar} src={userLogo} />}
+            <span>{ state.user?.speakerName }</span>
+          </div>
+        </ElDropdown>
+      </div>
+    )
+  }
+})

+ 2 - 1
src/pages/login/index.tsx

@@ -5,6 +5,7 @@ import request from "/src/helpers/request";
 import { removeToken, setToken } from "/src/utils/auth";
 import LogoPng from '././../../assets/home/logo.png'
 import FromBg from './images/from-bg.png'
+import qs from 'query-string'
 
 
 export default defineComponent({
@@ -113,7 +114,7 @@ export default defineComponent({
             sessionStorage.setItem('details',JSON.stringify(details.data))
             ElMessage.success('登录成功')
             // this.$router.push(this.redirect || '/')
-            window.location.href = window.location.origin + '/live/?roomUid=' + roomUid + '&time=' + new Date().getTime()
+            window.location.href = window.location.origin + '/live/?' + qs.stringify({ roomUid: roomUid, time: new Date().getTime() })
           } catch (error) {
             // console.log(error)
             removeToken()

+ 1 - 0
vite.config.ts

@@ -69,6 +69,7 @@ export default defineConfig({
     // })
   ],
   server: {
+    host: '0.0.0.0',
     cors: true,
     proxy: {
       '/api-im': {

部分文件因为文件数量过多而无法显示