|  | @@ -6,7 +6,8 @@ import {
 | 
	
		
			
				|  |  |    ref,
 | 
	
		
			
				|  |  |    Transition,
 | 
	
		
			
				|  |  |    computed,
 | 
	
		
			
				|  |  | -  nextTick
 | 
	
		
			
				|  |  | +  nextTick,
 | 
	
		
			
				|  |  | +  watch
 | 
	
		
			
				|  |  |  } from 'vue';
 | 
	
		
			
				|  |  |  import styles from './index.module.less';
 | 
	
		
			
				|  |  |  import 'plyr/dist/plyr.css';
 | 
	
	
		
			
				|  | @@ -73,6 +74,20 @@ import iconUp from './new-image/icon-up.png';
 | 
	
		
			
				|  |  |  import iconWhite from './new-image/icon-white.png';
 | 
	
		
			
				|  |  |  import iconWork from './new-image/icon-work.png';
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +import rightIconEnd from './image/right_icon1.png';
 | 
	
		
			
				|  |  | +import rightIconArrange from './image/right_icon2.png';
 | 
	
		
			
				|  |  | +import rightIconPostil from './image/right_icon3.png';
 | 
	
		
			
				|  |  | +import rightIconWhiteboard from './image/right_icon4.png';
 | 
	
		
			
				|  |  | +import rightIconMetronome from './image/right_icon5.png';
 | 
	
		
			
				|  |  | +import rightIconTuner from './image/right_icon6.png';
 | 
	
		
			
				|  |  | +import rightIconTimer from './image/right_icon7.png';
 | 
	
		
			
				|  |  | +import rightIconPackUp from './image/right_icon8.png';
 | 
	
		
			
				|  |  | +import bottomIconSwitch from './image/bottom_icon1.png';
 | 
	
		
			
				|  |  | +import bottomIconResource from './image/bottom_icon2.png';
 | 
	
		
			
				|  |  | +import bottomIconPre from './image/bottom_icon3.png';
 | 
	
		
			
				|  |  | +import bottomIconNext from './image/bottom_icon4.png';
 | 
	
		
			
				|  |  | +import rightHideIcon from './image/right_hide_icon.png';
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  export type ToolType = 'init' | 'pen' | 'whiteboard';
 | 
	
		
			
				|  |  |  export type ToolItem = {
 | 
	
		
			
				|  |  |    type: ToolType;
 | 
	
	
		
			
				|  | @@ -186,6 +201,10 @@ export default defineComponent({
 | 
	
		
			
				|  |  |        timer: null as any,
 | 
	
		
			
				|  |  |        item: null as any
 | 
	
		
			
				|  |  |      });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 键盘事件监听状态
 | 
	
		
			
				|  |  | +    const listenerKeyUpState = ref(false);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      const getDetail = async () => {
 | 
	
		
			
				|  |  |        try {
 | 
	
		
			
				|  |  |          const res = await queryCourseware({
 | 
	
	
		
			
				|  | @@ -279,7 +298,6 @@ export default defineComponent({
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      onMounted(() => {
 | 
	
		
			
				|  |  | -      // debugger
 | 
	
		
			
				|  |  |        // initMoveable();
 | 
	
		
			
				|  |  |        const query = route.query;
 | 
	
		
			
				|  |  |        console.log(query, props.preStudentNum, '学生人数');
 | 
	
	
		
			
				|  | @@ -291,10 +309,12 @@ export default defineComponent({
 | 
	
		
			
				|  |  |        data.classGroupId = props.classGroupId || query.classGroupId;
 | 
	
		
			
				|  |  |        data.classId = props.classId || query.classId;
 | 
	
		
			
				|  |  |        data.preStudentNum = props.preStudentNum || query.preStudentNum;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |        window.addEventListener('message', iframeHandle);
 | 
	
		
			
				|  |  |        getDetail();
 | 
	
		
			
				|  |  |        getLessonCoursewareDetail();
 | 
	
		
			
				|  |  | +      if (data.type === 'preview') {
 | 
	
		
			
				|  |  | +        rightList.splice(1,1)
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  |      });
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      const onFullScreen = () => {
 | 
	
	
		
			
				|  | @@ -824,8 +844,6 @@ export default defineComponent({
 | 
	
		
			
				|  |  |          setModelOpen();
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // 监听页面键盘事件 - 上下切换
 | 
	
		
			
				|  |  |      document.body.addEventListener('keyup', (e: KeyboardEvent) => {
 | 
	
		
			
				|  |  |        // console.log(e, 'e');
 | 
	
		
			
				|  |  |        if (e.code === 'ArrowLeft') {
 | 
	
	
		
			
				|  | @@ -839,6 +857,39 @@ export default defineComponent({
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      });
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    const toggleListenerKeyUp = (type: string) => {
 | 
	
		
			
				|  |  | +      if (type === 'remove') {
 | 
	
		
			
				|  |  | +        document.body.removeEventListener('keyup', () => {
 | 
	
		
			
				|  |  | +          listenerKeyUpState.value = false
 | 
	
		
			
				|  |  | +        })
 | 
	
		
			
				|  |  | +      } else {
 | 
	
		
			
				|  |  | +        // 监听页面键盘事件 - 上下切换
 | 
	
		
			
				|  |  | +        document.body.addEventListener('keyup', (e: KeyboardEvent) => {
 | 
	
		
			
				|  |  | +          // console.log(e, 'e');
 | 
	
		
			
				|  |  | +          if (e.code === 'ArrowLeft') {
 | 
	
		
			
				|  |  | +            // if (popupData.activeIndex === 0) return;
 | 
	
		
			
				|  |  | +            setModalOpen();
 | 
	
		
			
				|  |  | +            handlePreAndNext('up');
 | 
	
		
			
				|  |  | +          } else if (e.code === 'ArrowRight') {
 | 
	
		
			
				|  |  | +            // if (popupData.activeIndex === data.itemList.length - 1) return;
 | 
	
		
			
				|  |  | +            setModalOpen();
 | 
	
		
			
				|  |  | +            handlePreAndNext('down');
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +        listenerKeyUpState.value = true
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 监听切换到ppt课件时,手动移除键盘监听器
 | 
	
		
			
				|  |  | +    // watch(() => popupData.activeIndex, () => {
 | 
	
		
			
				|  |  | +    //   const activeItem = data.itemList[popupData.activeIndex];
 | 
	
		
			
				|  |  | +    //   if (activeItem?.type === 'PPT') {
 | 
	
		
			
				|  |  | +    //     toggleListenerKeyUp('remove')
 | 
	
		
			
				|  |  | +    //   } else {
 | 
	
		
			
				|  |  | +    //     !listenerKeyUpState.value && toggleListenerKeyUp('add')
 | 
	
		
			
				|  |  | +    //   }
 | 
	
		
			
				|  |  | +    // })
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      const setModalOpen = (status = true) => {
 | 
	
		
			
				|  |  |        clearTimeout(activeData.timer);
 | 
	
		
			
				|  |  |        activeData.model = status;
 | 
	
	
		
			
				|  | @@ -1053,6 +1104,161 @@ export default defineComponent({
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |        return {}
 | 
	
		
			
				|  |  |      })
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 右侧菜单栏
 | 
	
		
			
				|  |  | +    const rightList = reactive([
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +        name: '结束课程',
 | 
	
		
			
				|  |  | +        name2: '结束预览',
 | 
	
		
			
				|  |  | +        icon: rightIconEnd,
 | 
	
		
			
				|  |  | +        id: 1,
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +        name: '布置作业',
 | 
	
		
			
				|  |  | +        icon: rightIconArrange,
 | 
	
		
			
				|  |  | +        id: 2,
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +        name: '批注',
 | 
	
		
			
				|  |  | +        icon: rightIconPostil,
 | 
	
		
			
				|  |  | +        id: 3,
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +        name: '白板',
 | 
	
		
			
				|  |  | +        icon: rightIconWhiteboard,
 | 
	
		
			
				|  |  | +        id: 4,
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +        name: '节拍器',
 | 
	
		
			
				|  |  | +        icon: rightIconMetronome,
 | 
	
		
			
				|  |  | +        id: 5,
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +        name: '调音器',
 | 
	
		
			
				|  |  | +        icon: rightIconTuner,
 | 
	
		
			
				|  |  | +        id: 6,
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +        name: '计时器',
 | 
	
		
			
				|  |  | +        icon: rightIconTimer,
 | 
	
		
			
				|  |  | +        id: 7,
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +        name: '收起',
 | 
	
		
			
				|  |  | +        icon: rightIconPackUp,
 | 
	
		
			
				|  |  | +        id: 8,
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +    ]);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 底部菜单栏
 | 
	
		
			
				|  |  | +    const bottomList = reactive([
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +        name: '切换章节',
 | 
	
		
			
				|  |  | +        icon: bottomIconSwitch,
 | 
	
		
			
				|  |  | +        id: 1,
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +        name: '资源列表',
 | 
	
		
			
				|  |  | +        icon: bottomIconResource,
 | 
	
		
			
				|  |  | +        id: 2,
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +        name: '上一张',
 | 
	
		
			
				|  |  | +        icon: bottomIconPre,
 | 
	
		
			
				|  |  | +        id: 3,
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +        name: '下一张',
 | 
	
		
			
				|  |  | +        icon: bottomIconNext,
 | 
	
		
			
				|  |  | +        id: 4,
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    ]);
 | 
	
		
			
				|  |  | +    const rightColumnShow = ref(true);
 | 
	
		
			
				|  |  | + 
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 右边栏操作
 | 
	
		
			
				|  |  | +    const operateRightBtn = async (id: number) => {
 | 
	
		
			
				|  |  | +      switch (id) {
 | 
	
		
			
				|  |  | +        case 1:
 | 
	
		
			
				|  |  | +          if (data.type === 'preview') {
 | 
	
		
			
				|  |  | +            handleStop();
 | 
	
		
			
				|  |  | +            data.removeVisiable = true;
 | 
	
		
			
				|  |  | +            data.removeTitle = '结束预览';
 | 
	
		
			
				|  |  | +            data.removeContent = '请确认是否结束预览?';
 | 
	
		
			
				|  |  | +          } else {
 | 
	
		
			
				|  |  | +            data.removeVisiable = true;
 | 
	
		
			
				|  |  | +            data.removeTitle = '结束课程';
 | 
	
		
			
				|  |  | +            data.removeContent = '请确认是否结束课程?';
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +          break;
 | 
	
		
			
				|  |  | +        case 2:
 | 
	
		
			
				|  |  | +          // 学生人数必须大于0,才可以布置作业
 | 
	
		
			
				|  |  | +          if (data.preStudentNum <= 0) return;
 | 
	
		
			
				|  |  | +          const res = await lessonPreTrainingPage({
 | 
	
		
			
				|  |  | +            coursewareKnowledgeDetailId: data.detailId,
 | 
	
		
			
				|  |  | +            subjectId: data.subjectId,
 | 
	
		
			
				|  |  | +            page: 1,
 | 
	
		
			
				|  |  | +            rows: 99
 | 
	
		
			
				|  |  | +          });
 | 
	
		
			
				|  |  | +          if (res.data.rows && res.data.rows.length) {
 | 
	
		
			
				|  |  | +            data.modalAttendMessage =
 | 
	
		
			
				|  |  | +              '本节课已设置课后作业,是否布置?';
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +          data.modelAttendStatus = true;          
 | 
	
		
			
				|  |  | +          break;
 | 
	
		
			
				|  |  | +        case 3:
 | 
	
		
			
				|  |  | +          openStudyTool({
 | 
	
		
			
				|  |  | +            type: 'pen',
 | 
	
		
			
				|  |  | +            icon: iconNote,
 | 
	
		
			
				|  |  | +            name: '批注'
 | 
	
		
			
				|  |  | +          })          
 | 
	
		
			
				|  |  | +          break;
 | 
	
		
			
				|  |  | +        case 4:
 | 
	
		
			
				|  |  | +          openStudyTool({
 | 
	
		
			
				|  |  | +            type: 'whiteboard',
 | 
	
		
			
				|  |  | +            icon: iconWhite,
 | 
	
		
			
				|  |  | +            name: '白板'
 | 
	
		
			
				|  |  | +          })          
 | 
	
		
			
				|  |  | +          break;
 | 
	
		
			
				|  |  | +        case 5:
 | 
	
		
			
				|  |  | +          startShowModal('beatIcon')
 | 
	
		
			
				|  |  | +          break;
 | 
	
		
			
				|  |  | +        case 6:
 | 
	
		
			
				|  |  | +          startShowModal('toneIcon')
 | 
	
		
			
				|  |  | +          break;
 | 
	
		
			
				|  |  | +        case 7:
 | 
	
		
			
				|  |  | +          startShowModal('setTimeIcon')
 | 
	
		
			
				|  |  | +          break;
 | 
	
		
			
				|  |  | +        case 8:
 | 
	
		
			
				|  |  | +          rightColumnShow.value = false
 | 
	
		
			
				|  |  | +          break;                                                                  
 | 
	
		
			
				|  |  | +        default:
 | 
	
		
			
				|  |  | +          break;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 底部悬浮按钮操作
 | 
	
		
			
				|  |  | +    const operateBottomBtn = (id: number) => {
 | 
	
		
			
				|  |  | +      switch (id) {
 | 
	
		
			
				|  |  | +        case 1:
 | 
	
		
			
				|  |  | +          popupData.chapterOpen = true
 | 
	
		
			
				|  |  | +          break;
 | 
	
		
			
				|  |  | +        case 2:
 | 
	
		
			
				|  |  | +          popupData.open = true
 | 
	
		
			
				|  |  | +          break;
 | 
	
		
			
				|  |  | +        case 3:
 | 
	
		
			
				|  |  | +          if (!isUpArrow.value) return;
 | 
	
		
			
				|  |  | +          handlePreAndNext('up');
 | 
	
		
			
				|  |  | +          break;
 | 
	
		
			
				|  |  | +        case 4:
 | 
	
		
			
				|  |  | +          if (!isDownArrow.value) return;
 | 
	
		
			
				|  |  | +          handlePreAndNext('down');
 | 
	
		
			
				|  |  | +          break;      
 | 
	
		
			
				|  |  | +        default:
 | 
	
		
			
				|  |  | +          break;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      return () => (
 | 
	
		
			
				|  |  |        <div id="playContent" class={[styles.playContent, 'wrap']}>
 | 
	
		
			
				|  |  |          <div
 | 
	
	
		
			
				|  | @@ -1225,10 +1431,11 @@ export default defineComponent({
 | 
	
		
			
				|  |  |                            }}
 | 
	
		
			
				|  |  |                          />
 | 
	
		
			
				|  |  |                        ) 
 | 
	
		
			
				|  |  | -                      : m.type === 'PPT' ? <div class={styles.iframePpt}>
 | 
	
		
			
				|  |  | -                        <div class={styles.pptBox}></div>
 | 
	
		
			
				|  |  | -                        <iframe src={`https://view.officeapps.live.com/op/embed.aspx?src=${encodeURIComponent(m.content)}`} width='100%' height='100%' frameborder='1'></iframe>
 | 
	
		
			
				|  |  | -                      </div>
 | 
	
		
			
				|  |  | +                      // : m.type === 'PPT' ? <div class={styles.iframePpt}>
 | 
	
		
			
				|  |  | +                      //   <div class={styles.pptBox}></div>
 | 
	
		
			
				|  |  | +                      //   <iframe src={`https://view.officeapps.live.com/op/embed.aspx?src=${encodeURIComponent(m.content)}`} width='100%' height='100%' frameborder='1'></iframe>
 | 
	
		
			
				|  |  | +                      // </div>
 | 
	
		
			
				|  |  | +                      : m.type === 'PPT' ? <iframe src={`https://view.officeapps.live.com/op/embed.aspx?src=${encodeURIComponent(m.content)}`} width='100%' height='100%' frameborder='1'></iframe>                     
 | 
	
		
			
				|  |  |                        : (
 | 
	
		
			
				|  |  |                          <MusicScore
 | 
	
		
			
				|  |  |                            activeModel={activeData.model}
 | 
	
	
		
			
				|  | @@ -1251,14 +1458,14 @@ export default defineComponent({
 | 
	
		
			
				|  |  |          </div>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          {/* 头部样式 */}
 | 
	
		
			
				|  |  | -        <div
 | 
	
		
			
				|  |  | +        {/* <div
 | 
	
		
			
				|  |  |            style={{ transform: activeData.model ? '' : 'translateY(-100%)' }}
 | 
	
		
			
				|  |  |            class={styles.headerContainer}>
 | 
	
		
			
				|  |  |            <div class={styles.menu}>{activeName.value}</div>
 | 
	
		
			
				|  |  | -        </div>
 | 
	
		
			
				|  |  | +        </div> */}
 | 
	
		
			
				|  |  |          {/* 布置作业按钮 */}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        <div
 | 
	
		
			
				|  |  | +        {/* <div
 | 
	
		
			
				|  |  |            onClick={(e: any) => {
 | 
	
		
			
				|  |  |              e.stopPropagation();
 | 
	
		
			
				|  |  |              if (activeData.timer){
 | 
	
	
		
			
				|  | @@ -1392,6 +1599,41 @@ export default defineComponent({
 | 
	
		
			
				|  |  |                <p>下一个</p>
 | 
	
		
			
				|  |  |              </div>
 | 
	
		
			
				|  |  |            </NSpace>
 | 
	
		
			
				|  |  | +        </div> */}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        {/* 右边操作栏 */}
 | 
	
		
			
				|  |  | +        <div class={[styles.rightColumn, !rightColumnShow.value ? styles.rightColumnHide : '']}>
 | 
	
		
			
				|  |  | +          {rightList.map((item: any, index: number) => (
 | 
	
		
			
				|  |  | +              <div 
 | 
	
		
			
				|  |  | +                class={[
 | 
	
		
			
				|  |  | +                  styles.rightItem,
 | 
	
		
			
				|  |  | +                  (item.id === 2 && data.preStudentNum <= 0) ? styles.itemDisabled : ''
 | 
	
		
			
				|  |  | +                ]} 
 | 
	
		
			
				|  |  | +                onClick={() => operateRightBtn(item.id)}>
 | 
	
		
			
				|  |  | +                <img src={item.icon} />
 | 
	
		
			
				|  |  | +                <div class={styles.rightTips}>{index === 0 && data.type === 'preview' ? item.name2 : item.name}</div>
 | 
	
		
			
				|  |  | +              </div>
 | 
	
		
			
				|  |  | +            ))}
 | 
	
		
			
				|  |  | +        </div> 
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +          !rightColumnShow.value && <img 
 | 
	
		
			
				|  |  | +            class={[styles.rightHideIcon, !rightColumnShow.value ? styles.rightIconShow : '']} 
 | 
	
		
			
				|  |  | +            src={rightHideIcon}
 | 
	
		
			
				|  |  | +            onClick={() => rightColumnShow.value = true } />
 | 
	
		
			
				|  |  | +        }  
 | 
	
		
			
				|  |  | +        {/* 右下角悬浮按钮 */}
 | 
	
		
			
				|  |  | +        <div class={styles.bottomColumn}>
 | 
	
		
			
				|  |  | +          {bottomList.map((item: any, index: number) => (
 | 
	
		
			
				|  |  | +              <div 
 | 
	
		
			
				|  |  | +                class={[
 | 
	
		
			
				|  |  | +                  styles.bottomItem,
 | 
	
		
			
				|  |  | +                  ((item.id === 3 && !isUpArrow.value) || (item.id === 4 && !isDownArrow.value)) ? styles.itemDisabled : ''
 | 
	
		
			
				|  |  | +                ]} 
 | 
	
		
			
				|  |  | +                onClick={() => operateBottomBtn(item.id)}>
 | 
	
		
			
				|  |  | +                <img src={item.icon} />
 | 
	
		
			
				|  |  | +                <div class={styles.bottomTips}>{item.name}</div>
 | 
	
		
			
				|  |  | +              </div>
 | 
	
		
			
				|  |  | +          ))}
 | 
	
		
			
				|  |  |          </div>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          {/* 显示列表 */}
 |