浏览代码

更新打包

lex-xin 3 年之前
父节点
当前提交
66b77b72e6

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


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


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


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


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


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


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


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


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


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


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


+ 5 - 0
dist/assets/index.48a3b026.js

@@ -0,0 +1,5 @@
+<<<<<<< HEAD:dist/assets/index.d262b432.js
+import{d as i,a as s,l as t}from"./vendor.3c30bec5.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 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};
+>>>>>>> master:dist/assets/index.48a3b026.js

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


+ 4 - 0
dist/assets/index.d262b432.js

@@ -1 +1,5 @@
+<<<<<<< HEAD:dist/assets/index.d262b432.js
 import{d as i,a as s,l as t}from"./vendor.3c30bec5.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 s,l as t}from"./vendor.3c30bec5.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 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};
+>>>>>>> master:dist/assets/index.48a3b026.js

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


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


+ 9 - 0
dist/index.html

@@ -5,8 +5,13 @@
     <link rel="icon" href="./favicon.ico" />
     <link rel="icon" href="./favicon.ico" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     <title>管乐迷</title>
     <title>管乐迷</title>
+<<<<<<< HEAD
     <script type="module" crossorigin src="./assets/index.2ce46a24.js"></script>
     <script type="module" crossorigin src="./assets/index.2ce46a24.js"></script>
     <link rel="modulepreload" href="./assets/vendor.3c30bec5.js">
     <link rel="modulepreload" href="./assets/vendor.3c30bec5.js">
+=======
+    <script type="module" crossorigin src="./assets/index.a7165fd2.js"></script>
+    <link rel="modulepreload" href="./assets/vendor.9c266e46.js">
+>>>>>>> master
     <link rel="stylesheet" href="./assets/index.fb6968e4.css">
     <link rel="stylesheet" href="./assets/index.fb6968e4.css">
     <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>
     <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>
   </head>
@@ -15,6 +20,10 @@
     
     
     <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>
     <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>
     <script nomodule id="vite-legacy-polyfill" src="./assets/polyfills-legacy.d7e0e383.js"></script>
     <script nomodule id="vite-legacy-polyfill" src="./assets/polyfills-legacy.d7e0e383.js"></script>
+<<<<<<< HEAD
     <script nomodule id="vite-legacy-entry" data-src="./assets/index-legacy.32a54bb0.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
     <script nomodule id="vite-legacy-entry" data-src="./assets/index-legacy.32a54bb0.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
+=======
+    <script nomodule id="vite-legacy-entry" data-src="./assets/index-legacy.ee1451fc.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
+>>>>>>> master
   </body>
   </body>
 </html>
 </html>

+ 44 - 44
package.json

@@ -1,44 +1,44 @@
-{
-  "name": "dy-admin-live",
-  "private": true,
-  "version": "0.0.0",
-  "scripts": {
-    "dev": "vite",
-    "build": "vue-tsc --noEmit --skipLibCheck && vite build",
-    "preview": "vite preview",
-    "previews": "npx http-server ./dist -P https://test.dayaedu.com"
-  },
-  "dependencies": {
-    "@rongcloud/imlib-next": "^5.1.1",
-    "@rongcloud/plugin-rtc": "^5.3.1",
-    "@types/qrcode": "^1.4.2",
-    "clean-deep": "^3.4.0",
-    "clipboard": "^2.0.10",
-    "dayjs": "^1.10.7",
-    "element-plus": "^2.0.2",
-    "html-to-image": "^1.9.0",
-    "js-cookie": "^3.0.1",
-    "loaders.css": "^0.1.2",
-    "mitt": "^3.0.0",
-    "nprogress": "^0.2.0",
-    "qrcode": "^1.5.0",
-    "query-string": "^7.1.1",
-    "umi-request": "^1.4.0",
-    "vue": "^3.2.25",
-    "vue-router": "^4.0.12"
-  },
-  "devDependencies": {
-    "@types/js-cookie": "^3.0.1",
-    "@types/node": "^17.0.17",
-    "@types/webpack-env": "^1.16.3",
-    "@vitejs/plugin-legacy": "^1.7.1",
-    "@vitejs/plugin-vue": "^2.2.0",
-    "@vitejs/plugin-vue-jsx": "^1.3.7",
-    "less": "^4.1.2",
-    "typescript": "^4.5.4",
-    "vite": "^2.8.0",
-    "vite-plugin-pwa": "^0.11.13",
-    "vite-plugin-svg-icons": "^2.0.1",
-    "vue-tsc": "^0.29.8"
-  }
-}
+{
+  "name": "dy-admin-live",
+  "private": true,
+  "version": "0.0.0",
+  "scripts": {
+    "dev": "vite",
+    "build": "vue-tsc --noEmit --skipLibCheck && vite build",
+    "preview": "vite preview",
+    "previews": "npx http-server ./dist -P https://test.dayaedu.com"
+  },
+  "dependencies": {
+    "@rongcloud/imlib-next": "^5.1.1",
+    "@rongcloud/plugin-rtc": "^5.3.1",
+    "@types/qrcode": "^1.4.2",
+    "clean-deep": "^3.4.0",
+    "clipboard": "^2.0.10",
+    "dayjs": "^1.10.7",
+    "element-plus": "^2.0.2",
+    "html-to-image": "^1.9.0",
+    "js-cookie": "^3.0.1",
+    "loaders.css": "^0.1.2",
+    "mitt": "^3.0.0",
+    "nprogress": "^0.2.0",
+    "qrcode": "^1.5.0",
+    "query-string": "^7.1.1",
+    "umi-request": "^1.4.0",
+    "vue": "^3.2.25",
+    "vue-router": "^4.0.12"
+  },
+  "devDependencies": {
+    "@types/js-cookie": "^3.0.1",
+    "@types/node": "^17.0.17",
+    "@types/webpack-env": "^1.16.3",
+    "@vitejs/plugin-legacy": "^1.7.1",
+    "@vitejs/plugin-vue": "^2.2.0",
+    "@vitejs/plugin-vue-jsx": "^1.3.7",
+    "less": "^4.1.2",
+    "typescript": "^4.5.4",
+    "vite": "^2.8.0",
+    "vite-plugin-pwa": "^0.11.13",
+    "vite-plugin-svg-icons": "^2.0.1",
+    "vue-tsc": "^0.29.8"
+  }
+}

