Selaa lähdekoodia

初步完成了直播的对接

dusenyao 4 vuotta sitten
vanhempi
commit
1010492bef

+ 15 - 0
src/api/course.js

@@ -135,3 +135,18 @@ export function GetBookChapterStruct(data) {
     data
   });
 }
+
+/**
+ * 得到树节点信息(教材章节结构)
+ * @param data { id 节点ID }
+ */
+export function GetTreeNodeInfo_BookChapterStruct(data) {
+  let params = getRequestParams('book-book_manager-GetTreeNodeInfo_BookChapterStruct');
+
+  return request({
+    method: 'post',
+    url: process.env.VUE_APP_BookWebSI,
+    params,
+    data
+  });
+}

+ 4 - 4
src/api/live.js

@@ -1,11 +1,11 @@
 import { request, getRequestParams } from '@/utils/request';
 
 /**
- * @description 创建进入直播教室链接
- * @param { data } cs_item_id 课次ID
+ * 创建进入直播教室的会话
+ * @param data { task_id 任务ID }
  */
-export function createEnterLiveRoomLink(data) {
-  let params = getRequestParams('live_room-live_room_dispatch-CreateEnterLiveRoomLink');
+export function CreateEnterLiveRoomSession(data) {
+  let params = getRequestParams('live_room-live_room_dispatch-CreateEnterLiveRoomSession');
 
   return request({
     method: 'post',

+ 13 - 0
src/api/select.js

@@ -56,3 +56,16 @@ export function GetCourseBookListByCSItemID(data) {
     data
   });
 }
+
+/**
+ * 得到完成状态列表(课程)
+ */
+export function GetFinishStatusList_Course() {
+  let params = getRequestParams('dict_manager-GetFinishStatusList_Course');
+
+  return request({
+    method: 'post',
+    url: process.env.VUE_APP_FileServer,
+    params
+  });
+}

+ 3 - 3
src/api/table.js

@@ -1,11 +1,11 @@
 import { request, getRequestParams } from '@/utils/request';
 
 /**
- * 教师得到自己一天的任务
+ * 得到我的每日任务列表
  * @param {Object} data { date_stamp } 格式化后的时间 yyy-mm-dd
  */
-export function getMyTaskListDateTeacher(data) {
-  let params = getRequestParams('teaching-task_manager-GetMyTaskList_Date_Teacher');
+export function GetMyDayTaskList(data) {
+  let params = getRequestParams('teaching-task_manager-GetMyDayTaskList');
 
   return request({
     method: 'post',

+ 12 - 2
src/components/select/SelectCourse.vue

@@ -19,7 +19,12 @@
     <!--课件内容及章节结构-->
     <div class="content">
       <div class="content-tree">
-        <tree-menus :list="nodes" />
+        <tree-menus
+          ref="tree"
+          :current-course="currentCourse"
+          :list="nodes"
+          @curCourse="curCourse"
+        />
       </div>
       <div class="content-container"></div>
     </div>
@@ -52,6 +57,7 @@ export default {
   data() {
     return {
       curBook: {},
+      currentCourse: '',
       book_list: [],
       nodes: []
     };
@@ -69,7 +75,8 @@ export default {
       this.$emit('dialogClose');
     },
     confirm() {
-      this.$emit('selectCourse');
+      this.$emit('selectCourse', this.currentCourse);
+      this.currentCourse = '';
     },
     getCourseBookListByCSItemID() {
       GetCourseBookListByCSItemID({ cs_item_id: this.id }).then(({ book_list }) => {
@@ -78,6 +85,9 @@ export default {
         this.curBook = book_list[0];
       });
     },
+    curCourse(val) {
+      this.currentCourse = val;
+    },
     GetBookChapterStruct() {
       GetBookChapterStruct({ book_id: this.curBook.book_id }).then(({ nodes }) => {
         this.nodes = nodes;

+ 20 - 10
src/components/select/treeMenus.vue

@@ -5,6 +5,7 @@
         :key="item.id"
         :class="[
           'tree-node',
+          { selected: currentCourse === item.id },
           { children: depth > 0 },
           { 'has-children': item.is_leaf === 'false' }
         ]"
@@ -12,7 +13,7 @@
         <div
           class="tree-node-name"
           :style="{ 'font-weight': depth === 0 || item.nodes ? 700 : 400 }"
-          @click="handleTreeClick(item.is_leaf === 'true', i, $event)"
+          @click="handleTreeClick(item.is_leaf === 'true', i, item.id)"
         >
           <span class="tree-node-name-leaf">
             <i
@@ -23,7 +24,13 @@
           <span>{{ item.name }}</span>
         </div>
         <div v-if="item.is_leaf === 'false'" class="tree-node-children">
-          <tree-menus v-show="scopesDefault[i]" :list="item.nodes" :depth="depth + 1" />
+          <tree-menus
+            v-show="scopesDefault[i]"
+            :list="item.nodes"
+            :depth="depth + 1"
+            :current-course="currentCourse"
+            @curCourse="curCourse"
+          />
         </div>
       </div>
     </template>
@@ -43,6 +50,10 @@ export default {
     depth: {
       default: 0,
       type: Number
+    },
+    currentCourse: {
+      default: '',
+      type: String
     }
   },
   data() {
@@ -65,14 +76,13 @@ export default {
         }
       });
     },
-    handleTreeClick(is_leaf, i, { path }) {
+    curCourse(val) {
+      this.$emit('curCourse', val);
+    },
+    handleTreeClick(is_leaf, i, id) {
       if (is_leaf) {
-        for (let i in path) {
-          if (path[i].classList.contains('tree-node')) {
-            path[i].classList.add('selected');
-            return false;
-          }
-        }
+        this.curCourse(id);
+        return false;
       } else if (this.scopesDefault[i] === true) {
         this.$set(this.scopesDefault, i, false);
       } else {
@@ -112,7 +122,7 @@ export default {
     }
   }
 
-  &.children:not(.has-children) .tree-node-name:hover {
+  &:not(.has-children) .tree-node-name:hover {
     color: #fff;
     background-color: $basicColor;
 

+ 8 - 1
src/layouts/components/BreadCrumb.vue

@@ -3,7 +3,14 @@
     <div class="breadcrumb-container">
       <svg-icon icon-class="homepage" /><i class="el-icon-arrow-right" />
       <span v-for="item in routerList" :key="item.path">
-        <span class="router-title"> {{ item.meta.title }} </span>
+        <span class="router-title">
+          <template v-if="item.meta.link">
+            <router-link :to="item.meta.link"> {{ item.meta.title }} </router-link>
+          </template>
+          <template v-else>
+            {{ item.meta.title }}
+          </template>
+        </span>
         <i class="el-icon-arrow-right" />
       </span>
     </div>

+ 1 - 1
src/router/index.js

@@ -54,7 +54,7 @@ const routes = [
     path: '/create_course',
     component: Layout,
     redirect: '/create_course/index',
-    meta: { title: '课程列表' },
+    meta: { title: '课程列表', link: '/' },
     children: [
       {
         path: '/create_course/index',

+ 4 - 6
src/views/live/index.vue

@@ -104,9 +104,6 @@ export default {
   name: 'Live',
   data() {
     return {
-      userid: '53A22FC29AD2216D',
-      roomid: 'DCDD385394BFEDEB9C33DC5901307461',
-      sessionid: '958244269B68153D59A89B76263163F718F9C0729ED1220093D5B392FC86FFF6',
       rtc: null,
       roomData: {
         desc: '直播间标题',
@@ -222,10 +219,11 @@ export default {
     },
 
     initSDK() {
+      const { live_room_sys_user_id, room_id, session_id } = this.$route.query;
       this.rtc = common.initSDK({
-        userid: this.userid,
-        roomid: this.roomid,
-        sessionid: this.sessionid
+        userid: live_room_sys_user_id,
+        roomid: room_id,
+        sessionid: session_id
       });
       const that = this;
       common.initListener(that); // 注册监听事件

+ 31 - 19
src/views/live/live.js

@@ -17,8 +17,8 @@ export function initSDK(data) {
 }
 
 /**
+ * 推送本地流
  * @method publishStream
- * @description 推送本地流
  */
 export function publishStream() {
   rtc.publish({
@@ -75,8 +75,8 @@ export function startLive() {
 }
 
 /**
+ * 创建本地流
  * @method createLocalStram
- * @description 创建本地流
  */
 export function createLocalStream() {
   const createData = {
@@ -92,9 +92,10 @@ export function createLocalStream() {
       stream.show('live');
       getLiveStat({
         success: function (data) {
-          if (!data.started) {
-            startLive();
-          }
+          // if (!data.started) {
+          //   startLive();
+          // }
+          startLive();
         },
         fail: function (str) {
           startLive();
@@ -112,8 +113,8 @@ export function createLocalStream() {
 }
 
 /**
+ * 初始化监听事件
  * @method initListener
- * @description 初始化监听事件
  */
 export function initListener(vue) {
   rtc.on('login_success', data => {
@@ -146,10 +147,34 @@ export function initListener(vue) {
 
   // 必须在加入房间成功的“conference_join”事件回调里创建本地流
   rtc.on('conference_join', () => {
+    console.log('加入房间成功');
     // 有监听就是加入房间成功
+    // if (store.state.user.user_type === 'TEACHER') {
+    //   createLocalStream();
+    // }
     createLocalStream();
   });
 
+  rtc.on('allow_sub', function (stream) {
+    if (stream.isMixed()) {
+      console.log('是混合流,不订阅');
+    } else {
+      // 订阅远程流
+      rtc.trySubscribeStream({
+        tryStream: stream,
+        success: function (stream) {
+          // 订阅流成功
+          let streamId = stream.id(); // 获取流id
+          console.log('订阅流成功', streamId);
+          stream.show('live', 'contain'); // 将流显示到id为 live 的盒子中
+        },
+        fail: function (err) {
+          console.log(err);
+        }
+      });
+    }
+  });
+
   rtc.on('conference_join_failed', err => {
     // 加入房间失败  err为错误原因
     console.log('加入房间失败', err);
@@ -187,19 +212,6 @@ export function initListener(vue) {
     console.log(data); // 房间设置事件
   });
 
-  rtc.on('allow_sub', stream => {
-    console.log('监听到有流');
-    rtc.trySubscribeStream({
-      tryStream: stream,
-      success: function success(stream) {
-        stream.show('other');
-      },
-      fail: function fail(err) {
-        console.error(err);
-      }
-    });
-  });
-
   rtc.on('publishStreamErr', data => {
     console.log('推流意外终止:' + data.streamName);
     // 直播开启状态下,尝试重推这条流

+ 4 - 4
src/views/teacher/create_course/step_table/CreateTask.vue

@@ -13,7 +13,7 @@
     <div class="task-button">
       <el-button class="prev-step" @click="preStep"><i class="el-icon-back" />选择教材</el-button>
       <el-button class="preserve" type="primary"><svg-icon icon-class="preserve" />保存</el-button>
-      <el-button>关闭</el-button>
+      <el-button><router-link to="/create_course">关闭</router-link></el-button>
     </div>
     <!--任务课节-->
     <div class="task-item">
@@ -99,7 +99,7 @@
                             :key="li.courseware_id"
                             color="#fff"
                           >
-                            {{ li.courseware_id }}
+                            {{ li.courseware_name }}
                           </el-tag>
                         </div>
                       </div>
@@ -154,7 +154,7 @@
                             :key="li.courseware_id"
                             color="#fff"
                           >
-                            {{ li.courseware_id }}
+                            {{ li.courseware_name }}
                           </el-tag>
                         </div>
                       </div>
@@ -214,7 +214,7 @@
                             :key="li.courseware_id"
                             color="#fff"
                           >
-                            {{ li.courseware_id }}
+                            {{ li.courseware_name }}
                           </el-tag>
                         </div>
                       </div>

+ 93 - 22
src/views/teacher/create_course/step_table/NewTask.vue

@@ -60,6 +60,17 @@
                 <el-button @click="dialogVisible = true">
                   <i class="el-icon-plus" /> 添加课件
                 </el-button>
+                <div>
+                  <el-tag
+                    v-for="(item, i) in liveForm.coursewareInfo"
+                    :key="item.id"
+                    color="#fff"
+                    closable
+                    @close="closeCourse(i, 'live')"
+                  >
+                    {{ item.name }}
+                  </el-tag>
+                </div>
               </el-form-item>
 
               <el-form-item label="上传文档">
@@ -84,13 +95,17 @@
               </el-form-item>
 
               <el-form-item label="可见性">
-                <el-radio v-model="liveForm.is_visibility" :label="true">手动推送</el-radio>
-                <el-radio v-model="liveForm.is_visibility" :label="false">一直课件</el-radio>
+                <el-radio v-model="liveForm.courseware_visible_mode" :label="true">
+                  手动推送
+                </el-radio>
+                <el-radio v-model="liveForm.courseware_visible_mode" :label="false">
+                  一直可见
+                </el-radio>
               </el-form-item>
 
               <el-form-item label="直播录制">
-                <el-radio v-model="liveForm.recording" label="auto">自动开启</el-radio>
-                <el-radio v-model="liveForm.recording" label="manual">手动开启</el-radio>
+                <el-radio v-model="liveForm.zhibo_record_mode" label="auto">自动开启</el-radio>
+                <el-radio v-model="liveForm.zhibo_record_mode" label="manual">手动开启</el-radio>
               </el-form-item>
             </el-form>
           </div>
@@ -101,6 +116,17 @@
                 <el-button @click="dialogVisible = true">
                   <i class="el-icon-plus" /> 添加课件
                 </el-button>
+                <div>
+                  <el-tag
+                    v-for="(item, i) in courseForm.coursewareInfo"
+                    :key="item.id"
+                    color="#fff"
+                    closable
+                    @close="closeCourse(i, 'course')"
+                  >
+                    {{ item.name }}
+                  </el-tag>
+                </div>
               </el-form-item>
 
               <el-form-item label="任务模式">
@@ -114,8 +140,8 @@
               </el-form-item>
 
               <el-form-item label="留言功能">
-                <el-radio v-model="courseForm.leave_message" :label="true">开启</el-radio>
-                <el-radio v-model="courseForm.leave_message" :label="false">关闭</el-radio>
+                <el-radio v-model="courseForm.is_enable_message" :label="true">开启</el-radio>
+                <el-radio v-model="courseForm.is_enable_message" :label="false">关闭</el-radio>
               </el-form-item>
             </el-form>
           </div>
@@ -144,13 +170,13 @@
               </el-form-item>
 
               <el-form-item label="提交作业">
-                <el-radio v-model="basicForm.is_submit" :label="true">开启</el-radio>
-                <el-radio v-model="basicForm.is_submit" :label="false">关闭</el-radio>
+                <el-radio v-model="basicForm.is_enable_homework" :label="true">开启</el-radio>
+                <el-radio v-model="basicForm.is_enable_homework" :label="false">关闭</el-radio>
               </el-form-item>
 
               <el-form-item label="留言功能">
-                <el-radio v-model="basicForm.leave_message" :label="true">开启</el-radio>
-                <el-radio v-model="basicForm.leave_message" :label="false">关闭</el-radio>
+                <el-radio v-model="basicForm.is_enable_message" :label="true">开启</el-radio>
+                <el-radio v-model="basicForm.is_enable_message" :label="false">关闭</el-radio>
               </el-form-item>
             </el-form>
           </div>
@@ -162,14 +188,20 @@
       </el-form>
     </div>
 
-    <select-course :id="cs_item_id" :dialog-visible="dialogVisible" @dialogClose="dialogClose" />
+    <!--选择课件-->
+    <select-course
+      :id="cs_item_id"
+      :dialog-visible="dialogVisible"
+      @selectCourse="selectCourse"
+      @dialogClose="dialogClose"
+    />
   </div>
 </template>
 
 <script>
 import SelectCourse from '@/components/select/SelectCourse.vue';
 import { GetTaskTeachingTypeList, GetTaskModeList, GetTeacherListByCourseID } from '@/api/select';
-import { AddTaskToCSItem } from '@/api/course';
+import { AddTaskToCSItem, GetTreeNodeInfo_BookChapterStruct } from '@/api/course';
 import { fileUpload } from '@/api/app';
 
 export default {
@@ -196,20 +228,20 @@ export default {
         teacher_id: { required: true, message: '授课教师不能为空', trigger: 'blur' }
       },
       liveForm: {
-        courseware_id_list: [],
+        coursewareInfo: [],
         file_info_list: [],
-        is_visibility: true,
-        recording: 'auto'
+        courseware_visible_mode: true,
+        zhibo_record_mode: 'auto'
       },
       courseForm: {
-        courseware_id_list: [],
+        coursewareInfo: [],
         task_mode: 'PRACTICE',
-        leave_message: true
+        is_enable_message: true
       },
       basicForm: {
         file_info_list: [],
-        is_submit: true,
-        leave_message: true
+        is_enable_homework: true,
+        is_enable_message: true
       }
     };
   },
@@ -241,16 +273,28 @@ export default {
           };
 
           if (teaching_type === 10) {
-            data['courseware_id_list'] = this.liveForm.courseware_id_list;
+            let courseware_id_list = [];
+            this.liveForm.coursewareInfo.forEach(item => {
+              courseware_id_list.push(item.id);
+            });
+            data['courseware_id_list'] = courseware_id_list;
             let file_info_list = [];
             this.liveForm.file_info_list.forEach(item => {
               file_info_list.push(item.file_id);
             });
             data['file_id_list'] = file_info_list;
+            data['courseware_visible_mode'] = this.liveForm.courseware_visible_mode;
+            data['zhibo_record_mode'] = this.liveForm.zhibo_record_mode;
           }
 
           if (teaching_type === 11) {
-            data['courseware_id_list'] = this.courseForm.courseware_id_list;
+            let courseware_id_list = [];
+            this.courseForm.courseware_id_list.forEach(item => {
+              courseware_id_list.push(item.id);
+            });
+            data['courseware_id_list'] = courseware_id_list;
+            data['task_mode'] = this.courseForm.task_mode;
+            data['is_enable_message'] = this.courseForm.is_enable_message;
           }
 
           if (teaching_type === 12) {
@@ -259,6 +303,8 @@ export default {
               file_info_list.push(item.file_id);
             });
             data['file_id_list'] = file_info_list;
+            data['is_enable_homework'] = this.basicForm.is_enable_homework;
+            data['is_enable_message'] = this.basicForm.is_enable_message;
           }
 
           AddTaskToCSItem(data).then(({ status }) => {
@@ -301,9 +347,34 @@ export default {
       arr.splice(i, 1);
     },
     // 选择课件
-    addCourse() {},
     dialogClose() {
       this.dialogVisible = false;
+    },
+    selectCourse(course_id) {
+      let type = this.form.teaching_type;
+      if (type === 10) {
+        this.getTreeNodeInfo_BookChapterStruct(course_id, 'live');
+      }
+
+      if (type === 11) {
+        this.getTreeNodeInfo_BookChapterStruct(course_id, 'course');
+      }
+      this.dialogVisible = false;
+    },
+    getTreeNodeInfo_BookChapterStruct(id, type) {
+      GetTreeNodeInfo_BookChapterStruct({ id }).then(({ name, id }) => {
+        if (type === 'live') {
+          this.liveForm.coursewareInfo.push({ id, name });
+        }
+        if (type === 'course') {
+          this.courseForm.coursewareInfo.push({ id, name });
+        }
+      });
+    },
+    closeCourse(i, type) {
+      let courseInfo =
+        type === 'live' ? this.liveForm.coursewareInfo : this.courseForm.coursewareInfo;
+      courseInfo.splice(i, 1);
     }
   }
 };

+ 1 - 6
src/views/teacher/cs_item_detail/index.vue

@@ -59,7 +59,6 @@
 
 <script>
 import { getCSItemInfoBox } from '@/api/table';
-import { createEnterLiveRoomLink } from '@/api/live';
 import ClassroomTask from './ClassroomTask';
 import { updateWordPack } from '@/utils/i18n';
 
@@ -109,11 +108,7 @@ export default {
     });
   },
   methods: {
-    jumpLiveRoom() {
-      createEnterLiveRoomLink({ cs_item_id: this.id }).then(response => {
-        window.open(response.live_room_url, '_blank');
-      });
-    }
+    jumpLiveRoom() {}
   }
 };
 </script>

+ 12 - 10
src/views/teacher/main/CurriculaList.vue

@@ -7,10 +7,10 @@
         </el-input>
         <el-select v-model="finish_status">
           <el-option
-            v-for="item in statusList"
-            :key="item.value"
+            v-for="item in finish_status_list"
+            :key="item.finish_status"
             :label="item.name"
-            :value="item.value"
+            :value="item.finish_status"
           ></el-option>
         </el-select>
       </div>
@@ -52,19 +52,15 @@
 <script>
 import { updateWordPack } from '@/utils/i18n';
 import { pageQueryMyCourseList } from '@/api/table';
+import { GetFinishStatusList_Course } from '@/api/select';
 
 export default {
   name: 'CurriculaList',
   data() {
     return {
       search: '',
-      statusList: [
-        { value: 1, name: '草稿' },
-        { value: 2, name: '未开始' },
-        { value: 3, name: '已结束' },
-        { value: 4, name: '进行中' }
-      ],
-      finish_status: 1,
+      finish_status_list: [],
+      finish_status: 50,
       page_capacity: 10,
       cur_page: 1,
       total_count: 0,
@@ -73,11 +69,17 @@ export default {
   },
   created() {
     this.queryMyCourseList();
+    this.getFinishStatusList_Course();
     updateWordPack({
       word_key_list: ['Learn_New_Courses']
     });
   },
   methods: {
+    getFinishStatusList_Course() {
+      GetFinishStatusList_Course().then(({ finish_status_list }) => {
+        this.finish_status_list = finish_status_list;
+      });
+    },
     selectTab(status, i) {
       this.status = status;
       this.curTab = i;

+ 43 - 4
src/views/teacher/main/TaskList.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="tasks">
     <div class="tasks-top">
-      <el-calendar v-model="date" />
+      <el-calendar v-model="dateTime" />
       <div class="tasks-top-notification">
         <div class="tasks-top-notification-title">
           <div>
@@ -36,6 +36,13 @@
             <div v-for="list in item.task_list" :key="list.id" class="tasks-group-list-info">
               <div class="tasks-group-list-info-name">
                 {{ timeType(list.time_type) }}任务:{{ list.name }}
+                <el-link
+                  class="task-link"
+                  :underline="false"
+                  @click="taskLink(list.teaching_type, list.id)"
+                >
+                  {{ teachingType(list.teaching_type) }}
+                </el-link>
               </div>
               <div class="tasks-group-list-info-item-name">{{ list.cs_item_name }}</div>
               <div class="tasks-group-list-info-time">{{ list.time_space_view_txt }}</div>
@@ -49,7 +56,8 @@
 </template>
 
 <script>
-import { getMyTaskListDateTeacher } from '@/api/table';
+import { GetMyDayTaskList } from '@/api/table';
+import { CreateEnterLiveRoomSession } from '@/api/live';
 import { parseTime, formatDate } from '@/utils';
 
 export default {
@@ -88,12 +96,34 @@ export default {
           return '';
       }
     },
+    teachingType(type) {
+      switch (type) {
+        case 10:
+          return '进入直播间';
+        default:
+          return '查看';
+      }
+    },
+    taskLink(type, task_id) {
+      if (type === 10) {
+        CreateEnterLiveRoomSession({
+          task_id
+        }).then(({ live_room_sys_user_id, room_id, session_id }) => {
+          this.$router.push({
+            path: '/live',
+            query: { live_room_sys_user_id, room_id, session_id }
+          });
+        });
+      } else {
+        this.$message.warning('暂未实现');
+      }
+    },
     dateSkip(num) {
       let day = 24 * 60 * 60 * 1000 * num;
-      this.date = new Date(this.date.getTime() + day);
+      this.dateTime = new Date(this.date.getTime() + day);
     },
     getTaskList() {
-      getMyTaskListDateTeacher({ date_stamp: formatDate(this.date) }).then(response => {
+      GetMyDayTaskList({ date_stamp: formatDate(this.date) }).then(response => {
         this.task_group_list = response.task_group_list;
       });
     },
@@ -217,6 +247,15 @@ export default {
               margin: 8px 0;
             }
 
+            &-name {
+              .task-link {
+                font-size: 16px;
+                vertical-align: top;
+                margin-left: 8px;
+                color: $basicColor;
+              }
+            }
+
             &-item-name {
               font-size: 14px;
               color: #727280;