|  | @@ -0,0 +1,693 @@
 | 
	
		
			
				|  |  | +// import { Popup } from 'vant';
 | 
	
		
			
				|  |  | +import {
 | 
	
		
			
				|  |  | +  defineComponent,
 | 
	
		
			
				|  |  | +  onMounted,
 | 
	
		
			
				|  |  | +  reactive,
 | 
	
		
			
				|  |  | +  nextTick,
 | 
	
		
			
				|  |  | +  onUnmounted,
 | 
	
		
			
				|  |  | +  ref,
 | 
	
		
			
				|  |  | +  watch,
 | 
	
		
			
				|  |  | +  Transition
 | 
	
		
			
				|  |  | +} from 'vue';
 | 
	
		
			
				|  |  | +// import iconBack from './image/back.svg';
 | 
	
		
			
				|  |  | +import styles from './index.module.less';
 | 
	
		
			
				|  |  | +import 'plyr/dist/plyr.css';
 | 
	
		
			
				|  |  | +import MusicScore from './component/musicScore';
 | 
	
		
			
				|  |  | +import iconMenu from './image/icon-menu.svg';
 | 
	
		
			
				|  |  | +// import iconDian from './image/icon-dian.svg';
 | 
	
		
			
				|  |  | +// import iconPoint from './image/icon-point.svg';
 | 
	
		
			
				|  |  | +import iconUp from './image/icon-up.svg';
 | 
	
		
			
				|  |  | +import iconUpDisabled from './image/icon-up-disabled.svg';
 | 
	
		
			
				|  |  | +import iconDown from './image/icon-down.svg';
 | 
	
		
			
				|  |  | +import iconDownDisabled from './image/icon-down-disabled.svg';
 | 
	
		
			
				|  |  | +import iconWhiteboard from './image/icon-whiteboard.svg';
 | 
	
		
			
				|  |  | +// import Points from './component/points';
 | 
	
		
			
				|  |  | +import iconAssignHomework from './image/icon-assignHomework.svg';
 | 
	
		
			
				|  |  | +import { Vue3Lottie } from 'vue3-lottie';
 | 
	
		
			
				|  |  | +import playLoadData from './datas/data.json';
 | 
	
		
			
				|  |  | +import { usePageVisibility } from '@vant/use';
 | 
	
		
			
				|  |  | +import VideoPlay from './component/video-play';
 | 
	
		
			
				|  |  | +import { useMessage, NDrawer, NDrawerContent } from 'naive-ui';
 | 
	
		
			
				|  |  | +import CardType from '@/components/card-type';
 | 
	
		
			
				|  |  | +import { ToolItem, ToolType } from './component/tool';
 | 
	
		
			
				|  |  | +import Pen from './component/tools/pen';
 | 
	
		
			
				|  |  | +import AudioPay from './component/audio-pay';
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +export default defineComponent({
 | 
	
		
			
				|  |  | +  name: 'CoursewarePlay',
 | 
	
		
			
				|  |  | +  setup() {
 | 
	
		
			
				|  |  | +    const message = useMessage();
 | 
	
		
			
				|  |  | +    const pageVisibility = usePageVisibility();
 | 
	
		
			
				|  |  | +    const isPlay = ref(false);
 | 
	
		
			
				|  |  | +    /** 页面显示和隐藏 */
 | 
	
		
			
				|  |  | +    watch(pageVisibility, value => {
 | 
	
		
			
				|  |  | +      const activeItem = data.itemList[popupData.activeIndex];
 | 
	
		
			
				|  |  | +      if (activeItem.type != 'VIDEO') return;
 | 
	
		
			
				|  |  | +      if (value == 'hidden') {
 | 
	
		
			
				|  |  | +        isPlay.value = !activeItem.videoEle?.paused;
 | 
	
		
			
				|  |  | +        togglePlay(activeItem, false);
 | 
	
		
			
				|  |  | +      } else {
 | 
	
		
			
				|  |  | +        // 页面显示,并且
 | 
	
		
			
				|  |  | +        if (isPlay.value) togglePlay(activeItem, true);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +    /** 设置播放容器 16:9 */
 | 
	
		
			
				|  |  | +    const parentContainer = reactive({
 | 
	
		
			
				|  |  | +      width: '100vw'
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +    const setContainer = () => {
 | 
	
		
			
				|  |  | +      const min = Math.min(screen.width, screen.height);
 | 
	
		
			
				|  |  | +      const max = Math.max(screen.width, screen.height);
 | 
	
		
			
				|  |  | +      const width = min * (16 / 9);
 | 
	
		
			
				|  |  | +      if (width > max) {
 | 
	
		
			
				|  |  | +        parentContainer.width = '100vw';
 | 
	
		
			
				|  |  | +        return;
 | 
	
		
			
				|  |  | +      } else {
 | 
	
		
			
				|  |  | +        parentContainer.width = width + 'px';
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +    const handleInit = (type = 0) => {
 | 
	
		
			
				|  |  | +      //设置容器16:9
 | 
	
		
			
				|  |  | +      setContainer();
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +    handleInit();
 | 
	
		
			
				|  |  | +    onUnmounted(() => {
 | 
	
		
			
				|  |  | +      handleInit(1);
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // const route = useRoute();
 | 
	
		
			
				|  |  | +    // const router = useRouter();
 | 
	
		
			
				|  |  | +    // const headeRef = ref();
 | 
	
		
			
				|  |  | +    const data = reactive({
 | 
	
		
			
				|  |  | +      detail: null,
 | 
	
		
			
				|  |  | +      knowledgePointList: [] as any,
 | 
	
		
			
				|  |  | +      itemList: [] as any,
 | 
	
		
			
				|  |  | +      showHead: true,
 | 
	
		
			
				|  |  | +      isCourse: false,
 | 
	
		
			
				|  |  | +      isRecordPlay: false,
 | 
	
		
			
				|  |  | +      videoRefs: {} as any[]
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +    const activeData = reactive({
 | 
	
		
			
				|  |  | +      isAutoPlay: true, // 是否自动播放
 | 
	
		
			
				|  |  | +      nowTime: 0,
 | 
	
		
			
				|  |  | +      model: true, // 遮罩
 | 
	
		
			
				|  |  | +      isAnimation: true, // 是否动画
 | 
	
		
			
				|  |  | +      videoBtns: true, // 视频
 | 
	
		
			
				|  |  | +      currentTime: 0,
 | 
	
		
			
				|  |  | +      duration: 0,
 | 
	
		
			
				|  |  | +      timer: null as any,
 | 
	
		
			
				|  |  | +      item: null as any
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +    // const getTempList = async (materialList: any, name: any) => {
 | 
	
		
			
				|  |  | +    //   const list: any = [];
 | 
	
		
			
				|  |  | +    //   const browserInfo = browser();
 | 
	
		
			
				|  |  | +    //   for (let j = 0; j < materialList.length; j++) {
 | 
	
		
			
				|  |  | +    //     const material = materialList[j];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    //     list.push({
 | 
	
		
			
				|  |  | +    //       ...material,
 | 
	
		
			
				|  |  | +    //       iframeRef: null,
 | 
	
		
			
				|  |  | +    //       videoEle: null,
 | 
	
		
			
				|  |  | +    //       tabName: name,
 | 
	
		
			
				|  |  | +    //       autoPlay: false, //加载完成是否自动播放
 | 
	
		
			
				|  |  | +    //       isprepare: false, // 视频是否加载完成
 | 
	
		
			
				|  |  | +    //       isRender: false // 是否渲染了
 | 
	
		
			
				|  |  | +    //     });
 | 
	
		
			
				|  |  | +    //   }
 | 
	
		
			
				|  |  | +    //   return list;
 | 
	
		
			
				|  |  | +    // };
 | 
	
		
			
				|  |  | +    const getDetail = async () => {
 | 
	
		
			
				|  |  | +      data.knowledgePointList = [
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +          id: '5',
 | 
	
		
			
				|  |  | +          name: '歌曲表演 大鹿',
 | 
	
		
			
				|  |  | +          title: '歌曲表演 大鹿',
 | 
	
		
			
				|  |  | +          type: 'AUDIO',
 | 
	
		
			
				|  |  | +          content:
 | 
	
		
			
				|  |  | +            'https://cloud-coach.ks3-cn-beijing.ksyuncs.com/1686819360752.mp3',
 | 
	
		
			
				|  |  | +          url: 'https://lanhu-dds-backend.oss-cn-beijing.aliyuncs.com/merge_image/imgs/23cc71b5d7874dcf8752cd257483e687_mergeImage.png'
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +          id: '1',
 | 
	
		
			
				|  |  | +          name: '歌曲表演 大鹿',
 | 
	
		
			
				|  |  | +          title: '歌曲表演 大鹿',
 | 
	
		
			
				|  |  | +          type: 'VIDEO',
 | 
	
		
			
				|  |  | +          content:
 | 
	
		
			
				|  |  | +            'https://courseware.lexiaoya.cn/%E5%BF%85%E5%AD%A6%E5%BF%85%E7%9C%8B-%E8%90%A8%E5%85%8B%E6%96%AF-1-C4-4.mp4',
 | 
	
		
			
				|  |  | +          url: 'https://lanhu-dds-backend.oss-cn-beijing.aliyuncs.com/merge_image/imgs/23cc71b5d7874dcf8752cd257483e687_mergeImage.png'
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +          id: '2',
 | 
	
		
			
				|  |  | +          name: '知识 音的高低',
 | 
	
		
			
				|  |  | +          title: '知识 音的高低',
 | 
	
		
			
				|  |  | +          type: 'IMG',
 | 
	
		
			
				|  |  | +          content:
 | 
	
		
			
				|  |  | +            'https://gyt.ks3-cn-beijing.ksyuncs.com/courseware/1686815979899.png',
 | 
	
		
			
				|  |  | +          url: 'https://gyt.ks3-cn-beijing.ksyuncs.com/courseware/1686815979899.png'
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +          id: '3',
 | 
	
		
			
				|  |  | +          name: '欣赏 永远在童话里',
 | 
	
		
			
				|  |  | +          title: '欣赏 永远在童话里',
 | 
	
		
			
				|  |  | +          type: 'IMG',
 | 
	
		
			
				|  |  | +          content:
 | 
	
		
			
				|  |  | +            'https://gyt.ks3-cn-beijing.ksyuncs.com/courseware/1686815979899.png',
 | 
	
		
			
				|  |  | +          url: 'https://gyt.ks3-cn-beijing.ksyuncs.com/courseware/1686815979899.png'
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +          id: '4',
 | 
	
		
			
				|  |  | +          name: '唱歌 小红帽',
 | 
	
		
			
				|  |  | +          title: '唱歌 小红帽',
 | 
	
		
			
				|  |  | +          type: 'SONG',
 | 
	
		
			
				|  |  | +          content: '11707',
 | 
	
		
			
				|  |  | +          url: 'https://lanhu.oss-cn-beijing.aliyuncs.com/SketchPngd1f4e00a00bc8134db4ec43e51a66442f778756e2caf01d10a1ffdd51fc7c6cb'
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      ];
 | 
	
		
			
				|  |  | +      data.itemList = data.knowledgePointList.map((m: any) => {
 | 
	
		
			
				|  |  | +        return {
 | 
	
		
			
				|  |  | +          ...m,
 | 
	
		
			
				|  |  | +          iframeRef: null,
 | 
	
		
			
				|  |  | +          videoEle: null,
 | 
	
		
			
				|  |  | +          autoPlay: false, //加载完成是否自动播放
 | 
	
		
			
				|  |  | +          isprepare: false, // 视频是否加载完成
 | 
	
		
			
				|  |  | +          isRender: false // 是否渲染了
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +      });
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    onMounted(() => {
 | 
	
		
			
				|  |  | +      getDetail();
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // const playRef = ref();
 | 
	
		
			
				|  |  | +    // 返回
 | 
	
		
			
				|  |  | +    // const goback = () => {
 | 
	
		
			
				|  |  | +    //   try {
 | 
	
		
			
				|  |  | +    //     playRef.value?.handleOut();
 | 
	
		
			
				|  |  | +    //   } catch {
 | 
	
		
			
				|  |  | +    //     //
 | 
	
		
			
				|  |  | +    //   }
 | 
	
		
			
				|  |  | +    //   postMessage({ api: 'goBack' });
 | 
	
		
			
				|  |  | +    // };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    const popupData = reactive({
 | 
	
		
			
				|  |  | +      open: false,
 | 
	
		
			
				|  |  | +      activeIndex: 0,
 | 
	
		
			
				|  |  | +      // tabActive: '',
 | 
	
		
			
				|  |  | +      // tabName: '',
 | 
	
		
			
				|  |  | +      // itemActive: '',
 | 
	
		
			
				|  |  | +      // itemName: ''
 | 
	
		
			
				|  |  | +      // guideOpen: false,
 | 
	
		
			
				|  |  | +      toolOpen: false // 工具弹窗控制
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**停止所有的播放 */
 | 
	
		
			
				|  |  | +    const handleStop = () => {
 | 
	
		
			
				|  |  | +      for (let i = 0; i < data.itemList.length; i++) {
 | 
	
		
			
				|  |  | +        const activeItem = data.itemList[i];
 | 
	
		
			
				|  |  | +        if (activeItem.type === 'VIDEO' && activeItem.videoEle) {
 | 
	
		
			
				|  |  | +          activeItem.videoEle.stop();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        // console.log('🚀 ~ activeItem:', activeItem)
 | 
	
		
			
				|  |  | +        // 停止曲谱的播放
 | 
	
		
			
				|  |  | +        if (activeItem.type === 'SONG') {
 | 
	
		
			
				|  |  | +          activeItem.iframeRef?.contentWindow?.postMessage(
 | 
	
		
			
				|  |  | +            { api: 'setPlayState' },
 | 
	
		
			
				|  |  | +            '*'
 | 
	
		
			
				|  |  | +          );
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +    // 切换素材
 | 
	
		
			
				|  |  | +    const toggleMaterial = (itemActive: any) => {
 | 
	
		
			
				|  |  | +      const index = data.itemList.findIndex((n: any) => n.id == itemActive);
 | 
	
		
			
				|  |  | +      if (index > -1) {
 | 
	
		
			
				|  |  | +        handleSwipeChange(index);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +    /** 延迟收起模态框 */
 | 
	
		
			
				|  |  | +    const setModelOpen = () => {
 | 
	
		
			
				|  |  | +      clearTimeout(activeData.timer);
 | 
	
		
			
				|  |  | +      message.destroyAll();
 | 
	
		
			
				|  |  | +      activeData.timer = setTimeout(() => {
 | 
	
		
			
				|  |  | +        activeData.model = false;
 | 
	
		
			
				|  |  | +        Object.values(data.videoRefs).map((n: any) =>
 | 
	
		
			
				|  |  | +          n.toggleHideControl(false)
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +      }, 4000);
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /** 立即收起所有的模态框 */
 | 
	
		
			
				|  |  | +    const clearModel = () => {
 | 
	
		
			
				|  |  | +      clearTimeout(activeData.timer);
 | 
	
		
			
				|  |  | +      message.destroyAll();
 | 
	
		
			
				|  |  | +      activeData.model = false;
 | 
	
		
			
				|  |  | +      Object.values(data.videoRefs).map((n: any) => n.toggleHideControl(false));
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +    const toggleModel = (type = true) => {
 | 
	
		
			
				|  |  | +      activeData.model = type;
 | 
	
		
			
				|  |  | +      Object.values(data.videoRefs).map((n: any) => n.toggleHideControl(type));
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 双击
 | 
	
		
			
				|  |  | +    const handleDbClick = (item: any) => {
 | 
	
		
			
				|  |  | +      if (item && item.type === 'VIDEO') {
 | 
	
		
			
				|  |  | +        const videoEle: HTMLVideoElement = item.videoEle;
 | 
	
		
			
				|  |  | +        if (videoEle) {
 | 
	
		
			
				|  |  | +          if (videoEle.paused) {
 | 
	
		
			
				|  |  | +            message.destroyAll();
 | 
	
		
			
				|  |  | +            videoEle.play();
 | 
	
		
			
				|  |  | +          } else {
 | 
	
		
			
				|  |  | +            message.warning('已暂停');
 | 
	
		
			
				|  |  | +            videoEle.pause();
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 切换播放
 | 
	
		
			
				|  |  | +    const togglePlay = (m: any, isPlay: boolean) => {
 | 
	
		
			
				|  |  | +      if (isPlay) {
 | 
	
		
			
				|  |  | +        m.videoEle?.play();
 | 
	
		
			
				|  |  | +      } else {
 | 
	
		
			
				|  |  | +        m.videoEle?.pause();
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    const showIndex = ref(-4);
 | 
	
		
			
				|  |  | +    const effectIndex = ref(3);
 | 
	
		
			
				|  |  | +    const effects = [
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +        prev: {
 | 
	
		
			
				|  |  | +          transform: 'translate3d(0, 0, -800px) rotateX(180deg)'
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +        next: {
 | 
	
		
			
				|  |  | +          transform: 'translate3d(0, 0, -800px) rotateX(-180deg)'
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +        prev: {
 | 
	
		
			
				|  |  | +          transform: 'translate3d(-100%, 0, -800px)'
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +        next: {
 | 
	
		
			
				|  |  | +          transform: 'translate3d(100%, 0, -800px)'
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +        prev: {
 | 
	
		
			
				|  |  | +          transform: 'translate3d(-50%, 0, -800px) rotateY(80deg)'
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +        next: {
 | 
	
		
			
				|  |  | +          transform: 'translate3d(50%, 0, -800px) rotateY(-80deg)'
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +        prev: {
 | 
	
		
			
				|  |  | +          transform: 'translate3d(-100%, 0, -800px) rotateY(-120deg)'
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +        next: {
 | 
	
		
			
				|  |  | +          transform: 'translate3d(100%, 0, -800px) rotateY(120deg)'
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      // 风车4
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +        prev: {
 | 
	
		
			
				|  |  | +          transform: 'translate3d(-50%, 50%, -800px) rotateZ(-14deg)',
 | 
	
		
			
				|  |  | +          opacity: 0
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +        next: {
 | 
	
		
			
				|  |  | +          transform: 'translate3d(50%, 50%, -800px) rotateZ(14deg)',
 | 
	
		
			
				|  |  | +          opacity: 0
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      // 翻页5
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +        prev: {
 | 
	
		
			
				|  |  | +          transform: 'translateZ(-800px) rotate3d(0, -1, 0, 90deg)',
 | 
	
		
			
				|  |  | +          opacity: 0
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +        next: {
 | 
	
		
			
				|  |  | +          transform: 'translateZ(-800px) rotate3d(0, 1, 0, 90deg)',
 | 
	
		
			
				|  |  | +          opacity: 0
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +        current: { transitionDelay: '700ms' }
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    ];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    const acitveTimer = ref();
 | 
	
		
			
				|  |  | +    // 轮播切换
 | 
	
		
			
				|  |  | +    const handleSwipeChange = (index: number) => {
 | 
	
		
			
				|  |  | +      // 如果是当前正在播放 或者是视频最后一个
 | 
	
		
			
				|  |  | +      if (popupData.activeIndex == index) return;
 | 
	
		
			
				|  |  | +      handleStop();
 | 
	
		
			
				|  |  | +      clearTimeout(acitveTimer.value);
 | 
	
		
			
				|  |  | +      checkedAnimation(popupData.activeIndex, index);
 | 
	
		
			
				|  |  | +      popupData.activeIndex = index;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      acitveTimer.value = setTimeout(
 | 
	
		
			
				|  |  | +        () => {
 | 
	
		
			
				|  |  | +          const item = data.itemList[index];
 | 
	
		
			
				|  |  | +          if (item) {
 | 
	
		
			
				|  |  | +            // popupData.tabActive = item.knowledgePointId;
 | 
	
		
			
				|  |  | +            // popupData.itemActive = item.id;
 | 
	
		
			
				|  |  | +            // popupData.itemName = item.name;
 | 
	
		
			
				|  |  | +            // popupData.tabName = item.tabName;
 | 
	
		
			
				|  |  | +            if (item.type == 'SONG') {
 | 
	
		
			
				|  |  | +              activeData.model = true;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            if (item.type === 'VIDEO') {
 | 
	
		
			
				|  |  | +              // 自动播放下一个视频
 | 
	
		
			
				|  |  | +              clearTimeout(activeData.timer);
 | 
	
		
			
				|  |  | +              message.destroyAll();
 | 
	
		
			
				|  |  | +              item.autoPlay = true;
 | 
	
		
			
				|  |  | +              nextTick(() => {
 | 
	
		
			
				|  |  | +                item.videoEle?.play();
 | 
	
		
			
				|  |  | +              });
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +          //   requestAnimationFrame(() => {
 | 
	
		
			
				|  |  | +          //     const _effectIndex = effectIndex.value + 1;
 | 
	
		
			
				|  |  | +          //     effectIndex.value =
 | 
	
		
			
				|  |  | +          //       _effectIndex >= effects.length - 1 ? 0 : _effectIndex;
 | 
	
		
			
				|  |  | +          //   });
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +        activeData.isAnimation ? 800 : 0
 | 
	
		
			
				|  |  | +      );
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /** 是否有转场动画 */
 | 
	
		
			
				|  |  | +    const checkedAnimation = (index: number, nextIndex?: number) => {
 | 
	
		
			
				|  |  | +      const item = data.itemList[index];
 | 
	
		
			
				|  |  | +      const nextItem = data.itemList[nextIndex!];
 | 
	
		
			
				|  |  | +      if (nextItem) {
 | 
	
		
			
				|  |  | +        if (nextItem.knowledgePointId != item.knowledgePointId) {
 | 
	
		
			
				|  |  | +          activeData.isAnimation = true;
 | 
	
		
			
				|  |  | +          return;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        const videoEle = item.videoEle;
 | 
	
		
			
				|  |  | +        const nextVideo = nextItem.videoEle;
 | 
	
		
			
				|  |  | +        if (videoEle && videoEle.duration < 8 && index < nextIndex!) {
 | 
	
		
			
				|  |  | +          activeData.isAnimation = false;
 | 
	
		
			
				|  |  | +        } else if (nextVideo && nextVideo.duration < 8 && index > nextIndex!) {
 | 
	
		
			
				|  |  | +          activeData.isAnimation = false;
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +          activeData.isAnimation = true;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      } else {
 | 
	
		
			
				|  |  | +        activeData.isAnimation = item?.adviseStudyTimeSecond < 8 ? false : true;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 上一个知识点, 下一个知识点
 | 
	
		
			
				|  |  | +    const handlePreAndNext = (type: string) => {
 | 
	
		
			
				|  |  | +      if (type === 'up') {
 | 
	
		
			
				|  |  | +        handleSwipeChange(popupData.activeIndex - 1);
 | 
	
		
			
				|  |  | +      } else {
 | 
	
		
			
				|  |  | +        handleSwipeChange(popupData.activeIndex + 1);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /** 弹窗关闭 */
 | 
	
		
			
				|  |  | +    const handleClosePopup = () => {
 | 
	
		
			
				|  |  | +      const item = data.itemList[popupData.activeIndex];
 | 
	
		
			
				|  |  | +      if (item?.type == 'VIDEO' && !item.videoEle?.paused) {
 | 
	
		
			
				|  |  | +        setModelOpen();
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 监听页面键盘事件 - 上下切换
 | 
	
		
			
				|  |  | +    document.body.addEventListener('keyup', (e: KeyboardEvent) => {
 | 
	
		
			
				|  |  | +      if (e.key === 'ArrowUp') {
 | 
	
		
			
				|  |  | +        if (popupData.activeIndex === 0) return;
 | 
	
		
			
				|  |  | +        handlePreAndNext('up');
 | 
	
		
			
				|  |  | +      } else if (e.key === 'ArrowDown') {
 | 
	
		
			
				|  |  | +        if (popupData.activeIndex === data.itemList.length - 1) return;
 | 
	
		
			
				|  |  | +        handlePreAndNext('down');
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /** 教学数据 */
 | 
	
		
			
				|  |  | +    const studyData = reactive({
 | 
	
		
			
				|  |  | +      type: '' as ToolType,
 | 
	
		
			
				|  |  | +      penShow: false
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /** 打开教学工具 */
 | 
	
		
			
				|  |  | +    const openStudyTool = (item: ToolItem) => {
 | 
	
		
			
				|  |  | +      const activeItem = data.itemList[popupData.activeIndex];
 | 
	
		
			
				|  |  | +      // 暂停视频和曲谱的播放
 | 
	
		
			
				|  |  | +      if (activeItem.type === 'VIDEO' && activeItem.videoEle) {
 | 
	
		
			
				|  |  | +        activeItem.videoEle.pause();
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      if (activeItem.type === 'SONG') {
 | 
	
		
			
				|  |  | +        activeItem.iframeRef?.contentWindow?.postMessage(
 | 
	
		
			
				|  |  | +          { api: 'setPlayState' },
 | 
	
		
			
				|  |  | +          '*'
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      clearModel();
 | 
	
		
			
				|  |  | +      popupData.toolOpen = false;
 | 
	
		
			
				|  |  | +      studyData.type = item.type;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      switch (item.type) {
 | 
	
		
			
				|  |  | +        case 'pen':
 | 
	
		
			
				|  |  | +          studyData.penShow = true;
 | 
	
		
			
				|  |  | +          break;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /** 关闭教学工具 */
 | 
	
		
			
				|  |  | +    const closeStudyTool = () => {
 | 
	
		
			
				|  |  | +      studyData.type = 'init';
 | 
	
		
			
				|  |  | +      toggleModel();
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    return () => (
 | 
	
		
			
				|  |  | +      <div id="playContent" class={styles.playContent}>
 | 
	
		
			
				|  |  | +        <div
 | 
	
		
			
				|  |  | +          onClick={() => {
 | 
	
		
			
				|  |  | +            clearTimeout(activeData.timer);
 | 
	
		
			
				|  |  | +            activeData.model = !activeData.model;
 | 
	
		
			
				|  |  | +            Object.values(data.videoRefs).map((n: any) =>
 | 
	
		
			
				|  |  | +              n.toggleHideControl(activeData.model)
 | 
	
		
			
				|  |  | +            );
 | 
	
		
			
				|  |  | +          }}>
 | 
	
		
			
				|  |  | +          <div
 | 
	
		
			
				|  |  | +            class={styles.coursewarePlay}
 | 
	
		
			
				|  |  | +            style={{ width: parentContainer.width }}
 | 
	
		
			
				|  |  | +            onClick={(e: Event) => {
 | 
	
		
			
				|  |  | +              e.stopPropagation();
 | 
	
		
			
				|  |  | +              setModelOpen();
 | 
	
		
			
				|  |  | +            }}>
 | 
	
		
			
				|  |  | +            <div class={styles.wraps}>
 | 
	
		
			
				|  |  | +              {data.itemList.map((m: any, mIndex: number) => {
 | 
	
		
			
				|  |  | +                const isRender =
 | 
	
		
			
				|  |  | +                  m.isRender || Math.abs(popupData.activeIndex - mIndex) < 2;
 | 
	
		
			
				|  |  | +                const isEmtry = Math.abs(popupData.activeIndex - mIndex) > 4;
 | 
	
		
			
				|  |  | +                if (isRender) {
 | 
	
		
			
				|  |  | +                  m.isRender = true;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                return isRender ? (
 | 
	
		
			
				|  |  | +                  <div
 | 
	
		
			
				|  |  | +                    key={'index' + mIndex}
 | 
	
		
			
				|  |  | +                    class={[
 | 
	
		
			
				|  |  | +                      styles.itemDiv,
 | 
	
		
			
				|  |  | +                      popupData.activeIndex === mIndex && styles.itemActive,
 | 
	
		
			
				|  |  | +                      activeData.isAnimation && styles.acitveAnimation,
 | 
	
		
			
				|  |  | +                      Math.abs(popupData.activeIndex - mIndex) < 2
 | 
	
		
			
				|  |  | +                        ? styles.show
 | 
	
		
			
				|  |  | +                        : styles.hide
 | 
	
		
			
				|  |  | +                    ]}
 | 
	
		
			
				|  |  | +                    style={
 | 
	
		
			
				|  |  | +                      mIndex < popupData.activeIndex
 | 
	
		
			
				|  |  | +                        ? effects[effectIndex.value].prev
 | 
	
		
			
				|  |  | +                        : mIndex > popupData.activeIndex
 | 
	
		
			
				|  |  | +                        ? effects[effectIndex.value].next
 | 
	
		
			
				|  |  | +                        : {}
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                    onClick={(e: Event) => {
 | 
	
		
			
				|  |  | +                      e.stopPropagation();
 | 
	
		
			
				|  |  | +                      clearTimeout(activeData.timer);
 | 
	
		
			
				|  |  | +                      if (Date.now() - activeData.nowTime < 300) {
 | 
	
		
			
				|  |  | +                        handleDbClick(m);
 | 
	
		
			
				|  |  | +                        return;
 | 
	
		
			
				|  |  | +                      }
 | 
	
		
			
				|  |  | +                      activeData.nowTime = Date.now();
 | 
	
		
			
				|  |  | +                      activeData.timer = setTimeout(() => {
 | 
	
		
			
				|  |  | +                        activeData.model = !activeData.model;
 | 
	
		
			
				|  |  | +                        Object.values(data.videoRefs).map((n: any) =>
 | 
	
		
			
				|  |  | +                          n.toggleHideControl(activeData.model)
 | 
	
		
			
				|  |  | +                        );
 | 
	
		
			
				|  |  | +                        if (activeData.model) {
 | 
	
		
			
				|  |  | +                          setModelOpen();
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  | +                      }, 300);
 | 
	
		
			
				|  |  | +                    }}>
 | 
	
		
			
				|  |  | +                    {m.type === 'VIDEO' ? (
 | 
	
		
			
				|  |  | +                      <>
 | 
	
		
			
				|  |  | +                        <VideoPlay
 | 
	
		
			
				|  |  | +                          ref={(v: any) => (data.videoRefs[mIndex] = v)}
 | 
	
		
			
				|  |  | +                          item={m}
 | 
	
		
			
				|  |  | +                          isEmtry={isEmtry}
 | 
	
		
			
				|  |  | +                          onLoadedmetadata={(videoItem: any) => {
 | 
	
		
			
				|  |  | +                            m.videoEle = videoItem;
 | 
	
		
			
				|  |  | +                            m.isprepare = true;
 | 
	
		
			
				|  |  | +                          }}
 | 
	
		
			
				|  |  | +                          onTogglePlay={(paused: boolean) => {
 | 
	
		
			
				|  |  | +                            m.autoPlay = false;
 | 
	
		
			
				|  |  | +                            if (paused || popupData.open) {
 | 
	
		
			
				|  |  | +                              clearTimeout(activeData.timer);
 | 
	
		
			
				|  |  | +                            } else {
 | 
	
		
			
				|  |  | +                              setModelOpen();
 | 
	
		
			
				|  |  | +                            }
 | 
	
		
			
				|  |  | +                          }}
 | 
	
		
			
				|  |  | +                          onEnded={() => {
 | 
	
		
			
				|  |  | +                            const _index = popupData.activeIndex + 1;
 | 
	
		
			
				|  |  | +                            if (_index < data.itemList.length) {
 | 
	
		
			
				|  |  | +                              handleSwipeChange(_index);
 | 
	
		
			
				|  |  | +                            }
 | 
	
		
			
				|  |  | +                          }}
 | 
	
		
			
				|  |  | +                          onReset={() => {
 | 
	
		
			
				|  |  | +                            if (!m.videoEle?.paused) {
 | 
	
		
			
				|  |  | +                              setModelOpen();
 | 
	
		
			
				|  |  | +                            }
 | 
	
		
			
				|  |  | +                          }}
 | 
	
		
			
				|  |  | +                        />
 | 
	
		
			
				|  |  | +                        <Transition name="van-fade">
 | 
	
		
			
				|  |  | +                          {!m.isprepare && (
 | 
	
		
			
				|  |  | +                            <div class={styles.loadWrap}>
 | 
	
		
			
				|  |  | +                              <Vue3Lottie
 | 
	
		
			
				|  |  | +                                animationData={playLoadData}></Vue3Lottie>
 | 
	
		
			
				|  |  | +                            </div>
 | 
	
		
			
				|  |  | +                          )}
 | 
	
		
			
				|  |  | +                        </Transition>
 | 
	
		
			
				|  |  | +                      </>
 | 
	
		
			
				|  |  | +                    ) : m.type === 'IMG' ? (
 | 
	
		
			
				|  |  | +                      <img src={m.content} />
 | 
	
		
			
				|  |  | +                    ) : m.type === 'AUDIO' ? (
 | 
	
		
			
				|  |  | +                      <AudioPay item={m} />
 | 
	
		
			
				|  |  | +                    ) : (
 | 
	
		
			
				|  |  | +                      <MusicScore
 | 
	
		
			
				|  |  | +                        activeModel={activeData.model}
 | 
	
		
			
				|  |  | +                        data-vid={m.id}
 | 
	
		
			
				|  |  | +                        music={m}
 | 
	
		
			
				|  |  | +                        onSetIframe={(el: any) => {
 | 
	
		
			
				|  |  | +                          m.iframeRef = el;
 | 
	
		
			
				|  |  | +                        }}
 | 
	
		
			
				|  |  | +                      />
 | 
	
		
			
				|  |  | +                    )}
 | 
	
		
			
				|  |  | +                  </div>
 | 
	
		
			
				|  |  | +                ) : null;
 | 
	
		
			
				|  |  | +              })}
 | 
	
		
			
				|  |  | +            </div>
 | 
	
		
			
				|  |  | +            <Transition name="right">
 | 
	
		
			
				|  |  | +              {activeData.model && (
 | 
	
		
			
				|  |  | +                <div
 | 
	
		
			
				|  |  | +                  class={styles.rightFixedBtns}
 | 
	
		
			
				|  |  | +                  onClick={(e: Event) => {
 | 
	
		
			
				|  |  | +                    e.stopPropagation();
 | 
	
		
			
				|  |  | +                    clearTimeout(activeData.timer);
 | 
	
		
			
				|  |  | +                  }}>
 | 
	
		
			
				|  |  | +                  <div
 | 
	
		
			
				|  |  | +                    class={[styles.fullBtn, styles.point]}
 | 
	
		
			
				|  |  | +                    onClick={() => (popupData.open = true)}>
 | 
	
		
			
				|  |  | +                    <img src={iconMenu} />
 | 
	
		
			
				|  |  | +                  </div>
 | 
	
		
			
				|  |  | +                </div>
 | 
	
		
			
				|  |  | +              )}
 | 
	
		
			
				|  |  | +            </Transition>
 | 
	
		
			
				|  |  | +          </div>
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        {/* <div
 | 
	
		
			
				|  |  | +          style={{ transform: activeData.model ? '' : 'translateY(-100%)' }}
 | 
	
		
			
				|  |  | +          class={styles.headerContainer}
 | 
	
		
			
				|  |  | +          ref={headeRef}>
 | 
	
		
			
				|  |  | +          <div class={styles.backBtn} onClick={() => goback()}>
 | 
	
		
			
				|  |  | +            <Icon name={iconBack} />
 | 
	
		
			
				|  |  | +            返回
 | 
	
		
			
				|  |  | +          </div>
 | 
	
		
			
				|  |  | +          <div class={styles.menu}>{popupData.itemName}</div>
 | 
	
		
			
				|  |  | +        </div> */}
 | 
	
		
			
				|  |  | +        {/* 布置作业按钮 */}
 | 
	
		
			
				|  |  | +        <div class={styles.assignHomework}>
 | 
	
		
			
				|  |  | +          <img src={iconAssignHomework} />
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        {/* 上下切换 */}
 | 
	
		
			
				|  |  | +        <div
 | 
	
		
			
				|  |  | +          class={[
 | 
	
		
			
				|  |  | +            styles.switchChangeSection,
 | 
	
		
			
				|  |  | +            activeData.model ? '' : styles.sectionAnimate
 | 
	
		
			
				|  |  | +          ]}>
 | 
	
		
			
				|  |  | +          <div
 | 
	
		
			
				|  |  | +            class={[styles.switchBtn]}
 | 
	
		
			
				|  |  | +            onClick={() => {
 | 
	
		
			
				|  |  | +              if (popupData.activeIndex === 0) return;
 | 
	
		
			
				|  |  | +              handlePreAndNext('up');
 | 
	
		
			
				|  |  | +            }}>
 | 
	
		
			
				|  |  | +            <img src={popupData.activeIndex === 0 ? iconUpDisabled : iconUp} />
 | 
	
		
			
				|  |  | +          </div>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          <div
 | 
	
		
			
				|  |  | +            class={[styles.switchBtn]}
 | 
	
		
			
				|  |  | +            onClick={() => {
 | 
	
		
			
				|  |  | +              if (popupData.activeIndex === data.itemList.length - 1) return;
 | 
	
		
			
				|  |  | +              handlePreAndNext('down');
 | 
	
		
			
				|  |  | +            }}>
 | 
	
		
			
				|  |  | +            <img
 | 
	
		
			
				|  |  | +              src={
 | 
	
		
			
				|  |  | +                popupData.activeIndex === data.itemList.length - 1
 | 
	
		
			
				|  |  | +                  ? iconDownDisabled
 | 
	
		
			
				|  |  | +                  : iconDown
 | 
	
		
			
				|  |  | +              }
 | 
	
		
			
				|  |  | +            />
 | 
	
		
			
				|  |  | +          </div>
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        {/* 白板 */}
 | 
	
		
			
				|  |  | +        <div
 | 
	
		
			
				|  |  | +          class={[
 | 
	
		
			
				|  |  | +            styles.switchDisplaySection,
 | 
	
		
			
				|  |  | +            activeData.model ? '' : styles.sectionAnimate
 | 
	
		
			
				|  |  | +          ]}>
 | 
	
		
			
				|  |  | +          <div
 | 
	
		
			
				|  |  | +            class={styles.displayBtn}
 | 
	
		
			
				|  |  | +            onClick={() =>
 | 
	
		
			
				|  |  | +              openStudyTool({
 | 
	
		
			
				|  |  | +                type: 'pen',
 | 
	
		
			
				|  |  | +                icon: iconWhiteboard,
 | 
	
		
			
				|  |  | +                name: '白板'
 | 
	
		
			
				|  |  | +              })
 | 
	
		
			
				|  |  | +            }>
 | 
	
		
			
				|  |  | +            <img src={iconWhiteboard} />
 | 
	
		
			
				|  |  | +          </div>
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        <NDrawer
 | 
	
		
			
				|  |  | +          v-model:show={popupData.open}
 | 
	
		
			
				|  |  | +          class={styles.drawerContainer}
 | 
	
		
			
				|  |  | +          onAfterLeave={handleClosePopup}
 | 
	
		
			
				|  |  | +          showMask={false}>
 | 
	
		
			
				|  |  | +          <NDrawerContent title="资源列表" closable>
 | 
	
		
			
				|  |  | +            {data.knowledgePointList.map((item: any, index: number) => (
 | 
	
		
			
				|  |  | +              <CardType
 | 
	
		
			
				|  |  | +                item={item}
 | 
	
		
			
				|  |  | +                isActive={popupData.activeIndex === index}
 | 
	
		
			
				|  |  | +                isCollect={false}
 | 
	
		
			
				|  |  | +                onClick={(item: any) => {
 | 
	
		
			
				|  |  | +                  popupData.open = false;
 | 
	
		
			
				|  |  | +                  toggleMaterial(item.id);
 | 
	
		
			
				|  |  | +                }}
 | 
	
		
			
				|  |  | +              />
 | 
	
		
			
				|  |  | +            ))}
 | 
	
		
			
				|  |  | +          </NDrawerContent>
 | 
	
		
			
				|  |  | +        </NDrawer>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        {studyData.penShow && (
 | 
	
		
			
				|  |  | +          <Pen show={studyData.type === 'pen'} close={() => closeStudyTool()} />
 | 
	
		
			
				|  |  | +        )}
 | 
	
		
			
				|  |  | +      </div>
 | 
	
		
			
				|  |  | +    );
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +});
 |