|
@@ -0,0 +1,517 @@
|
|
|
+<template>
|
|
|
+ <div class="group">
|
|
|
+ <!--顶部-->
|
|
|
+ <div class="group-top">
|
|
|
+ <div class="live-title">
|
|
|
+ <div class="live-title-name">{{ roomInfo.cs_item_name }} {{ roomInfo.task_name }}</div>
|
|
|
+ <div>
|
|
|
+ <el-button @click="exitRoom">退出房间</el-button>
|
|
|
+ <el-button @click="getLiveStat">getLiveStat</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="live-course-name">{{ roomInfo.course_name }}</div>
|
|
|
+ <div class="live-teacher">
|
|
|
+ <span class="live-teacher-name">
|
|
|
+ <svg-icon icon-class="person" />{{ roomInfo.teacher_name }}
|
|
|
+ </span>
|
|
|
+ <span><svg-icon icon-class="people" />{{ roomInfo.student_count }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 主容器 -->
|
|
|
+ <div class="group-container">
|
|
|
+ <!-- 左侧 -->
|
|
|
+ <div class="group-container-left">
|
|
|
+ <div class="group-discussion">
|
|
|
+ <div id="group-local" class="group-box"></div>
|
|
|
+ <div
|
|
|
+ v-for="(item, i) in streamList"
|
|
|
+ :id="`group-${i}`"
|
|
|
+ :key="item.id()"
|
|
|
+ class="group-box"
|
|
|
+ ></div>
|
|
|
+ </div>
|
|
|
+ <div class="button-group">
|
|
|
+ <div class="button-group-left"></div>
|
|
|
+ <div class="button-group-right"></div>
|
|
|
+ </div>
|
|
|
+ <div class="group-container-left-chat">
|
|
|
+ <div class="chat-top">
|
|
|
+ <span>聊天</span>
|
|
|
+ </div>
|
|
|
+ <div class="chat-window">
|
|
|
+ <ul class="chat-window-ul">
|
|
|
+ <li v-for="(item, i) in chatList" :key="i">
|
|
|
+ <div class="msg-normal">
|
|
|
+ <span>{{ item.username }}: </span>
|
|
|
+ <span>{{ item.msg }}</span>
|
|
|
+ </div>
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ </div>
|
|
|
+ <div class="chat-speak">
|
|
|
+ <el-input
|
|
|
+ v-model="msg"
|
|
|
+ placeholder="输入发言"
|
|
|
+ maxlength="400"
|
|
|
+ @keydown.enter.native="sendMsg"
|
|
|
+ >
|
|
|
+ <el-button slot="append" @click="sendMsg">发送</el-button>
|
|
|
+ </el-input>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 右侧 -->
|
|
|
+ <div class="group-container-right">
|
|
|
+ <div
|
|
|
+ class="live-teacher-lens"
|
|
|
+ @mouseover="liveMenuShow = true"
|
|
|
+ @mouseout="liveMenuShow = false"
|
|
|
+ >
|
|
|
+ <div id="live"></div>
|
|
|
+ <div :style="{ bottom: liveMenuShow ? '0' : '-40px' }" class="live-wrapper">
|
|
|
+ <div>
|
|
|
+ {{ roomInfo.teacher_name }}
|
|
|
+ </div>
|
|
|
+ <div></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="student-list">
|
|
|
+ <div class="student-list-title">学生列表</div>
|
|
|
+ <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>
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import {
|
|
|
+ GetLiveRoomStudentList,
|
|
|
+ StudentExitLiveRoom,
|
|
|
+ GetLiveRoomInfo,
|
|
|
+ IsEnableGroup,
|
|
|
+ GetMyGroupInfo_Student
|
|
|
+} from '@/api/live';
|
|
|
+import * as common from './group';
|
|
|
+
|
|
|
+export default {
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ task_id: this.$route.query.task_id,
|
|
|
+ room_user_id: this.$route.query.live_room_sys_user_id,
|
|
|
+ // 定时器
|
|
|
+ timer: null,
|
|
|
+ timer_group: null,
|
|
|
+ rtc: null,
|
|
|
+ streamList: [],
|
|
|
+ roomData: {
|
|
|
+ desc: '直播间标题',
|
|
|
+ name: '姓名',
|
|
|
+ user: {
|
|
|
+ id: '',
|
|
|
+ name: '',
|
|
|
+ role: 'talker',
|
|
|
+ rommid: ''
|
|
|
+ },
|
|
|
+ max_users: 1,
|
|
|
+ allow_chat: true,
|
|
|
+ allow_audio: true,
|
|
|
+ allow_speak: true
|
|
|
+ },
|
|
|
+ roomInfo: {
|
|
|
+ room_id: '',
|
|
|
+ video_mode: 1,
|
|
|
+ task_name: '',
|
|
|
+ cs_item_name: '',
|
|
|
+ course_name: '',
|
|
|
+ teacher_name: '',
|
|
|
+ student_count: 0,
|
|
|
+ teacher_image_url: ''
|
|
|
+ },
|
|
|
+ loadedNumber: 0,
|
|
|
+ speakData: {},
|
|
|
+ roomContext: {},
|
|
|
+ msg: '',
|
|
|
+ chatList: [],
|
|
|
+ // 直播间学员列表
|
|
|
+ student_list: [],
|
|
|
+ // 直播状态
|
|
|
+ liveStat: false,
|
|
|
+ liveMenuShow: false
|
|
|
+ };
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ loadedNumber(newVal) {
|
|
|
+ if (newVal === 5) {
|
|
|
+ common.createScript(
|
|
|
+ 'https://class.csslcloud.net/static/SDK/docSDK/drawSdk_3.0.js'
|
|
|
+ ).onload = () => {
|
|
|
+ const { live_room_sys_user_id, room_id, sessionid } = this.$route.query;
|
|
|
+ this.rtc = common.initSDK({
|
|
|
+ userid: live_room_sys_user_id,
|
|
|
+ roomid: room_id,
|
|
|
+ sessionid
|
|
|
+ });
|
|
|
+ common.initListener(this); // 注册监听事件
|
|
|
+ this.getLiveStat();
|
|
|
+ this.$loading().close();
|
|
|
+ };
|
|
|
+ }
|
|
|
+ },
|
|
|
+ streamList(newVal) {
|
|
|
+ if (newVal.length > 0) {
|
|
|
+ this.$nextTick(() => {
|
|
|
+ newVal[newVal.length - 1].show(`group-${newVal.length - 1}`);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ this.getLiveRoomStudentList();
|
|
|
+ this.getLiveRoomInfo();
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ // const { live_room_sys_user_id, room_id, sessionid } = this.$route.query;
|
|
|
+ // this.rtc = common.initSDK({
|
|
|
+ // userid: live_room_sys_user_id,
|
|
|
+ // roomid: room_id,
|
|
|
+ // sessionid
|
|
|
+ // });
|
|
|
+ // common.initListener(this); // 注册监听事件
|
|
|
+ // this.getLiveStat();
|
|
|
+ common.downloadWebSDK(this);
|
|
|
+ this.getLiveRoomStudentListPolling();
|
|
|
+ this.isEnableGroup();
|
|
|
+ },
|
|
|
+ beforeDestroy() {
|
|
|
+ clearInterval(this.timer);
|
|
|
+ clearInterval(this.timer_group);
|
|
|
+ StudentExitLiveRoom({ task_id: this.task_id, room_user_id: this.room_user_id });
|
|
|
+ common.closeVideo('picture');
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ getLiveRoomInfo() {
|
|
|
+ GetLiveRoomInfo({ task_id: this.task_id }).then(
|
|
|
+ ({
|
|
|
+ room_id,
|
|
|
+ video_mode,
|
|
|
+ task_name,
|
|
|
+ cs_item_name,
|
|
|
+ course_name,
|
|
|
+ teacher_name,
|
|
|
+ student_count,
|
|
|
+ teacher_image_url
|
|
|
+ }) => {
|
|
|
+ this.roomInfo = {
|
|
|
+ room_id,
|
|
|
+ video_mode,
|
|
|
+ task_name,
|
|
|
+ cs_item_name,
|
|
|
+ course_name,
|
|
|
+ teacher_name,
|
|
|
+ student_count,
|
|
|
+ teacher_image_url
|
|
|
+ };
|
|
|
+ }
|
|
|
+ );
|
|
|
+ },
|
|
|
+
|
|
|
+ exitRoom() {
|
|
|
+ StudentExitLiveRoom({ task_id: this.task_id, room_user_id: this.room_user_id }).then(() => {
|
|
|
+ this.$router.push('/');
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ getLiveStat() {
|
|
|
+ common.getLiveStat({
|
|
|
+ success: data => {
|
|
|
+ this.liveStat = data.started;
|
|
|
+ },
|
|
|
+ fail: str => {
|
|
|
+ this.liveStat = false;
|
|
|
+ console.log('直播关闭状态或查询直播失败', str);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ // 发消息
|
|
|
+ sendMsg() {
|
|
|
+ common.sendMsg(this.msg);
|
|
|
+ this.msg = '';
|
|
|
+ },
|
|
|
+
|
|
|
+ getDevice() {
|
|
|
+ common.getDevice();
|
|
|
+ },
|
|
|
+
|
|
|
+ getLiveRoomStudentList() {
|
|
|
+ GetLiveRoomStudentList({ task_id: this.task_id }).then(({ student_list }) => {
|
|
|
+ this.student_list = student_list;
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ getLiveRoomStudentListPolling() {
|
|
|
+ this.timer = setInterval(() => {
|
|
|
+ this.getLiveRoomStudentList();
|
|
|
+ }, 5000);
|
|
|
+ },
|
|
|
+
|
|
|
+ // 分组讨论
|
|
|
+ isEnableGroup() {
|
|
|
+ this.timer_group = setInterval(() => {
|
|
|
+ IsEnableGroup({ task_id: this.task_id })
|
|
|
+ .then(({ is_enable_group }) => {
|
|
|
+ if (is_enable_group === 'true') {
|
|
|
+ clearInterval(this.timer_group);
|
|
|
+ this.getMyGroupInfo_Student();
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ clearInterval(this.timer_group);
|
|
|
+ });
|
|
|
+ }, 5000);
|
|
|
+ },
|
|
|
+
|
|
|
+ getMyGroupInfo_Student() {
|
|
|
+ GetMyGroupInfo_Student({
|
|
|
+ task_id: this.task_id
|
|
|
+ }).then(({ student_list }) => {
|
|
|
+ let data = student_list.find(el => {
|
|
|
+ return el.is_self === 'true';
|
|
|
+ });
|
|
|
+ console.log(data);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss">
|
|
|
+@import '~@/styles/mixin.scss';
|
|
|
+$live-bc: #3d3938;
|
|
|
+
|
|
|
+.group {
|
|
|
+ @include container;
|
|
|
+
|
|
|
+ // 顶部
|
|
|
+ &-top {
|
|
|
+ background-color: #fff;
|
|
|
+ padding: 24px 32px;
|
|
|
+ border-top-left-radius: 8px;
|
|
|
+ border-top-right-radius: 8px;
|
|
|
+
|
|
|
+ .live-title {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+
|
|
|
+ &-name {
|
|
|
+ font-size: 22px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-button {
|
|
|
+ border-radius: 4px;
|
|
|
+ padding: 7px 12px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .live-course-name {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #737373;
|
|
|
+ line-height: 30px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .live-teacher {
|
|
|
+ margin-top: 12px;
|
|
|
+
|
|
|
+ .svg-icon {
|
|
|
+ margin-right: 8px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &-name {
|
|
|
+ margin-right: 60px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 主容器
|
|
|
+ &-container {
|
|
|
+ display: flex;
|
|
|
+ justify-content: left;
|
|
|
+
|
|
|
+ &-left {
|
|
|
+ width: 832px;
|
|
|
+ background-color: #fff;
|
|
|
+ border-radius: 8px;
|
|
|
+
|
|
|
+ // 分组讨论
|
|
|
+ .group-discussion {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ width: 100%;
|
|
|
+ height: 468px;
|
|
|
+ position: relative;
|
|
|
+ background-color: $live-bc;
|
|
|
+ overflow: hidden;
|
|
|
+
|
|
|
+ .group-box {
|
|
|
+ width: 256px;
|
|
|
+ height: 144px;
|
|
|
+ margin: 8px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .button-group {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ height: 48px;
|
|
|
+ background-color: #4d4d4d;
|
|
|
+ padding: 0 15px;
|
|
|
+ border-bottom-left-radius: 5px;
|
|
|
+
|
|
|
+ .svg-icon {
|
|
|
+ font-size: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &-left {
|
|
|
+ > span {
|
|
|
+ display: inline-block;
|
|
|
+ height: 100%;
|
|
|
+ padding: 14px 16px;
|
|
|
+ cursor: pointer;
|
|
|
+
|
|
|
+ &:active,
|
|
|
+ &:hover {
|
|
|
+ background-color: #3d3d3d;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 聊天窗口
|
|
|
+ &-chat {
|
|
|
+ height: 278px;
|
|
|
+ border: 1px solid #ccc;
|
|
|
+ border-bottom-left-radius: 8px;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ justify-content: space-between;
|
|
|
+
|
|
|
+ .chat-top {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 15px 15px 10px;
|
|
|
+ border-bottom: 1px solid #e6e6e6;
|
|
|
+ color: #959595;
|
|
|
+
|
|
|
+ label {
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+
|
|
|
+ .allow-chat {
|
|
|
+ margin-right: 12px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .chat-window {
|
|
|
+ position: relative;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ overflow: hidden;
|
|
|
+
|
|
|
+ &-ul {
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ overflow: auto;
|
|
|
+
|
|
|
+ .msg-normal {
|
|
|
+ padding: 7px 16px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .chat-speak {
|
|
|
+ padding: 16px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ &-right {
|
|
|
+ padding: 8px;
|
|
|
+ background-color: #2c2c2c;
|
|
|
+ border-end-end-radius: 8px;
|
|
|
+
|
|
|
+ .live-teacher-lens {
|
|
|
+ position: relative;
|
|
|
+ overflow: hidden;
|
|
|
+
|
|
|
+ #live {
|
|
|
+ width: 352px;
|
|
|
+ height: 198px;
|
|
|
+ background-color: $live-bc;
|
|
|
+ }
|
|
|
+
|
|
|
+ .live-wrapper {
|
|
|
+ position: absolute;
|
|
|
+ height: 40px;
|
|
|
+ width: 100%;
|
|
|
+ background-color: #000;
|
|
|
+ opacity: 0.7;
|
|
|
+ color: #fff;
|
|
|
+ line-height: 40px;
|
|
|
+ padding: 0 16px;
|
|
|
+ transition: all 300ms ease-in 0s;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .student-list {
|
|
|
+ width: 100%;
|
|
|
+ padding: 24px 16px;
|
|
|
+ margin-top: 2px;
|
|
|
+ height: calc(100% - 200px);
|
|
|
+ background-color: #2c2c2c;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #fff;
|
|
|
+
|
|
|
+ &-title {
|
|
|
+ margin-bottom: 16px;
|
|
|
+ }
|
|
|
+
|
|
|
+ li {
|
|
|
+ display: flex;
|
|
|
+ margin-bottom: 16px;
|
|
|
+
|
|
|
+ .student-list-left {
|
|
|
+ flex: 7;
|
|
|
+
|
|
|
+ .name {
|
|
|
+ vertical-align: super;
|
|
|
+ margin-left: 8px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .student-list-right {
|
|
|
+ flex: 3;
|
|
|
+
|
|
|
+ .svg-icon {
|
|
|
+ font-size: 18px;
|
|
|
+ cursor: pointer;
|
|
|
+ margin-top: 7px;
|
|
|
+ margin-right: 8px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|