|  | @@ -0,0 +1,546 @@
 | 
	
		
			
				|  |  | +<template>
 | 
	
		
			
				|  |  | +  <BaseLive>
 | 
	
		
			
				|  |  | +    <div class="teacher">
 | 
	
		
			
				|  |  | +      <div class="middle">
 | 
	
		
			
				|  |  | +        <!-- 教师学员列表 -->
 | 
	
		
			
				|  |  | +        <div :class="['live-list', { 'only-teacher': studentList.length <= 0 }]">
 | 
	
		
			
				|  |  | +          <div class="live-list-item">
 | 
	
		
			
				|  |  | +            <div class="portrait">
 | 
	
		
			
				|  |  | +              <span>{{ roomInfo.teacher_name }}</span>
 | 
	
		
			
				|  |  | +            </div>
 | 
	
		
			
				|  |  | +            <span class="teacher-card">教师</span>
 | 
	
		
			
				|  |  | +            <span class="name">
 | 
	
		
			
				|  |  | +              {{ roomInfo.teacher_name }}
 | 
	
		
			
				|  |  | +            </span>
 | 
	
		
			
				|  |  | +          </div>
 | 
	
		
			
				|  |  | +          <div
 | 
	
		
			
				|  |  | +            v-for="{ student_id, student_name, student_image_url } in studentList"
 | 
	
		
			
				|  |  | +            :key="student_id"
 | 
	
		
			
				|  |  | +            class="live-list-item"
 | 
	
		
			
				|  |  | +          >
 | 
	
		
			
				|  |  | +            <el-avatar :size="122" :src="student_image_url" />
 | 
	
		
			
				|  |  | +            <span class="student-card">学生</span>
 | 
	
		
			
				|  |  | +            <span class="name">
 | 
	
		
			
				|  |  | +              {{ student_name }}
 | 
	
		
			
				|  |  | +            </span>
 | 
	
		
			
				|  |  | +          </div>
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        <!-- 直播视频 -->
 | 
	
		
			
				|  |  | +        <div id="live" class=""></div>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        <!-- 聊天 -->
 | 
	
		
			
				|  |  | +        <div v-show="chatShow" class="chat">
 | 
	
		
			
				|  |  | +          <div class="title">聊天</div>
 | 
	
		
			
				|  |  | +          <div class="chat-main"></div>
 | 
	
		
			
				|  |  | +          <div class="msg"></div>
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        <!-- 成员列表 -->
 | 
	
		
			
				|  |  | +        <div v-show="memberShow" class="member-list">
 | 
	
		
			
				|  |  | +          <div class="title">成员管理</div>
 | 
	
		
			
				|  |  | +          <div
 | 
	
		
			
				|  |  | +            v-for="{ student_id, student_name, student_image_url } in studentList"
 | 
	
		
			
				|  |  | +            :key="student_id"
 | 
	
		
			
				|  |  | +            :title="student_image_url"
 | 
	
		
			
				|  |  | +          >
 | 
	
		
			
				|  |  | +            <span>{{ student_name }}</span>
 | 
	
		
			
				|  |  | +          </div>
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +      </div>
 | 
	
		
			
				|  |  | +      <div class="bottom">
 | 
	
		
			
				|  |  | +        <div class="operation">
 | 
	
		
			
				|  |  | +          <div class="operation-item">
 | 
	
		
			
				|  |  | +            <img src="@/assets/live/voice-off.png" alt="" />
 | 
	
		
			
				|  |  | +            <span>解除静音</span>
 | 
	
		
			
				|  |  | +          </div>
 | 
	
		
			
				|  |  | +          <div class="operation-item">
 | 
	
		
			
				|  |  | +            <img src="@/assets/live/monitor-off.png" alt="" />
 | 
	
		
			
				|  |  | +            <span>开启视频</span>
 | 
	
		
			
				|  |  | +          </div>
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +        <div class="operation">
 | 
	
		
			
				|  |  | +          <div class="operation-item">
 | 
	
		
			
				|  |  | +            <img src="@/assets/live/laptop-computer.png" alt="" />
 | 
	
		
			
				|  |  | +            <span>共享屏幕</span>
 | 
	
		
			
				|  |  | +          </div>
 | 
	
		
			
				|  |  | +          <div class="operation-item">
 | 
	
		
			
				|  |  | +            <img src="@/assets/live/folder-upload.png" alt="" />
 | 
	
		
			
				|  |  | +            <span>课件推送</span>
 | 
	
		
			
				|  |  | +          </div>
 | 
	
		
			
				|  |  | +          <div class="operation-item">
 | 
	
		
			
				|  |  | +            <img src="@/assets/live/every-user.png" alt="" />
 | 
	
		
			
				|  |  | +            <span>分组讨论</span>
 | 
	
		
			
				|  |  | +          </div>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          <span class="line"></span>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          <div class="operation-item" @click="toggle">
 | 
	
		
			
				|  |  | +            <img src="@/assets/live/communication.png" alt="" />
 | 
	
		
			
				|  |  | +            <span>聊天</span>
 | 
	
		
			
				|  |  | +          </div>
 | 
	
		
			
				|  |  | +          <div class="operation-item" @click="memberToggle">
 | 
	
		
			
				|  |  | +            <img src="@/assets/live/peoples.png" alt="" />
 | 
	
		
			
				|  |  | +            <span>成员列表</span>
 | 
	
		
			
				|  |  | +          </div>
 | 
	
		
			
				|  |  | +          <div class="operation-item">
 | 
	
		
			
				|  |  | +            <img src="@/assets/live/recording.png" alt="" />
 | 
	
		
			
				|  |  | +            <span>录制</span>
 | 
	
		
			
				|  |  | +          </div>
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +        <div class="operation">
 | 
	
		
			
				|  |  | +          <button class="live-button" @click="() => (liveStat ? closeLiveRoom() : startLive())">
 | 
	
		
			
				|  |  | +            {{ liveStat ? '结束直播' : '开始直播' }}
 | 
	
		
			
				|  |  | +          </button>
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +      </div>
 | 
	
		
			
				|  |  | +    </div>
 | 
	
		
			
				|  |  | +  </BaseLive>
 | 
	
		
			
				|  |  | +</template>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +<script>
 | 
	
		
			
				|  |  | +export default {
 | 
	
		
			
				|  |  | +  name: 'TeacherLive'
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +</script>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +<script setup>
 | 
	
		
			
				|  |  | +import {
 | 
	
		
			
				|  |  | +  CloseLiveRoom,
 | 
	
		
			
				|  |  | +  StudentExitLiveRoom,
 | 
	
		
			
				|  |  | +  StartGroup,
 | 
	
		
			
				|  |  | +  GetGroupStatus,
 | 
	
		
			
				|  |  | +  DealStudentConnection,
 | 
	
		
			
				|  |  | +  GetStudentInfo_Connection,
 | 
	
		
			
				|  |  | +  GetLiveRoomData_DRTD,
 | 
	
		
			
				|  |  | +  GetLiveRoomInfo
 | 
	
		
			
				|  |  | +} from '@/api/live';
 | 
	
		
			
				|  |  | +import { ref, provide, inject, onMounted, onBeforeUnmount } from 'vue';
 | 
	
		
			
				|  |  | +import { Loading, Message, MessageBox } from 'element-ui';
 | 
	
		
			
				|  |  | +import { useRoute, useRouter } from 'vue-router/composables';
 | 
	
		
			
				|  |  | +import { useChat, useMemberList, useDownloadSDK, useLive, rtc } from '../index';
 | 
	
		
			
				|  |  | +import { useTeacherLive } from './live';
 | 
	
		
			
				|  |  | +import store from '@/store';
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import BaseLive from '../index.vue';
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const router = useRouter();
 | 
	
		
			
				|  |  | +const route = useRoute();
 | 
	
		
			
				|  |  | +const task_id = route.query.task_id;
 | 
	
		
			
				|  |  | +provide('task_id', task_id);
 | 
	
		
			
				|  |  | +const $t = inject('$t');
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const { msg, chatShow, sendMsg, toggle } = useChat(rtc);
 | 
	
		
			
				|  |  | +const { memberShow, toggle: memberToggle } = useMemberList(rtc);
 | 
	
		
			
				|  |  | +const { startLive, stopLive } = useTeacherLive(rtc);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const isTeacher = store.getters.isTeacher;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// 连麦
 | 
	
		
			
				|  |  | +let connect = ref(false);
 | 
	
		
			
				|  |  | +// 连线学员信息
 | 
	
		
			
				|  |  | +let connectStudent = ref({});
 | 
	
		
			
				|  |  | +// 等待接通
 | 
	
		
			
				|  |  | +let callLoading = ref(false);
 | 
	
		
			
				|  |  | +let dialogVisible = ref(false);
 | 
	
		
			
				|  |  | +// 学员完成
 | 
	
		
			
				|  |  | +let dialogVisibleComplete = ref(false);
 | 
	
		
			
				|  |  | +// 定时器
 | 
	
		
			
				|  |  | +let timer = ref(null);
 | 
	
		
			
				|  |  | +let remoteStreamType = ref(-1);
 | 
	
		
			
				|  |  | +let roomData = ref({
 | 
	
		
			
				|  |  | +  desc: '直播间标题',
 | 
	
		
			
				|  |  | +  name: '姓名',
 | 
	
		
			
				|  |  | +  user: {
 | 
	
		
			
				|  |  | +    id: '',
 | 
	
		
			
				|  |  | +    name: '',
 | 
	
		
			
				|  |  | +    role: 'talker',
 | 
	
		
			
				|  |  | +    rommid: ''
 | 
	
		
			
				|  |  | +  },
 | 
	
		
			
				|  |  | +  max_users: 1,
 | 
	
		
			
				|  |  | +  allow_chat: true,
 | 
	
		
			
				|  |  | +  allow_audio: true,
 | 
	
		
			
				|  |  | +  allow_speak: true
 | 
	
		
			
				|  |  | +});
 | 
	
		
			
				|  |  | +let roomInfo = ref({
 | 
	
		
			
				|  |  | +  room_id: '',
 | 
	
		
			
				|  |  | +  video_mode: 1,
 | 
	
		
			
				|  |  | +  task_name: '',
 | 
	
		
			
				|  |  | +  cs_item_name: '',
 | 
	
		
			
				|  |  | +  course_name: '',
 | 
	
		
			
				|  |  | +  teacher_name: '',
 | 
	
		
			
				|  |  | +  student_count: 0,
 | 
	
		
			
				|  |  | +  student_connection_info: {}
 | 
	
		
			
				|  |  | +});
 | 
	
		
			
				|  |  | +let loadedNumber = ref(0);
 | 
	
		
			
				|  |  | +let speakData = ref({});
 | 
	
		
			
				|  |  | +let roomContext = ref({});
 | 
	
		
			
				|  |  | +let chatList = ref([]);
 | 
	
		
			
				|  |  | +let isDrawSetting = ref(false);
 | 
	
		
			
				|  |  | +let curColor = ref('#343434');
 | 
	
		
			
				|  |  | +let drawColorList = ['#FF4747', '#343434', '#628EFF', '#FFCA0E'];
 | 
	
		
			
				|  |  | +let drawThicknessList = ['1', '3', '5'];
 | 
	
		
			
				|  |  | +// 直播间学员列表
 | 
	
		
			
				|  |  | +let student_list = ref([]);
 | 
	
		
			
				|  |  | +// 直播状态
 | 
	
		
			
				|  |  | +let liveStat = ref(false);
 | 
	
		
			
				|  |  | +let liveMenuShow = ref(false);
 | 
	
		
			
				|  |  | +// 分组讨论
 | 
	
		
			
				|  |  | +let groupNumList = ref([]);
 | 
	
		
			
				|  |  | +let group_count = ref(1);
 | 
	
		
			
				|  |  | +// 网络整体情况
 | 
	
		
			
				|  |  | +let netStatus = ref(0);
 | 
	
		
			
				|  |  | +let dialogVisibleGroup = ref(false);
 | 
	
		
			
				|  |  | +let dialogVisibleDevice = ref(false);
 | 
	
		
			
				|  |  | +let isRecreate = ref(false);
 | 
	
		
			
				|  |  | +let device = ref({
 | 
	
		
			
				|  |  | +  video: [],
 | 
	
		
			
				|  |  | +  audio: []
 | 
	
		
			
				|  |  | +});
 | 
	
		
			
				|  |  | +// 本地视频流画面、声音
 | 
	
		
			
				|  |  | +let hasVideo = ref(false);
 | 
	
		
			
				|  |  | +let hasAudio = ref(false);
 | 
	
		
			
				|  |  | +let material_list = ref([]);
 | 
	
		
			
				|  |  | +let materialId = ref('');
 | 
	
		
			
				|  |  | +let materialType = ref('');
 | 
	
		
			
				|  |  | +let docListInfo = ref(null);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const { downloadWebSDK } = useDownloadSDK();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const { init, getLiveStat, closeVideo, pauseVideo, playVideo, pauseAudio, playAudio } = useLive();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +onMounted(() => {
 | 
	
		
			
				|  |  | +  getLiveRoomData_DRTDPolling();
 | 
	
		
			
				|  |  | +});
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +onBeforeUnmount(() => {
 | 
	
		
			
				|  |  | +  clearInterval(timer.value);
 | 
	
		
			
				|  |  | +  closeVideo('main');
 | 
	
		
			
				|  |  | +});
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * 得到分组状态
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +let loadingInstance = null;
 | 
	
		
			
				|  |  | +GetGroupStatus({ task_id }).then(({ is_enable_group }) => {
 | 
	
		
			
				|  |  | +  if (is_enable_group === 'true') {
 | 
	
		
			
				|  |  | +    router.push({
 | 
	
		
			
				|  |  | +      path: '/live/teacher/group',
 | 
	
		
			
				|  |  | +      query: {
 | 
	
		
			
				|  |  | +        task_id
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    loadingInstance = Loading.service({
 | 
	
		
			
				|  |  | +      text: $t('Key425'),
 | 
	
		
			
				|  |  | +      background: '#fff'
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +    loadingInstance;
 | 
	
		
			
				|  |  | +    downloadWebSDK(initSDK);
 | 
	
		
			
				|  |  | +    getLiveRoomData_DRTD();
 | 
	
		
			
				|  |  | +    getLiveRoomInfo();
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +});
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +function initSDK() {
 | 
	
		
			
				|  |  | +  const { live_room_sys_user_id, room_id, session_id } = route.query;
 | 
	
		
			
				|  |  | +  init({
 | 
	
		
			
				|  |  | +    userid: live_room_sys_user_id,
 | 
	
		
			
				|  |  | +    roomid: room_id,
 | 
	
		
			
				|  |  | +    sessionid: session_id
 | 
	
		
			
				|  |  | +  });
 | 
	
		
			
				|  |  | +  // common.initListener(this); // 注册监听事件
 | 
	
		
			
				|  |  | +  getLiveStat({
 | 
	
		
			
				|  |  | +    success: (data) => {
 | 
	
		
			
				|  |  | +      liveStat.value = data.started;
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    fail: (str) => {
 | 
	
		
			
				|  |  | +      liveStat.value = false;
 | 
	
		
			
				|  |  | +      console.log('直播关闭状态或查询直播失败', str);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  });
 | 
	
		
			
				|  |  | +  loadingInstance.close();
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * 获取直播间学员列表
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +function getLiveRoomData_DRTD() {
 | 
	
		
			
				|  |  | +  GetLiveRoomData_DRTD({ task_id }).then(({ student_list: sList, material_list: mList }) => {
 | 
	
		
			
				|  |  | +    student_list.value = sList;
 | 
	
		
			
				|  |  | +    material_list.value = mList;
 | 
	
		
			
				|  |  | +  });
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +function getLiveRoomData_DRTDPolling() {
 | 
	
		
			
				|  |  | +  timer.value = setInterval(() => {
 | 
	
		
			
				|  |  | +    getLiveRoomData_DRTD();
 | 
	
		
			
				|  |  | +  }, 5000);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * 获取直播间信息
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +function getLiveRoomInfo() {
 | 
	
		
			
				|  |  | +  GetLiveRoomInfo({ task_id }).then(
 | 
	
		
			
				|  |  | +    ({
 | 
	
		
			
				|  |  | +      room_id,
 | 
	
		
			
				|  |  | +      video_mode,
 | 
	
		
			
				|  |  | +      task_name,
 | 
	
		
			
				|  |  | +      cs_item_name,
 | 
	
		
			
				|  |  | +      course_name,
 | 
	
		
			
				|  |  | +      teacher_name,
 | 
	
		
			
				|  |  | +      student_count,
 | 
	
		
			
				|  |  | +      student_connection_info
 | 
	
		
			
				|  |  | +    }) => {
 | 
	
		
			
				|  |  | +      roomInfo.value = {
 | 
	
		
			
				|  |  | +        room_id,
 | 
	
		
			
				|  |  | +        video_mode,
 | 
	
		
			
				|  |  | +        task_name,
 | 
	
		
			
				|  |  | +        cs_item_name,
 | 
	
		
			
				|  |  | +        course_name,
 | 
	
		
			
				|  |  | +        teacher_name,
 | 
	
		
			
				|  |  | +        student_count,
 | 
	
		
			
				|  |  | +        student_connection_info
 | 
	
		
			
				|  |  | +      };
 | 
	
		
			
				|  |  | +      connectStudent.value = student_connection_info;
 | 
	
		
			
				|  |  | +      if (student_connection_info.connection_status === 1) {
 | 
	
		
			
				|  |  | +        callLoading.value = true;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      if (student_connection_info.connection_status === 2) {
 | 
	
		
			
				|  |  | +        connect.value = true;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  );
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * 本地流视频开启、关闭
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +function playOrPauseVideo() {
 | 
	
		
			
				|  |  | +  if (device.value.video.length === 0) {
 | 
	
		
			
				|  |  | +    return Message.warning($t('Key399'));
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  if (hasVideo.value) {
 | 
	
		
			
				|  |  | +    pauseVideo({
 | 
	
		
			
				|  |  | +      streamName: 'main',
 | 
	
		
			
				|  |  | +      success: () => {
 | 
	
		
			
				|  |  | +        Message.success($t('Key433'));
 | 
	
		
			
				|  |  | +        hasVideo.value = false;
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      fail: (str) => {
 | 
	
		
			
				|  |  | +        Message.warning(str);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    playVideo({
 | 
	
		
			
				|  |  | +      streamName: 'main',
 | 
	
		
			
				|  |  | +      success: () => {
 | 
	
		
			
				|  |  | +        Message.success($t('Key434'));
 | 
	
		
			
				|  |  | +        hasVideo.value = true;
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      fail: (str) => {
 | 
	
		
			
				|  |  | +        Message.warning(str);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * 本地流音频开启、关闭
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +function playOrPauseAudio() {
 | 
	
		
			
				|  |  | +  if (device.value.audio.length === 0) {
 | 
	
		
			
				|  |  | +    return Message.warning($t('Key401'));
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  if (hasAudio.value) {
 | 
	
		
			
				|  |  | +    pauseAudio({
 | 
	
		
			
				|  |  | +      streamName: 'main',
 | 
	
		
			
				|  |  | +      success: () => {
 | 
	
		
			
				|  |  | +        Message.success($t('Key435'));
 | 
	
		
			
				|  |  | +        hasAudio.value = false;
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      fail: (str) => {
 | 
	
		
			
				|  |  | +        Message.warning(str);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    playAudio({
 | 
	
		
			
				|  |  | +      streamName: 'main',
 | 
	
		
			
				|  |  | +      success: () => {
 | 
	
		
			
				|  |  | +        Message.success($t('Key436'));
 | 
	
		
			
				|  |  | +        hasAudio.value = true;
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      fail: (str) => {
 | 
	
		
			
				|  |  | +        Message.warning(str);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * 关闭直播间
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +function closeLiveRoom() {
 | 
	
		
			
				|  |  | +  MessageBox.confirm('是否关闭当前直播?', '提示', {
 | 
	
		
			
				|  |  | +    confirmButtonText: '确定',
 | 
	
		
			
				|  |  | +    cancelButtonText: '取消',
 | 
	
		
			
				|  |  | +    type: 'warning'
 | 
	
		
			
				|  |  | +  }).then(() => {
 | 
	
		
			
				|  |  | +    CloseLiveRoom({ task_id }).then(() => {
 | 
	
		
			
				|  |  | +      router.push('/');
 | 
	
		
			
				|  |  | +      Message.success($t('Key426'));
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +    stopLive();
 | 
	
		
			
				|  |  | +  });
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +</script>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +<style lang="scss" scoped>
 | 
	
		
			
				|  |  | +.teacher {
 | 
	
		
			
				|  |  | +  display: flex;
 | 
	
		
			
				|  |  | +  flex-direction: column;
 | 
	
		
			
				|  |  | +  height: 100%;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  .middle {
 | 
	
		
			
				|  |  | +    flex: 1;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    .live-list {
 | 
	
		
			
				|  |  | +      display: flex;
 | 
	
		
			
				|  |  | +      gap: 40px;
 | 
	
		
			
				|  |  | +      height: 100%;
 | 
	
		
			
				|  |  | +      padding: 53px 65px 32px;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      &.only-teacher {
 | 
	
		
			
				|  |  | +        align-items: center;
 | 
	
		
			
				|  |  | +        justify-content: center;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      &-item {
 | 
	
		
			
				|  |  | +        position: relative;
 | 
	
		
			
				|  |  | +        display: flex;
 | 
	
		
			
				|  |  | +        flex-direction: column;
 | 
	
		
			
				|  |  | +        row-gap: 16px;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        .portrait {
 | 
	
		
			
				|  |  | +          width: 122px;
 | 
	
		
			
				|  |  | +          height: 122px;
 | 
	
		
			
				|  |  | +          line-height: 122px;
 | 
	
		
			
				|  |  | +          color: #fff;
 | 
	
		
			
				|  |  | +          text-align: center;
 | 
	
		
			
				|  |  | +          background-color: #7a9fff;
 | 
	
		
			
				|  |  | +          border-radius: 50%;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        %card,
 | 
	
		
			
				|  |  | +        .teacher-card {
 | 
	
		
			
				|  |  | +          position: absolute;
 | 
	
		
			
				|  |  | +          top: 105px;
 | 
	
		
			
				|  |  | +          left: 34px;
 | 
	
		
			
				|  |  | +          padding: 4px 8px;
 | 
	
		
			
				|  |  | +          background-color: #ffb342;
 | 
	
		
			
				|  |  | +          border-radius: 4px;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        .student-card {
 | 
	
		
			
				|  |  | +          @extend %card;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          background-color: #c2ff42;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        .name {
 | 
	
		
			
				|  |  | +          text-align: center;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    %right-fixed {
 | 
	
		
			
				|  |  | +      position: fixed;
 | 
	
		
			
				|  |  | +      top: 96px;
 | 
	
		
			
				|  |  | +      right: 0;
 | 
	
		
			
				|  |  | +      width: 227px;
 | 
	
		
			
				|  |  | +      height: calc(100% - 192px);
 | 
	
		
			
				|  |  | +      background-color: #f3f3f3;
 | 
	
		
			
				|  |  | +      border-left: 1px solid #e5e5e5;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      .title {
 | 
	
		
			
				|  |  | +        height: 38px;
 | 
	
		
			
				|  |  | +        padding: 8px;
 | 
	
		
			
				|  |  | +        font-size: 14px;
 | 
	
		
			
				|  |  | +        font-weight: 400;
 | 
	
		
			
				|  |  | +        line-height: 22px;
 | 
	
		
			
				|  |  | +        border-bottom: 1px solid #e5e5e5;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    .chat {
 | 
	
		
			
				|  |  | +      @extend %right-fixed;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      &-main {
 | 
	
		
			
				|  |  | +        height: calc(100% - 156px);
 | 
	
		
			
				|  |  | +        background-color: #fff;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      .msg {
 | 
	
		
			
				|  |  | +        height: 118px;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    .member-list {
 | 
	
		
			
				|  |  | +      @extend %right-fixed;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  .bottom {
 | 
	
		
			
				|  |  | +    display: flex;
 | 
	
		
			
				|  |  | +    align-items: center;
 | 
	
		
			
				|  |  | +    justify-content: space-between;
 | 
	
		
			
				|  |  | +    height: 96px;
 | 
	
		
			
				|  |  | +    padding: 12px 16px;
 | 
	
		
			
				|  |  | +    background-color: #f8f8f8;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    .operation {
 | 
	
		
			
				|  |  | +      display: flex;
 | 
	
		
			
				|  |  | +      column-gap: 16px;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      &-item {
 | 
	
		
			
				|  |  | +        display: flex;
 | 
	
		
			
				|  |  | +        flex-direction: column;
 | 
	
		
			
				|  |  | +        row-gap: 4px;
 | 
	
		
			
				|  |  | +        align-items: center;
 | 
	
		
			
				|  |  | +        width: 80px;
 | 
	
		
			
				|  |  | +        height: 70px;
 | 
	
		
			
				|  |  | +        padding: 8px;
 | 
	
		
			
				|  |  | +        cursor: pointer;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        &:active {
 | 
	
		
			
				|  |  | +          background-color: #e5e5e5;
 | 
	
		
			
				|  |  | +          border-radius: 8px;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        img {
 | 
	
		
			
				|  |  | +          width: 32px;
 | 
	
		
			
				|  |  | +          height: 32px;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      .line {
 | 
	
		
			
				|  |  | +        width: 2px;
 | 
	
		
			
				|  |  | +        height: 70px;
 | 
	
		
			
				|  |  | +        background-color: #d0d0d0;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      .live-button {
 | 
	
		
			
				|  |  | +        height: 48px;
 | 
	
		
			
				|  |  | +        padding: 8px 24px;
 | 
	
		
			
				|  |  | +        font-size: 20px;
 | 
	
		
			
				|  |  | +        font-weight: 500;
 | 
	
		
			
				|  |  | +        color: #e52e2e;
 | 
	
		
			
				|  |  | +        cursor: pointer;
 | 
	
		
			
				|  |  | +        border: 2px solid #e52e2e;
 | 
	
		
			
				|  |  | +        border-radius: 4px;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +</style>
 |