فهرست منبع

最新追问及录制

yangg 1 هفته پیش
والد
کامیت
ad6418a1e1

+ 708 - 30
pages/identity-verify/identity-verify.vue

@@ -48,8 +48,8 @@
             开始回答
           </button>
         </div>
-        <!-- 添加字幕覆盖层 :data-time="formatTime(recordingTimerCount) || '03:30'"-->
-        <div class="subtitle-overlay" v-if="currentSubtitle">
+        <!-- 添加字幕覆盖层 -->
+        <div class="subtitle-overlay" v-if="currentSubtitle || (showSubtitleText && subtitleText)">
           <!-- 添加题号显示 -->
           <div class="subtitle-header" v-if="currentVideoIndex > 0">
             <span class="question-tag">{{ currentVideoIndex }}/{{ totalQuestions }}</span>
@@ -60,10 +60,9 @@
           <template v-else>
             <div class="parent-question">{{ parentQuestion }}</div>
             <div class="followup-container">
-              <!-- <div class="followup-divider"></div> -->
               <div class="followup-content">
                 <span class="followup-label">追问:</span>
-                <span class="followup-text">{{ currentSubtitle }}</span>
+                <span class="followup-text">{{ subtitleText || currentSubtitle }}</span>
               </div>
             </div>
           </template>
