Ver código fonte

直播页面基础完成

dusenyao 3 anos atrás
pai
commit
2c5c713d31
3 arquivos alterados com 115 adições e 31 exclusões
  1. 11 0
      src/api/live.js
  2. 30 7
      src/views/live/index.vue
  3. 74 24
      src/views/live/live.js

+ 11 - 0
src/api/live.js

@@ -29,3 +29,14 @@ export function GetLiveRoomStudentList(data) {
     data
   });
 }
+
+export function StudentExitLiveRoom(data) {
+  let params = getRequestParams('live_room-live_room_dispatch-StudentExitLiveRoom');
+
+  return request({
+    method: 'post',
+    url: process.env.VUE_APP_LearnWebSI,
+    params,
+    data
+  });
+}

+ 30 - 7
src/views/live/index.vue

@@ -5,15 +5,20 @@
       <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="startLive">开启直播</el-button> -->
+        <div>
+          <span class="live-name">{{ roomData.name }}</span>
+        </div>
+        <div>
+          <el-button @click="startLive">开启直播</el-button>
+          <el-button @click="stopLive">结束直播</el-button>
+        </div>
       </div>
     </div>
     <div class="live-container">
       <!--左侧-->
       <div class="live-container-left">
-        <div id="draw-parent">
+        <div v-show="connection" id="student"></div>
+        <div v-show="!connection" id="draw-parent">
           <div v-show="isDrawSetting" class="draw-setting">
             <span class="brush-shape">
               <svg-icon icon-class="brush-shape" />
@@ -85,19 +90,20 @@
                   icon-class="video"
                   @click="invite(item.room_user_id)"
                 />
-                <span @click="handsDown(item.room_user_id)">下麦</span>
+                <span v-if="userType === 'TEACHER'" @click="handsDown(item.room_user_id)">
+                  下麦
+                </span>
               </div>
             </li>
           </ul>
         </div>
       </div>
     </div>
-    <div id="student" style="width: 300px; height: 200px"></div>
   </div>
 </template>
 
 <script>
