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

加入背景视频和对话视频类型逻辑

liyanbo 2 недель назад
Родитель
Сommit
4b8a230c80
1 измененных файлов с 129 добавлено и 6 удалено
  1. 129 6
      src/views/AIPage/aiGenerate/DialogContent.vue

+ 129 - 6
src/views/AIPage/aiGenerate/DialogContent.vue

@@ -67,6 +67,19 @@
           <div class="poem-text" v-html="formatPoemContent(currentPoemContent)" ></div>
         </div>
       </div>
+      
+      <!-- 视频显示区域 -->
+      <div v-if="currentDialogue && currentDialogue.type === 'video'" class="video-display">
+        <video 
+          :src="currentDialogue.videoUrl" 
+          class="dialogue-video" 
+          controls 
+          autoplay
+          @ended="handleVideoEnded"
+        >
+          您的浏览器不支持视频播放
+        </video>
+      </div>
 
       <!-- 用户输入卡片 -->
       <div
@@ -116,7 +129,12 @@
       </div>
     </div>
 
-    <img :src="currentBackgroundImage" alt="背景图" class="background-image">
+    <!-- 背景图 -->
+    <img v-if="currentBackgroundType === 'imageAudio'" :src="currentBackgroundImage" alt="背景图" class="background-image">
+    <!-- 背景视频 -->
+    <video v-else-if="currentBackgroundType === 'video'" ref="backgroundVideoRef" :src="currentBackgroundVideo" class="background-video" loop muted playsinline>
+      您的浏览器不支持视频播放
+    </video>
   </div>
 </template>
 
@@ -182,8 +200,12 @@ const currentPoemContent = ref('')
 const backgroundAudio = ref(null)
 // 对话音频
 const dialogueAudio = ref(null)
+// 背景视频
+const backgroundVideoRef = ref(null)
 // 遮罩层显示状态
 const showMask = ref(true)
+// 是否开始播放
+const isPlaybackStarted = ref(false)
 
 // 计算属性
 // 当前章节信息
@@ -203,6 +225,19 @@ const currentBackgroundImage = computed(() => {
   return currentSection.value.backgroundImage.url
 })
 
+// 当前背景类型
+const currentBackgroundType = computed(() => {
+  return currentSection.value?.backgroundType || 'imageAudio'
+})
+
+// 当前背景视频
+const currentBackgroundVideo = computed(() => {
+  if (!currentSection.value || !currentSection.value.backgroundVideo || !currentSection.value.backgroundVideo.url) {
+    return ''
+  }
+  return currentSection.value.backgroundVideo.url
+})
+
 // 当前对话缓存
 const currentDialogueCache = ref(null)
 
@@ -296,6 +331,9 @@ const stopAllAudio = () => {
     dialogueAudio.value.pause()
     dialogueAudio.value.currentTime = 0
   }