@@ -210,8 +209,18 @@
 import { apiBaseUrl, personDetectionWsUrl } from '@/common/config.js';
 export default {
   name: 'IdentityVerify',
-  data() {
-    return {
+      data() {
+      return {
+        followUpQuestion: '', // 追问问题
+        followUpAudioUrl: '', // 追问音频URL
+        audioContext: null, // 音频上下文
+        followUpQuestions: [], // 追问问题列表
+        isWaitingForAnswer: false, // 添加新的状态来控制是否在等待用户回答
+        currentFollowUpIndex: -1, // 当前追问问题索引
+        showSubtitleText: false, // 是否显示字幕
+        subtitleText: '', // 字幕文本
+        parentQuestion: '', // 父问题文本
+        isFollowUpQuestion: false, // 是否是追问问题
       loading: false,
       responses: [],
       processedResponses: [],
@@ -312,6 +321,15 @@ export default {
       personDetectionInterval: null, // 定时器对象
       showCameraWarning: false, // 添加新的数据属性
       showPageWarning: false, // 添加新的数据属性
+      followUpQuestion: '', // 追问问题
+      followUpAudioUrl: '', // 追问音频URL
+      audioContext: null, // 音频上下文
+      followUpQuestions: [], // 追问问题列表
+      currentFollowUpIndex: -1, // 当前追问问题索引
+      showSubtitleText: false, // 是否显示字幕
+      subtitleText: '', // 字幕文本
+      isAudioPlaying: false,
+      isWaitingForAnswer: false, // 添加新的状态来控制是否在等待用户回答
     }
   },
   mounted() {
@@ -367,7 +385,350 @@ export default {
     uni.offUserCaptureScreen();
     this.cleanupPersonDetectionWebSocket();
   },
-  methods: {
+      methods: {
+      // 处理音频播放完成
+      handleAudioEnd() {
+        console.log('音频播放完成');
+        // 设置等待回答状态
+        this.isWaitingForAnswer = true;
+        // 显示开始作答按钮
+        this.showStartRecordingButton = true;
+        
+        // 延迟一下再开始倒计时,避免重复触发
+        setTimeout(() => {
+          // 开始倒计时
+          this.startCountdown();
+        }, 100);
+      },
+      
+      // 开始倒计时
+      startCountdown() {
+        this.showCountdown = true;
+        this.countdownValue = 5; // 重置倒计时值
+        
+        this.countdownTimer = setInterval(() => {
+          this.countdownValue--;
+          
+          if (this.countdownValue <= 0) {
+            // 倒计时结束,清除定时器
+            this.clearCountdown();
+            
+            // 隐藏开始作答按钮
+            this.showStartRecordingButton = false;
+            
+            // 开始录制
+            this.startRecordingAnswer();
+          }
+        }, 1000);
+      },
+      
+      // 清除倒计时
+      clearCountdown() {
+        if (this.countdownTimer) {
+          clearInterval(this.countdownTimer);
+          this.countdownTimer = null;
+        }
+        this.showCountdown = false;
+      },
+
+      // 处理追问问题
+      async handleFollowUpQuestion(questionData) {
+        console.log('处理追问问题数据:', questionData);
+        
+        // 检查数据完整性
+        if (!questionData || !questionData.follow_up_voice_url || !questionData.follow_up_question) {
+          console.error('追问数据不完整:', questionData);
+          uni.showToast({
+            title: '获取追问数据失败',
+            icon: 'none'
+          });
+          return;
+        }
+        
+        // 保存父问题
+        this.parentQuestion = questionData.original_question || '';
+        
+        // 确保音频URL正确
+        let audioUrl = '';
+        if (questionData.follow_up_voice_url.direct_url) {
+          audioUrl = questionData.follow_up_voice_url.direct_url;
+        } else if (questionData.follow_up_voice_url.file_url) {
+          audioUrl = questionData.follow_up_voice_url.file_url;
+        }
+        
+        // 确保音频URL是完整的
+        if (!audioUrl.startsWith('http')) {
+          audioUrl = apiBaseUrl + audioUrl;
+        }
+        
+        console.log('处理后的音频URL:', audioUrl);
+        
+        // 创建追问问题对象
+        const followUpQuestionObj = {
+          id: Date.now(),
+          question: questionData.follow_up_question.trim(), // 去除可能的空白字符
+          audioUrl: audioUrl,
+          originalQuestion: questionData.original_question,
+          sessionId: questionData.session_id
+        };
+        
+        console.log('创建的追问问题对象:', followUpQuestionObj);
+        
+        // 添加到追问问题列表
+        this.followUpQuestions.push(followUpQuestionObj);
+        this.currentFollowUpIndex = this.followUpQuestions.length - 1;
+        
+        // 更新当前追问问题
+        this.followUpQuestion = followUpQuestionObj.question;
+        this.followUpAudioUrl = followUpQuestionObj.audioUrl;
+        
+        // 标记当前是追问问题
+        this.isFollowUpQuestion = true;
+        this.currentFollowUpQuestion = followUpQuestionObj;
+        
+        // 显示字幕
+        this.showSubtitle(followUpQuestionObj.question, true);
+        
+        // 等待音频播放完成
+        try {
+          await this.playFollowUpAudio();
+          console.log('音频播放完成,准备录制回答');
+          // 开始准备录制回答
+          this.prepareToAnswer(true, followUpQuestionObj);
+        } catch (error) {
+          console.error('音频播放失败:', error);
+          // 即使音频播放失败,也继续准备录制回答
+          this.prepareToAnswer(true, followUpQuestionObj);
+        }
+      },
+      // 准备回答问题
+      prepareToAnswer(isFollowUp = false, questionData = null) {
+        console.log('准备回答问题:', { isFollowUp, questionData });
+        
+        // 重置录制状态
+        this.isRecording = false;
+        this.recordedTime = 0;
+        this.showStopRecordingButton = false;
+        
+        // 设置当前问题状态
+        if (isFollowUp && questionData) {
+          this.currentFollowUpQuestion = questionData;
+          this.isFollowUpQuestion = true;
+        }
+        
+        // 设置等待回答状态
+        this.isWaitingForAnswer = true;
+        
+        // 显示开始回答按钮和倒计时
+        this.handleAudioEnd();
+      },
+      // 调用面试互动接口
+      async callInterviewInteraction(questionId) {
+        const userInfo = JSON.parse(uni.getStorageSync('userInfo'));
+        const appId = uni.getStorageSync('appId');
+        
+        try {
+          console.log('开始调用面试互动接口', { questionId, appId });
+          const res = await uni.request({
+            url: `${apiBaseUrl}/api/voice_interview_interaction/`,
+            method: 'POST',
+            data: {
+              tenant_id: userInfo.tenant_id || 1,
+              question_id: questionId,
+              position_config_id: 6,
+              application_id: appId
+            },
+            header: {
+              'content-type': 'application/json'
+            }
+          });
+          console.log('面试互动接口返回数据:', res);
+          
+          if (res.data.success) {
+            // 等待处理追问问题完成
+            await this.handleFollowUpQuestion(res.data);
+          } else {
+            console.error('面试互动接口返回错误:', res.data);
+            uni.showToast({
+              title: '获取追问失败',
+              icon: 'none'
+            });
+          }
+        } catch (error) {
+          console.error('调用面试互动接口失败:', error);
+        }
+      },
+      
+      // 播放追问音频
+      async playFollowUpAudio() {
+        return new Promise((resolve, reject) => {
+          console.log('开始播放追问音频, URL:', this.followUpAudioUrl);
+          
+          // 检查音频URL
+          if (!this.followUpAudioUrl) {
+            console.error('没有音频URL');
+            uni.showToast({
+              title: '音频URL无效',
+              icon: 'none'
+            });
+            reject(new Error('没有音频URL'));
+            return;
+          }
+          
+          // 显示加载提示
+          uni.showLoading({
+            title: '加载音频中...'
+          });
+          
+          // 停止并销毁之前的音频实例
+          this.stopAndDestroyAudio();
+          
+          try {
+            // 创建新的音频上下文
+            const innerAudioContext = uni.createInnerAudioContext();
+            this.audioContext = innerAudioContext;
+            
+            // 设置音频属性
+            innerAudioContext.autoplay = true;
+            innerAudioContext.obeyMuteSwitch = false;
+            innerAudioContext.volume = 1.0;
+            
+            // 监听音频加载状态
+            innerAudioContext.onCanplay(() => {
+              console.log('音频可以播放');
+              uni.hideLoading();
+              this.isAudioPlaying = true;
+              uni.showToast({
+                title: '正在播放追问',
+                icon: 'none',
+                duration: 2000
+              });
+            });
+            
+            // 监听音频播放完成
+            innerAudioContext.onEnded(() => {
+              console.log('追问音频播放完成');
+              this.isAudioPlaying = false;
+              resolve();
+              // 延迟清理资源,确保不会影响播放完成的回调
+              setTimeout(() => {
+                this.stopAndDestroyAudio();
+                // 音频播放完成后,自动准备录制回答
+                this.prepareToAnswer(true, this.currentFollowUpQuestion);
+              }, 100);
+            });
+            
+            // 监听音频播放错误
+            innerAudioContext.onError((res) => {
+              console.error('音频播放错误:', res);
+              this.isAudioPlaying = false;
+              uni.hideLoading();
+              uni.showToast({
+                title: '音频播放失败',
+                icon: 'none'
+              });
+              reject(res);
+              this.stopAndDestroyAudio();
+            });
+            
+            // 设置音频源
+            console.log('设置音频源:', this.followUpAudioUrl);
+            innerAudioContext.src = this.followUpAudioUrl;
+            
+          } catch (error) {
+            console.error('创建或播放音频失败:', error);
+            this.isAudioPlaying = false;
+            uni.hideLoading();
+            uni.showToast({
+              title: '音频播放失败',
+              icon: 'none'
+            });
+            this.stopAndDestroyAudio();
+            reject(error);
+          }
+        });
+      },
+      
+      // 停止并销毁音频
+      stopAndDestroyAudio() {
+        if (!this.audioContext) {
+          return;
+        }
+        
+        const ctx = this.audioContext;
+        this.audioContext = null; // 先清除引用
+        
+        try {
+          if (this.isAudioPlaying) {
+            ctx.stop();
+          }
+        } catch (error) {
+          console.error('停止音频播放失败:', error);
+        }
+        
+        try {
+          ctx.destroy();
+        } catch (error) {
+          console.error('销毁音频实例失败:', error);
+        }
+        
+        this.isAudioPlaying = false;
+      },
+      
+      // 绑定音频事件
+      bindAudioEvents(audioContext, resolve, reject) {
+        // 监听音频加载状态
+        audioContext.onCanplay(() => {
+          console.log('音频可以播放');
+          uni.showToast({
+            title: '正在播放追问',
+            icon: 'none',
+            duration: 2000
+          });
+        });
+        
+        // 监听播放进度
+        audioContext.onTimeUpdate(() => {
+          console.log('音频播放进度:', audioContext.currentTime);
+        });
+        
+        // 监听音频播放完成
+        audioContext.onEnded(() => {
+          console.log('追问音频播放完成');
+          this.cleanupAudioContext();
+          resolve();
+        });
+        
+        // 监听音频播放错误
+        audioContext.onError((res) => {
+          console.error('音频播放错误:', res);
+          uni.showToast({
+            title: '音频播放失败',
+            icon: 'none'
+          });
+          this.cleanupAudioContext();
+          reject(res);
+        });
+      },
+
+      // 修改准备回答方法
+      prepareToAnswer(isFollowUp = false, questionData = null) {
+        // 重置录制状态
+        this.isRecording = false;
+        this.recordedTime = 0;
+        this.showStopRecordingButton = false;
+        
+        // 设置当前问题状态
+        if (isFollowUp && questionData) {
+          this.currentFollowUpQuestion = questionData;
+          this.isFollowUpQuestion = true;
+        }
+        
+        // 设置等待回答状态
+        this.isWaitingForAnswer = true;
+        // 显示开始作答按钮和倒计时
+        this.handleAudioEnd();
+      },
     // 初始化相机
     async initCamera() {
       // 检查平台
@@ -1007,22 +1368,29 @@ export default {
     
     // 添加新方法:开始倒计时
     startCountdown() {
+      // 先清除可能存在的倒计时
+      this.clearCountdown();
+      
       // 显示倒计时蒙层
       this.showCountdown = true;
       this.countdownValue = 10;
       
       // 开始倒计时
       this.countdownTimer = setInterval(() => {
+        if (!this.showStartRecordingButton) {
+          // 如果开始回答按钮已经被点击,清除倒计时
+          this.clearCountdown();
+          return;
+        }
+        
         this.countdownValue--;
         
         if (this.countdownValue <= 0) {
           // 倒计时结束,清除定时器
           this.clearCountdown();
           
-          // 隐藏"开始回答"按钮
+          // 自动开始录制
           this.showStartRecordingButton = false;
-          
-          // 开始录制
           this.startRecordingAnswer();
         }
       }, 1000);
@@ -1045,6 +1413,9 @@ export default {
       // 如果倒计时正在进行,清除倒计时
       this.clearCountdown();
       
+      // 重置等待回答状态
+      this.isWaitingForAnswer = false;
+      
       // 直接开始录制
       this.startRecordingAnswer();
     },
@@ -1054,6 +1425,12 @@ export default {
       // 如果倒计时正在进行,先清除倒计时
       this.clearCountdown();
       
+      // 重置等待回答状态
+      this.isWaitingForAnswer = false;
+      
+      // 重置等待回答状态
+      this.isWaitingForAnswer = false;
+      
       // 检查录制时长
       const recordingDuration = this.getRecordingDuration();
       const minimumDuration = 3; // 最小录制时长(秒),改为3秒
@@ -1538,6 +1915,9 @@ export default {
         this.showCountdown = false;
       }
       
+      // 重置等待回答状态
+      this.isWaitingForAnswer = false;
+      
       // 检查录制时长
       const recordingDuration = this.getRecordingDuration();
       const minimumDuration = 3; // 最小录制时长(秒),改为3秒
@@ -1689,7 +2069,7 @@ export default {
       
       // 停止录制
       this.cameraContext.stopRecord({
-        success: (res) => {
+        success: async (res) => {
           console.log('小程序录制停止成功:', res);
           
           // 获取录制的视频文件路径
@@ -1697,8 +2077,8 @@ export default {
           
           // 上传视频文件
           if (videoPath) {
-            // 确保传递正确的问题ID,特别是对于追问问题
-            this.uploadRecordedVideo(videoPath);
+            // 等待上传完成后再继续
+            await this.uploadRecordedVideo(videoPath);
           } else {
             console.error('未获取到录制视频路径');
             this.proceedToNextQuestion();
@@ -1776,7 +2156,7 @@ export default {
         questionForm: questionForm,
         attempts: 0,
         maxAttempts: 3,
-        parentQuestionId: this.currentParentQuestionId // 添加父问题ID
+        parentQuestionId: this.currentParentQuestionId
       };
       
       // 如果不是追问问题,记录当前问题ID作为父问题ID
@@ -1793,21 +2173,35 @@ export default {
       
       // 显示上传状态提示
       uni.showToast({
-        title: '已完成回答',
-        icon: 'none',
+        title: '正在上传回答...',
+        icon: 'loading',
         duration: 1500
       });
       
       // 更新上传状态文本
       this.updateUploadStatusText();
       
-      // 如果当前没有上传任务在进行,开始处理队列
-      if (!this.isUploading) {
-        this.processUploadQueue();
-      }
-
-      // 立即执行后续逻辑
-      this.handlePostUploadActions(uploadTask);
+      // 等待上传完成后再执行后续操作
+      return new Promise((resolve) => {
+        const checkUploadStatus = () => {
+          if (!this.isUploading && this.uploadQueue.length === 0) {
+            // 上传完成后执行后续操作
+            this.handlePostUploadActions(uploadTask);
+            resolve();
+          } else {
+            // 如果还在上传,继续检查
+            setTimeout(checkUploadStatus, 500);
+          }
+        };
+        
+        // 如果当前没有上传任务在进行,开始处理队列
+        if (!this.isUploading) {
+          this.processUploadQueue();
+        }
+        
+        // 开始检查上传状态
+        checkUploadStatus();
+      });
     },
 
     // 添加新方法:处理上传后的逻辑
@@ -2053,6 +2447,8 @@ export default {
         question_text: task.questionText
       };
       
+      console.log('提交视频到面试接口', requestData);
+      
       // 发送请求到面试接口
       uni.request({
         url: `${apiBaseUrl}/api/job/upload_video`,
@@ -2061,8 +2457,34 @@ export default {
         header: {
           'content-type': 'application/x-www-form-urlencoded'
         },
-        success: (res) => {
+        success: async (res) => {
           if (res.data.code === 200 || res.data.code === 2000) {
+            console.log('视频提交成功,准备调用面试互动接口');
+            
+            // 如果不是追问回答,才调用面试互动接口获取追问
+            if (!task.isFollowUp) {
+              try {
+                // 调用面试互动接口
+                await this.callInterviewInteraction(res.data.data.job_position_question_id);
+                console.log('面试互动接口调用成功');
+              } catch (error) {
+                console.error('面试互动接口调用失败:', error);
+                // 如果获取追问失败,继续处理下一个问题
+                this.proceedToNextQuestion();
+              }
+            } else {
+              // 如果是追问回答,直接继续下一个问题
+              console.log('追问回答上传完成,继续下一个问题');
+              this.proceedToNextQuestion();
+            }
+            
+            // 显示成功提示
+            uni.showToast({
+              title: '回答已提交',
+              icon: 'success',
+              duration: 1500
+            });
+            
             // 从队列中移除已完成的任务
             this.uploadQueue.shift();
             
@@ -2073,7 +2495,8 @@ export default {
           }
         },
         fail: (err) => {
-          this.handleUploadError(task, '网络错误: ' + err.errMsg);
+          console.error('提交视频失败:', err);
+          this.handleUploadError(task, '提交失败: ' + err.errMsg);
         }
       });
     },
@@ -2428,6 +2851,9 @@ export default {
       // 如果倒计时正在进行,清除倒计时
       this.clearCountdown();
       
+      // 重置等待回答状态
+      this.isWaitingForAnswer = false;
+      
       // 直接开始录制
       this.startRecordingAnswer();
     },
@@ -3295,6 +3721,12 @@ export default {
     checkAndPlayFollowUpQuestion(parentQuestionId) {
       console.log('检查是否有追问问题,父问题ID:', parentQuestionId);
       
+      // 如果正在等待用户回答,不进行任何操作
+      if (this.isWaitingForAnswer) {
+        console.log('正在等待用户回答,暂不处理追问');
+        return;
+      }
+      
       if (!parentQuestionId) {
         console.warn('没有父问题ID,无法检查追问问题');
         this.proceedToNextQuestion();
@@ -3461,7 +3893,6 @@ export default {
         this.personDetectionSocket.onMessage((res) => {
           try {
             const data = JSON.parse(res.data);
-            console.log(data);
             if (data.type === 'person_detection_result') {
               this.handlePersonDetectionResult(data);
             }
@@ -3528,8 +3959,8 @@ export default {
     },
 
     handlePersonDetectionResult(data) {
-      console.log(data.data.detection.has_person);
-      console.log(data.data.identity.status);//identity_verified
+      /* console.log(data.data.detection.has_person);
+      console.log(data.data.identity.status);//identity_verified */
       
       /* // 首先检查是否有人
       if (!data.data.detection.has_person) {
@@ -3554,7 +3985,7 @@ export default {
       }
       // 然后检查身份验证状态
       else */ if (data.data.identity.status !== "identity_verified") {
-        this.showPageWarning = true;
+         /*this.showPageWarning = true;
         uni.showToast({
           title: data.data.identity.message,
           icon: 'none',
@@ -3567,12 +3998,226 @@ export default {
           fail: function (err) {
             console.error('Vibration failed:', err);
           }
-        });
+        }); */
         setTimeout(() => {
           this.showPageWarning = false;
         }, 3000);
       }
     },
+
+    // 添加新方法:处理追问问题
+          async handleFollowUpQuestion(questionData) {
+        console.log('处理追问问题数据:', questionData);
+        
+        // 检查数据完整性
+        if (!questionData || !questionData.follow_up_voice_url || !questionData.follow_up_question) {
+          console.error('追问数据不完整:', questionData);
+          uni.showToast({
+            title: '获取追问数据失败',
+            icon: 'none'
+          });
+          return;
+        }
+        
+        // 保存父问题
+        this.parentQuestion = questionData.original_question || '';
+        
+        // 确保音频URL正确
+        let audioUrl = '';
+        if (questionData.follow_up_voice_url.direct_url) {
+          audioUrl = questionData.follow_up_voice_url.direct_url;
+        } else if (questionData.follow_up_voice_url.file_url) {
+          audioUrl = questionData.follow_up_voice_url.file_url;
+        }
+        
+        // 确保音频URL是完整的
+        if (!audioUrl.startsWith('http')) {
+          audioUrl = apiBaseUrl + audioUrl;
+        }
+        
+        console.log('处理后的音频URL:', audioUrl);
+        
+        // 创建追问问题对象
+        const followUpQuestionObj = {
+          id: Date.now(),
+          question: questionData.follow_up_question.trim(), // 去除可能的空白字符
+          audioUrl: audioUrl,
+          originalQuestion: questionData.original_question,
+          sessionId: questionData.session_id
+        };
+        
+        console.log('创建的追问问题对象:', followUpQuestionObj);
+        
+        // 添加到追问问题列表
+        this.followUpQuestions.push(followUpQuestionObj);
+        this.currentFollowUpIndex = this.followUpQuestions.length - 1;
+        
+        // 更新当前追问问题
+        this.followUpQuestion = followUpQuestionObj.question;
+        this.followUpAudioUrl = followUpQuestionObj.audioUrl;
+        
+        // 标记当前是追问问题
+        this.isFollowUpQuestion = true;
+        this.currentFollowUpQuestion = followUpQuestionObj;
+        
+        // 显示字幕
+        this.showSubtitle(followUpQuestionObj.question, true);
+        
+        // 等待音频播放完成
+        try {
+          await this.playFollowUpAudio();
+          console.log('音频播放完成,准备录制回答');
+          // 开始准备录制回答
+          this.prepareToAnswer(true, followUpQuestionObj);
+        } catch (error) {
+          console.error('音频播放失败:', error);
+          // 即使音频播放失败,也继续准备录制回答
+          this.prepareToAnswer(true, followUpQuestionObj);
+        }
+      },
+
+      // 播放追问音频
+      async playFollowUpAudio() {
+        return new Promise((resolve, reject) => {
+          console.log('开始播放追问音频, URL:', this.followUpAudioUrl);
+          
+          // 检查音频URL
+          if (!this.followUpAudioUrl) {
+            console.error('没有音频URL');
+            reject(new Error('没有音频URL'));
+            return;
+          }
+          
+          // 显示加载提示
+          uni.showLoading({
+            title: '加载音频中...'
+          });
+          
+          // 停止并销毁之前的音频实例
+          this.stopAndDestroyAudio();
+          
+          try {
+            // 创建新的音频上下文
+            const innerAudioContext = uni.createInnerAudioContext();
+            this.audioContext = innerAudioContext;
+            
+            // 设置音频属性
+            innerAudioContext.autoplay = true;
+            innerAudioContext.obeyMuteSwitch = false;
+            innerAudioContext.volume = 1.0;
+            
+            // 监听音频加载状态
+            innerAudioContext.onCanplay(() => {
+              console.log('音频可以播放');
+              uni.hideLoading();
+              this.isAudioPlaying = true;
+              uni.showToast({
+                title: '正在播放追问',
+                icon: 'none',
+                duration: 2000
+              });
+            });
+            
+            // 监听音频播放完成
+            innerAudioContext.onEnded(() => {
+              console.log('追问音频播放完成');
+              this.isAudioPlaying = false;
+              resolve();
+              // 延迟清理资源,确保不会影响播放完成的回调
+              setTimeout(() => {
+                this.stopAndDestroyAudio();
+                // 音频播放完成后,自动准备录制回答
+                this.prepareToAnswer(true, this.currentFollowUpQuestion);
+              }, 100);
+            });
+            
+            // 监听音频播放错误
+            innerAudioContext.onError((res) => {
+              console.error('音频播放错误:', res);
+              this.isAudioPlaying = false;
+              uni.hideLoading();
+              uni.showToast({
+                title: '音频播放失败',
+                icon: 'none'
+              });
+              reject(res);
+              this.stopAndDestroyAudio();
+            });
+            
+            // 设置音频源
+            console.log('设置音频源:', this.followUpAudioUrl);
+            innerAudioContext.src = this.followUpAudioUrl;
+            
+          } catch (error) {
+            console.error('创建或播放音频失败:', error);
+            this.isAudioPlaying = false;
+            uni.hideLoading();
+            uni.showToast({
+              title: '音频播放失败',
+              icon: 'none'
+            });
+            this.stopAndDestroyAudio();
+            reject(error);
+          }
+        });
+      },
+      
+      // 停止并销毁音频
+      stopAndDestroyAudio() {
+        if (!this.audioContext) {
+          return;
+        }
+        
+        const ctx = this.audioContext;
+        this.audioContext = null; // 先清除引用
+        
+        try {
+          if (this.isAudioPlaying) {
+            ctx.stop();
+          }
+        } catch (error) {
+          console.error('停止音频播放失败:', error);
+        }
+        
+        try {
+          ctx.destroy();
+        } catch (error) {
+          console.error('销毁音频实例失败:', error);
+        }
+        
+        this.isAudioPlaying = false;
+      },
+
+      // 显示字幕
+      showSubtitle(text, isFollowUp = true) {
+        console.log('显示字幕:', text);
+        this.subtitleText = text;
+        this.showSubtitleText = true;
+        this.isFollowUpQuestion = isFollowUp;
+        
+        // 确保字幕显示在界面上
+        this.$nextTick(() => {
+          // 如果需要,可以添加字幕动画效果
+          setTimeout(() => {
+            this.showSubtitleText = false;
+          }, 8000); // 8秒后隐藏字幕
+        });
+      },
+
+      // 显示问题对话框
+      showQuestionDialog() {
+        if (this.followUpQuestion) {
+          uni.showModal({
+            title: '追问问题',
+            content: this.followUpQuestion,
+            showCancel: false,
+            success: () => {
+              // 准备开始回答
+              this.prepareToAnswer(true, this.followUpQuestions[this.currentFollowUpIndex]);
+            }
+          });
+        }
+      },
   },
   computed: {
     // 计算进度比例
@@ -3614,6 +4259,39 @@ export default {
 </script>
 
 <style scoped>
+.subtitle-container {
+  position: fixed;
+  bottom: 20%;
+  left: 0;
+  right: 0;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  z-index: 1000;
+}
+
+.subtitle-text {
+  background-color: rgba(0, 0, 0, 0.7);
+  color: white;
+  padding: 10px 20px;
+  border-radius: 5px;
+  font-size: 16px;
+  max-width: 80%;
+  text-align: center;
+  animation: fadeIn 0.5s ease-in-out;
+}
+
+@keyframes fadeIn {
+  from {
+    opacity: 0;
+    transform: translateY(20px);
+  }
+  to {
+    opacity: 1;
+    transform: translateY(0);
+  }
+}
+
 .identity-verify-container {
   padding: 0;
   max-width: 100%;

+ 503 - 31
unpackage/dist/dev/mp-weixin/pages/identity-verify/identity-verify.js

@@ -5,6 +5,26 @@ const _sfc_main = {
   name: "IdentityVerify",
   data() {
     return {
+      followUpQuestion: "",
+      // 追问问题
+      followUpAudioUrl: "",
+      // 追问音频URL
+      audioContext: null,
+      // 音频上下文
+      followUpQuestions: [],
+      // 追问问题列表
+      isWaitingForAnswer: false,
+      // 添加新的状态来控制是否在等待用户回答
+      currentFollowUpIndex: -1,
+      // 当前追问问题索引
+      showSubtitleText: false,
+      // 是否显示字幕
+      subtitleText: "",
+      // 字幕文本
+      parentQuestion: "",
+      // 父问题文本
+      isFollowUpQuestion: false,
+      // 是否是追问问题
       loading: false,
       responses: [],
       processedResponses: [],
@@ -160,8 +180,25 @@ const _sfc_main = {
       // 定时器对象
       showCameraWarning: false,
       // 添加新的数据属性
-      showPageWarning: false
+      showPageWarning: false,
       // 添加新的数据属性
+      followUpQuestion: "",
+      // 追问问题
+      followUpAudioUrl: "",
+      // 追问音频URL
+      audioContext: null,
+      // 音频上下文
+      followUpQuestions: [],
+      // 追问问题列表
+      currentFollowUpIndex: -1,
+      // 当前追问问题索引
+      showSubtitleText: false,
+      // 是否显示字幕
+      subtitleText: "",
+      // 字幕文本
+      isAudioPlaying: false,
+      isWaitingForAnswer: false
+      // 添加新的状态来控制是否在等待用户回答
     };
   },
   mounted() {
@@ -213,6 +250,258 @@ const _sfc_main = {
     this.cleanupPersonDetectionWebSocket();
   },
   methods: {
+    // 处理音频播放完成
+    handleAudioEnd() {
+      console.log("音频播放完成");
+      this.isWaitingForAnswer = true;
+      this.showStartRecordingButton = true;
+      setTimeout(() => {
+        this.startCountdown();
+      }, 100);
+    },
+    // 开始倒计时
+    startCountdown() {
+      this.showCountdown = true;
+      this.countdownValue = 5;
+      this.countdownTimer = setInterval(() => {
+        this.countdownValue--;
+        if (this.countdownValue <= 0) {
+          this.clearCountdown();
+          this.showStartRecordingButton = false;
+          this.startRecordingAnswer();
+        }
+      }, 1e3);
+    },
+    // 清除倒计时
+    clearCountdown() {
+      if (this.countdownTimer) {
+        clearInterval(this.countdownTimer);
+        this.countdownTimer = null;
+      }
+      this.showCountdown = false;
+    },
+    // 处理追问问题
+    async handleFollowUpQuestion(questionData) {
+      console.log("处理追问问题数据:", questionData);
+      if (!questionData || !questionData.follow_up_voice_url || !questionData.follow_up_question) {
+        console.error("追问数据不完整:", questionData);
+        common_vendor.index.showToast({
+          title: "获取追问数据失败",
+          icon: "none"
+        });
+        return;
+      }
+      this.parentQuestion = questionData.original_question || "";
+      let audioUrl = "";
+      if (questionData.follow_up_voice_url.direct_url) {
+        audioUrl = questionData.follow_up_voice_url.direct_url;
+      } else if (questionData.follow_up_voice_url.file_url) {
+        audioUrl = questionData.follow_up_voice_url.file_url;
+      }
+      if (!audioUrl.startsWith("http")) {
+        audioUrl = common_config.apiBaseUrl + audioUrl;
+      }
+      console.log("处理后的音频URL:", audioUrl);
+      const followUpQuestionObj = {
+        id: Date.now(),
+        question: questionData.follow_up_question.trim(),
+        // 去除可能的空白字符
+        audioUrl,
+        originalQuestion: questionData.original_question,
+        sessionId: questionData.session_id
+      };
+      console.log("创建的追问问题对象:", followUpQuestionObj);
+      this.followUpQuestions.push(followUpQuestionObj);
+      this.currentFollowUpIndex = this.followUpQuestions.length - 1;
+      this.followUpQuestion = followUpQuestionObj.question;
+      this.followUpAudioUrl = followUpQuestionObj.audioUrl;
+      this.isFollowUpQuestion = true;
+      this.currentFollowUpQuestion = followUpQuestionObj;
+      this.showSubtitle(followUpQuestionObj.question, true);
+      try {
+        await this.playFollowUpAudio();
+        console.log("音频播放完成,准备录制回答");
+        this.prepareToAnswer(true, followUpQuestionObj);
+      } catch (error) {
+        console.error("音频播放失败:", error);
+        this.prepareToAnswer(true, followUpQuestionObj);
+      }
+    },
+    // 准备回答问题
+    prepareToAnswer(isFollowUp = false, questionData = null) {
+      console.log("准备回答问题:", { isFollowUp, questionData });
+      this.isRecording = false;
+      this.recordedTime = 0;
+      this.showStopRecordingButton = false;
+      if (isFollowUp && questionData) {
+        this.currentFollowUpQuestion = questionData;
+        this.isFollowUpQuestion = true;
+      }
+      this.isWaitingForAnswer = true;
+      this.handleAudioEnd();
+    },
+    // 调用面试互动接口
+    async callInterviewInteraction(questionId) {
+      const userInfo = JSON.parse(common_vendor.index.getStorageSync("userInfo"));
+      const appId = common_vendor.index.getStorageSync("appId");
+      try {
+        console.log("开始调用面试互动接口", { questionId, appId });
+        const res = await common_vendor.index.request({
+          url: `${common_config.apiBaseUrl}/api/voice_interview_interaction/`,
+          method: "POST",
+          data: {
+            tenant_id: userInfo.tenant_id || 1,
+            question_id: questionId,
+            position_config_id: 6,
+            application_id: appId
+          },
+          header: {
+            "content-type": "application/json"
+          }
+        });
+        console.log("面试互动接口返回数据:", res);
+        if (res.data.success) {
+          await this.handleFollowUpQuestion(res.data);
+        } else {
+          console.error("面试互动接口返回错误:", res.data);
+          common_vendor.index.showToast({
+            title: "获取追问失败",
+            icon: "none"
+          });
+        }
+      } catch (error) {
+        console.error("调用面试互动接口失败:", error);
+      }
+    },
+    // 播放追问音频
+    async playFollowUpAudio() {
+      return new Promise((resolve, reject) => {
+        console.log("开始播放追问音频, URL:", this.followUpAudioUrl);
+        if (!this.followUpAudioUrl) {
+          console.error("没有音频URL");
+          common_vendor.index.showToast({
+            title: "音频URL无效",
+            icon: "none"
+          });
+          reject(new Error("没有音频URL"));
+          return;
+        }
+        common_vendor.index.showLoading({
+          title: "加载音频中..."
+        });
+        this.stopAndDestroyAudio();
+        try {
+          const innerAudioContext = common_vendor.index.createInnerAudioContext();
+          this.audioContext = innerAudioContext;
+          innerAudioContext.autoplay = true;
+          innerAudioContext.obeyMuteSwitch = false;
+          innerAudioContext.volume = 1;
+          innerAudioContext.onCanplay(() => {
+            console.log("音频可以播放");
+            common_vendor.index.hideLoading();
+            this.isAudioPlaying = true;
+            common_vendor.index.showToast({
+              title: "正在播放追问",
+              icon: "none",
+              duration: 2e3
+            });
+          });
+          innerAudioContext.onEnded(() => {
+            console.log("追问音频播放完成");
+            this.isAudioPlaying = false;
+            resolve();
+            setTimeout(() => {
+              this.stopAndDestroyAudio();
+              this.prepareToAnswer(true, this.currentFollowUpQuestion);
+            }, 100);
+          });
+          innerAudioContext.onError((res) => {
+            console.error("音频播放错误:", res);
+            this.isAudioPlaying = false;
+            common_vendor.index.hideLoading();
+            common_vendor.index.showToast({
+              title: "音频播放失败",
+              icon: "none"
+            });
+            reject(res);
+            this.stopAndDestroyAudio();
+          });
+          console.log("设置音频源:", this.followUpAudioUrl);
+          innerAudioContext.src = this.followUpAudioUrl;
+        } catch (error) {
+          console.error("创建或播放音频失败:", error);
+          this.isAudioPlaying = false;
+          common_vendor.index.hideLoading();
+          common_vendor.index.showToast({
+            title: "音频播放失败",
+            icon: "none"
+          });
+          this.stopAndDestroyAudio();
+          reject(error);
+        }
+      });
+    },
+    // 停止并销毁音频
+    stopAndDestroyAudio() {
+      if (!this.audioContext) {
+        return;
+      }
+      const ctx = this.audioContext;
+      this.audioContext = null;
+      try {
+        if (this.isAudioPlaying) {
+          ctx.stop();
+        }
+      } catch (error) {
+        console.error("停止音频播放失败:", error);
+      }
+      try {
+        ctx.destroy();
+      } catch (error) {
+        console.error("销毁音频实例失败:", error);
+      }
+      this.isAudioPlaying = false;
+    },
+    // 绑定音频事件
+    bindAudioEvents(audioContext, resolve, reject) {
+      audioContext.onCanplay(() => {
+        console.log("音频可以播放");
+        common_vendor.index.showToast({
+          title: "正在播放追问",
+          icon: "none",
+          duration: 2e3
+        });
+      });
+      audioContext.onTimeUpdate(() => {
+        console.log("音频播放进度:", audioContext.currentTime);
+      });
+      audioContext.onEnded(() => {
+        console.log("追问音频播放完成");
+        this.cleanupAudioContext();
+        resolve();
+      });
+      audioContext.onError((res) => {
+        console.error("音频播放错误:", res);
+        common_vendor.index.showToast({
+          title: "音频播放失败",
+          icon: "none"
+        });
+        this.cleanupAudioContext();
+        reject(res);
+      });
+    },
+    // 修改准备回答方法
+    prepareToAnswer(isFollowUp = false, questionData = null) {
+      this.isRecording = false;
+      this.recordedTime = 0;
+      this.showStopRecordingButton = false;
+      if (isFollowUp && questionData) {
+        this.currentFollowUpQuestion = questionData;
+        this.isFollowUpQuestion = true;
+      }
+      this.isWaitingForAnswer = true;
+      this.handleAudioEnd();
+    },
     // 初始化相机
     async initCamera() {
       const systemInfo = common_vendor.index.getSystemInfoSync();
@@ -671,9 +960,14 @@ const _sfc_main = {
     },
     // 添加新方法:开始倒计时
     startCountdown() {
+      this.clearCountdown();
       this.showCountdown = true;
       this.countdownValue = 10;
       this.countdownTimer = setInterval(() => {
+        if (!this.showStartRecordingButton) {
+          this.clearCountdown();
+          return;
+        }
         this.countdownValue--;
         if (this.countdownValue <= 0) {
           this.clearCountdown();
@@ -694,11 +988,14 @@ const _sfc_main = {
     handleStartRecordingClick() {
       this.showStartRecordingButton = false;
       this.clearCountdown();
+      this.isWaitingForAnswer = false;
       this.startRecordingAnswer();
     },
     // 修改 stopRecordingAnswer 方法,添加录制时长检查
     stopRecordingAnswer() {
       this.clearCountdown();
+      this.isWaitingForAnswer = false;
+      this.isWaitingForAnswer = false;
       const recordingDuration = this.getRecordingDuration();
       const minimumDuration = 3;
       const lowScoreDuration = 7;
@@ -1051,6 +1348,7 @@ const _sfc_main = {
         this.countdownTimer = null;
         this.showCountdown = false;
       }
+      this.isWaitingForAnswer = false;
       const recordingDuration = this.getRecordingDuration();
       const minimumDuration = 3;
       const lowScoreDuration = 7;
@@ -1147,11 +1445,11 @@ const _sfc_main = {
         return;
       }
       this.cameraContext.stopRecord({
-        success: (res) => {
+        success: async (res) => {
           console.log("小程序录制停止成功:", res);
           const videoPath = res.tempVideoPath;
           if (videoPath) {
-            this.uploadRecordedVideo(videoPath);
+            await this.uploadRecordedVideo(videoPath);
           } else {
             console.error("未获取到录制视频路径");
             this.proceedToNextQuestion();
@@ -1219,7 +1517,6 @@ const _sfc_main = {
         attempts: 0,
         maxAttempts: 3,
         parentQuestionId: this.currentParentQuestionId
-        // 添加父问题ID
       };
       if (!isFollowUpQuestionUpload) {
         this.currentParentQuestionId = questionId;
@@ -1228,15 +1525,25 @@ const _sfc_main = {
       this.uploadProgress[uploadTask.id] = 0;
       this.uploadStatus[uploadTask.id] = "pending";
       common_vendor.index.showToast({
-        title: "已完成回答",
-        icon: "none",
+        title: "正在上传回答...",
+        icon: "loading",
         duration: 1500
       });
       this.updateUploadStatusText();
-      if (!this.isUploading) {
-        this.processUploadQueue();
-      }
-      this.handlePostUploadActions(uploadTask);
+      return new Promise((resolve) => {
+        const checkUploadStatus = () => {
+          if (!this.isUploading && this.uploadQueue.length === 0) {
+            this.handlePostUploadActions(uploadTask);
+            resolve();
+          } else {
+            setTimeout(checkUploadStatus, 500);
+          }
+        };
+        if (!this.isUploading) {
+          this.processUploadQueue();
+        }
+        checkUploadStatus();
+      });
     },
     // 添加新方法:处理上传后的逻辑
     handlePostUploadActions(task) {
@@ -1414,6 +1721,7 @@ const _sfc_main = {
         question_form: task.questionForm,
         question_text: task.questionText
       };
+      console.log("提交视频到面试接口", requestData);
       common_vendor.index.request({
         url: `${common_config.apiBaseUrl}/api/job/upload_video`,
         method: "POST",
@@ -1421,8 +1729,26 @@ const _sfc_main = {
         header: {
           "content-type": "application/x-www-form-urlencoded"
         },
-        success: (res) => {
+        success: async (res) => {
           if (res.data.code === 200 || res.data.code === 2e3) {
+            console.log("视频提交成功,准备调用面试互动接口");
+            if (!task.isFollowUp) {
+              try {
+                await this.callInterviewInteraction(res.data.data.job_position_question_id);
+                console.log("面试互动接口调用成功");
+              } catch (error) {
+                console.error("面试互动接口调用失败:", error);
+                this.proceedToNextQuestion();
+              }
+            } else {
+              console.log("追问回答上传完成,继续下一个问题");
+              this.proceedToNextQuestion();
+            }
+            common_vendor.index.showToast({
+              title: "回答已提交",
+              icon: "success",
+              duration: 1500
+            });
             this.uploadQueue.shift();
             this.processUploadQueue();
           } else {
@@ -1430,7 +1756,8 @@ const _sfc_main = {
           }
         },
         fail: (err) => {
-          this.handleUploadError(task, "网络错误: " + err.errMsg);
+          console.error("提交视频失败:", err);
+          this.handleUploadError(task, "提交失败: " + err.errMsg);
         }
       });
     },
@@ -1672,6 +1999,7 @@ const _sfc_main = {
     handleStartRecordingClick() {
       this.showStartRecordingButton = false;
       this.clearCountdown();
+      this.isWaitingForAnswer = false;
       this.startRecordingAnswer();
     },
     // 修改 checkAudioPermission 方法,确保在录制前获取音频权限
@@ -2302,6 +2630,10 @@ const _sfc_main = {
     // 修改检查并播放追问问题的方法
     checkAndPlayFollowUpQuestion(parentQuestionId) {
       console.log("检查是否有追问问题,父问题ID:", parentQuestionId);
+      if (this.isWaitingForAnswer) {
+        console.log("正在等待用户回答,暂不处理追问");
+        return;
+      }
       if (!parentQuestionId) {
         console.warn("没有父问题ID,无法检查追问问题");
         this.proceedToNextQuestion();
@@ -2409,7 +2741,6 @@ const _sfc_main = {
         this.personDetectionSocket.onMessage((res) => {
           try {
             const data = JSON.parse(res.data);
-            console.log(data);
             if (data.type === "person_detection_result") {
               this.handlePersonDetectionResult(data);
             }
@@ -2471,26 +2802,167 @@ const _sfc_main = {
       }
     },
     handlePersonDetectionResult(data) {
-      console.log(data.data.detection.has_person);
-      console.log(data.data.identity.status);
       if (data.data.identity.status !== "identity_verified") {
-        this.showPageWarning = true;
+        setTimeout(() => {
+          this.showPageWarning = false;
+        }, 3e3);
+      }
+    },
+    // 添加新方法:处理追问问题
+    async handleFollowUpQuestion(questionData) {
+      console.log("处理追问问题数据:", questionData);
+      if (!questionData || !questionData.follow_up_voice_url || !questionData.follow_up_question) {
+        console.error("追问数据不完整:", questionData);
         common_vendor.index.showToast({
-          title: data.data.identity.message,
-          icon: "none",
-          duration: 3e3
+          title: "获取追问数据失败",
+          icon: "none"
         });
-        common_vendor.index.vibrateLong({
-          success: function() {
-            console.log("Vibration successful");
-          },
-          fail: function(err) {
-            console.error("Vibration failed:", err);
-          }
+        return;
+      }
+      this.parentQuestion = questionData.original_question || "";
+      let audioUrl = "";
+      if (questionData.follow_up_voice_url.direct_url) {
+        audioUrl = questionData.follow_up_voice_url.direct_url;
+      } else if (questionData.follow_up_voice_url.file_url) {
+        audioUrl = questionData.follow_up_voice_url.file_url;
+      }
+      if (!audioUrl.startsWith("http")) {
+        audioUrl = common_config.apiBaseUrl + audioUrl;
+      }
+      console.log("处理后的音频URL:", audioUrl);
+      const followUpQuestionObj = {
+        id: Date.now(),
+        question: questionData.follow_up_question.trim(),
+        // 去除可能的空白字符
+        audioUrl,
+        originalQuestion: questionData.original_question,
+        sessionId: questionData.session_id
+      };
+      console.log("创建的追问问题对象:", followUpQuestionObj);
+      this.followUpQuestions.push(followUpQuestionObj);
+      this.currentFollowUpIndex = this.followUpQuestions.length - 1;
+      this.followUpQuestion = followUpQuestionObj.question;
+      this.followUpAudioUrl = followUpQuestionObj.audioUrl;
+      this.isFollowUpQuestion = true;
+      this.currentFollowUpQuestion = followUpQuestionObj;
+      this.showSubtitle(followUpQuestionObj.question, true);
+      try {
+        await this.playFollowUpAudio();
+        console.log("音频播放完成,准备录制回答");
+        this.prepareToAnswer(true, followUpQuestionObj);
+      } catch (error) {
+        console.error("音频播放失败:", error);
+        this.prepareToAnswer(true, followUpQuestionObj);
+      }
+    },
+    // 播放追问音频
+    async playFollowUpAudio() {
+      return new Promise((resolve, reject) => {
+        console.log("开始播放追问音频, URL:", this.followUpAudioUrl);
+        if (!this.followUpAudioUrl) {
+          console.error("没有音频URL");
+          reject(new Error("没有音频URL"));
+          return;
+        }
+        common_vendor.index.showLoading({
+          title: "加载音频中..."
         });
+        this.stopAndDestroyAudio();
+        try {
+          const innerAudioContext = common_vendor.index.createInnerAudioContext();
+          this.audioContext = innerAudioContext;
+          innerAudioContext.autoplay = true;
+          innerAudioContext.obeyMuteSwitch = false;
+          innerAudioContext.volume = 1;
+          innerAudioContext.onCanplay(() => {
+            console.log("音频可以播放");
+            common_vendor.index.hideLoading();
+            this.isAudioPlaying = true;
+            common_vendor.index.showToast({
+              title: "正在播放追问",
+              icon: "none",
+              duration: 2e3
+            });
+          });
+          innerAudioContext.onEnded(() => {
+            console.log("追问音频播放完成");
+            this.isAudioPlaying = false;
+            resolve();
+            setTimeout(() => {
+              this.stopAndDestroyAudio();
+              this.prepareToAnswer(true, this.currentFollowUpQuestion);
+            }, 100);
+          });
+          innerAudioContext.onError((res) => {
+            console.error("音频播放错误:", res);
+            this.isAudioPlaying = false;
+            common_vendor.index.hideLoading();
+            common_vendor.index.showToast({
+              title: "音频播放失败",
+              icon: "none"
+            });
+            reject(res);
+            this.stopAndDestroyAudio();
+          });
+          console.log("设置音频源:", this.followUpAudioUrl);
+          innerAudioContext.src = this.followUpAudioUrl;
+        } catch (error) {
+          console.error("创建或播放音频失败:", error);
+          this.isAudioPlaying = false;
+          common_vendor.index.hideLoading();
+          common_vendor.index.showToast({
+            title: "音频播放失败",
+            icon: "none"
+          });
+          this.stopAndDestroyAudio();
+          reject(error);
+        }
+      });
+    },
+    // 停止并销毁音频
+    stopAndDestroyAudio() {
+      if (!this.audioContext) {
+        return;
+      }
+      const ctx = this.audioContext;
+      this.audioContext = null;
+      try {
+        if (this.isAudioPlaying) {
+          ctx.stop();
+        }
+      } catch (error) {
+        console.error("停止音频播放失败:", error);
+      }
+      try {
+        ctx.destroy();
+      } catch (error) {
+        console.error("销毁音频实例失败:", error);
+      }
+      this.isAudioPlaying = false;
+    },
+    // 显示字幕
+    showSubtitle(text, isFollowUp = true) {
+      console.log("显示字幕:", text);
+      this.subtitleText = text;
+      this.showSubtitleText = true;
+      this.isFollowUpQuestion = isFollowUp;
+      this.$nextTick(() => {
         setTimeout(() => {
-          this.showPageWarning = false;
-        }, 3e3);
+          this.showSubtitleText = false;
+        }, 8e3);
+      });
+    },
+    // 显示问题对话框
+    showQuestionDialog() {
+      if (this.followUpQuestion) {
+        common_vendor.index.showModal({
+          title: "追问问题",
+          content: this.followUpQuestion,
+          showCancel: false,
+          success: () => {
+            this.prepareToAnswer(true, this.followUpQuestions[this.currentFollowUpIndex]);
+          }
+        });
       }
     }
   },
@@ -2537,8 +3009,8 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
   }, $data.showAnswerButton ? {
     h: common_vendor.o((...args) => $options.handleAnswerButtonClick && $options.handleAnswerButtonClick(...args))
   } : {}, {
-    i: $data.currentSubtitle
-  }, $data.currentSubtitle ? common_vendor.e({
+    i: $data.currentSubtitle || $data.showSubtitleText && $data.subtitleText
+  }, $data.currentSubtitle || $data.showSubtitleText && $data.subtitleText ? common_vendor.e({
     j: $data.currentVideoIndex > 0
   }, $data.currentVideoIndex > 0 ? {
     k: common_vendor.t($data.currentVideoIndex),
@@ -2549,7 +3021,7 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
     n: common_vendor.t($data.currentSubtitle)
   } : {
     o: common_vendor.t($data.parentQuestion),
-    p: common_vendor.t($data.currentSubtitle)
+    p: common_vendor.t($data.subtitleText || $data.currentSubtitle)
   }) : {}, {
     q: $data.useMiniProgramCameraComponent
   }, $data.useMiniProgramCameraComponent ? {

+ 30 - 0
unpackage/dist/dev/mp-weixin/pages/identity-verify/identity-verify.wxss

@@ -1,4 +1,34 @@
 
+.subtitle-container.data-v-464e78c6 {
+  position: fixed;
+  bottom: 20%;
+  left: 0;
+  right: 0;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  z-index: 1000;
+}
+.subtitle-text.data-v-464e78c6 {
+  background-color: rgba(0, 0, 0, 0.7);
+  color: white;
+  padding: 10px 20px;
+  border-radius: 5px;
+  font-size: 16px;
+  max-width: 80%;
+  text-align: center;
+  animation: fadeIn-464e78c6 0.5s ease-in-out;
+}
+@keyframes fadeIn-464e78c6 {
+from {
+    opacity: 0;
+    transform: translateY(20px);
+}
+to {
+    opacity: 1;
+    transform: translateY(0);
+}
+}
 .identity-verify-container.data-v-464e78c6 {
   padding: 0;
   max-width: 100%;