+ 7 - 4
src/components/live-broadcast/action-bar.tsx

@@ -51,8 +51,11 @@ export default defineComponent({
             <div class={styles.btnInner}>
             <div class={styles.btnInner}>
               <SvgIcon
               <SvgIcon
                 onClick={() => {
                 onClick={() => {
-                  state.barStatus.camera = !state.barStatus.camera
                   RuntimeUtils.toggleDevice('camera')
                   RuntimeUtils.toggleDevice('camera')
+                  if (runtime.screenShareStatus) {
+                    return
+                  }
+                  state.barStatus.camera = !state.barStatus.camera
                 }}
                 }}
                 name={this.isCameraDisabled ? 'bar-camera-disabled' : 'bar-camera'}
                 name={this.isCameraDisabled ? 'bar-camera-disabled' : 'bar-camera'}
                 style={{
                 style={{
@@ -130,17 +133,17 @@ export default defineComponent({
             <span class={styles['bar-btn-text']}>音量调节</span>
             <span class={styles['bar-btn-text']}>音量调节</span>
           </div> */}
           </div> */}
 
 
-          <div class={styles['bar-btn']} onClick={RuntimeUtils.shareScreenVideo}>
+          <div class={styles['bar-btn']} onClick={RuntimeUtils.toggleShareScreenVideo}>
             <div class={styles.btnInner}>
             <div class={styles.btnInner}>
               <SvgIcon
               <SvgIcon
-                name="bar-screen-share"
+                name={runtime.videoStatus === 'liveing' ? 'bar-screen-share' : 'bar-screen-share-disabled2'}
                 style={{
                 style={{
                   width: '22px',
                   width: '22px',
                   cursor: 'pointer'
                   cursor: 'pointer'
                 }}
                 }}
               />
               />
             </div>
             </div>
-            <span class={styles['bar-btn-text']}>屏幕共享</span>
+            <span class={styles['bar-btn-text']}>{runtime.screenShareStatus ? '取消共享' : '屏幕共享'}</span>
           </div>
           </div>
 
 
           {/* <div class={styles['bar-btn']} >
           {/* <div class={styles['bar-btn']} >

+ 84 - 84
src/components/live-broadcast/header.tsx

@@ -1,84 +1,84 @@
-import { defineComponent } from 'vue'
-import { ElButton, ElMessage, ElMessageBox } from 'element-plus'
-import runtime, * as RuntimeUtils from './runtime'
-import { state } from '/src/state'
-import request from '/src/helpers/request'
-import styles from './header.module.less'
-import { removeToken } from '/src/utils/auth'
-
-export default defineComponent({
-  name: 'LiveBroadcastHeader',
-  methods: {
-    async startLive() {
-      try {
-        await ElMessageBox.confirm('开启后学生将看到视频画面', '提示', {
-          confirmButtonText: '确定',
-          cancelButtonText: '取消',
-          type: 'warning',
-        })
-        await RuntimeUtils.startLive()
-        ElMessage.success('开启成功')
-      } catch (error) {
-        console.log(error)
-      }
-    },
-    async closeLive() {
-      try {
-        await ElMessageBox.confirm('关闭后将切断视频,学生不可观看', '提示', {
-          confirmButtonText: '确定',
-          cancelButtonText: '取消',
-          type: 'warning',
-        })
-        // await request.post('/api-im/user/statusImUser', {
-        //   data: {
-        //     os: 'PC',
-        //     status: '3',
-        //     userId: state.user?.speakerId
-        //   }
-        // })
-        await RuntimeUtils.closeLive()
-        ElMessage.success('关闭成功')
-      } catch (error) {
-      }
-    },
-    async closeRoom() {
-      try {
-        await ElMessageBox.confirm('结束后将无法进入直播间', '提示', {
-          confirmButtonText: '确定',
-          cancelButtonText: '取消',
-          type: 'warning',
-        })
-        // 异步获取用户信息
-        const id = state.user?.id
-        await request.get('/api-web/imLiveBroadcastRoom/roomDestroy/' + id, {})
-        RuntimeUtils.closeDevice('camera')
-        RuntimeUtils.closeDevice('microphone')
-        state.user = null
-        removeToken();
-        ElMessage.success('结束');
-        (this as any).$router.push({
-          path: '/login',
-          query: {
-            ...this.$route.query
-          }
-        });
-      } catch (error) {}
-    }
-  },
-  render() {
-    return (
-      <div class={styles.header} >
-        <h3 class={styles.title}>直播内容:{ state.user?.liveRemark }</h3>
-        <div>
-          {runtime.videoStatus === 'liveing' ? (
-            <ElButton type="danger" color="#EA4132" onClick={this.closeLive}>关闭视频</ElButton>
-          ) : (
-            <ElButton type="primary" color="#01A79E" onClick={this.startLive}>开启视频</ElButton>
-          )}
-
-          <ElButton type="primary" color="#EA4132" onClick={this.closeRoom}>结束直播</ElButton>
-        </div>
-      </div>
-    )
-  }
-})
+import { defineComponent } from 'vue'
+import { ElButton, ElMessage, ElMessageBox } from 'element-plus'
+import runtime, * as RuntimeUtils from './runtime'
+import { state } from '/src/state'
+import request from '/src/helpers/request'
+import styles from './header.module.less'
+import { removeToken } from '/src/utils/auth'
+
+export default defineComponent({
+  name: 'LiveBroadcastHeader',
+  methods: {
+    async startLive() {
+      try {
+        await ElMessageBox.confirm('开启后学生将看到视频画面', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning',
+        })
+        await RuntimeUtils.startLive()
+        ElMessage.success('开启成功')
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    async closeLive() {
+      try {
+        await ElMessageBox.confirm('关闭后将切断视频,学生不可观看', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning',
+        })
+        // await request.post('/api-im/user/statusImUser', {
+        //   data: {
+        //     os: 'PC',
+        //     status: '3',
+        //     userId: state.user?.speakerId
+        //   }
+        // })
+        await RuntimeUtils.closeLive()
+        ElMessage.success('关闭成功')
+      } catch (error) {
+      }
+    },
+    async closeRoom() {
+      try {
+        await ElMessageBox.confirm('结束后将无法进入直播间', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning',
+        })
+        // 异步获取用户信息
+        const id = state.user?.id
+        await request.get('/api-web/imLiveBroadcastRoom/roomDestroy/' + id, {})
+        RuntimeUtils.closeDevice('camera')
+        RuntimeUtils.closeDevice('microphone')
+        state.user = null
+        removeToken();
+        ElMessage.success('结束');
+        (this as any).$router.push({
+          path: '/login',
+          query: {
+            ...this.$route.query
+          }
+        });
+      } catch (error) {}
+    }
+  },
+  render() {
+    return (
+      <div class={styles.header} >
+        <h3 class={styles.title}>直播内容:{ state.user?.liveRemark }</h3>
+        <div>
+          {runtime.videoStatus === 'liveing' ? (
+            <ElButton type="danger" color="#01A79E" onClick={this.closeLive}>暂停直播</ElButton>
+          ) : (
+            <ElButton type="primary" color="#01A79E" onClick={this.startLive}>开启直播</ElButton>
+          )}
+
+          <ElButton type="primary" color="#EA4132" onClick={this.closeRoom}>结束直播</ElButton>
+        </div>
+      </div>
+    )
+  }
+})

+ 63 - 6
src/components/live-broadcast/runtime.ts

@@ -1,4 +1,4 @@
-import { ElMessage } from 'element-plus';
+import { ElMessage, ElMessageBox } from 'element-plus';
 import { reactive, ref, Ref } from 'vue'
 import { reactive, ref, Ref } from 'vue'
 import * as RongIMLib from '@rongcloud/imlib-next'
 import * as RongIMLib from '@rongcloud/imlib-next'
 import * as RTC from '@rongcloud/plugin-rtc'
 import * as RTC from '@rongcloud/plugin-rtc'
@@ -113,6 +113,7 @@ const MessageSeatMember = RongIMLib.registerMessageType('RC:Chatroom:SeatMember'
 type MessageProps = {
 type MessageProps = {
   messageType: 'RC:Chatroom:Welcome' | 'RC:TxtMsg' | 'RC:Chatroom:Barrage' | 'RC:Chatroom:Like' | 'RC:Chatroom:SeatsCtrl' | 'RC:Chatroom:ChatBan' | 'RC:Chatroom:SeatApply',
   messageType: 'RC:Chatroom:Welcome' | 'RC:TxtMsg' | 'RC:Chatroom:Barrage' | 'RC:Chatroom:Like' | 'RC:Chatroom:SeatsCtrl' | 'RC:Chatroom:ChatBan' | 'RC:Chatroom:SeatApply',
   content: any,
   content: any,
+  senderUserId: any
 }
 }
 
 
 type MessageEvent = {
 type MessageEvent = {
@@ -129,7 +130,8 @@ const Events = RongIMLib.Events
    const { messages } = evt
    const { messages } = evt
    for (const message of messages) {
    for (const message of messages) {
     //  console.log(LIVE_EVENT_MESSAGE[message.messageType], message)
     //  console.log(LIVE_EVENT_MESSAGE[message.messageType], message)
-     if (LIVE_EVENT_MESSAGE[message.messageType]) {
+    const isSelf = message.senderUserId && Number(message.senderUserId) === state.user?.speakerId
+     if (!isSelf && LIVE_EVENT_MESSAGE[message.messageType]) {
       event.emit(LIVE_EVENT_MESSAGE[message.messageType], {...message.content, $EventMessage: message})
       event.emit(LIVE_EVENT_MESSAGE[message.messageType], {...message.content, $EventMessage: message})
      }
      }
    }
    }
@@ -159,6 +161,9 @@ const Events = RongIMLib.Events
  RongIMLib.addEventListener(Events.DISCONNECT, () => {
  RongIMLib.addEventListener(Events.DISCONNECT, () => {
   console.log('disconnect')
   console.log('disconnect')
    runtime.imConnectStatus = 'disconnect'
    runtime.imConnectStatus = 'disconnect'
+   if (runtime.joinedRoom && runtime.videoStatus === 'liveing') {
+    closeLive(true)
+   }
  })
  })
 
 
  export const connectIM = async (imToken: string) => {
  export const connectIM = async (imToken: string) => {
@@ -206,14 +211,28 @@ export const setVideoSrcObject = (video: HTMLVideoElement | null, mediaStreams:
  * 发起屏幕共享
  * 发起屏幕共享
  */
  */
 export const shareScreenVideo = async () => {
 export const shareScreenVideo = async () => {
-  if (runtime.rtcClient && !runtime.screenShareStatus) {
-    const screenTrack = await getTrack('screen')
+  if (runtime.screenShareStatus) {
+    ElMessage.error('正在屏幕共享中,请先关闭屏幕共享')
+    return
+  }
+  if (runtime.rtcClient && !runtime.screenShareStatus && runtime.videoStatus === 'liveing') {
+    let screenTrack: RTC.RCLocalTrack | undefined
+    try {
+      screenTrack = await getTrack('screen')
+    } catch (error) {
+      ElMessage.error('屏幕分享失败,请检查是否授权')
+    }
+    if (!screenTrack) {
+      return
+    }
     const oldTrack = runtime.activeTracks.camera as RTC.RCLocalTrack
     const oldTrack = runtime.activeTracks.camera as RTC.RCLocalTrack
     // removeTrack([oldTrack], 'camera')
     // removeTrack([oldTrack], 'camera')
-    runtime.joinedRoom?.unpublish([oldTrack])
+    if (oldTrack) {
+      await runtime.joinedRoom?.unpublish([oldTrack])
+    }
     setTrack([screenTrack as RTC.RCLocalTrack], 'screen')
     setTrack([screenTrack as RTC.RCLocalTrack], 'screen')
     if (runtime.videoRef) {
     if (runtime.videoRef) {
-      screenTrack.play(runtime.videoRef)
+      screenTrack?.play(runtime.videoRef)
       runtime.screenShareStatus = true
       runtime.screenShareStatus = true
     }
     }
     screenTrack?.on(RTC.RCLocalTrack.EVENT_LOCAL_TRACK_END, (track: RTC.RCLocalTrack) => {
     screenTrack?.on(RTC.RCLocalTrack.EVENT_LOCAL_TRACK_END, (track: RTC.RCLocalTrack) => {
@@ -233,6 +252,36 @@ export const shareScreenVideo = async () => {
 }
 }
 
 
 /**
 /**
+ * 取消屏幕共享流的访问,会导致取消屏幕共享
+ */
+
+export const closeShareScreenVideo = () => {
+  const screenTrack = runtime.activeTracks.screen as RTC.RCLocalTrack
+  if (screenTrack) {
+    screenTrack.destroy()
+    runtime.screenShareStatus = false
+  }
+  const oldTrack = runtime.activeTracks.camera as RTC.RCLocalTrack
+  if (oldTrack) {
+    setTrack([oldTrack as RTC.RCLocalTrack], 'camera')
+    if (runtime.videoRef) {
+      oldTrack.play(runtime.videoRef)
+    }
+  }
+}
+
+export const toggleShareScreenVideo = async () => {
+  if (runtime.screenShareStatus) {
+    try {
+      await ElMessageBox.confirm('是否确认取消屏幕共享?')
+      closeShareScreenVideo()
+    } catch (error) {}
+  } else {
+    shareScreenVideo()
+  }
+}
+
+/**
  *
  *
  * 获取所有音频输入设备
  * 获取所有音频输入设备
  * @returns {Promise<void>}
  * @returns {Promise<void>}
@@ -328,6 +377,9 @@ export const getTrack = async (trackType: TrackType): Promise<RTC.RCLocalTrack>
   // if (res.code !== RTC.RCRTCCode.SUCCESS || !Track) {
   // if (res.code !== RTC.RCRTCCode.SUCCESS || !Track) {
   //   throw new Error('获取数据流失败')
   //   throw new Error('获取数据流失败')
   // }
   // }
+  if (res.code === RTC.RCRTCCode.GET_DISPLAY_MEDIA_FAILED) {
+    throw new Error('获取屏幕共享失败')
+  }
   return Track
   return Track
 }
 }
 
 
@@ -345,6 +397,7 @@ export const setTrack = async (tracks: RTC.RCLocalTrack[], trackType: TrackType,
     // }
     // }
     runtime.activeTracks[trackType] = track
     runtime.activeTracks[trackType] = track
   }
   }
+  console.log(needPublish)
   if (needPublish) {
   if (needPublish) {
     // console.log('publish', runtime.joinedRoom)
     // console.log('publish', runtime.joinedRoom)
     await runtime.joinedRoom?.publish(tracks.filter(track => !!track))
     await runtime.joinedRoom?.publish(tracks.filter(track => !!track))
@@ -547,6 +600,10 @@ export const closeDevice = async (trackType: TrackType, needPublish = true) => {
 }
 }
 
 
 export const toggleDevice = async (trackType: TrackType) => {
 export const toggleDevice = async (trackType: TrackType) => {
+  if (runtime.screenShareStatus) {
+    await toggleShareScreenVideo()
+    return
+  }
   const track = runtime.activeTracks[trackType]
   const track = runtime.activeTracks[trackType]
   const needPublish = runtime.videoStatus === 'liveing'
   const needPublish = runtime.videoStatus === 'liveing'
   if (track) {
   if (track) {

+ 11 - 1
src/components/live-message/model/join-model.tsx

@@ -47,16 +47,26 @@ export default defineComponent({
     event.on(LIVE_EVENT_MESSAGE['RC:Chatroom:Leave'], this.onLeave); // 移动端接收的消息
     event.on(LIVE_EVENT_MESSAGE['RC:Chatroom:Leave'], this.onLeave); // 移动端接收的消息
     event.on(LIVE_EVENT_MESSAGE['RC:LookerLoginOut'], this.onLeave); // 后台接收的消息
     event.on(LIVE_EVENT_MESSAGE['RC:LookerLoginOut'], this.onLeave); // 后台接收的消息
   },
   },
+  unmounted() {
+    event.off(LIVE_EVENT_MESSAGE['RC:Chatroom:SeatApply'], this.onSeatApply);
+    event.off(LIVE_EVENT_MESSAGE['RC:Chatroom:SeatResponse'], this.onSeatApply);
+    event.off(LIVE_EVENT_MESSAGE['RM:RTC:UserLeave'], this.onSeatApply);
+    event.off(LIVE_EVENT_MESSAGE['RM:RTC:SwitchRole'], this.onSwitchRole);
+    event.off(LIVE_EVENT_MESSAGE['RC:Chatroom:Leave'], this.onLeave); // 移动端接收的消息
+    event.off(LIVE_EVENT_MESSAGE['RC:LookerLoginOut'], this.onLeave); // 后台接收的消息
+  },
   methods: {
   methods: {
     async onLeave(value: any) {
     async onLeave(value: any) {
       // 学生离开时处理
       // 学生离开时处理
-      runtime.lookCount = runtime.lookCount - 1 >= 0 ? runtime.lookCount - 1 : 0
       const userId = value.userId || value.fromUserId
       const userId = value.userId || value.fromUserId
       if(runtimeModel.joinList[userId]) {
       if(runtimeModel.joinList[userId]) {
         RuntimeModelUtils.removeJoin(userId)
         RuntimeModelUtils.removeJoin(userId)
       }
       }
       if(runtimeModel.lookList[userId]) {
       if(runtimeModel.lookList[userId]) {
         RuntimeModelUtils.removeLook(userId)
         RuntimeModelUtils.removeLook(userId)
+
+        // 判断是否有学生
+        runtime.lookCount = runtime.lookCount - 1 >= 0 ? runtime.lookCount - 1 : 0
       }
       }
       // 同步移动端观看人数
       // 同步移动端观看人数
       await RuntimeUtils.sendMessage({ count: runtime.lookCount }, 'MemberCount')
       await RuntimeUtils.sendMessage({ count: runtime.lookCount }, 'MemberCount')

+ 17 - 0
src/icons/bar/screen-share-disabled2.svg

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="21px" height="17px" viewBox="0 0 21 17" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>屏幕分享(关闭)</title>
+    <g id="后台直播界面" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="图标状态" transform="translate(-234.000000, -125.000000)">
+            <g id="屏幕分享备份-3" transform="translate(218.000000, 117.000000)">
+                <g id="屏幕分享(关闭)" transform="translate(16.000000, 8.000000)">
+                    <rect id="矩形" x="0" y="0" width="20" height="17"></rect>
+                    <g id="编组" transform="translate(1.000000, 0.535534)">
+                        <path d="M12.015,14.3037518 C12.3380866,14.3037518 12.6,14.5635865 12.6,14.8841089 C12.6,15.2046313 12.3380866,15.4644661 12.015,15.4644661 L5.98500001,15.4644661 C5.82984836,15.4644661 5.68105131,15.4033215 5.57134253,15.2944834 C5.46163374,15.1856453 5.4,15.0380292 5.4,14.8841089 C5.4,14.7301887 5.46163375,14.5825725 5.57134253,14.4737345 C5.68105132,14.3648964 5.82984836,14.3037518 5.98500001,14.3037518 L12.015,14.3037518 Z M15.385,0.464213562 L11.402,4.44721356 L10.049229,3.24700097 C9.91550447,3.12870837 9.7309643,3.08531493 9.55911111,3.12699053 L9.47453576,3.1549645 C9.28103216,3.23699802 9.15545308,3.42175909 9.1540358,3.62650732 L9.1540358,3.62650732 L9.1454796,5.1403851 C8.15054491,5.14038509 7.19841159,5.52274183 6.49639906,6.20334118 C5.79438652,6.88394054 5.4,7.80703136 5.4,8.7695442 C5.4,9.05587695 5.63942152,9.28799551 5.93476294,9.28799551 C6.23010435,9.28799551 6.46952588,9.05587695 6.46952588,8.7695442 C6.46952481,7.3390944 7.66467809,6.17900424 9.14013198,6.1772877 L9.14013198,6.1772877 L9.137,6.71121356 L2.884,12.9642136 L1.80000001,12.9644661 C1.38228404,12.9644661 0.979538055,12.8204235 0.659235868,12.5600652 L0.527207799,12.4414425 C0.189642315,12.1065561 0,11.6523527 0,11.1787518 L0,11.1787518 L0,2.25018037 C0,1.7765795 0.189642315,1.32237608 0.527207799,0.98748969 C0.864773283,0.6526033 1.32261033,0.464466094 1.80000001,0.464466094 L1.80000001,0.464466094 L15.385,0.464213562 Z M17.5759,1.09882413 C17.848726,1.41967927 18,1.82719333 18,2.25018037 L18,2.25018037 L18,11.1787518 C18,11.6523527 17.8103577,12.1065561 17.4727922,12.4414425 C17.1352267,12.7763289 16.6773897,12.9644661 16.2,12.9644661 L16.2,12.9644661 L5.713,12.9642136 L17.5563492,1.12132034 L17.5563492,1.12132034 Z" id="形状结合" fill="#FFFFFF" fill-rule="nonzero"></path>
+                        <rect id="矩形" fill="#FF3D00" transform="translate(11.131728, 8.131728) rotate(-315.000000) translate(-11.131728, -8.131728) " x="10.131728" y="-2.36827202" width="2" height="21" rx="1"></rect>
+                    </g>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 203 - 202
src/pages/login/index.tsx

@@ -1,202 +1,203 @@
-import { defineComponent } from "vue"
-import { ElForm, ElFormItem, ElInput, ElMessage } from "element-plus";
-import styles from './index.module.less'
-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'
-
-
-export default defineComponent({
-  data() {
-    const validatePassword = (rule: any, value: string | any[], callback: () => void) => {
-      if (value.length < 6) {
-        // @ts-ignore
-        callback(new Error("密码必须大于六位"));
-      } else {
-        callback();
-      }
-    }
-    return {
-      loginForm: {
-        username: null,
-        password: null
-      } as any,
-      loginRules: {
-        username: [
-          { required: true, message: '请输入手机号', trigger: 'blur' },
-          {
-            pattern: /^1[3456789]\d{9}$/,
-            message: '请输入正确的手机号',
-            trigger: 'blur',
-          },
-        ],
-        password: [
-          { required: true, trigger: "blur", validator: validatePassword }
-        ]
-      },
-      passwordType: "password",
-      redirect: undefined as any,
-      isSaveUserInfo: true
-    }
-  },
-  mounted() {
-    if (this.$route.query.redirect) {
-      this.redirect = this.$route.query.redirect;
-    }
-    this.loginForm.username = localStorage.getItem('username');
-    this.loginForm.password = localStorage.getItem('password');
-  },
-  methods: {
-    showPwd() {
-      if (this.passwordType === "password") {
-        this.passwordType = "";
-      } else {
-        this.passwordType = "password";
-      }
-      this.$nextTick(() => {
-        (this as any).$refs.password.focus();
-      });
-    },
-    handleLogin() {
-      // 判断是否点击了记住密码 =>  存储密码
-      const loginForm = this.loginForm;
-      if (this.isSaveUserInfo) {
-        localStorage.setItem('username', loginForm.username);
-        localStorage.setItem('password', loginForm.password);
-      } else {
-        localStorage.setItem('username', '');
-        localStorage.setItem('password', '');
-      }
-      (this as any).$refs.loginForm.validate(async (valid: any) => {
-        if (valid) {
-          try {
-            // 根据手机号获取学生信息
-            const resPhone: any = await request('/api-auth/user/queryClient', {
-              params: {
-                phone: loginForm.username
-              }
-            })
-            console.log(resPhone)
-            // "SYSTEM,STUDENT,TEACHER"
-            const authType = resPhone?.data || ""
-            let clientType = 'SYSTEM'
-            if (authType.includes('SYSTEM')) {
-              clientType = 'SYSTEM'
-            } else if(authType.includes('TEACHER')) {
-              clientType = 'TEACHER'
-            }
-            const res: any = await request.post('/api-auth/usernameLogin', {
-              data: {
-                username: loginForm.username,
-                password: loginForm.password,
-                clientId: clientType,
-                clientSecret: clientType
-              }
-            })
-            let token: string = res?.data.authentication.token_type + ' ' + res?.data.authentication.access_token;
-            setToken(token)
-
-            const roomUid = sessionStorage.getItem('roomUid')
-            // 主讲人进入房间
-            const details:any = await request.get('/api-web/imLiveBroadcastRoom/speakerJoinRoom', {
-              params: {
-                roomUid: roomUid
-              }
-            })
-            // const details:any =  await request.get('/api-web/imLiveBroadcastRoom/queryRoom', {
-            //   params: {
-            //     roomUid: roomUid
-            //   }
-            // })
-
-            sessionStorage.setItem('details',JSON.stringify(details.data))
-            ElMessage.success('登录成功')
-            this.$router.push(this.redirect || '/')
-          } catch (error) {
-            // console.log(error)
-            removeToken()
-          }
-        } else {
-          return false;
-        }
-      });
-    },
-    saveUserInfo() {
-      this.isSaveUserInfo = !this.isSaveUserInfo;
-    }
-  },
-  render() {
-    return (
-      <div class={styles.loginContainer}>
-        <div class={styles.loginHeader}>
-          <div class={styles.logo}>
-            <img src={LogoPng} alt="" />
-          </div>
-          <i class={styles.line}></i>
-          <div class={styles.logoName}>乐团管理系统</div>
-        </div>
-
-
-        <div>
-          <div class={styles.loginSection}>
-            <div class={styles.formBg}>
-              <img src={FromBg} alt="" />
-            </div>
-            <ElForm ref="loginForm"
-              model={this.loginForm}
-              rules={this.loginRules}
-              class={styles.loginForm}
-              auto-complete="on"
-              label-position="left">
-              <div class={styles.titleContainer}>登录</div>
-              <ElFormItem prop="username"
-                class={styles.logitem}>
-                <span class={styles.svgContainer}>
-                  {/* <img class={styles.icon} src="/src/icons/svg/user.svg" alt="" /> */}
-                  <SvgIcon class={styles.icon} name="svg-user" color="#fff" />
-                </span>
-                <ElInput ref="username"
-                  class={styles.loginInput}
-                  v-model={this.loginForm.username}
-                  placeholder="请输入手机号"
-                  // @ts-ignore
-                  maxlength={11}
-                  type="tel"
-                  tabindex="1"
-                  auto-complete="off" />
-              </ElFormItem>
-              <ElFormItem prop="password"
-                class={styles.logitem}>
-                <span class={styles.svgContainer}>
-                  {/* <img class={styles.icon} src="/src/icons/svg/password.svg" alt="" /> */}
-                  <SvgIcon class={styles.icon} name="svg-password" color="#fff" />
-                </span>
-                <ElInput
-                  ref="password"
-                  class={styles.loginInput}
-                  v-model={this.loginForm.password}
-                  type={this.passwordType}
-                  placeholder="请输入密码"
-                  tabindex="2"
-                  auto-complete="off" />
-                <span class={styles.showPwd} onClick={this.showPwd}>
-                  {this.passwordType === 'password' ? <SvgIcon class={styles.icon} name="svg-eye" color="#fff" /> : <SvgIcon class={styles.icon} name="svg-eye-open" color="#fff" />}
-                </span>
-              </ElFormItem>
-              <div class={[!this.loginForm.username || !this.loginForm.password ? styles.disabled : '', styles.loginBtn]}
-                onClick={this.handleLogin}>登录</div>
-              <div class={styles.remberBox} onClick={() => { this.isSaveUserInfo = !this.isSaveUserInfo }}>
-                <div class={[this.isSaveUserInfo ? styles.checked : '', styles.dotWrap]}></div>
-                记住密码
-              </div>
-            </ElForm>
-          </div>
-          <div class={styles.footer}>
-            Copyright © 2022 管乐迷, Inc.ALL Rights Reserved
-          </div>
-        </div>
-      </div>
-    )
-  }
-})
+import { defineComponent } from "vue"
+import { ElForm, ElFormItem, ElInput, ElMessage } from "element-plus";
+import styles from './index.module.less'
+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'
+
+
+export default defineComponent({
+  data() {
+    const validatePassword = (rule: any, value: string | any[], callback: () => void) => {
+      if (value.length < 6) {
+        // @ts-ignore
+        callback(new Error("密码必须大于六位"));
+      } else {
+        callback();
+      }
+    }
+    return {
+      loginForm: {
+        username: null,
+        password: null
+      } as any,
+      loginRules: {
+        username: [
+          { required: true, message: '请输入手机号', trigger: 'blur' },
+          {
+            pattern: /^1[3456789]\d{9}$/,
+            message: '请输入正确的手机号',
+            trigger: 'blur',
+          },
+        ],
+        password: [
+          { required: true, trigger: "blur", validator: validatePassword }
+        ]
+      },
+      passwordType: "password",
+      redirect: undefined as any,
+      isSaveUserInfo: true
+    }
+  },
+  mounted() {
+    if (this.$route.query.redirect) {
+      this.redirect = this.$route.query.redirect;
+    }
+    this.loginForm.username = localStorage.getItem('username');
+    this.loginForm.password = localStorage.getItem('password');
+  },
+  methods: {
+    showPwd() {
+      if (this.passwordType === "password") {
+        this.passwordType = "";
+      } else {
+        this.passwordType = "password";
+      }
+      this.$nextTick(() => {
+        (this as any).$refs.password.focus();
+      });
+    },
+    handleLogin() {
+      // 判断是否点击了记住密码 =>  存储密码
+      const loginForm = this.loginForm;
+      if (this.isSaveUserInfo) {
+        localStorage.setItem('username', loginForm.username);
+        localStorage.setItem('password', loginForm.password);
+      } else {
+        localStorage.setItem('username', '');
+        localStorage.setItem('password', '');
+      }
+      (this as any).$refs.loginForm.validate(async (valid: any) => {
+        if (valid) {
+          try {
+            // 根据手机号获取学生信息
+            const resPhone: any = await request('/api-auth/user/queryClient', {
+              params: {
+                phone: loginForm.username
+              }
+            })
+            console.log(resPhone)
+            // "SYSTEM,STUDENT,TEACHER"
+            const authType = resPhone?.data || ""
+            let clientType = 'SYSTEM'
+            if (authType.includes('SYSTEM')) {
+              clientType = 'SYSTEM'
+            } else if(authType.includes('TEACHER')) {
+              clientType = 'TEACHER'
+            }
+            const res: any = await request.post('/api-auth/usernameLogin', {
+              data: {
+                username: loginForm.username,
+                password: loginForm.password,
+                clientId: clientType,
+                clientSecret: clientType
+              }
+            })
+            let token: string = res?.data.authentication.token_type + ' ' + res?.data.authentication.access_token;
+            setToken(token)
+
+            const roomUid = sessionStorage.getItem('roomUid')
+            // 主讲人进入房间
+            const details:any = await request.get('/api-web/imLiveBroadcastRoom/speakerJoinRoom', {
+              params: {
+                roomUid: roomUid
+              }
+            })
+            // const details:any =  await request.get('/api-web/imLiveBroadcastRoom/queryRoom', {
+            //   params: {
+            //     roomUid: roomUid
+            //   }
+            // })
+
+            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()
+          } catch (error) {
+            // console.log(error)
+            removeToken()
+          }
+        } else {
+          return false;
+        }
+      });
+    },
+    saveUserInfo() {
+      this.isSaveUserInfo = !this.isSaveUserInfo;
+    }
+  },
+  render() {
+    return (
+      <div class={styles.loginContainer}>
+        <div class={styles.loginHeader}>
+          <div class={styles.logo}>
+            <img src={LogoPng} alt="" />
+          </div>
+          <i class={styles.line}></i>
+          <div class={styles.logoName}>乐团管理系统</div>
+        </div>
+
+
+        <div>
+          <div class={styles.loginSection}>
+            <div class={styles.formBg}>
+              <img src={FromBg} alt="" />
+            </div>
+            <ElForm ref="loginForm"
+              model={this.loginForm}
+              rules={this.loginRules}
+              class={styles.loginForm}
+              auto-complete="on"
+              label-position="left">
+              <div class={styles.titleContainer}>登录</div>
+              <ElFormItem prop="username"
+                class={styles.logitem}>
+                <span class={styles.svgContainer}>
+                  {/* <img class={styles.icon} src="/src/icons/svg/user.svg" alt="" /> */}
+                  <SvgIcon class={styles.icon} name="svg-user" color="#fff" />
+                </span>
+                <ElInput ref="username"
+                  class={styles.loginInput}
+                  v-model={this.loginForm.username}
+                  placeholder="请输入手机号"
+                  // @ts-ignore
+                  maxlength={11}
+                  type="tel"
+                  tabindex="1"
+                  auto-complete="off" />
+              </ElFormItem>
+              <ElFormItem prop="password"
+                class={styles.logitem}>
+                <span class={styles.svgContainer}>
+                  {/* <img class={styles.icon} src="/src/icons/svg/password.svg" alt="" /> */}
+                  <SvgIcon class={styles.icon} name="svg-password" color="#fff" />
+                </span>
+                <ElInput
+                  ref="password"
+                  class={styles.loginInput}
+                  v-model={this.loginForm.password}
+                  type={this.passwordType}
+                  placeholder="请输入密码"
+                  tabindex="2"
+                  auto-complete="off" />
+                <span class={styles.showPwd} onClick={this.showPwd}>
+                  {this.passwordType === 'password' ? <SvgIcon class={styles.icon} name="svg-eye" color="#fff" /> : <SvgIcon class={styles.icon} name="svg-eye-open" color="#fff" />}
+                </span>
+              </ElFormItem>
+              <div class={[!this.loginForm.username || !this.loginForm.password ? styles.disabled : '', styles.loginBtn]}
+                onClick={this.handleLogin}>登录</div>
+              <div class={styles.remberBox} onClick={() => { this.isSaveUserInfo = !this.isSaveUserInfo }}>
+                <div class={[this.isSaveUserInfo ? styles.checked : '', styles.dotWrap]}></div>
+                记住密码
+              </div>
+            </ElForm>
+          </div>
+          <div class={styles.footer}>
+            Copyright © 2022 管乐迷, Inc.ALL Rights Reserved
+          </div>
+        </div>
+      </div>
+    )
+  }
+})

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