Просмотр исходного кода

优化全屏方法监控更改自定义到浏览器全屏,处理弹框事项显示

liyanbo 3 месяцев назад
Родитель
Сommit
e14d53ec9b
1 измененных файлов с 65 добавлено и 63 удалено
  1. 65 63
      src/components/videopage/VideoPlayer.vue

+ 65 - 63
src/components/videopage/VideoPlayer.vue

@@ -1,46 +1,46 @@
 <template>
   <div class="video-container">
     <div class="box-video">
-       <!-- 视频 -->
+      <!-- 视频 -->
       <template v-if="contentType === 'video'">
         <div class="video-wrapper" :class="{ 'video-paused': isVideoPaused }">
           <video
-            class="full-box-video"
-            ref="videoRef"
-            :controls="true"
-            :controlsList="'nofullscreen'"
-            @timeupdate="handleTimeUpdate"
-            @seeked="handleSeeked"
-            @ended="handleVideoEnded"
-            @loadedmetadata="handleLoadedMetadata"
-            @pause="handleVideoPause"
-            @play="handleVideoPlay"
-            @click="handleVideoClick"
+              class="full-box-video"
+              ref="videoRef"
+              :controls="true"
+              :controlsList="'nofullscreen'"
+              @timeupdate="handleTimeUpdate"
+              @seeked="handleSeeked"
+              @ended="handleVideoEnded"
+              @loadedmetadata="handleLoadedMetadata"
+              @pause="handleVideoPause"
+              @play="handleVideoPlay"
+              @click="handleVideoClick"
           ></video>
           <!-- 历史播放位置提示 -->
-          <div 
-            v-if="showHistoryTip" 
-            class="history-tip"
-            :style="{ left: historyTipPosition + '%' }"
+          <div
+              v-if="showHistoryTip"
+              class="history-tip"
+              :style="{ left: historyTipPosition + '%' }"
           >
             <el-icon @click.stop="closeHistoryTip" class="close-icon"><CloseBold /></el-icon>
             <span @click="goToLastPosition">回到上次播放位置</span>
           </div>
           <!-- 章节要点小圆点 -->
           <div class="progress-markers" v-if="chapterMarkers.length > 0">
-            <div 
-              v-for="marker in chapterMarkers" 
-              :key="marker.time"
-              class="progress-marker"
-              :style="{ left: marker.position + '%' }"
-              @click="seekToTime(marker.time)"
+            <div
+                v-for="marker in chapterMarkers"
+                :key="marker.time"
+                class="progress-marker"
+                :style="{ left: marker.position + '%' }"
+                @click="seekToTime(marker.time)"
             ></div>
           </div>
           <!-- 网页全屏按钮 -->
-          <el-tooltip 
-            :content="isWebFullscreen ? '退出网页全屏' : '进入网页全屏'" 
-            placement="left"
-            effect="dark"
+          <el-tooltip
+              :content="isWebFullscreen ? '退出网页全屏' : '进入网页全屏'"
+              placement="left"
+              effect="dark"
           >
             <div class="fullscreen-btn" @click="toggleWebFullscreen">
               <el-icon v-if="!isWebFullscreen"><FullScreen /></el-icon>