-import { GetLiveRoomStudentList } from '@/api/live';
+import { GetLiveRoomStudentList, StudentExitLiveRoom } from '@/api/live';
 import * as common from './live';
 
 export default {
@@ -106,6 +112,7 @@ export default {
     return {
       userType: this.$store.state.user.user_type,
       task_id: this.$route.query.task_id,
+      connection: false,
       rtc: null,
       roomData: {
         desc: '直播间标题',
@@ -293,6 +300,12 @@ export default {
       GetLiveRoomStudentList({ task_id: this.task_id }).then(({ student_list }) => {
         this.student_list = student_list;
       });
+    },
+
+    studentExitLiveRoom(room_user_id) {
+      StudentExitLiveRoom({ task_id: this.task_id, room_user_id }).then(() => {
+        this.getLiveRoomStudentList();
+      });
     }
   }
 };
@@ -331,6 +344,15 @@ export default {
     &-left {
       width: 832px;
 
+      #student {
+        width: 100%;
+        height: 468px;
+        margin-bottom: 14px;
+        border: 1px solid #ccc;
+        position: relative;
+        background-color: #3d3938;
+      }
+
       #draw-parent {
         width: 100%;
         height: 468px;
@@ -474,6 +496,7 @@ export default {
 
         li {
           display: flex;
+          margin-bottom: 16px;
 
           .student-list-left {
             flex: 8;

+ 74 - 24
src/views/live/live.js

@@ -21,9 +21,9 @@ export function initSDK(data) {
  * 推送本地流
  * @method publishStream
  */
-export function publishStream() {
+export function publishStream(streamName) {
   rtc.publish({
-    streamName: 'main',
+    streamName,
     // 推流成功,更新上麦结果
     success: function (stream) {
       console.log('推流成功', stream);
@@ -60,7 +60,7 @@ export function startLive() {
   rtc.startLive({
     success(data) {
       console.log(data);
-      publishStream(); // 如果需要立即推流,执行 publish 方法
+      publishStream('main'); // 如果需要立即推流,执行 publish 方法
       Message({
         message: '开启直播成功',
         type: 'success'
@@ -91,7 +91,7 @@ export function createLocalStream() {
       console.log('创建本地流成功', stream);
       // 创建本地流成功,将流展示到id为 live 的dom元素盒子中
       stream.show('live');
-      publishStream(); // 如果需要立即推流,执行 publish 方法
+      publishStream('main'); // 如果需要立即推流,执行 publish 方法
       // getLiveStat({
       //   success: function (data) {
       //     console.log(data.started);
@@ -112,6 +112,22 @@ export function createLocalStream() {
 }
 
 /**
+ * @method closeVideo
+ * @description 结束本地流
+ */
+export function closeVideo(streamName) {
+  rtc.closeVideo({
+    streamName,
+    success: function () {
+      console.log('结束本地流成功');
+    },
+    fail: function (str) {
+      console.log(str);
+    }
+  });
+}
+
+/**
  * 初始化监听事件
  * @method initListener
  */
@@ -156,6 +172,7 @@ export function initListener(vue) {
 
   // 新增订阅流事件
   rtc.on('allow_sub', function (stream) {
+    console.log('stream', stream);
     if (stream.isMixed()) {
       console.log('是混合流,不订阅');
     } else {
@@ -164,9 +181,13 @@ export function initListener(vue) {
         tryStream: stream,
         success: function (stream) {
           // 订阅流成功
+          console.log(stream.streamType());
           let streamId = stream.id(); // 获取流id
           console.log('订阅流成功', streamId);
-          stream.show('live', 'contain'); // 将流显示到id为 live 的盒子中
+          stream.show(stream.streamType() === 0 ? 'live' : 'student', 'contain'); // 将流显示到id为 live 的盒子中
+          if (stream.streamType() === 10) {
+            vue.connection = true;
+          }
         },
         fail: function (err) {
           console.log('订阅流失败', err);
@@ -180,7 +201,17 @@ export function initListener(vue) {
     console.log('加入房间失败', err);
   });
 
-  // 房间全量信息事件
+  // 直播未开始,不能推流
+  rtc.on('not_live', function () {
+    console.log('直播未开始,不能推流');
+  });
+
+  // 推流前查询直播状态失败,导致没有推流
+  rtc.on('local_stream_publish_failed', function () {
+    console.log('推流前查询直播状态失败,导致没有推流');
+  });
+
+  // 房间全量信息事件(人员进出时广播)
   rtc.on('room_context', roomData => {
     vue.roomContext = JSON.parse(roomData);
     vue.getLiveRoomStudentList();
@@ -224,6 +255,35 @@ export function initListener(vue) {
     console.log('视频无法自动播放', data);
   });
 
+  // 监听通知移除流事件
+  rtc.on('stream_removed', function (stream) {
+    console.log('监听通知移除流事件');
+    if (stream.streamType() === 10) {
+      vue.connection = false;
+    }
+  });
+
+  // 用户退出房间通知其他人员事件
+  rtc.on('exit_room_user', function (data) {
+    console.log('用户退出房间通知其他人员事件', data);
+    vue.studentExitLiveRoom(data.id);
+  });
+
+  // 停止订阅流
+  rtc.on('unSub', function (stream) {
+    console.log('停止订阅流');
+    rtc.unSubscribeStream({
+      unSubStream: stream,
+      success: function (stream) {
+        console.log('取消订阅流成功', stream.id());
+      },
+
+      fail: function (str) {
+        console.log(str);
+      }
+    });
+  });
+
   /**
    * 排麦监听事件
    */
@@ -241,6 +301,11 @@ export function initListener(vue) {
     });
   });
 
+  rtc.on('mcDown', () => {
+    closeVideo('picture');
+    vue.connection = false;
+  });
+
   rtc.on('createLocalStream', () => {
     // 创建本地流推流
     console.log('创建本地流推流');
@@ -249,13 +314,14 @@ export function initListener(vue) {
       audio: true
     };
     rtc.createLocalStream({
-      streamName: 'main',
+      streamName: 'picture',
       createData,
       success: function (stream) {
+        vue.connection = true;
         console.log('创建本地流成功', stream);
         // 创建本地流成功,将流展示到id为 live 的dom元素盒子中
         stream.show('student');
-        publishStream(); // 如果需要立即推流,执行 publish 方法
+        publishStream('picture'); // 如果需要立即推流,执行 publish 方法
       },
       fail: function (data) {
         console.log('创建本地流失败,应用层处理', data);
@@ -313,22 +379,6 @@ export function stopLive() {
 }
 
 /**
- * @method closeVideo
- * @description 结束本地流
- */
-export function closeVideo() {
-  rtc.closeVideo({
-    streamName: 'main',
-    success: function () {
-      console.log('结束本地流成功');
-    },
-    fail: function (str) {
-      console.log(str);
-    }
-  });
-}
-
-/**
  * @method pauseAudio
  * @description 关闭本地流声音
  */