|  | @@ -0,0 +1,871 @@
 | 
											
												
													
														|  | 
 |  | +import {
 | 
											
												
													
														|  | 
 |  | +  closeToast,
 | 
											
												
													
														|  | 
 |  | +  Icon,
 | 
											
												
													
														|  | 
 |  | +  Loading,
 | 
											
												
													
														|  | 
 |  | +  Popup,
 | 
											
												
													
														|  | 
 |  | +  showToast,
 | 
											
												
													
														|  | 
 |  | +  Slider,
 | 
											
												
													
														|  | 
 |  | +  Swipe,
 | 
											
												
													
														|  | 
 |  | +  SwipeInstance,
 | 
											
												
													
														|  | 
 |  | +  SwipeItem
 | 
											
												
													
														|  | 
 |  | +} from 'vant'
 | 
											
												
													
														|  | 
 |  | +import {
 | 
											
												
													
														|  | 
 |  | +  defineComponent,
 | 
											
												
													
														|  | 
 |  | +  onMounted,
 | 
											
												
													
														|  | 
 |  | +  reactive,
 | 
											
												
													
														|  | 
 |  | +  nextTick,
 | 
											
												
													
														|  | 
 |  | +  onUnmounted,
 | 
											
												
													
														|  | 
 |  | +  ref,
 | 
											
												
													
														|  | 
 |  | +  watch,
 | 
											
												
													
														|  | 
 |  | +  Transition,
 | 
											
												
													
														|  | 
 |  | +  TransitionGroup
 | 
											
												
													
														|  | 
 |  | +} from 'vue'
 | 
											
												
													
														|  | 
 |  | +import iconBack from './image/back.svg'
 | 
											
												
													
														|  | 
 |  | +import styles from './index.module.less'
 | 
											
												
													
														|  | 
 |  | +import 'plyr/dist/plyr.css'
 | 
											
												
													
														|  | 
 |  | +import request from '@/helpers/request'
 | 
											
												
													
														|  | 
 |  | +import { state } from '@/state'
 | 
											
												
													
														|  | 
 |  | +import { useRoute, useRouter } from 'vue-router'
 | 
											
												
													
														|  | 
 |  | +import { listenerMessage, postMessage, promisefiyPostMessage } from '@/helpers/native-message'
 | 
											
												
													
														|  | 
 |  | +import MusicScore from './component/musicScore'
 | 
											
												
													
														|  | 
 |  | +import iconMenu from './image/icon-menu.svg'
 | 
											
												
													
														|  | 
 |  | +import iconDian from './image/icon-dian.svg'
 | 
											
												
													
														|  | 
 |  | +import iconTouping from './image/icon-touping.svg'
 | 
											
												
													
														|  | 
 |  | +import iconPoint from './image/icon-point.svg'
 | 
											
												
													
														|  | 
 |  | +import iconLoop from './image/icon-loop.svg'
 | 
											
												
													
														|  | 
 |  | +import iconLoopActive from './image/icon-loop-active.svg'
 | 
											
												
													
														|  | 
 |  | +import iconplay from './image/icon-play.svg'
 | 
											
												
													
														|  | 
 |  | +import iconpause from './image/icon-pause.svg'
 | 
											
												
													
														|  | 
 |  | +import iconUp from './image/icon-up.svg'
 | 
											
												
													
														|  | 
 |  | +import iconDown from './image/icon-down.svg'
 | 
											
												
													
														|  | 
 |  | +import Points from './component/points'
 | 
											
												
													
														|  | 
 |  | +import { browser, getSecondRPM } from '@/helpers/utils'
 | 
											
												
													
														|  | 
 |  | +import { Vue3Lottie } from 'vue3-lottie'
 | 
											
												
													
														|  | 
 |  | +import playLoadData from './datas/data.json'
 | 
											
												
													
														|  | 
 |  | +import { usePageVisibility, useRect } from '@vant/use'
 | 
											
												
													
														|  | 
 |  | +import PlayRecordTime from './playRecordTime'
 | 
											
												
													
														|  | 
 |  | +import dayjs from 'dayjs'
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +import {
 | 
											
												
													
														|  | 
 |  | +  Pagination,
 | 
											
												
													
														|  | 
 |  | +  Navigation,
 | 
											
												
													
														|  | 
 |  | +  Virtual,
 | 
											
												
													
														|  | 
 |  | +  EffectFade,
 | 
											
												
													
														|  | 
 |  | +  EffectFlip,
 | 
											
												
													
														|  | 
 |  | +  EffectCreative,
 | 
											
												
													
														|  | 
 |  | +  Lazy
 | 
											
												
													
														|  | 
 |  | +} from 'swiper'
 | 
											
												
													
														|  | 
 |  | +import { Swiper, SwiperSlide } from 'swiper/vue'
 | 
											
												
													
														|  | 
 |  | +import 'swiper/less'
 | 
											
												
													
														|  | 
 |  | +import 'swiper/less/effect-fade'
 | 
											
												
													
														|  | 
 |  | +import 'swiper/less/effect-flip'
 | 
											
												
													
														|  | 
 |  | +import 'swiper/less/effect-creative'
 | 
											
												
													
														|  | 
 |  | +import { handleCheckVip } from '../hook/useFee'
 | 
											
												
													
														|  | 
 |  | +import OGuide from '@/components/o-guide'
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +export default defineComponent({
 | 
											
												
													
														|  | 
 |  | +  name: 'CoursewarePlay',
 | 
											
												
													
														|  | 
 |  | +  setup() {
 | 
											
												
													
														|  | 
 |  | +    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.paused
 | 
											
												
													
														|  | 
 |  | +        handlePaused(activeItem)
 | 
											
												
													
														|  | 
 |  | +      } else {
 | 
											
												
													
														|  | 
 |  | +        // 页面显示,并且
 | 
											
												
													
														|  | 
 |  | +        if (isPlay.value) handlePlay(activeItem)
 | 
											
												
													
														|  | 
 |  | +      }
 | 
											
												
													
														|  | 
 |  | +    })
 | 
											
												
													
														|  | 
 |  | +    /** 设置播放容器 16:9 */
 | 
											
												
													
														|  | 
 |  | +    const parentContainer = reactive({
 | 
											
												
													
														|  | 
 |  | +      width: '100vw'
 | 
											
												
													
														|  | 
 |  | +    })
 | 
											
												
													
														|  | 
 |  | +    const setContainer = () => {
 | 
											
												
													
														|  | 
 |  | +      let min = Math.min(screen.width, screen.height)
 | 
											
												
													
														|  | 
 |  | +      let max = Math.max(screen.width, screen.height)
 | 
											
												
													
														|  | 
 |  | +      let width = min * (16 / 9)
 | 
											
												
													
														|  | 
 |  | +      if (width > max) {
 | 
											
												
													
														|  | 
 |  | +        parentContainer.width = '100vw'
 | 
											
												
													
														|  | 
 |  | +        return
 | 
											
												
													
														|  | 
 |  | +      } else {
 | 
											
												
													
														|  | 
 |  | +        parentContainer.width = width + 'px'
 | 
											
												
													
														|  | 
 |  | +      }
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +    const handleInit = (type = 0) => {
 | 
											
												
													
														|  | 
 |  | +      // postMessage({
 | 
											
												
													
														|  | 
 |  | +      //   api: 'courseLoading',
 | 
											
												
													
														|  | 
 |  | +      //   content: {
 | 
											
												
													
														|  | 
 |  | +      //     show: true,
 | 
											
												
													
														|  | 
 |  | +      //     type: 'fullscreen'
 | 
											
												
													
														|  | 
 |  | +      //   }
 | 
											
												
													
														|  | 
 |  | +      // })
 | 
											
												
													
														|  | 
 |  | +      //设置容器16:9
 | 
											
												
													
														|  | 
 |  | +      setContainer()
 | 
											
												
													
														|  | 
 |  | +      // 横屏
 | 
											
												
													
														|  | 
 |  | +      postMessage({
 | 
											
												
													
														|  | 
 |  | +        api: 'setRequestedOrientation',
 | 
											
												
													
														|  | 
 |  | +        content: {
 | 
											
												
													
														|  | 
 |  | +          orientation: type
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +      })
 | 
											
												
													
														|  | 
 |  | +      // 头,包括返回箭头
 | 
											
												
													
														|  | 
 |  | +      postMessage({
 | 
											
												
													
														|  | 
 |  | +        api: 'setTitleBarVisibility',
 | 
											
												
													
														|  | 
 |  | +        content: {
 | 
											
												
													
														|  | 
 |  | +          status: type
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +      })
 | 
											
												
													
														|  | 
 |  | +      // 安卓的状态栏
 | 
											
												
													
														|  | 
 |  | +      postMessage({
 | 
											
												
													
														|  | 
 |  | +        api: 'setStatusBarVisibility',
 | 
											
												
													
														|  | 
 |  | +        content: {
 | 
											
												
													
														|  | 
 |  | +          isVisibility: type
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +      })
 | 
											
												
													
														|  | 
 |  | +      // 进入页面设置常量
 | 
											
												
													
														|  | 
 |  | +      postMessage({
 | 
											
												
													
														|  | 
 |  | +        api: 'keepScreenLongLight',
 | 
											
												
													
														|  | 
 |  | +        content: {
 | 
											
												
													
														|  | 
 |  | +          isOpenLight: type ? true : false
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +      })
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +    handleInit()
 | 
											
												
													
														|  | 
 |  | +    onUnmounted(() => {
 | 
											
												
													
														|  | 
 |  | +      handleInit(1)
 | 
											
												
													
														|  | 
 |  | +      window.removeEventListener('message', iframeHandle)
 | 
											
												
													
														|  | 
 |  | +    })
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    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
 | 
											
												
													
														|  | 
 |  | +    })
 | 
											
												
													
														|  | 
 |  | +    const activeData = reactive({
 | 
											
												
													
														|  | 
 |  | +      nowTime: 0,
 | 
											
												
													
														|  | 
 |  | +      model: true, // 遮罩
 | 
											
												
													
														|  | 
 |  | +      videoBtns: true, // 视频
 | 
											
												
													
														|  | 
 |  | +      currentTime: 0,
 | 
											
												
													
														|  | 
 |  | +      duration: 0,
 | 
											
												
													
														|  | 
 |  | +      timer: null as any,
 | 
											
												
													
														|  | 
 |  | +      item: null as any
 | 
											
												
													
														|  | 
 |  | +    })
 | 
											
												
													
														|  | 
 |  | +    // 获取缓存路径
 | 
											
												
													
														|  | 
 |  | +    const getCacheFilePath = async (material: any) => {
 | 
											
												
													
														|  | 
 |  | +      const res = await promisefiyPostMessage({
 | 
											
												
													
														|  | 
 |  | +        api: 'getCourseFilePath',
 | 
											
												
													
														|  | 
 |  | +        content: {
 | 
											
												
													
														|  | 
 |  | +          url: material.content,
 | 
											
												
													
														|  | 
 |  | +          localPath: '',
 | 
											
												
													
														|  | 
 |  | +          materialId: material.materialId,
 | 
											
												
													
														|  | 
 |  | +          updateTime: material.updateTime,
 | 
											
												
													
														|  | 
 |  | +          type: material.type // SONG VIDEO IMAGE
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +      })
 | 
											
												
													
														|  | 
 |  | +      // console.log('缓存路径返回', res)
 | 
											
												
													
														|  | 
 |  | +      return res
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +    // 获取当前课程是否签退
 | 
											
												
													
														|  | 
 |  | +    const getCourseSchedule = async () => {
 | 
											
												
													
														|  | 
 |  | +      if (!route.query.courseId) return
 | 
											
												
													
														|  | 
 |  | +      try {
 | 
											
												
													
														|  | 
 |  | +        const res = await request.get(
 | 
											
												
													
														|  | 
 |  | +          `${state.platformApi}/courseSchedule/detail/${route.query.courseId}`,
 | 
											
												
													
														|  | 
 |  | +          {
 | 
											
												
													
														|  | 
 |  | +            hideLoading: true
 | 
											
												
													
														|  | 
 |  | +          }
 | 
											
												
													
														|  | 
 |  | +        )
 | 
											
												
													
														|  | 
 |  | +        if (res?.data) {
 | 
											
												
													
														|  | 
 |  | +          data.isCourse =
 | 
											
												
													
														|  | 
 |  | +            res.data.status === 'ING' && state.platformType == 'TEACHER' ? true : false
 | 
											
												
													
														|  | 
 |  | +          // data.isRecordPlay = Date.now() > dayjs(res.data.startTime).valueOf()
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +      } catch (e) {
 | 
											
												
													
														|  | 
 |  | +        console.log(e)
 | 
											
												
													
														|  | 
 |  | +      }
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +    const getItemList = async () => {
 | 
											
												
													
														|  | 
 |  | +      const list: any = []
 | 
											
												
													
														|  | 
 |  | +      const browserInfo = browser()
 | 
											
												
													
														|  | 
 |  | +      for (let i = 0; i < data.knowledgePointList.length; i++) {
 | 
											
												
													
														|  | 
 |  | +        const item = data.knowledgePointList[i]
 | 
											
												
													
														|  | 
 |  | +        const itemLength = item.materialList.length - 1
 | 
											
												
													
														|  | 
 |  | +        for (let j = 0; j < item.materialList.length; j++) {
 | 
											
												
													
														|  | 
 |  | +          const material = item.materialList[j]
 | 
											
												
													
														|  | 
 |  | +          //请求本地缓存
 | 
											
												
													
														|  | 
 |  | +          if (browserInfo.isApp && ['VIDEO', 'IMG'].includes(material.type)) {
 | 
											
												
													
														|  | 
 |  | +            const localData = await getCacheFilePath(material)
 | 
											
												
													
														|  | 
 |  | +            if (localData?.content?.localPath) {
 | 
											
												
													
														|  | 
 |  | +              material.url = material.content
 | 
											
												
													
														|  | 
 |  | +              material.content = localData.content.localPath
 | 
											
												
													
														|  | 
 |  | +              // console.log("🚀 ~ material", material)
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +          }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +          let videoItem = {}
 | 
											
												
													
														|  | 
 |  | +          if (material.type === 'VIDEO') {
 | 
											
												
													
														|  | 
 |  | +            videoItem = {
 | 
											
												
													
														|  | 
 |  | +              currentTime: 0,
 | 
											
												
													
														|  | 
 |  | +              duration: 0,
 | 
											
												
													
														|  | 
 |  | +              progress: 0,
 | 
											
												
													
														|  | 
 |  | +              paused: true,
 | 
											
												
													
														|  | 
 |  | +              loop: false,
 | 
											
												
													
														|  | 
 |  | +              videoEle: null,
 | 
											
												
													
														|  | 
 |  | +              timer: null,
 | 
											
												
													
														|  | 
 |  | +              playModel: false,
 | 
											
												
													
														|  | 
 |  | +              isprepare: false,
 | 
											
												
													
														|  | 
 |  | +              isDrage: false,
 | 
											
												
													
														|  | 
 |  | +              muted: true // 是否静音
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +          }
 | 
											
												
													
														|  | 
 |  | +          list.push({
 | 
											
												
													
														|  | 
 |  | +            ...material,
 | 
											
												
													
														|  | 
 |  | +            ...videoItem,
 | 
											
												
													
														|  | 
 |  | +            iframeRef: null,
 | 
											
												
													
														|  | 
 |  | +            tabName: item.name,
 | 
											
												
													
														|  | 
 |  | +            isLast: j === itemLength, // 当前知识点
 | 
											
												
													
														|  | 
 |  | +            autoPlay: false, //加载完成是否自动播放
 | 
											
												
													
														|  | 
 |  | +            display: false
 | 
											
												
													
														|  | 
 |  | +          })
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +      }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +      let item: any = null
 | 
											
												
													
														|  | 
 |  | +      if (route.query.kId) {
 | 
											
												
													
														|  | 
 |  | +        item = list.find((n: any) => n.materialId == route.query.kId)
 | 
											
												
													
														|  | 
 |  | +        const _firstIndex = list.findIndex((n: any) => n.materialId == route.query.kId)
 | 
											
												
													
														|  | 
 |  | +        console.log('🚀 ~ item:', _firstIndex, list)
 | 
											
												
													
														|  | 
 |  | +        popupData.firstIndex = _firstIndex > -1 ? _firstIndex : 0
 | 
											
												
													
														|  | 
 |  | +      }
 | 
											
												
													
														|  | 
 |  | +      item = item ? item : list[0] || {}
 | 
											
												
													
														|  | 
 |  | +      if (item) {
 | 
											
												
													
														|  | 
 |  | +        popupData.tabName = item.tabName
 | 
											
												
													
														|  | 
 |  | +        popupData.tabActive = item.knowledgePointId
 | 
											
												
													
														|  | 
 |  | +        popupData.itemActive = item.id
 | 
											
												
													
														|  | 
 |  | +        popupData.itemName = item.name
 | 
											
												
													
														|  | 
 |  | +        popupData.activeIndex = popupData.firstIndex
 | 
											
												
													
														|  | 
 |  | +        console.log("🚀 ~ popupData.activeIndex:", popupData.activeIndex)
 | 
											
												
													
														|  | 
 |  | +        item.autoPlay = true
 | 
											
												
													
														|  | 
 |  | +        item.muted = true
 | 
											
												
													
														|  | 
 |  | +        item.display = true
 | 
											
												
													
														|  | 
 |  | +      }
 | 
											
												
													
														|  | 
 |  | +      // console.log('🚀 ~ list', list)
 | 
											
												
													
														|  | 
 |  | +      nextTick(() => {
 | 
											
												
													
														|  | 
 |  | +        data.itemList = list
 | 
											
												
													
														|  | 
 |  | +        postMessage({
 | 
											
												
													
														|  | 
 |  | +          api: 'courseLoading',
 | 
											
												
													
														|  | 
 |  | +          content: {
 | 
											
												
													
														|  | 
 |  | +            show: false,
 | 
											
												
													
														|  | 
 |  | +            type: 'fullscreen'
 | 
											
												
													
														|  | 
 |  | +          }
 | 
											
												
													
														|  | 
 |  | +        })
 | 
											
												
													
														|  | 
 |  | +      })
 | 
											
												
													
														|  | 
 |  | +      // setTimeout(() => {
 | 
											
												
													
														|  | 
 |  | +      // }, 300)
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +    const getDetail = async () => {
 | 
											
												
													
														|  | 
 |  | +      try {
 | 
											
												
													
														|  | 
 |  | +        const res: any = await request.get(
 | 
											
												
													
														|  | 
 |  | +          state.platformApi + `/lessonCoursewareDetail/detail/${route.query.id}`,
 | 
											
												
													
														|  | 
 |  | +          {
 | 
											
												
													
														|  | 
 |  | +            hideLoading: true
 | 
											
												
													
														|  | 
 |  | +          }
 | 
											
												
													
														|  | 
 |  | +        )
 | 
											
												
													
														|  | 
 |  | +        if (Array.isArray(res?.data)) {
 | 
											
												
													
														|  | 
 |  | +          data.detail = res.data
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +        if (Array.isArray(res?.data?.knowledgePointList)) {
 | 
											
												
													
														|  | 
 |  | +          let index = 0
 | 
											
												
													
														|  | 
 |  | +          data.knowledgePointList = res.data.knowledgePointList.map((n: any) => {
 | 
											
												
													
														|  | 
 |  | +            if (Array.isArray(n.materialList)) {
 | 
											
												
													
														|  | 
 |  | +              n.materialList = n.materialList.map((item: any) => {
 | 
											
												
													
														|  | 
 |  | +                index++
 | 
											
												
													
														|  | 
 |  | +                return {
 | 
											
												
													
														|  | 
 |  | +                  ...item,
 | 
											
												
													
														|  | 
 |  | +                  materialId: item.id,
 | 
											
												
													
														|  | 
 |  | +                  id: index + ''
 | 
											
												
													
														|  | 
 |  | +                }
 | 
											
												
													
														|  | 
 |  | +              })
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +            return n
 | 
											
												
													
														|  | 
 |  | +          })
 | 
											
												
													
														|  | 
 |  | +          getItemList()
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +      } catch (error) {}
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +    // ifram事件处理
 | 
											
												
													
														|  | 
 |  | +    const iframeHandle = (ev: MessageEvent) => {
 | 
											
												
													
														|  | 
 |  | +      if (ev.data?.api === 'headerTogge') {
 | 
											
												
													
														|  | 
 |  | +        // console.log("🚀 ~ ev.data", ev.data)
 | 
											
												
													
														|  | 
 |  | +        activeData.model = ev.data.show || (ev.data.playState == 'play' ? true : false)
 | 
											
												
													
														|  | 
 |  | +      }
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    const swiperDom = ref()
 | 
											
												
													
														|  | 
 |  | +    onMounted(() => {
 | 
											
												
													
														|  | 
 |  | +      const hasVip = handleCheckVip()
 | 
											
												
													
														|  | 
 |  | +      if (!hasVip) {
 | 
											
												
													
														|  | 
 |  | +        nextTick(() => {
 | 
											
												
													
														|  | 
 |  | +          postMessage({
 | 
											
												
													
														|  | 
 |  | +            api: 'courseLoading',
 | 
											
												
													
														|  | 
 |  | +            content: {
 | 
											
												
													
														|  | 
 |  | +              show: false,
 | 
											
												
													
														|  | 
 |  | +              type: 'fullscreen'
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +          })
 | 
											
												
													
														|  | 
 |  | +        })
 | 
											
												
													
														|  | 
 |  | +        return
 | 
											
												
													
														|  | 
 |  | +      }
 | 
											
												
													
														|  | 
 |  | +      getDetail()
 | 
											
												
													
														|  | 
 |  | +      getCourseSchedule()
 | 
											
												
													
														|  | 
 |  | +      window.addEventListener('message', iframeHandle)
 | 
											
												
													
														|  | 
 |  | +    })
 | 
											
												
													
														|  | 
 |  | +    const playRef = ref()
 | 
											
												
													
														|  | 
 |  | +    // 返回
 | 
											
												
													
														|  | 
 |  | +    const goback = () => {
 | 
											
												
													
														|  | 
 |  | +      try {
 | 
											
												
													
														|  | 
 |  | +        playRef.value?.handleOut()
 | 
											
												
													
														|  | 
 |  | +      } catch (error) {}
 | 
											
												
													
														|  | 
 |  | +      if (route.query.source == 'my-course') {
 | 
											
												
													
														|  | 
 |  | +        router.back()
 | 
											
												
													
														|  | 
 |  | +        return
 | 
											
												
													
														|  | 
 |  | +      }
 | 
											
												
													
														|  | 
 |  | +      postMessage({ api: 'goBack' })
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    const swipeRef = ref<SwipeInstance>()
 | 
											
												
													
														|  | 
 |  | +    const popupData = reactive({
 | 
											
												
													
														|  | 
 |  | +      firstIndex: 0,
 | 
											
												
													
														|  | 
 |  | +      open: false,
 | 
											
												
													
														|  | 
 |  | +      activeIndex: 0,
 | 
											
												
													
														|  | 
 |  | +      tabActive: '',
 | 
											
												
													
														|  | 
 |  | +      tabName: '',
 | 
											
												
													
														|  | 
 |  | +      itemActive: '',
 | 
											
												
													
														|  | 
 |  | +      itemName: '',
 | 
											
												
													
														|  | 
 |  | +      guideOpen: false
 | 
											
												
													
														|  | 
 |  | +    })
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    /**停止所有的播放 */
 | 
											
												
													
														|  | 
 |  | +    const handleStop = () => {
 | 
											
												
													
														|  | 
 |  | +      const activeItem = data.itemList[popupData.activeIndex]
 | 
											
												
													
														|  | 
 |  | +      for (let i = 0; i < data.itemList.length; i++) {
 | 
											
												
													
														|  | 
 |  | +        const item = data.itemList[i]
 | 
											
												
													
														|  | 
 |  | +        // 停止视频播放
 | 
											
												
													
														|  | 
 |  | +        if (item.type === 'VIDEO') {
 | 
											
												
													
														|  | 
 |  | +          // console.log("🚀 ~ item", item)
 | 
											
												
													
														|  | 
 |  | +          if (item?.id != activeItem.id) {
 | 
											
												
													
														|  | 
 |  | +            item.currentTime = 0
 | 
											
												
													
														|  | 
 |  | +            item.progress = 0
 | 
											
												
													
														|  | 
 |  | +            if (item.videoEle) {
 | 
											
												
													
														|  | 
 |  | +              item.videoEle.currentTime = 0
 | 
											
												
													
														|  | 
 |  | +              item.videoEle.pause()
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +          }
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +        // 停止曲谱的播放
 | 
											
												
													
														|  | 
 |  | +        if (item.type === 'SONG') {
 | 
											
												
													
														|  | 
 |  | +          item.iframeRef?.contentWindow?.postMessage({ api: 'setPlayState' }, '*')
 | 
											
												
													
														|  | 
 |  | +          item.display = false
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +      }
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +    // 切换素材
 | 
											
												
													
														|  | 
 |  | +    const toggleMaterial = () => {
 | 
											
												
													
														|  | 
 |  | +      const index = data.itemList.findIndex((n: any) => n.id == popupData.itemActive)
 | 
											
												
													
														|  | 
 |  | +      if (index > -1) {
 | 
											
												
													
														|  | 
 |  | +        // swipeRef.value?.swipeTo(index, {
 | 
											
												
													
														|  | 
 |  | +        //   immediate: true
 | 
											
												
													
														|  | 
 |  | +        // })
 | 
											
												
													
														|  | 
 |  | +        swiperDom.value?.slideTo(index, 1000)
 | 
											
												
													
														|  | 
 |  | +      }
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +    /** 延迟收起模态框 */
 | 
											
												
													
														|  | 
 |  | +    const setModelOpen = () => {
 | 
											
												
													
														|  | 
 |  | +      clearTimeout(activeData.timer)
 | 
											
												
													
														|  | 
 |  | +      closeToast()
 | 
											
												
													
														|  | 
 |  | +      activeData.timer = setTimeout(() => {
 | 
											
												
													
														|  | 
 |  | +        activeData.model = false
 | 
											
												
													
														|  | 
 |  | +      }, 4000)
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +    // 轮播切换
 | 
											
												
													
														|  | 
 |  | +    const handleSwipeChange = (val: any) => {
 | 
											
												
													
														|  | 
 |  | +      console.log('轮播切换')
 | 
											
												
													
														|  | 
 |  | +      popupData.activeIndex = val
 | 
											
												
													
														|  | 
 |  | +      const item = data.itemList[val]
 | 
											
												
													
														|  | 
 |  | +      handleStop()
 | 
											
												
													
														|  | 
 |  | +      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
 | 
											
												
													
														|  | 
 |  | +          item.display = true
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +        if (item.type === 'VIDEO') {
 | 
											
												
													
														|  | 
 |  | +          // console.log("🚀 ~ item", item)
 | 
											
												
													
														|  | 
 |  | +          // 自动播放下一个视频
 | 
											
												
													
														|  | 
 |  | +          clearTimeout(activeData.timer)
 | 
											
												
													
														|  | 
 |  | +          closeToast()
 | 
											
												
													
														|  | 
 |  | +          item.currentTime = 0
 | 
											
												
													
														|  | 
 |  | +          item.videoEle && (item.videoEle.currentTime = 0)
 | 
											
												
													
														|  | 
 |  | +          nextTick(() => {
 | 
											
												
													
														|  | 
 |  | +            item.autoPlay = true
 | 
											
												
													
														|  | 
 |  | +            item.videoEle?.play()
 | 
											
												
													
														|  | 
 |  | +          })
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +      }
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    // 去点名,签退
 | 
											
												
													
														|  | 
 |  | +    const gotoRollCall = (pageTag: string) => {
 | 
											
												
													
														|  | 
 |  | +      postMessage({
 | 
											
												
													
														|  | 
 |  | +        api: 'open_app_page',
 | 
											
												
													
														|  | 
 |  | +        content: {
 | 
											
												
													
														|  | 
 |  | +          action: 'app',
 | 
											
												
													
														|  | 
 |  | +          pageTag: pageTag,
 | 
											
												
													
														|  | 
 |  | +          url: '',
 | 
											
												
													
														|  | 
 |  | +          params: JSON.stringify({ courseId: route.query.courseId })
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +      })
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    // 双击
 | 
											
												
													
														|  | 
 |  | +    const handleDbClick = (item: any) => {
 | 
											
												
													
														|  | 
 |  | +      // console.log(item)
 | 
											
												
													
														|  | 
 |  | +      if (item && item.type === 'VIDEO') {
 | 
											
												
													
														|  | 
 |  | +        const videoEle: HTMLVideoElement = item.videoEle
 | 
											
												
													
														|  | 
 |  | +        if (videoEle) {
 | 
											
												
													
														|  | 
 |  | +          if (videoEle.paused) {
 | 
											
												
													
														|  | 
 |  | +            closeToast()
 | 
											
												
													
														|  | 
 |  | +            videoEle.play()
 | 
											
												
													
														|  | 
 |  | +          } else {
 | 
											
												
													
														|  | 
 |  | +            showToast('已暂停')
 | 
											
												
													
														|  | 
 |  | +            videoEle.pause()
 | 
											
												
													
														|  | 
 |  | +          }
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +      }
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    // 暂停播放
 | 
											
												
													
														|  | 
 |  | +    const handlePaused = (m: any) => {
 | 
											
												
													
														|  | 
 |  | +      m.videoEle?.pause()
 | 
											
												
													
														|  | 
 |  | +      m.paused = true
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +    // 开始播放
 | 
											
												
													
														|  | 
 |  | +    const handlePlay = (m: any) => {
 | 
											
												
													
														|  | 
 |  | +      closeToast()
 | 
											
												
													
														|  | 
 |  | +      m.videoEle?.play()
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    // 调整播放进度
 | 
											
												
													
														|  | 
 |  | +    const handleChangeSlider = (m: any) => {
 | 
											
												
													
														|  | 
 |  | +      if (m?.videoEle) {
 | 
											
												
													
														|  | 
 |  | +        // console.log('进度条', m.progress)
 | 
											
												
													
														|  | 
 |  | +        m.currentTime = m.duration * (m.progress / 100)
 | 
											
												
													
														|  | 
 |  | +        m.videoEle.currentTime = m.currentTime
 | 
											
												
													
														|  | 
 |  | +      }
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    //当前视频播放完
 | 
											
												
													
														|  | 
 |  | +    const handleEnded = (m: any) => {
 | 
											
												
													
														|  | 
 |  | +      // console.log(m)
 | 
											
												
													
														|  | 
 |  | +      if (popupData.activeIndex != data.itemList.length - 1) {
 | 
											
												
													
														|  | 
 |  | +        swiperDom.value.slideNext(800)
 | 
											
												
													
														|  | 
 |  | +      }
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    const effects = [
 | 
											
												
													
														|  | 
 |  | +      {
 | 
											
												
													
														|  | 
 |  | +        prev: {
 | 
											
												
													
														|  | 
 |  | +          shadow: true,
 | 
											
												
													
														|  | 
 |  | +          translate: [0, 0, -400]
 | 
											
												
													
														|  | 
 |  | +        },
 | 
											
												
													
														|  | 
 |  | +        next: {
 | 
											
												
													
														|  | 
 |  | +          translate: ['100%', 0, 0]
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +      },
 | 
											
												
													
														|  | 
 |  | +      {
 | 
											
												
													
														|  | 
 |  | +        prev: {
 | 
											
												
													
														|  | 
 |  | +          shadow: true,
 | 
											
												
													
														|  | 
 |  | +          translate: ['-120%', 0, -500]
 | 
											
												
													
														|  | 
 |  | +        },
 | 
											
												
													
														|  | 
 |  | +        next: {
 | 
											
												
													
														|  | 
 |  | +          shadow: true,
 | 
											
												
													
														|  | 
 |  | +          translate: ['120%', 0, -500]
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +      },
 | 
											
												
													
														|  | 
 |  | +      {
 | 
											
												
													
														|  | 
 |  | +        prev: {
 | 
											
												
													
														|  | 
 |  | +          shadow: true,
 | 
											
												
													
														|  | 
 |  | +          translate: ['-20%', 0, -1]
 | 
											
												
													
														|  | 
 |  | +        },
 | 
											
												
													
														|  | 
 |  | +        next: {
 | 
											
												
													
														|  | 
 |  | +          translate: ['100%', 0, 0]
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +      },
 | 
											
												
													
														|  | 
 |  | +      {
 | 
											
												
													
														|  | 
 |  | +        prev: {
 | 
											
												
													
														|  | 
 |  | +          shadow: true,
 | 
											
												
													
														|  | 
 |  | +          translate: [0, 0, -800],
 | 
											
												
													
														|  | 
 |  | +          rotate: [-180, 0, 0]
 | 
											
												
													
														|  | 
 |  | +        },
 | 
											
												
													
														|  | 
 |  | +        next: {
 | 
											
												
													
														|  | 
 |  | +          shadow: true,
 | 
											
												
													
														|  | 
 |  | +          translate: [0, 0, -800],
 | 
											
												
													
														|  | 
 |  | +          rotate: [180, 0, 0]
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +      },
 | 
											
												
													
														|  | 
 |  | +      {
 | 
											
												
													
														|  | 
 |  | +        prev: {
 | 
											
												
													
														|  | 
 |  | +          shadow: true,
 | 
											
												
													
														|  | 
 |  | +          translate: ['-125%', 0, -800],
 | 
											
												
													
														|  | 
 |  | +          rotate: [0, 0, -90]
 | 
											
												
													
														|  | 
 |  | +        },
 | 
											
												
													
														|  | 
 |  | +        next: {
 | 
											
												
													
														|  | 
 |  | +          shadow: true,
 | 
											
												
													
														|  | 
 |  | +          translate: ['125%', 0, -800],
 | 
											
												
													
														|  | 
 |  | +          rotate: [0, 0, 90]
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +      },
 | 
											
												
													
														|  | 
 |  | +      {
 | 
											
												
													
														|  | 
 |  | +        prev: {
 | 
											
												
													
														|  | 
 |  | +          shadow: true,
 | 
											
												
													
														|  | 
 |  | +          origin: 'right center',
 | 
											
												
													
														|  | 
 |  | +          translate: ['5%', 0, -200],
 | 
											
												
													
														|  | 
 |  | +          rotate: [0, -100, 0]
 | 
											
												
													
														|  | 
 |  | +        },
 | 
											
												
													
														|  | 
 |  | +        next: {
 | 
											
												
													
														|  | 
 |  | +          origin: 'left center',
 | 
											
												
													
														|  | 
 |  | +          translate: ['-5%', 0, -200],
 | 
											
												
													
														|  | 
 |  | +          rotate: [0, 100, 0]
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +      },
 | 
											
												
													
														|  | 
 |  | +      {
 | 
											
												
													
														|  | 
 |  | +        prev: {
 | 
											
												
													
														|  | 
 |  | +          scale: 0.3,
 | 
											
												
													
														|  | 
 |  | +          opacity: 0.4
 | 
											
												
													
														|  | 
 |  | +        },
 | 
											
												
													
														|  | 
 |  | +        next: {
 | 
											
												
													
														|  | 
 |  | +          opacity: 0.4,
 | 
											
												
													
														|  | 
 |  | +          scale: 0.3
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +      }
 | 
											
												
													
														|  | 
 |  | +    ]
 | 
											
												
													
														|  | 
 |  | +    const swiperType = ref(effects[3])
 | 
											
												
													
														|  | 
 |  | +    // 上一个知识点, 下一个知识点
 | 
											
												
													
														|  | 
 |  | +    const handlePreAndNext = (type: string) => {
 | 
											
												
													
														|  | 
 |  | +      setTimeout(() => {
 | 
											
												
													
														|  | 
 |  | +        if (type === 'up') {
 | 
											
												
													
														|  | 
 |  | +          swiperDom.value.slidePrev(800)
 | 
											
												
													
														|  | 
 |  | +        } else {
 | 
											
												
													
														|  | 
 |  | +          swiperDom.value.slideNext(800)
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +      }, 400)
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    return () => (
 | 
											
												
													
														|  | 
 |  | +      <div class={styles.playContent}>
 | 
											
												
													
														|  | 
 |  | +        <div class={styles.coursewarePlay} style={{ width: parentContainer.width }}>
 | 
											
												
													
														|  | 
 |  | +          {data.itemList.length && (
 | 
											
												
													
														|  | 
 |  | +            <Swiper
 | 
											
												
													
														|  | 
 |  | +              style={{ height: '100%' }}
 | 
											
												
													
														|  | 
 |  | +              class={styles.swiperContainer}
 | 
											
												
													
														|  | 
 |  | +              effect="creative"
 | 
											
												
													
														|  | 
 |  | +              modules={[Pagination, Navigation, EffectCreative]}
 | 
											
												
													
														|  | 
 |  | +              creativeEffect={swiperType.value}
 | 
											
												
													
														|  | 
 |  | +              direction="vertical"
 | 
											
												
													
														|  | 
 |  | +              navigation
 | 
											
												
													
														|  | 
 |  | +              allowTouchMove={false}
 | 
											
												
													
														|  | 
 |  | +              onSwiper={(swiper: any) => {
 | 
											
												
													
														|  | 
 |  | +                swiperDom.value = swiper
 | 
											
												
													
														|  | 
 |  | +              }}
 | 
											
												
													
														|  | 
 |  | +              onSlideChange={(swiper: any) => {
 | 
											
												
													
														|  | 
 |  | +                handleSwipeChange(swiper.activeIndex)
 | 
											
												
													
														|  | 
 |  | +              }}
 | 
											
												
													
														|  | 
 |  | +              initialSlide={popupData.activeIndex}
 | 
											
												
													
														|  | 
 |  | +            >
 | 
											
												
													
														|  | 
 |  | +              {data.itemList.map((m: any, mIndex: number) => {
 | 
											
												
													
														|  | 
 |  | +                return (
 | 
											
												
													
														|  | 
 |  | +                  <SwiperSlide class={styles.swipeItem} key={'index' + mIndex}>
 | 
											
												
													
														|  | 
 |  | +                    <div
 | 
											
												
													
														|  | 
 |  | +                      class={[styles.itemDiv]}
 | 
											
												
													
														|  | 
 |  | +                      onClick={() => {
 | 
											
												
													
														|  | 
 |  | +                        clearTimeout(activeData.timer)
 | 
											
												
													
														|  | 
 |  | +                        if (Date.now() - activeData.nowTime < 300) {
 | 
											
												
													
														|  | 
 |  | +                          handleDbClick(m)
 | 
											
												
													
														|  | 
 |  | +                          return
 | 
											
												
													
														|  | 
 |  | +                        }
 | 
											
												
													
														|  | 
 |  | +                        activeData.nowTime = Date.now()
 | 
											
												
													
														|  | 
 |  | +                        activeData.timer = setTimeout(() => {
 | 
											
												
													
														|  | 
 |  | +                          activeData.model = !activeData.model
 | 
											
												
													
														|  | 
 |  | +                          setModelOpen()
 | 
											
												
													
														|  | 
 |  | +                        }, 300)
 | 
											
												
													
														|  | 
 |  | +                      }}
 | 
											
												
													
														|  | 
 |  | +                    >
 | 
											
												
													
														|  | 
 |  | +                      {m.type === 'VIDEO' ? (
 | 
											
												
													
														|  | 
 |  | +                        <>
 | 
											
												
													
														|  | 
 |  | +                          <video
 | 
											
												
													
														|  | 
 |  | +                            class={['player']}
 | 
											
												
													
														|  | 
 |  | +                            playsinline="false"
 | 
											
												
													
														|  | 
 |  | +                            muted={m.muted}
 | 
											
												
													
														|  | 
 |  | +                            preload="auto"
 | 
											
												
													
														|  | 
 |  | +                            data-vid={m.id}
 | 
											
												
													
														|  | 
 |  | +                            src={m.content}
 | 
											
												
													
														|  | 
 |  | +                            loop={m.loop}
 | 
											
												
													
														|  | 
 |  | +                            autoplay={m.autoPlay}
 | 
											
												
													
														|  | 
 |  | +                            onLoadedmetadata={(e: Event) => {
 | 
											
												
													
														|  | 
 |  | +                              const videoEle = e.target as unknown as HTMLVideoElement
 | 
											
												
													
														|  | 
 |  | +                              m.currentTime = videoEle.currentTime
 | 
											
												
													
														|  | 
 |  | +                              m.duration = videoEle.duration
 | 
											
												
													
														|  | 
 |  | +                              m.videoEle = videoEle
 | 
											
												
													
														|  | 
 |  | +                              m.isprepare = true
 | 
											
												
													
														|  | 
 |  | +                            }}
 | 
											
												
													
														|  | 
 |  | +                            onTimeupdate={(e: Event) => {
 | 
											
												
													
														|  | 
 |  | +                              if (!m.isprepare) return
 | 
											
												
													
														|  | 
 |  | +                              const videoEle = e.target as unknown as HTMLVideoElement
 | 
											
												
													
														|  | 
 |  | +                              m.currentTime = videoEle.currentTime
 | 
											
												
													
														|  | 
 |  | +                              m.progress = Number((videoEle.currentTime / m.duration) * 100)
 | 
											
												
													
														|  | 
 |  | +                            }}
 | 
											
												
													
														|  | 
 |  | +                            onPlay={() => {
 | 
											
												
													
														|  | 
 |  | +                              // 播放
 | 
											
												
													
														|  | 
 |  | +                              m.paused = false
 | 
											
												
													
														|  | 
 |  | +                              console.log('播放')
 | 
											
												
													
														|  | 
 |  | +                              setModelOpen()
 | 
											
												
													
														|  | 
 |  | +                              // 第一次播放
 | 
											
												
													
														|  | 
 |  | +                              if (m.muted) {
 | 
											
												
													
														|  | 
 |  | +                                m.muted = false
 | 
											
												
													
														|  | 
 |  | +                                m.autoPlay = false
 | 
											
												
													
														|  | 
 |  | +                              }
 | 
											
												
													
														|  | 
 |  | +                            }}
 | 
											
												
													
														|  | 
 |  | +                            onPause={() => {
 | 
											
												
													
														|  | 
 |  | +                              //暂停
 | 
											
												
													
														|  | 
 |  | +                              clearTimeout(activeData.timer)
 | 
											
												
													
														|  | 
 |  | +                              m.paused = true
 | 
											
												
													
														|  | 
 |  | +                            }}
 | 
											
												
													
														|  | 
 |  | +                            onEnded={() => handleEnded(m)}
 | 
											
												
													
														|  | 
 |  | +                          >
 | 
											
												
													
														|  | 
 |  | +                            <source src={m.content} type="video/mp4" />
 | 
											
												
													
														|  | 
 |  | +                          </video>
 | 
											
												
													
														|  | 
 |  | +                          {m.muted && (
 | 
											
												
													
														|  | 
 |  | +                            <div class={styles.loadWrap}>
 | 
											
												
													
														|  | 
 |  | +                              <Vue3Lottie animationData={playLoadData}></Vue3Lottie>
 | 
											
												
													
														|  | 
 |  | +                            </div>
 | 
											
												
													
														|  | 
 |  | +                          )}
 | 
											
												
													
														|  | 
 |  | +                          <div
 | 
											
												
													
														|  | 
 |  | +                            style={{ transform: activeData.model ? '' : 'translateY(100%)' }}
 | 
											
												
													
														|  | 
 |  | +                            class={styles.bottomFixedContainer}
 | 
											
												
													
														|  | 
 |  | +                            onClick={(e: Event) => {
 | 
											
												
													
														|  | 
 |  | +                              e.stopPropagation()
 | 
											
												
													
														|  | 
 |  | +                              setModelOpen()
 | 
											
												
													
														|  | 
 |  | +                            }}
 | 
											
												
													
														|  | 
 |  | +                          >
 | 
											
												
													
														|  | 
 |  | +                            <div style={{ opacity: m.isprepare ? '1' : '0' }}>
 | 
											
												
													
														|  | 
 |  | +                              <div class={styles.time}>
 | 
											
												
													
														|  | 
 |  | +                                <span>{getSecondRPM(m.currentTime)}</span>
 | 
											
												
													
														|  | 
 |  | +                                <span>{getSecondRPM(m.duration)}</span>
 | 
											
												
													
														|  | 
 |  | +                              </div>
 | 
											
												
													
														|  | 
 |  | +                              <div class={styles.slider}>
 | 
											
												
													
														|  | 
 |  | +                                <Slider
 | 
											
												
													
														|  | 
 |  | +                                  onClick={() => setModelOpen()}
 | 
											
												
													
														|  | 
 |  | +                                  buttonSize={16}
 | 
											
												
													
														|  | 
 |  | +                                  step={1}
 | 
											
												
													
														|  | 
 |  | +                                  modelValue={m.progress}
 | 
											
												
													
														|  | 
 |  | +                                  onUpdate:modelValue={(val: any) => {
 | 
											
												
													
														|  | 
 |  | +                                    console.log('val', val)
 | 
											
												
													
														|  | 
 |  | +                                    m.progress = val
 | 
											
												
													
														|  | 
 |  | +                                    handleChangeSlider(m)
 | 
											
												
													
														|  | 
 |  | +                                  }}
 | 
											
												
													
														|  | 
 |  | +                                  onDragStart={(e: Event) => {
 | 
											
												
													
														|  | 
 |  | +                                    // 开始拖动,暂停播放
 | 
											
												
													
														|  | 
 |  | +                                    console.log('开始拖动')
 | 
											
												
													
														|  | 
 |  | +                                    // 如果拖动之前,视频是播放状态,拖动完毕后继续播放
 | 
											
												
													
														|  | 
 |  | +                                    if (!m.paused) {
 | 
											
												
													
														|  | 
 |  | +                                      m.isDrage = true
 | 
											
												
													
														|  | 
 |  | +                                    }
 | 
											
												
													
														|  | 
 |  | +                                    handlePaused(m)
 | 
											
												
													
														|  | 
 |  | +                                  }}
 | 
											
												
													
														|  | 
 |  | +                                  onDragEnd={(e: Event) => {
 | 
											
												
													
														|  | 
 |  | +                                    console.log('结束拖动')
 | 
											
												
													
														|  | 
 |  | +                                    if (m.isDrage) {
 | 
											
												
													
														|  | 
 |  | +                                      m.isDrage = false
 | 
											
												
													
														|  | 
 |  | +                                      handlePlay(m)
 | 
											
												
													
														|  | 
 |  | +                                    }
 | 
											
												
													
														|  | 
 |  | +                                  }}
 | 
											
												
													
														|  | 
 |  | +                                  min={0}
 | 
											
												
													
														|  | 
 |  | +                                  max={100}
 | 
											
												
													
														|  | 
 |  | +                                />
 | 
											
												
													
														|  | 
 |  | +                              </div>
 | 
											
												
													
														|  | 
 |  | +                            </div>
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +                            <div class={styles.actions}>
 | 
											
												
													
														|  | 
 |  | +                              <div class={styles.actionBtn}>
 | 
											
												
													
														|  | 
 |  | +                                {m.isprepare ? (
 | 
											
												
													
														|  | 
 |  | +                                  <>
 | 
											
												
													
														|  | 
 |  | +                                    {m.paused ? (
 | 
											
												
													
														|  | 
 |  | +                                      <img src={iconplay} onClick={(e: Event) => handlePlay(m)} />
 | 
											
												
													
														|  | 
 |  | +                                    ) : (
 | 
											
												
													
														|  | 
 |  | +                                      <img
 | 
											
												
													
														|  | 
 |  | +                                        src={iconpause}
 | 
											
												
													
														|  | 
 |  | +                                        onClick={(e: Event) => handlePaused(m)}
 | 
											
												
													
														|  | 
 |  | +                                      />
 | 
											
												
													
														|  | 
 |  | +                                    )}
 | 
											
												
													
														|  | 
 |  | +                                  </>
 | 
											
												
													
														|  | 
 |  | +                                ) : (
 | 
											
												
													
														|  | 
 |  | +                                  <Loading color="#fff" />
 | 
											
												
													
														|  | 
 |  | +                                )}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +                                {m.loop ? (
 | 
											
												
													
														|  | 
 |  | +                                  <img
 | 
											
												
													
														|  | 
 |  | +                                    src={iconLoopActive}
 | 
											
												
													
														|  | 
 |  | +                                    onClick={(e: Event) => (m.loop = false)}
 | 
											
												
													
														|  | 
 |  | +                                  />
 | 
											
												
													
														|  | 
 |  | +                                ) : (
 | 
											
												
													
														|  | 
 |  | +                                  <img src={iconLoop} onClick={(e: Event) => (m.loop = true)} />
 | 
											
												
													
														|  | 
 |  | +                                )}
 | 
											
												
													
														|  | 
 |  | +                              </div>
 | 
											
												
													
														|  | 
 |  | +                              <div>{m.name}</div>
 | 
											
												
													
														|  | 
 |  | +                            </div>
 | 
											
												
													
														|  | 
 |  | +                          </div>
 | 
											
												
													
														|  | 
 |  | +                        </>
 | 
											
												
													
														|  | 
 |  | +                      ) : m.type === 'IMG' ? (
 | 
											
												
													
														|  | 
 |  | +                        <img src={m.content} />
 | 
											
												
													
														|  | 
 |  | +                      ) : (
 | 
											
												
													
														|  | 
 |  | +                        <MusicScore
 | 
											
												
													
														|  | 
 |  | +                          data-vid={m.id}
 | 
											
												
													
														|  | 
 |  | +                          music={m}
 | 
											
												
													
														|  | 
 |  | +                          onSetIframe={(el: any) => {
 | 
											
												
													
														|  | 
 |  | +                            m.iframeRef = el
 | 
											
												
													
														|  | 
 |  | +                          }}
 | 
											
												
													
														|  | 
 |  | +                        />
 | 
											
												
													
														|  | 
 |  | +                      )}
 | 
											
												
													
														|  | 
 |  | +                    </div>
 | 
											
												
													
														|  | 
 |  | +                  </SwiperSlide>
 | 
											
												
													
														|  | 
 |  | +                )
 | 
											
												
													
														|  | 
 |  | +              })}
 | 
											
												
													
														|  | 
 |  | +            </Swiper>
 | 
											
												
													
														|  | 
 |  | +          )}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +          <div
 | 
											
												
													
														|  | 
 |  | +            style={{ transform: activeData.model ? '' : 'translateY(-100%)' }}
 | 
											
												
													
														|  | 
 |  | +            id="coursePlayHeader"
 | 
											
												
													
														|  | 
 |  | +            class={styles.headerContainer}
 | 
											
												
													
														|  | 
 |  | +            ref={headeRef}
 | 
											
												
													
														|  | 
 |  | +          >
 | 
											
												
													
														|  | 
 |  | +            <div class={styles.backBtn} onClick={() => goback()}>
 | 
											
												
													
														|  | 
 |  | +              <Icon name={iconBack} />
 | 
											
												
													
														|  | 
 |  | +              返回
 | 
											
												
													
														|  | 
 |  | +            </div>
 | 
											
												
													
														|  | 
 |  | +            <div class={styles.menu}>{popupData.tabName}</div>
 | 
											
												
													
														|  | 
 |  | +            {data.isCourse && <PlayRecordTime ref={playRef} list={data.itemList} />}
 | 
											
												
													
														|  | 
 |  | +          </div>
 | 
											
												
													
														|  | 
 |  | +          <Transition name="right">
 | 
											
												
													
														|  | 
 |  | +            {activeData.model && (
 | 
											
												
													
														|  | 
 |  | +              <div class={styles.rightFixedBtns}>
 | 
											
												
													
														|  | 
 |  | +                <div class={styles.btnsWrap}>
 | 
											
												
													
														|  | 
 |  | +                  <div
 | 
											
												
													
														|  | 
 |  | +                    class={[styles.fullBtn, styles.point]}
 | 
											
												
													
														|  | 
 |  | +                    onClick={() => {
 | 
											
												
													
														|  | 
 |  | +                      clearTimeout(activeData.timer)
 | 
											
												
													
														|  | 
 |  | +                      popupData.open = true
 | 
											
												
													
														|  | 
 |  | +                    }}
 | 
											
												
													
														|  | 
 |  | +                  >
 | 
											
												
													
														|  | 
 |  | +                    <img src={iconMenu} />
 | 
											
												
													
														|  | 
 |  | +                    <span>知识点</span>
 | 
											
												
													
														|  | 
 |  | +                  </div>
 | 
											
												
													
														|  | 
 |  | +                </div>
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +                <div class={[styles.btnsWrap, styles.btnsBottom]}>
 | 
											
												
													
														|  | 
 |  | +                  <div class={styles.fullBtn} onClick={() => (popupData.guideOpen = true)}>
 | 
											
												
													
														|  | 
 |  | +                    <img src={iconTouping} />
 | 
											
												
													
														|  | 
 |  | +                    <span>投屏</span>
 | 
											
												
													
														|  | 
 |  | +                  </div>
 | 
											
												
													
														|  | 
 |  | +                  {data.isCourse && (
 | 
											
												
													
														|  | 
 |  | +                    <>
 | 
											
												
													
														|  | 
 |  | +                      <div class={styles.fullBtn} onClick={() => gotoRollCall('student_roll_call')}>
 | 
											
												
													
														|  | 
 |  | +                        <img src={iconDian} />
 | 
											
												
													
														|  | 
 |  | +                        <span>点名</span>
 | 
											
												
													
														|  | 
 |  | +                      </div>
 | 
											
												
													
														|  | 
 |  | +                      <div class={styles.fullBtn} onClick={() => gotoRollCall('sign_out')}>
 | 
											
												
													
														|  | 
 |  | +                        <img src={iconPoint} />
 | 
											
												
													
														|  | 
 |  | +                        <span>签退</span>
 | 
											
												
													
														|  | 
 |  | +                      </div>
 | 
											
												
													
														|  | 
 |  | +                    </>
 | 
											
												
													
														|  | 
 |  | +                  )}
 | 
											
												
													
														|  | 
 |  | +                </div>
 | 
											
												
													
														|  | 
 |  | +              </div>
 | 
											
												
													
														|  | 
 |  | +            )}
 | 
											
												
													
														|  | 
 |  | +          </Transition>
 | 
											
												
													
														|  | 
 |  | +          <Transition name="left">
 | 
											
												
													
														|  | 
 |  | +            {activeData.model && (
 | 
											
												
													
														|  | 
 |  | +              <div class={styles.leftFixedBtns}>
 | 
											
												
													
														|  | 
 |  | +                {popupData.activeIndex != 0 && (
 | 
											
												
													
														|  | 
 |  | +                  <div
 | 
											
												
													
														|  | 
 |  | +                    class={[styles.fullBtn, styles.prePoint]}
 | 
											
												
													
														|  | 
 |  | +                    onClick={() => handlePreAndNext('up')}
 | 
											
												
													
														|  | 
 |  | +                  >
 | 
											
												
													
														|  | 
 |  | +                    <img src={iconUp} />
 | 
											
												
													
														|  | 
 |  | +                    <span style={{ textAlign: 'center' }}>上一个</span>
 | 
											
												
													
														|  | 
 |  | +                  </div>
 | 
											
												
													
														|  | 
 |  | +                )}
 | 
											
												
													
														|  | 
 |  | +                {popupData.activeIndex != data.itemList.length - 1 && (
 | 
											
												
													
														|  | 
 |  | +                  <div class={[styles.fullBtn]} onClick={() => handlePreAndNext('down')}>
 | 
											
												
													
														|  | 
 |  | +                    <span style={{ textAlign: 'center' }}>下一个</span>
 | 
											
												
													
														|  | 
 |  | +                    <img src={iconDown} />
 | 
											
												
													
														|  | 
 |  | +                  </div>
 | 
											
												
													
														|  | 
 |  | +                )}
 | 
											
												
													
														|  | 
 |  | +              </div>
 | 
											
												
													
														|  | 
 |  | +            )}
 | 
											
												
													
														|  | 
 |  | +          </Transition>
 | 
											
												
													
														|  | 
 |  | +          <Popup
 | 
											
												
													
														|  | 
 |  | +            class={styles.popup}
 | 
											
												
													
														|  | 
 |  | +            overlayClass={styles.overlayClass}
 | 
											
												
													
														|  | 
 |  | +            position="right"
 | 
											
												
													
														|  | 
 |  | +            round
 | 
											
												
													
														|  | 
 |  | +            v-model:show={popupData.open}
 | 
											
												
													
														|  | 
 |  | +            onClose={() => {
 | 
											
												
													
														|  | 
 |  | +              const item = data.itemList[popupData.activeIndex]
 | 
											
												
													
														|  | 
 |  | +              if (item?.type == 'VIDEO') {
 | 
											
												
													
														|  | 
 |  | +                setModelOpen()
 | 
											
												
													
														|  | 
 |  | +              }
 | 
											
												
													
														|  | 
 |  | +            }}
 | 
											
												
													
														|  | 
 |  | +          >
 | 
											
												
													
														|  | 
 |  | +            <Points
 | 
											
												
													
														|  | 
 |  | +              data={data.knowledgePointList}
 | 
											
												
													
														|  | 
 |  | +              tabActive={popupData.tabActive}
 | 
											
												
													
														|  | 
 |  | +              itemActive={popupData.itemActive}
 | 
											
												
													
														|  | 
 |  | +              onHandleSelect={(res: any) => {
 | 
											
												
													
														|  | 
 |  | +                // console.log(res)
 | 
											
												
													
														|  | 
 |  | +                popupData.tabActive = res.tabActive
 | 
											
												
													
														|  | 
 |  | +                popupData.itemActive = res.itemActive
 | 
											
												
													
														|  | 
 |  | +                popupData.tabName = res.tabName
 | 
											
												
													
														|  | 
 |  | +                popupData.open = false
 | 
											
												
													
														|  | 
 |  | +                toggleMaterial()
 | 
											
												
													
														|  | 
 |  | +              }}
 | 
											
												
													
														|  | 
 |  | +            />
 | 
											
												
													
														|  | 
 |  | +          </Popup>
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +          <Popup
 | 
											
												
													
														|  | 
 |  | +            class={styles.popup}
 | 
											
												
													
														|  | 
 |  | +            overlayClass={styles.overlayClass}
 | 
											
												
													
														|  | 
 |  | +            position="right"
 | 
											
												
													
														|  | 
 |  | +            round
 | 
											
												
													
														|  | 
 |  | +            v-model:show={popupData.guideOpen}
 | 
											
												
													
														|  | 
 |  | +          >
 | 
											
												
													
														|  | 
 |  | +            <OGuide />
 | 
											
												
													
														|  | 
 |  | +          </Popup>
 | 
											
												
													
														|  | 
 |  | +        </div>
 | 
											
												
													
														|  | 
 |  | +      </div>
 | 
											
												
													
														|  | 
 |  | +    )
 | 
											
												
													
														|  | 
 |  | +  }
 | 
											
												
													
														|  | 
 |  | +})
 |