@@ -76,7 +76,7 @@ const props = defineProps({
   contentType: { type: String, required: true }, // contentType类型
   videoPath: { type: String }, // 变为可选
   courseId: { type: String, required: true },
-  typeId: { type: String, required: true }, 
+  typeId: { type: String, required: true },
   courseConfigList: { type: Array, default: () => [] },
   allIndices: { type: Array, default: () => [] },
   currentIndex: { type: String, required: true }
@@ -129,12 +129,12 @@ const saveProgress = throttle(async (progress, currentTime) => {
   try {
     // 保存到localStorage,下次加载视频续播
     localStorage.setItem(
-      `videoProgress_${props.courseId}`,
-      JSON.stringify({
-        progress: progress,
-        currentTime: currentTime,
-        timestamp: Date.now()
-      })
+        `videoProgress_${props.courseId}`,
+        JSON.stringify({
+          progress: progress,
+          currentTime: currentTime,
+          timestamp: Date.now()
+        })
     )
 
     // 通过emit事件通知父组件保存进度
@@ -152,11 +152,11 @@ const handleLoadedMetadata = () => {
   if (duration && props.courseConfigList && props.courseConfigList.length) {
     // 根据courseConfigList生成章节标记,过滤掉ccTime不存在或无效的配置项
     chapterMarkers.value = props.courseConfigList
-      .filter(config => config.ccTime !== undefined && config.ccTime !== null && config.ccTime !== '')
-      .map(config => ({
-        time: config.ccTime,
-        position: (config.ccTime / duration) * 100
-      }))
+        .filter(config => config.ccTime !== undefined && config.ccTime !== null && config.ccTime !== '')
+        .map(config => ({
+          time: config.ccTime,
+          position: (config.ccTime / duration) * 100
+        }))
   } else {
     // 确保在courseConfigList为空时清空标记
     chapterMarkers.value = []
@@ -167,7 +167,7 @@ const handleLoadedMetadata = () => {
 const seekToTime = (time) => {
   if (videoRef.value) {
     videoRef.value.currentTime = time
-    // 清除暂停索引,用户点击后可以再次触发暂停
+    // 清除暂停索引,确保用户点击后可以再次触发暂停
     pausedIndices.value = pausedIndices.value.filter(t => t !== time)
   }
 }
@@ -182,7 +182,7 @@ const handleTimeUpdate = ev => {
   }
 
   const progressPercentage =
-    duration > 0 ? Math.round((currentTime / duration) * 100) : 0
+      duration > 0 ? Math.round((currentTime / duration) * 100) : 0
 
   // 更新最后播放进度
   lastPlayProgress.value = progressPercentage
@@ -204,12 +204,13 @@ const handleTimeUpdate = ev => {
 
   // 触发父组件的时间更新事件
   emits('timeUpdate', { currentTime, progressPercentage })
-    if (!props.courseConfigList.length) return
+  if (!props.courseConfigList.length) return
   props.courseConfigList.forEach(courseCofig => {
     // 暂停时间
     let time = courseCofig.ccTime
     // 检查是否到达时间点且还未暂停过
     if (currentTime === time && !pausedIndices.value.includes(time)) {
+      // 无论 ccQuestSource 是什么值,都暂停视频
       videoRef.value.pause()
       // 记录暂停时间
       pausedIndices.value.push(currentTime)
@@ -232,7 +233,7 @@ const handleSeeked = () => {
   pausedIndices.value = []
 }
 
-// 视频结束事件处理
+// 添加视频结束事件处理
 const handleVideoEnded = () => {
   // 视频结束时保存100%进度
   if (!savedProgress.value.includes(100)) {
@@ -259,12 +260,12 @@ const setLastPlayPosition = () => {
         const duration = videoRef.value.duration
         historyTipPosition.value = duration > 0 ? (currentTime / duration) * 100 : 0
         showHistoryTip.value = true
-        
+
         // 检查是否已有保存的进度点
         if (progress >= 10) savedProgress.value.push(10)
         if (progress >= 50) savedProgress.value.push(50)
         if (progress >= 100) savedProgress.value.push(100)
-        
+
         // 5秒后自动隐藏历史位置提示
         setTimeout(() => {
           showHistoryTip.value = false
@@ -346,9 +347,9 @@ const initVideoPlayer = () => {
         hlsRef.value.on(Hls.Events.ERROR, (event, data) => {
           console.error('HLS错误:', data)
           // 只对致命错误显示错误提示
-        if (data.fatal) {
-          ElMessage.error('视频加载失败,请稍后重试')
-        }
+          if (data.fatal) {
+            ElMessage.error('视频加载失败,请稍后重试')
+          }
         })
       } else if (videoRef.value.canPlayType('application/vnd.apple.mpegurl')) {
         // 对于不支持HLS但支持原生m3u8的浏览器
@@ -410,10 +411,11 @@ const removeVideoKeyboardListener = () => {
     videoRef.value.removeEventListener('keydown', handleKeyPress);
   }
 }
+
 // 组件挂载时
 onMounted(() => {
   initVideoPlayer()
- // 键盘事件监听
+  // 键盘事件监听
   document.addEventListener('keydown', handleKeyPress);
   // 为视频元素添加键盘事件监听器
   addVideoKeyboardListener();
@@ -442,7 +444,7 @@ watch([() => props.contentType, () => props.videoPath], () => {
 const toggleWebFullscreen = () => {
   const videoWrapper = document.querySelector('.video-wrapper')
   if (!videoWrapper) return
-  
+
   if (!isWebFullscreen.value) {
     // 进入网页全屏
     videoWrapper.style.position = 'fixed'
@@ -455,7 +457,7 @@ const toggleWebFullscreen = () => {
     videoWrapper.style.display = 'flex'
     videoWrapper.style.justifyContent = 'center'
     videoWrapper.style.alignItems = 'center'
-    
+
     // 调整视频大小
     const video = videoWrapper.querySelector('.full-box-video')
     if (video) {
@@ -463,7 +465,7 @@ const toggleWebFullscreen = () => {
       video.style.height = '100%'
       video.style.objectFit = 'contain'
     }
-    
+
     isWebFullscreen.value = true
   } else {
     // 退出网页全屏
@@ -477,7 +479,7 @@ const toggleWebFullscreen = () => {
     videoWrapper.style.display = 'flex'
     videoWrapper.style.justifyContent = 'center'
     videoWrapper.style.alignItems = 'center'
-    
+
     // 恢复视频大小
     const video = videoWrapper.querySelector('.full-box-video')
     if (video) {
@@ -485,7 +487,7 @@ const toggleWebFullscreen = () => {
       video.style.height = '100%'
       video.style.objectFit = 'cover'
     }
-    
+
     isWebFullscreen.value = false
   }
 }
@@ -496,7 +498,7 @@ onBeforeUnmount(() => {
     hlsRef.value.destroy()
     hlsRef.value = null
   }
-  
+
   // 确保退出网页全屏
   if (isWebFullscreen.value) {
     const videoWrapper = document.querySelector('.video-wrapper')
@@ -510,7 +512,7 @@ onBeforeUnmount(() => {
       videoWrapper.style.backgroundColor = ''
     }
   }
-  
+
   // 移除键盘事件监听
   document.removeEventListener('keydown', handleKeyPress);
   // 移除视频元素的键盘事件监听器
@@ -553,7 +555,7 @@ onBeforeUnmount(() => {
   border-radius: rpx(12);
 }
 .ppt-box{
-   width: 100%;
+  width: 100%;
   height: rpx(300);
   display: flex;
   justify-content: center;
@@ -576,7 +578,7 @@ onBeforeUnmount(() => {
   width: 70%;
   height: 100%;
   border-radius: rpx(12);
-  overflow: hidden; 
+  overflow: hidden;
 }
 .ppt-container ::v-deep(.pptx-preview-wrapper) {
   // 滚动条整体样式
@@ -612,14 +614,14 @@ onBeforeUnmount(() => {
 .ppt-btn {
   background-color: rgb(255, 255, 255, 0.5);
   color: white;
-   border: 1px white solid;
+  border: 1px white solid;
   border-radius: rpx(12);
   font-size: rpx(7);
   cursor: pointer;
   transition: background-color 0.3s;
-  display: flex; 
-  align-items: center; 
-  justify-content: center; 
+  display: flex;
+  align-items: center;
+  justify-content: center;
   height: rpx(15);
 }
 
@@ -635,8 +637,8 @@ onBeforeUnmount(() => {
 /* 章节要点标记样式 */
 .progress-markers {
   position: absolute;
-  bottom: 26px; 
-  left: 15px; 
+  bottom: 26px;
+  left: 15px;
   right: 15px;
   height: 10px;
   pointer-events: none;