dusenyao 4 роки тому
батько
коміт
0084863d32
4 змінених файлів з 157 додано та 40 видалено
  1. 6 0
      src/icons/svg/video.svg
  2. 6 2
      src/styles/index.scss
  3. 77 32
      src/views/live/index.vue
  4. 68 6
      src/views/live/live.js

+ 6 - 0
src/icons/svg/video.svg

@@ -0,0 +1,6 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M24 0H0V24H24V0Z" fill="white" fill-opacity="0.01"/>
+<path d="M18 5H2V19H18V5Z" stroke="white" stroke-width="1.5" stroke-linejoin="round"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M22 7L18 10.375V13.625L22 17V7Z" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+<circle cx="7" cy="10" r="2" stroke="white" stroke-width="1.5"/>
+</svg>

+ 6 - 2
src/styles/index.scss

@@ -3,7 +3,6 @@
 @import './element-ui.scss';
 
 body {
-  height: 100%;
   -moz-osx-font-smoothing: grayscale;
   -webkit-font-smoothing: antialiased;
   text-rendering: optimizeLegibility;
@@ -18,10 +17,15 @@ label {
 }
 
 html {
-  height: 100%;
   box-sizing: border-box;
 }
 
+html,
+body {
+  font-size: 16px !important;
+  height: 100%;
+}
+
 #app {
   height: 100%;
 }

+ 77 - 32
src/views/live/index.vue

@@ -1,14 +1,17 @@
 <template>
   <div class="live">
-    <div>
+    <!--顶部-->
+    <div class="live-top">
       <div class="live-page-title">直播间</div>
       <div class="live-desc">{{ roomData.desc }}</div>
       <div class="live-info">
         <span class="live-name">{{ roomData.name }}</span>
-        <el-button @click="stopLive">下课</el-button>
+        <el-button @click="stopLive">结束直播</el-button>
+        <!-- <el-button @click="startLive">开启直播</el-button> -->
       </div>
     </div>
     <div class="live-container">
+      <!--左侧-->
       <div class="live-container-left">
         <div id="draw-parent">
           <div v-show="isDrawSetting" class="draw-setting">
@@ -31,30 +34,6 @@
         </div>
         <div class="button-group">
           <div>
-            <el-dropdown placement="top" @command="invite">
-              <el-button>语音连麦</el-button>
-              <el-dropdown-menu slot="dropdown">
-                <el-dropdown-item
-                  v-for="item in roomContext.onlineUsers"
-                  :key="item.id"
-                  :command="item.uid"
-                >
-                  {{ item.name }}
-                </el-dropdown-item>
-              </el-dropdown-menu>
-            </el-dropdown>
-            <el-dropdown placement="top" @command="invite">
-              <el-button>视屏连麦</el-button>
-              <el-dropdown-menu slot="dropdown">
-                <el-dropdown-item
-                  v-for="item in roomContext.onlineUsers"
-                  :key="item.id"
-                  :command="item.uid"
-                >
-                  {{ item.name }}
-                </el-dropdown-item>
-              </el-dropdown-menu>
-            </el-dropdown>
             <!-- <el-button>群组讨论</el-button>
             <el-button>推送课件</el-button> -->
             <el-button @click="showDrawSetting">屏幕画笔</el-button>
@@ -88,12 +67,32 @@
           </div>
         </div>
       </div>
+      <!--右侧-->
       <div class="live-container-right">
         <div class="live-teacher-lens">
           <div id="live"></div>
         </div>
+        <div class="student-list">
+          <ul>
+            <li v-for="item in student_list" :key="item.room_user_id">
+              <div class="student-list-left">
+                <el-avatar icon="el-icon-user" size="small" :src="item.student_image_url" />
+                <span class="name">{{ item.student_name }}</span>
+              </div>
+              <div class="student-list-right">
+                <svg-icon
+                  v-if="userType === 'TEACHER'"
+                  icon-class="video"
+                  @click="invite(item.room_user_id)"
+                />
+                <span @click="handsDown(item.room_user_id)">下麦</span>
+              </div>
+            </li>
+          </ul>
+        </div>
       </div>
     </div>
+    <div id="student" style="width: 300px; height: 200px"></div>
   </div>
 </template>
 
