liushengqiang há 2 anos atrás
pai
commit
fd08a7e2b6

+ 1 - 9
src/router/routes-common.ts

@@ -22,15 +22,7 @@ export const router: RouteRecordRaw[] = [
   {
     path: '/coursewarePlay',
     name: 'coursewarePlay',
-    component: () => import('@/views/coursewarePlay/play'),
-    meta: {
-      title: '课程播放'
-    }
-  },
-  {
-    path: '/play',
-    name: 'play',
-    component: () => import('@/views/coursewarePlay/play'),
+    component: () => import('@/views/coursewarePlay'),
     meta: {
       title: '课程播放'
     }

+ 79 - 23
src/views/coursewarePlay/index.module.less

@@ -3,22 +3,17 @@
   height: 100vh;
   background-color: #000;
   overflow: hidden;
-
-  // :global {
-  //   // 更改动画样式
-  //   .van-swipe__track {
-  //     height: 100% !important;
-  //     transform: translateY(0px) !important;
-  //     position: relative;
-  //   }
-  // }
+  --plyr-color-main: var(--van-primary);
+  --plyr-range-track-height: 3px;
 }
+
 .coursewarePlay {
   position: relative;
   height: 100vh;
   margin: 0 auto;
   overflow: hidden;
 }
+
 .playModel {
   position: absolute;
   left: 0;
@@ -28,6 +23,7 @@
   box-shadow: inset 0px 0px 164px 0px rgba(0, 0, 0, 1);
   pointer-events: none;
 }
+
 .headerContainer {
   position: fixed;
   top: 0;
@@ -40,6 +36,7 @@
   background: linear-gradient(180deg, rgba(0, 0, 0, 0.6), transparent);
   transition: transform 0.5s;
 }
+
 .backBtn {
   color: #fff;
   height: 26px;
@@ -48,12 +45,14 @@
   align-items: center;
   z-index: 10;
   padding: 4px 10px 4px 15px;
+
   :global {
     .van-icon {
       margin-right: 8px;
     }
   }
 }
+
 .menu {
   position: absolute;
   width: 100%;
@@ -64,31 +63,52 @@
   font-size: 12px;
   color: #fff;
 }
+
 .tabsContent {
   width: 100vw;
   height: 100vh;
+
   :global {
     .van-tabs__wrap {
       display: none !important;
     }
+
     .van-tabs__content {
       width: 100%;
       height: 100%;
     }
   }
 }
-.swipeItem {
-  overflow: hidden;
+
+.wraps {
+  width: 100%;
+  height: 100%;
+  transform-style: preserve-3d;
+  perspective: (32rem);
+  transition-timing-function: initial;
 }
+
 .itemDiv {
-  position: relative;
+  position: absolute;
+  left: 0;
+  top: 0;
   width: 100%;
   height: 100%;
   background-color: #000;
+  transition-duration: .8s;
+  transform-style: preserve-3d;
+  transition-property: transform, opacity, height;
+  backface-visibility: hidden;
+  overflow: hidden;
+  z-index: 1;
+  &.itemActive{
+    z-index: 10;
+  }
   video {
     width: 100%;
     height: 100%;
   }
+
   img {
     display: block;
     width: 100%;
@@ -96,9 +116,10 @@
     object-fit: contain;
   }
 }
+
 .fullBtn {
   width: 38px;
-  height: 55px;
+  height: 46px;
   display: flex;
   flex-direction: column;
   align-items: center;
@@ -106,32 +127,42 @@
   justify-content: space-evenly;
   overflow: hidden;
   white-space: nowrap;
+
   &:active {
     background: rgba(255, 255, 255, 0.2);
   }
 }
+
 .rightFixedBtns {
   position: absolute;
   top: 50%;
   transform: translateY(-50%);
   right: 12px;
   z-index: 10;
-  
+
   .btnsBottom {
     margin-top: 10px;
   }
 }
+
 .leftFixedBtns {
   position: absolute;
   top: 50%;
   transform: translateY(-50%);
   left: 12px;
   z-index: 10;
+
   .prePoint {
     margin-bottom: 8px;
   }
 }
 
+.btnsWrap {
+  background: rgba(51, 51, 51, 0.4);
+  border-radius: 6px;
+  overflow: hidden;
+}
+
 .bottomFixedContainer {
   position: absolute;
   left: 0;
@@ -140,6 +171,7 @@
   z-index: 10;
   background: linear-gradient(0deg, rgba(0, 0, 0, 0.5), transparent);
   transition: transform 0.5s;
+
   .time {
     display: flex;
     justify-content: space-between;
@@ -147,14 +179,17 @@
     font-size: 10px;
     padding: 4px 20px;
   }
+
   .slider {
     padding: 8px 20px;
+
     :global {
       .van-slider__button {
         background: var(--van-primary);
       }
     }
   }
+
   .actions {
     display: flex;
     justify-content: space-between;
@@ -162,10 +197,12 @@
     font-size: 12px;
     padding: 0 10px 4px 20px;
     align-items: center;
+
     .actionBtn {
       display: flex;
     }
-    .actionBtn > img {
+
+    .actionBtn>img {
       width: 30px;
       height: 30px;
       display: block;
@@ -173,22 +210,22 @@
     }
   }
 }
-.btnsWrap {
-  background: rgba(51, 51, 51, 0.4);
-  border-radius: 6px;
-  overflow: hidden;
-}
+
 .popup {
   background: rgba(0, 0, 0, 0.5);
 }
+
 .overlayClass {
   --van-overlay-background: transparent;
 }
+
 :global {
+
   .top-enter-active,
   .top-leave-active {
     transition: transform 0.5s;
   }
+
   .top-enter-from,
   .top-leave-to {
     transform: translateY(-100%);
@@ -198,6 +235,7 @@
   .left-leave-active {
     transition: all 0.5s;
   }
+
   .left-enter-from,
   .left-leave-to {
     left: -60px;
@@ -237,6 +275,7 @@
   justify-content: center;
   align-items: center;
 }
+
 .playRecordTime {
   width: 90px;
   margin-right: 10px;
@@ -248,6 +287,7 @@
   align-items: center;
   justify-content: center;
   color: #fff;
+
   .timeLoad {
     width: 5px;
     height: 5px;
@@ -263,17 +303,33 @@
   0% {
     opacity: 0;
   }
+
   50% {
     opacity: 0.5;
   }
+
   100% {
     opacity: 1;
   }
 }
-.swiperContainer{
-  :global{
-    .swiper-wrapper{
+
+.swiperContainer {
+  :global {
+    .swiper-wrapper {
       height: 100vh;
     }
   }
 }
+
+// .preItem{
+//   transform: translate3d(0, 0, -800px) rotateX(180deg);
+// }
+// .nextItem {
+//   transform: translate3d(0, 0, -800px) rotateX(-180deg);
+// }
+// .preItem{
+//   transform: translate3d(-100%, 0, -800px);
+// }
+// .nextItem {
+//   transform: translate3d(100%, 0, -800px);
+// }

+ 326 - 460
src/views/coursewarePlay/index.tsx

@@ -21,7 +21,7 @@ import {
   TransitionGroup
 } from 'vue'
 import iconBack from './image/back.svg'
-import styles from './index.module.less'
+import styles from './play.module.less'
 import 'plyr/dist/plyr.css'
 import request from '@/helpers/request'
 import { state } from '@/state'
@@ -44,8 +44,7 @@ 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 VideoPlay from './component/video-play'
 import {
   Pagination,
   Navigation,
@@ -73,11 +72,11 @@ export default defineComponent({
       const activeItem = data.itemList[popupData.activeIndex]
       if (activeItem.type != 'VIDEO') return
       if (value == 'hidden') {
-        isPlay.value = !activeItem.paused
-        handlePaused(activeItem)
+        isPlay.value = !activeItem.videoEle.paused
+        togglePlay(activeItem, false)
       } else {
         // 页面显示,并且
-        if (isPlay.value) handlePlay(activeItem)
+        if (isPlay.value) togglePlay(activeItem, true)
       }
     })
     /** 设置播放容器 16:9 */
@@ -96,22 +95,20 @@ export default defineComponent({
       }
     }
     const handleInit = (type = 0) => {
-      // postMessage({
-      //   api: 'courseLoading',
-      //   content: {
-      //     show: true,
-      //     type: 'fullscreen'
-      //   }
-      // })
       //设置容器16:9
       setContainer()
       // 横屏
-      postMessage({
-        api: 'setRequestedOrientation',
-        content: {
-          orientation: type
+      postMessage(
+        {
+          api: 'setRequestedOrientation',
+          content: {
+            orientation: type
+          }
+        },
+        () => {
+          console.log(234)
         }
-      })
+      )
       // 头,包括返回箭头
       postMessage({
         api: 'setTitleBarVisibility',
@@ -149,7 +146,8 @@ export default defineComponent({
       itemList: [] as any,
       showHead: true,
       isCourse: false,
-      isRecordPlay: false
+      isRecordPlay: false,
+      videoRefs: {}
     })
     const activeData = reactive({
       nowTime: 0,
@@ -208,57 +206,31 @@ export default defineComponent({
             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,
+            videoEle: null,
             tabName: item.name,
             isLast: j === itemLength, // 当前知识点
             autoPlay: false, //加载完成是否自动播放
-            display: false
+            isprepare: false, // 视频是否加载完成
+            isRender: 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
-      }
+      let _firstIndex = list.findIndex((n: any) => n.materialId == route.query.kId)
+      _firstIndex = _firstIndex > -1 ? _firstIndex : 0
+      const item = list[_firstIndex]
+      item.autoPlay = true
+      popupData.activeIndex = _firstIndex
+      popupData.tabName = item.tabName
+      popupData.tabActive = item.knowledgePointId
+      popupData.itemActive = item.id
+      popupData.itemName = item.name
       // console.log('🚀 ~ list', list)
       nextTick(() => {
         data.itemList = list
@@ -270,8 +242,6 @@ export default defineComponent({
           }
         })
       })
-      // setTimeout(() => {
-      // }, 300)
     }
     const getDetail = async () => {
       try {
@@ -303,15 +273,18 @@ export default defineComponent({
         }
       } catch (error) {}
     }
+
+    const iframTime = ref()
     // 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)
+        clearTimeout(iframTime.value)
+        iframTime.value = setTimeout(() => {
+          activeData.model = ev.data.show || (ev.data.playState == 'play' ? false : true)
+        }, 500)
       }
     }
 
-    const swiperDom = ref()
     onMounted(() => {
       const hasVip = handleCheckVip()
       if (!hasVip) {
@@ -343,9 +316,7 @@ export default defineComponent({
       postMessage({ api: 'goBack' })
     }
 
-    const swipeRef = ref<SwipeInstance>()
     const popupData = reactive({
-      firstIndex: 0,
       open: false,
       activeIndex: 0,
       tabActive: '',
@@ -357,25 +328,17 @@ export default defineComponent({
 
     /**停止所有的播放 */
     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()
-            }
+        const activeItem = data.itemList[i]
+        if (popupData.activeIndex !== i) {
+          if (activeItem.type === 'VIDEO' && activeItem.videoEle) {
+            activeItem.videoEle.stop()
+          }
+          // console.log('🚀 ~ activeItem:', activeItem)
+          // 停止曲谱的播放
+          if (activeItem.type === 'SONG') {
+            activeItem.iframeRef?.contentWindow?.postMessage({ api: 'setPlayState' }, '*')
           }
-        }
-        // 停止曲谱的播放
-        if (item.type === 'SONG') {
-          item.iframeRef?.contentWindow?.postMessage({ api: 'setPlayState' }, '*')
-          item.display = false
         }
       }
     }
@@ -383,10 +346,7 @@ export default defineComponent({
     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)
+        handleSwipeChange(index)
       }
     }
     /** 延迟收起模态框 */
@@ -395,37 +355,9 @@ export default defineComponent({
       closeToast()
       activeData.timer = setTimeout(() => {
         activeData.model = false
+        Object.values(data.videoRefs).map((n: any) => n.toggleHideControl(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) => {
@@ -442,7 +374,6 @@ export default defineComponent({
 
     // 双击
     const handleDbClick = (item: any) => {
-      // console.log(item)
       if (item && item.type === 'VIDEO') {
         const videoEle: HTMLVideoElement = item.videoEle
         if (videoEle) {
@@ -457,419 +388,354 @@ export default defineComponent({
       }
     }
 
-    // 暂停播放
-    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 togglePlay = (m: any, isPlay: boolean) => {
+      if (isPlay) {
+        m.videoEle?.play()
+      } else {
+        m.videoEle?.pause()
       }
     }
 
+    const showIndex = ref(-4)
+    const effectIndex = ref(0)
     const effects = [
       {
         prev: {
-          shadow: true,
-          translate: [0, 0, -400]
+          transform: 'translate3d(0, 0, -800px) rotateX(180deg)'
         },
         next: {
-          translate: ['100%', 0, 0]
+          transform: 'translate3d(0, 0, -800px) rotateX(-180deg)'
         }
       },
       {
         prev: {
-          shadow: true,
-          translate: ['-120%', 0, -500]
+          transform: 'translate3d(-100%, 0, -800px)'
         },
         next: {
-          shadow: true,
-          translate: ['120%', 0, -500]
+          transform: 'translate3d(100%, 0, -800px)'
         }
       },
       {
         prev: {
-          shadow: true,
-          translate: ['-20%', 0, -1]
+          transform: 'translate3d(-50%, 0, -800px) rotateY(80deg)'
         },
         next: {
-          translate: ['100%', 0, 0]
+          transform: 'translate3d(50%, 0, -800px) rotateY(-80deg)'
         }
       },
       {
         prev: {
-          shadow: true,
-          translate: [0, 0, -800],
-          rotate: [-180, 0, 0]
+          transform: 'translate3d(-100%, 0, -800px) rotateY(-120deg)'
         },
         next: {
-          shadow: true,
-          translate: [0, 0, -800],
-          rotate: [180, 0, 0]
+          transform: 'translate3d(100%, 0, -800px) rotateY(120deg)'
         }
       },
+      //风车4
       {
         prev: {
-          shadow: true,
-          translate: ['-125%', 0, -800],
-          rotate: [0, 0, -90]
+          transform: 'translate3d(-50%, 50%, -800px) rotateZ(-14deg)',
+          opacity: 0
         },
         next: {
-          shadow: true,
-          translate: ['125%', 0, -800],
-          rotate: [0, 0, 90]
+          transform: 'translate3d(50%, 50%, -800px) rotateZ(14deg)',
+          opacity: 0
         }
       },
+      //翻页5
       {
         prev: {
-          shadow: true,
-          origin: 'right center',
-          translate: ['5%', 0, -200],
-          rotate: [0, -100, 0]
+          transform: 'translateZ(-800px) rotate3d(0, -1, 0, 90deg)',
+          opacity: 0
         },
         next: {
-          origin: 'left center',
-          translate: ['-5%', 0, -200],
-          rotate: [0, 100, 0]
-        }
-      },
-      {
-        prev: {
-          scale: 0.3,
-          opacity: 0.4
+          transform: 'translateZ(-800px) rotate3d(0, 1, 0, 90deg)',
+          opacity: 0
         },
-        next: {
-          opacity: 0.4,
-          scale: 0.3
-        }
+        current: { transitionDelay: '700ms' }
       }
     ]
-    const swiperType = ref(effects[3])
-    console.log("🚀 ~ swiperType:", swiperType.value)
-    // 上一个知识点, 下一个知识点
-    const handlePreAndNext = (type: string) => {
+
+    // 轮播切换
+    const handleSwipeChange = (index: number) => {
+      if (popupData.activeIndex == index) return
+      // console.log('轮播切换')
+      popupData.activeIndex = index
       setTimeout(() => {
-        if (type === 'up') {
-          swiperDom.value.slidePrev(800)
-        } else {
-          swiperDom.value.slideNext(800)
+        handleStop()
+        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)
+            closeToast()
+            item.autoPlay = true
+            nextTick(() => {
+              item.videoEle?.play()
+            })
+          }
         }
-      }, 400)
+      }, 800)
+    }
+
+    // 上一个知识点, 下一个知识点
+    const handlePreAndNext = (type: string) => {
+      if (type === 'up') {
+        handleSwipeChange(popupData.activeIndex - 1)
+      } else {
+        handleSwipeChange(popupData.activeIndex + 1)
+      }
     }
 
     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}
-            >
+        <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) => {
-                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
+                const isRender = m.isRender || Math.abs(popupData.activeIndex - mIndex) < 2
+                if (isRender) {
+                  m.isRender = true
+                }
+                return isRender ? (
+                  <div
+                    key={'index' + mIndex}
+                    class={[styles.itemDiv, popupData.activeIndex === mIndex && styles.itemActive]}
+                    style={
+                      mIndex < popupData.activeIndex
+                        ? effects[effectIndex.value].prev
+                        : mIndex > popupData.activeIndex
+                        ? effects[effectIndex.value].next
+                        : effects[effectIndex.value].current
+                    }
+                    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' ? (
-                        <>
-                          <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
+                        }
+                      }, 300)
+                    }}
+                  >
+                    {m.type === 'VIDEO' ? (
+                      <>
+                        <VideoPlay
+                          ref={(v: any) => (data.videoRefs[mIndex] = v)}
+                          item={m}
+                          onLoadedmetadata={(videoItem: any) => {
+                            m.videoEle = videoItem
+                          }}
+                          onTogglePlay={(paused: boolean) => {
+                            // console.log('播放切换', paused)
+                            // 首次播放完成
+                            if (!m.isprepare) {
                               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={() => {
-                              //暂停
+                            }
+                            m.autoPlay = false
+                            if (paused || popupData.open || popupData.guideOpen) {
                               clearTimeout(activeData.timer)
-                              m.paused = true
-                            }}
-                            onEnded={() => handleEnded(m)}
-                          >
-                            <source src={m.content} type="video/mp4" />
-                          </video>
-                          {m.muted && (
+                            } else {
+                              setModelOpen()
+                            }
+                          }}
+                          onEnded={() => handleSwipeChange(popupData.activeIndex + 1)}
+                          onReset={() => {
+                            if (!m.videoEle?.paused) {
+                              setModelOpen()
+                            }
+                          }}
+                        />
+                        <Transition name="van-fade">
+                          {!m.isprepare && (
                             <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>
-                )
+                        </Transition>
+                      </>
+                    ) : m.type === 'IMG' ? (
+                      <img src={m.content} />
+                    ) : (
+                      <MusicScore
+                        data-vid={m.id}
+                        music={m}
+                        onSetIframe={(el: any) => {
+                          m.iframeRef = el
+                        }}
+                      />
+                    )}
+                  </div>
+                ) : null
               })}
-            </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>
+            <Transition name="right">
+              {activeData.model && (
+                <div
+                  class={styles.rightFixedBtns}
+                  onClick={(e: Event) => {
+                    e.stopPropagation()
+                    clearTimeout(activeData.timer)
+                  }}
+                >
+                  <div class={styles.btnsWrap}>
+                    <div
+                      class={[styles.fullBtn, styles.point]}
+                      onClick={() => (popupData.open = true)}
+                    >
+                      <img src={iconMenu} />
+                      <span>知识点</span>
+                    </div>
                   </div>
-                </div>
 
-                <div class={[styles.btnsWrap, styles.btnsBottom]}>
-                  <div class={styles.fullBtn} onClick={() => (popupData.guideOpen = true)}>
-                    <img src={iconTouping} />
-                    <span>投屏</span>
+                  <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>
-                  {data.isCourse && (
-                    <>
-                      <div class={styles.fullBtn} onClick={() => gotoRollCall('student_roll_call')}>
-                        <img src={iconDian} />
-                        <span>点名</span>
+                </div>
+              )}
+            </Transition>
+
+            <Transition name="left">
+              {activeData.model && (
+                <div class={styles.leftFixedBtns} onClick={(e: Event) => e.stopPropagation()}>
+                  {popupData.activeIndex != 0 && (
+                    <div class={[styles.btnsWrap, styles.prePoint]}>
+                      <div class={styles.fullBtn} onClick={() => handlePreAndNext('up')}>
+                        <img src={iconUp} />
+                        <span style={{ textAlign: 'center' }}>上一个</span>
                       </div>
-                      <div class={styles.fullBtn} onClick={() => gotoRollCall('sign_out')}>
-                        <img src={iconPoint} />
-                        <span>签退</span>
+                    </div>
+                  )}
+                  {popupData.activeIndex != data.itemList.length - 1 && (
+                    <div class={styles.btnsWrap}>
+                      <div class={styles.fullBtn} onClick={() => handlePreAndNext('down')}>
+                        <span style={{ textAlign: 'center' }}>下一个</span>
+                        <img src={iconDown} />
                       </div>
-                    </>
+                    </div>
                   )}
                 </div>
-              </div>
-            )}
-          </Transition>
-          <Transition name="left">
-            {activeData.model && (
-              <div class={styles.leftFixedBtns}>
-                {popupData.activeIndex != 0 && (
-                  <div class={[styles.btnsWrap, styles.prePoint]}>
-                    <div
-                      class={styles.fullBtn}
-                      onClick={() => handlePreAndNext('up')}
-                    >
-                      <img src={iconUp} />
-                      <span style={{ textAlign: 'center' }}>上一个</span>
-                    </div>
-                  </div>
-                )}
-                {popupData.activeIndex != data.itemList.length - 1 && (
-                  <div class={[styles.btnsWrap, styles.prePoint]}>
-                    <div class={styles.fullBtn} onClick={() => handlePreAndNext('down')}>
-                      <span style={{ textAlign: 'center' }}>下一个</span>
-                      <img src={iconDown} />
-                    </div>
-                  </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()
+              )}
+            </Transition>
+          </div>
+        </div>
+
+        <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}
+            onClick={() => {
+              showIndex.value += 1
+              if (showIndex.value > 0) {
+                effectIndex.value = effectIndex.value >= effects.length ? 0 : effectIndex.value + 1
               }
+              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>
+            {popupData.tabName} {showIndex.value > 0 ? `动画${effectIndex.value}` : ''}
+          </div>
+          {data.isCourse && <PlayRecordTime ref={playRef} list={data.itemList} />}
         </div>
+
+        <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' && !item.videoEle?.paused) {
+              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}
+          onClose={() => {
+            const item = data.itemList[popupData.activeIndex]
+            if (item?.type == 'VIDEO' && !item.videoEle?.paused) {
+              setModelOpen()
+            }
+          }}
+        >
+          <OGuide />
+        </Popup>
       </div>
     )
   }