+  if (backgroundVideoRef.value) {
+    backgroundVideoRef.value.pause()
+  }
 }
 
 const playBackgroundAudio = () => {
@@ -305,13 +343,24 @@ const playBackgroundAudio = () => {
     backgroundAudio.value.currentTime = 0
   }
   
-  // 播放当前环节的背景音
-  if (currentSection.value?.backgroundAudio?.url && isPlaying.value) {
+  // 只有当背景类型为 imageAudio 时才播放背景音
+  if (currentBackgroundType.value === 'imageAudio' && currentSection.value?.backgroundAudio?.url && isPlaying.value) {
     backgroundAudio.value = new Audio(currentSection.value.backgroundAudio.url)
     backgroundAudio.value.loop = true
     backgroundAudio.value.volume = 1
     backgroundAudio.value.play().catch(e => console.error('背景音播放失败:', e))
   }
+  
+  // 处理背景视频
+  if (currentBackgroundType.value === 'video' && isPlaybackStarted.value && isPlaying.value) {
+    // 视频已经在模板中渲染,这里只需要确保它在播放状态
+    if (backgroundVideoRef.value) {
+      backgroundVideoRef.value.play().catch(e => console.error('背景视频播放失败:', e))
+    }
+  } else if (backgroundVideoRef.value) {
+    // 暂停视频
+    backgroundVideoRef.value.pause()
+  }
 }
 
 const playDialogueAudio = (isAutoPlay = false) => {
@@ -414,16 +463,36 @@ const togglePlay = () => {
   if (isPlaying.value) {
     // 播放背景音
     playBackgroundAudio()
+    // 继续播放背景视频
+    if (backgroundVideoRef.value) {
+      backgroundVideoRef.value.play().catch(e => console.error('背景视频播放失败:', e))
+    }
     if(!getIsPlaying() && !conversationInProgress.value){
       // 开始播放序列
       playSequence()
     }
   } else {
-    // 暂停所有音频
+    // 暂停所有音频和视频
     stopAllAudio()
   }
 }
 
+// 处理视频结束事件
+const handleVideoEnded = () => {
+  // 视频播放完毕后,继续播放下一条对话
+  if (isPlaying.value) {
+    if (!playNext(true)) {
+      // 播放完毕,检查是否是最后一个对话
+      if (isAtLastDialogue()) {
+        console.log('视频序列:已到达最后一个对话,触发 dialogueEnded 事件');
+        emit('dialogueEnded', props.isLastCourse);
+      }
+      isPlaying.value = false
+      stopAllAudio()
+    }
+  }
+}
+
 // 自动播放序列
 const playSequence = () => {
   if (!isPlaying.value) return
@@ -448,6 +517,10 @@ const playSequence = () => {
         stopAllAudio()
       }
     }, 500)
+  } else if (currentDialogue.value?.type === 'video') {
+    // 视频类型对话,不自动播放下一条,等待视频播放完毕
+    showPoem.value = false
+    currentPoemContent.value = ''
   } else {
     // 播放当前对话语音,传递isAutoPlay参数
     playDialogueAudio(true)
@@ -486,6 +559,10 @@ const playPrevious = () => {
     // 显示诗词并替换内容为最新的诗词
     showPoem.value = true
     currentPoemContent.value = currentDialogue.value.content
+  } else if (currentDialogue.value?.type === 'video') {
+    // 视频类型对话,隐藏诗词
+    showPoem.value = false
+    currentPoemContent.value = ""
   } else {
     showPoem.value = false
     currentPoemContent.value = ""
@@ -544,6 +621,11 @@ const playNext = (isAutoPlay = false) => {
         playNext(isAutoPlay)
       }, 500)
       return true
+    } else if (currentDialogue.value?.type === 'video') {
+      // 视频类型对话,隐藏诗词,不自动播放下一条
+      showPoem.value = false
+      currentPoemContent.value = ''
+      return true
     }
     
     // 根据是否为自动播放状态决定如何播放语音
@@ -570,6 +652,10 @@ const playNext = (isAutoPlay = false) => {
       setTimeout(() => {
         playNext(isAutoPlay)
       }, 500)
+    } else if (currentDialogue.value?.type === 'video') {
+      // 视频类型对话,隐藏诗词
+      showPoem.value = false
+      currentPoemContent.value = ''
     } else {
       // 根据是否为自动播放状态决定如何播放语音
       if (isPlaying.value) {
@@ -594,6 +680,14 @@ const goBackToMain = () => {
 // 开始播放
 const maskLayer = ref(null)
 const startPlayback = () => {
+  // 设置开始播放状态
+  isPlaybackStarted.value = true
+  
+  // 开始播放背景视频
+  if (backgroundVideoRef.value) {
+    backgroundVideoRef.value.play().catch(e => console.error('背景视频播放失败:', e))
+  }
+  
   // 消失动画
   if (maskLayer.value) {
     maskLayer.value.classList.add('fade-out')
@@ -612,6 +706,10 @@ const startPlayback = () => {
     setTimeout(() => {
       playNext()
     }, 500)
+  } else if (currentDialogue.value?.type === 'video') {
+    // 视频类型对话,隐藏诗词
+    showPoem.value = false
+    currentPoemContent.value = ''
   } else {
     // 播放当前对话语音
     playDialogueAudio()
@@ -1059,6 +1157,14 @@ onUnmounted(() => {
   position: relative;
 }
 
+.background-video {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+  z-index: 1;
+  position: relative;
+}
+
 /* 遮罩层样式 */
 .mask-layer {
   position: absolute;
@@ -1732,7 +1838,7 @@ onUnmounted(() => {
   background-size: 100%;
   background-repeat: no-repeat;
   background-position: center;
-  opacity: 0.5;
+  opacity: 0.8;
   z-index: -1;
 }
 
@@ -1755,7 +1861,8 @@ onUnmounted(() => {
   display: flex;
   align-items: center;
   justify-content: center;
-  flex-direction: column;
+  //flex-direction: column;
+  text-align: center;
   transition: all 0.5s ease-in-out;
 }
 
@@ -1775,6 +1882,22 @@ onUnmounted(() => {
   background: rgba(0, 0, 0, 0.5);
 }
 
+.video-display {
+  position: absolute;
+  top: 45%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  z-index: 5;
+  width: 65%;
+}
+
+.dialogue-video {
+  width: 100%;
+  height: 100%;
+  border-radius: rpx(10);
+  box-shadow: 0 rpx(5) rpx(15) rgba(0, 0, 0, 0.2);
+}
+
 .poem-text::before {
   content: '';
   position: absolute;