@@ -105,6 +104,7 @@ export default {
   name: 'Live',
   data() {
     return {
+      userType: this.$store.state.user.user_type,
       task_id: this.$route.query.task_id,
       rtc: null,
       roomData: {
@@ -143,6 +143,7 @@ export default {
   },
   created() {
     this.downloadWebSDK();
+    this.getLiveRoomStudentList();
   },
   mounted() {
     document.addEventListener(
@@ -237,6 +238,10 @@ export default {
       common.stopLive();
     },
 
+    startLive() {
+      common.startLive();
+    },
+
     // 推送桌面共享
     publishShareStream() {
       common.publishShareStream();
@@ -247,10 +252,17 @@ export default {
       this.rtc.unPubShareStream();
     },
 
+    // 老师邀请学生上麦
     invite(uid) {
       common.invite(uid);
     },
 
+    // 下麦
+    handsDown(uid) {
+      common.handsDown(uid);
+    },
+
+    // 发消息
     sendMsg() {
       common.sendMsg(this.msg);
       this.msg = '';
@@ -278,7 +290,7 @@ export default {
     },
 
     getLiveRoomStudentList() {
-      GetLiveRoomStudentList(this.task_id).then(({ student_list }) => {
+      GetLiveRoomStudentList({ task_id: this.task_id }).then(({ student_list }) => {
         this.student_list = student_list;
       });
     }
@@ -317,12 +329,11 @@ export default {
     margin-top: 17px;
 
     &-left {
-      width: 661px;
-      margin-right: 18px;
+      width: 832px;
 
       #draw-parent {
         width: 100%;
-        height: 331px;
+        height: 468px;
         margin-bottom: 14px;
         border: 1px solid #ccc;
         position: relative;
@@ -448,8 +459,42 @@ export default {
 
     &-right {
       #live {
-        width: 321px;
-        height: 91px;
+        width: 352px;
+        height: 198px;
+      }
+
+      .student-list {
+        width: 100%;
+        padding: 24px;
+        margin-top: 2px;
+        height: calc(100% - 200px);
+        background-color: #2c2c2c;
+        font-size: 14px;
+        color: #fff;
+
+        li {
+          display: flex;
+
+          .student-list-left {
+            flex: 8;
+
+            .name {
+              vertical-align: super;
+              margin-left: 8px;
+            }
+          }
+
+          .student-list-right {
+            flex: 2;
+
+            .svg-icon {
+              font-size: 18px;
+              cursor: pointer;
+              margin-top: 7px;
+              margin-right: 8px;
+            }
+          }
+        }
       }
     }
   }

+ 68 - 6
src/views/live/live.js

@@ -156,8 +156,6 @@ export function initListener(vue) {
 
   // 新增订阅流事件
   rtc.on('allow_sub', function (stream) {
-    let streamType = stream.streamType();
-    console.log(streamType);
     if (stream.isMixed()) {
       console.log('是混合流,不订阅');
     } else {
@@ -185,7 +183,8 @@ export function initListener(vue) {
   // 房间全量信息事件
   rtc.on('room_context', roomData => {
     vue.roomContext = JSON.parse(roomData);
-    console.log('房间全量信息事件', JSON.parse(roomData));
+    vue.getLiveRoomStudentList();
+    console.log('房间全量信息事件(人员进出时广播)', JSON.parse(roomData));
   });
 
   rtc.on('publish_stream', str => {
@@ -208,10 +207,11 @@ export function initListener(vue) {
   // 人员列表事件(人员麦序变化时广播)
   rtc.on('speak_context', speakData => {
     vue.speakData = JSON.parse(speakData);
+    console.log('人员列表事件(人员麦序变化时广播)', JSON.parse(speakData));
   });
 
   rtc.on('switch_settings', data => {
-    console.log(data); // 房间设置事件
+    console.log('房间设置事件', data); // 房间设置事件
   });
 
   rtc.on('publishStreamErr', data => {
@@ -221,10 +221,56 @@ export function initListener(vue) {
 
   // 视频无法自动播放
   rtc.on('playError', data => {
-    console.log(data);
+    console.log('视频无法自动播放', data);
   });
 
-  // 监听聊天事件
+  /**
+   * 排麦监听事件
+   */
+
+  // 监听自己被邀请事件
+  rtc.on('inviteUp', uid => {
+    console.log('监听自己被邀请事件', uid);
+    rtc.inviteAccept({
+      success: function (str) {
+        console.log('接受邀请成功', str);
+      },
+      fail: function (data) {
+        console.log('接受邀请失败', data);
+      }
+    });
+  });
+
+  rtc.on('createLocalStream', () => {
+    // 创建本地流推流
+    console.log('创建本地流推流');
+    const createData = {
+      video: true,
+      audio: true
+    };
+    rtc.createLocalStream({
+      streamName: 'main',
+      createData,
+      success: function (stream) {
+        console.log('创建本地流成功', stream);
+        // 创建本地流成功,将流展示到id为 live 的dom元素盒子中
+        stream.show('student');
+        publishStream(); // 如果需要立即推流,执行 publish 方法
+      },
+      fail: function (data) {
+        console.log('创建本地流失败,应用层处理', data);
+        // 创建本地流失败,应用层处理
+        Message({
+          type: 'error',
+          message: '创建本地流失败:' + data
+        });
+      }
+    });
+  });
+
+  /**
+   * 监听聊天事件
+   */
   rtc.on('chat_message', data => {
     let dat = JSON.parse(data);
     console.log(dat);
@@ -407,6 +453,22 @@ export function handsUp(data) {
 }
 
 /**
+ * 下麦操作
+ * @param { String } uid
+ */
+export function handsDown(uid) {
+  rtc.handsDown({
+    uid,
+    success: function (str) {
+      console.log('下麦成功', str);
+    },
+    fail: function (data) {
+      console.log('下麦失败', data);
+    }
+  });
+}
+
+/**
  * @description 学生端接受老师的上麦邀请,同意上麦
  */
 export function inviteAccept() {