浏览代码

追问demo

yangg 1 月之前
父节点
当前提交
90b7c2d1c5

+ 8 - 0
pages.json

@@ -141,6 +141,14 @@
 				"navigationBarTitleText": "体态照片补拍",
 				"navigationStyle": "default"
 			}
+		},
+		{
+			"path" : "pages/demo/demo",
+			"style" : 
+			{
+				"navigationBarTitleText": "",
+				"navigationStyle": "custom"
+			}
 		}
 	],
 	

+ 5931 - 0
pages/demo/demo.vue

@@ -0,0 +1,5931 @@
+<template>
+	<view class="custom-navbar" :style="{paddingTop: statusBarHeight + 'px'}">
+	      <!-- <view class="navbar-title">我的标题</view>1 -->
+	    </view>
+  <div class="identity-verify-container" :class="{ 'page-warning': showPageWarning }">
+    <div class="digital-human-container">
+      <!-- 添加题号显示 -->
+     <!--  <div class="question-counter" v-if="currentVideoIndex > 0">
+        <span class="question-number">{{ currentVideoIndex }}/{{ totalQuestions }}</span>
+      </div> -->
+      
+      <!-- AI数字人视频/图像显示区域 -->
+      <div class="digital-human-video">
+        <!-- 添加GIF图片显示区域 -->
+        <!-- <img v-if="showGif && gifUrl" :src="gifUrl" class="gif-player" alt="面试官GIF" /> -->
+        <!-- <video 
+        v-if="showGif && gifUrl"
+						:src="gifUrl"
+						id="mpVideo"
+						autoplay 
+						class="video-player"
+						:controls="false"
+						loop
+						muted
+						object-fit="contain"
+					></video>   v-if="!showGif"-->
+        
+        <!-- 视频播放区域,当showGif为false时显示 -->
+        <video 
+          :src="videoUrl"
+          id="myVideo"
+          ref="videoPlayer" 
+          autoplay 
+          playsinline
+          disablePictureInPicture
+          controlsList="nodownload nofullscreen noremoteplayback"
+          class="video-player"
+          :controls="false"
+          @error="handleVideoError"
+          @ended="handleVideoEnded"
+          @timeupdate="handleTimeUpdate"
+          @click.prevent="preventVideoControl"
+          @touchstart.prevent="preventVideoControl">
+        </video>
+        
+        <!-- 添加透明蒙层 -->
+        <div class="video-overlay"></div>
+        
+        <div class="answer-button-container" v-if="showAnswerButton">
+          <button class="answer-button" @click="handleAnswerButtonClick">
+            开始回答
+          </button>
+        </div>
+        <!-- 添加字幕覆盖层 -->
+        <div class="subtitle-overlay" v-if="currentSubtitle || (showSubtitleText && subtitleText)">
+          <!-- 添加题号显示 -->
+          <div class="subtitle-header" v-if="currentVideoIndex > 0">
+            <span class="question-tag">{{ currentVideoIndex }}/{{ totalQuestions }}</span>
+          </div>
+          <!-- 显示父问题 -->
+          <div class="subtitle-main" v-if="!isFollowUpQuestion">{{ currentSubtitle }}</div>
+          <!-- 当是追问时显示父问题和追问问题 -->
+          <template v-else>
+            <div class="parent-question">{{ parentQuestion }}</div>
+            <div class="followup-container">
+              <div class="followup-content">
+                <span class="followup-label">追问:</span>
+                <span class="followup-text">{{ subtitleText || currentSubtitle }}</span>
+              </div>
+            </div>
+          </template>
+        </div>
+        
+        <!-- 添加答题按钮 -->
+       
+      </div>
+      
+      <!-- 用户摄像头视频显示区域 -->
+      <div class="user-camera-container" :class="{ 'camera-warning': showPageWarning }">
+        <!-- 在小程序环境中使用camera组件 -->
+        <camera v-if="useMiniProgramCameraComponent" 
+                device-position="front" 
+                flash="off" 
+                class="user-camera-video"
+                @error="handleCameraError"
+                :record-audio="true"
+                frame-size="small"
+                resolution="low"
+                :disable-zoom="true"
+                :enable-camera="true"
+                :enable-record="true"
+                mode="normal">
+        </camera>
+        <!-- 在H5/App环境中使用video元素 -->
+        <video v-else
+          id="userCamera"
+          ref="userCameraVideo"
+          autoplay
+          playsinline
+          muted
+          class="user-camera-video"
+          :controls="false">
+        </video>
+      </div>
+      
+      <!-- 字幕/文本覆盖区域 -->
+      <!-- <div class="subtitle-overlay" v-if="assistantResponse">
+        {{ assistantResponse }}
+      </div> -->
+    </div>
+
+    <!-- 加载状态 -->
+    <div v-if="loading" class="loading">加载中...</div>
+    
+    <!-- 控制面板(可选,可以隐藏) -->
+    
+    <!-- 响应数据(可以设为隐藏,仅用于调试) -->
+    <div v-if="showDebugInfo" class="response-container">
+      <div v-if="assistantResponse" class="response-item">
+        <div class="response-content">
+          <span>助手回复: {{ assistantResponse }}</span>
+        </div>
+      </div>
+      <div v-if="audioTranscript" class="response-item">
+        <div class="response-content">
+          <span>音频转写: {{ audioTranscript }}</span>
+        </div>
+      </div>
+      <div v-for="(item, index) in processedResponses" :key="index" class="response-item">
+        <div class="response-content">
+          <span v-if="item.role">角色: {{ item.role }}</span>
+          <span v-if="item.transcript">文本: {{ item.transcript }}</span>
+        </div>
+      </div>
+    </div>
+
+    <!-- 添加停止录制按钮 -->
+    <div class="stop-recording-button-container" v-if="showStopRecordingButton">
+      <button class="stop-recording-button" @click="stopRecordingAnswer">
+        完成作答
+      </button>
+    </div>
+
+    <!-- 添加录制指示器 -->
+    <div class="recording-indicator" v-if="isRecording">
+      <!-- 替换原有的progress组件为自定义环形进度条 -->
+      <div class="circle-progress-container">
+        <div class="circle-progress" :style="{ 
+          background: `conic-gradient(${progressColor} ${progressPercent}%, ${progressBgColor} 0%)` 
+        }">
+          <div class="circle-progress-inner">
+            <span class="progress-text">{{ recordingTimeDisplay }}</span><!--  -->
+          </div>
+        </div>
+      </div>
+     <!--  <span class="timer-text">{{ recordingTimeDisplay || '00:00 / 05:00' }}</span> -->
+    </div>
+
+    <!-- 添加开始回答按钮 -->
+    <div class="start-recording-button-container" v-if="showStartRecordingButton">
+      <button class="start-recording-button" @click="handleStartRecordingClick">
+        开始作答
+      </button>
+    </div>
+
+    <!-- 添加重试上传按钮 -->
+    <div class="retry-button-container" v-if="showRetryButton">
+      <button class="retry-button" @click="retryVideoUpload">
+        重新上传
+      </button>
+    </div>
+
+    <!-- 在模板部分添加录制时长显示 -->
+    <!-- <div class="recording-timer" v-if="isRecording">
+      <span class="timer-text">{{ recordingTimeDisplay || '00:00' }}</span>
+    </div> -->
+
+    <!-- 添加上传状态指示器 -->
+   <!-- <div class="upload-status-indicator" v-if="showUploadStatus && uploadStatusText">
+      <div class="upload-status-content">
+        <div class="upload-status-icon" :class="{'uploading': isUploading}"></div>
+        <span class="upload-status-text">{{ uploadStatusText }}</span>
+      </div>
+    </div> -->
+
+    <!-- 修改录制时长显示 -->
+    <!-- <div class="recording-timer" v-if="isRecording">
+      <span class="timer-text">{{ recordingTimeDisplay || '00:00 / 05:00' }}</span>
+      <span class="remaining-time" :class="{'warning': remainingTime <= 10}">
+        剩余: {{ formatTime(remainingTime) }}
+      </span>
+    </div> -->
+
+    <!-- 在模板部分添加倒计时蒙层 -->
+    <div class="countdown-overlay" v-if="showCountdown">
+      <div class="countdown-content">
+        <div class="countdown-number">{{ countdownValue }}</div>
+        <div class="countdown-text">准备开始回答</div>
+      </div>
+    </div>
+
+    <!-- 添加重新录制按钮 -->
+    <div class="rerecord-button-container" v-if="showRerecordButton">
+      <button class="rerecord-button" @click="handleRerecordButtonClick">
+        重新作答
+      </button>
+    </div>
+  </div>
+</template>
+
+<script>
+import { apiBaseUrl, personDetectionWsUrl } from '@/common/config.js';
+export default {
+  name: 'IdentityVerify',
+      data() {
+      return {
+        followUpQuestion: '', // 追问问题
+        followUpAudioUrl: '', // 追问音频URL
+        audioContext: null, // 音频上下文
+        followUpQuestions: [], // 追问问题列表
+        isWaitingForAnswer: false, // 添加新的状态来控制是否在等待用户回答
+        currentFollowUpIndex: -1, // 当前追问问题索引
+        showSubtitleText: false, // 是否显示字幕
+        subtitleText: '', // 字幕文本
+        parentQuestion: '', // 父问题文本
+        isFollowUpQuestion: false, // 是否是追问问题
+      loading: false,
+      responses: [],
+      processedResponses: [],
+      assistantResponse: '',
+      audioTranscript: '',
+      videoPlaying: false,
+      showDebugInfo: false, // 设置为true可以显示调试信息
+      videoUrl: '', // 修改为空字符串,将通过API获取
+      showReplayButton: false,
+      cameraStream: null, // 存储摄像头流
+      cameraError: null, // 存储摄像头错误信息
+      useMiniProgramCameraComponent: false, // 添加小程序相机组件标志
+      cameraContext: null, // 添加相机上下文
+      currentSubtitle: '',
+      currentTranslation: '', // 添加翻译文本
+      subtitles: [], // 修改为空数组,将通过API获取
+      // 移除硬编码的字幕数组
+      // secondVideoSubtitles: [...],
+      // thirdVideoSubtitles: [...],
+      // 等等...
+      showAnswerButton: false, // 控制答题按钮显示
+      currentVideoIndex: 0, // 当前播放的视频索引
+      videoList: [], // 修改为空数组,将通过API获取
+      // 其他属性保持不变...
+      questions: [], // 添加新属性存储API返回的问题数据
+      introVideoUrl: (() => {
+					const DEFAULT_VIDEO_URL = 'https://data.qicai321.com/minlong/ee4d9cce-c3d5-4350-8c6e-684283827897.mp4';
+					try {
+						const configStr = uni.getStorageSync('configData');
+						if (!configStr) return DEFAULT_VIDEO_URL;
+						
+						const config = JSON.parse(configStr);
+						return config.digital_human_opening_video_url || DEFAULT_VIDEO_URL;
+					} catch (error) {
+						console.warn('解析配置数据失败:', error);
+						return DEFAULT_VIDEO_URL;
+					}
+				})(),//'https://data.qicai321.com/minlong/ee4d9cce-c3d5-4350-8c6e-684283827897.mp4', // 保留介绍视频
+      isRecording: false,
+      recordingTimer: null,
+      showStopRecordingButton: false,
+      mediaRecorder: null,
+      recordedChunks: [],
+      recorder: null,
+      lastUploadedVideoUrl: '',
+      showStartRecordingButton: false,
+      showRetryButton: false, // 控制重试按钮显示
+      lastVideoToRetry: null, // 存储上次失败的视频URL,用于重试
+      recordingStartTime: null, // 录制开始时间
+      recordingTimerCount: 0, // 录制计时器计数
+      recordingTimeDisplay: '00:00', // 格式化的录制时间显示
+      
+      // 添加上传队列相关数据
+      uploadQueue: [], // 存储待上传的视频
+      backgroundUploadQueue: [], // 存储后台上传的视频
+      isUploading: false, // 标记是否正在上传
+      uploadProgress: {}, // 存储每个视频的上传进度
+      uploadStatus: {}, // 存储每个视频的上传状态
+      showUploadStatus: false, // 是否显示上传状态指示器
+      uploadStatusText: '', // 上传状态文本
+      mediaRecorderTimeout: null, // 用于存储MediaRecorder的超时机制
+      maxRecordingTime: 300, // 最大录制时间(秒)- 从60秒改为300秒(5分钟)
+      remainingTime: 300,    // 剩余录制时间(秒)- 从60秒改为300秒
+      countdownValue: 10, // 倒计时数值
+      showCountdown: false, // 是否显示倒计时蒙层
+      countdownTimer: null,
+      showGif: false, // 控制是否显示GIF
+      gifUrl: '', // GIF图片的URL
+      globalSocketTask: null, // 添加全局 WebSocket 连接对象
+      lowScoreVideoUrl: (() => {
+					const DEFAULT_VIDEO_URL = 'https://data.qicai321.com/minlong/latentsync/0530e7f5-1957-422d-8f34-ba4a92608081_result.mp4';
+					try {
+						const configStr = uni.getStorageSync('configData');
+						if (!configStr) return DEFAULT_VIDEO_URL;
+						
+						const config = JSON.parse(configStr);
+						return config.digital_human?.middle_video_url || DEFAULT_VIDEO_URL;
+					} catch (error) {
+						console.warn('解析配置数据失败:', error);
+						return DEFAULT_VIDEO_URL;
+					}
+				})(),//'https://data.qicai321.com/minlong/latentsync/0530e7f5-1957-422d-8f34-ba4a92608081_result.mp4', // 低分提示视频URL
+      showRerecordButton: false, // 控制重新录制按钮显示
+      isPlayingLowScoreVideo: false, // 标记是否正在播放低分提示视频
+      lowScoreVideoSubtitles: [
+        {
+          startTime: 0,
+          endTime: 10, // 假设视频长度为10秒,可根据实际情况调整
+          text: '我未听清楚您在说什么,请您再说一遍!'
+        }
+      ], // 用于存储低分提示视频的字幕
+      retryCount: 0, // 添加重试次数计数器
+      maxRetryAttempts: 2, // 最大重试次数限制
+      needPlayLowScoreVideo: false, // 是否需要播放低分视频
+      finalRecordingDuration: 0, // 最终录制时长
+      historyTime: 0, // 添加历史时间记录
+      followUpQuestions: [], // 存储追问问题数据
+      currentParentQuestionId: null, // 当前父问题ID
+      hasPlayedFollowUp: {}, // 记录已播放的追问,格式: {questionId: true}
+      isFollowUpQuestion: false, // 标记当前是否正在播放追问问题
+      currentFollowUpQuestion: null, // 添加当前追问问题的完整信息
+      lastQuestionWasFollowUp: false,
+      lastFollowUpQuestionId: null,
+      // 追问次数控制
+      defaultFollowUpLimit: 1, // 默认每个主题目最多2次追问
+      followUpLimitMap: {}, // { parentJobPositionQuestionId: limit }
+      followUpAskedCountMap: {}, // { parentJobPositionQuestionId: askedCount }
+      followUpRequestInFlight: {}, // { parentJobPositionQuestionId: boolean }
+      lastUpdateTime: Date.now(), // 添加最后更新时间戳
+      subtitleMap: {}, // 用于存储字幕和翻译的映射
+      progressPercent: 0, // 录制进度百分比
+      progressColor: '#05dc8b', // 进度条颜色
+      progressBgColor: 'rgba(0, 0, 0,0.3)', // 进度条背景色
+      parentQuestion: '', // 添加父问题存储
+      screenCaptureCount: 0, // 添加截屏次数记录
+      personDetectionSocket: null, // WebSocket对象
+      personDetectionInterval: null, // 定时器对象
+      showCameraWarning: false, // 添加新的数据属性
+      showPageWarning: false, // 添加新的数据属性
+      followUpQuestion: '', // 追问问题
+      followUpAudioUrl: '', // 追问音频URL
+      audioContext: null, // 音频上下文
+      followUpQuestions: [], // 追问问题列表
+      currentFollowUpIndex: -1, // 当前追问问题索引
+      showSubtitleText: false, // 是否显示字幕
+      subtitleText: '', // 字幕文本
+      isAudioPlaying: false,
+      isWaitingForAnswer: false, // 添加新的状态来控制是否在等待用户回答
+      currentRecordingDuration: 0, // 添加当前录制时长
+      parentJobPositionQuestionId: null, // 添加父问题的job_position_question_id
+      isFollowUpMode: false, // 是否处于追问模式
+      mainQuestionIndex: 0, // 当前主问题的索引
+      isVideoSwitching: false, // 添加视频切换状态锁
+      originalQuestionSubtitle: null, // 保存原始字幕信息
+      isThinking: false, // 面试官思考中状态
+      thinkingTimer: null, // 思考计时器
+      questionRetryMap: {}, // 用于跟踪每个问题的重试次数
+      maxQuestionRetries: 2, // 每个问题最大重试次数
+	    statusBarHeight: 0
+    }
+  },
+   onLoad() {
+      // 获取状态栏高度
+      this.statusBarHeight = uni.getSystemInfoSync().statusBarHeight || 0
+    },
+  mounted() {
+    this.fetchQuestions();
+    //this.fetchFollowUpQuestions();
+    this.checkAudioPermission();
+    this.initCamera();
+    this.checkIOSCameraRecordPermission();
+    this.checkAndFixRenderingIssues();
+    setTimeout(() => {
+      if (this.cameraStream && !this.useMiniProgramCameraComponent) {
+        this.testAudioInput();
+      }
+    }, 3e3);
+    this.historyTime = 0;
+    uni.setKeepScreenOn({
+      keepScreenOn: true
+    });
+
+    // 添加截屏监听
+    uni.onUserCaptureScreen(() => {
+      console.log('User captured screen');
+      this.screenCaptureCount++;
+      
+      if (this.screenCaptureCount === 1) {
+        uni.showModal({
+          title: 'Warning',
+          content: '检测到屏幕截图。如果你再次捕捉屏幕,你的面试将无效.',
+          showCancel: false,
+          confirmText: 'OK'
+        });
+      } else if (this.screenCaptureCount >= 2) {
+        uni.showModal({
+          title: 'Interview Invalid',
+          content: '由于多次屏幕截图,您的面试已无效。请联系招聘人员寻求帮助.',
+          showCancel: false,
+          confirmText: 'OK',
+          success: () => {
+            this.invalidateInterview();
+          }
+        });
+      }
+    });
+
+    const systemInfo = uni.getSystemInfoSync();
+    const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith('mp-');
+    console.log('isMiniProgram', isMiniProgram);
+    if (isMiniProgram) {
+      this.initPersonDetectionWebSocket();
+    }
+  },
+  beforeDestroy() {
+    // 移除截屏监听
+    uni.offUserCaptureScreen();
+    this.cleanupPersonDetectionWebSocket();
+  },
+      methods: {
+      // ===== 追问次数控制:工具方法 =====
+      getFollowUpLimit(parentId) {
+        if (!parentId) return this.defaultFollowUpLimit;
+        return this.followUpLimitMap[parentId] || this.defaultFollowUpLimit;
+      },
+      setFollowUpLimit(parentId, limit) {
+        if (!parentId) return;
+        const parsed = parseInt(limit);
+        this.followUpLimitMap[parentId] = Number.isFinite(parsed) && parsed > 0 ? parsed : this.defaultFollowUpLimit;
+      },
+      resetFollowUpAskedCount(parentId) {
+        if (!parentId) return;
+        this.followUpAskedCountMap[parentId] = 0;
+      },
+      incrementFollowUpCount(parentId) {
+        if (!parentId) return;
+        const current = this.followUpAskedCountMap[parentId] || 0;
+        this.followUpAskedCountMap[parentId] = current + 1;
+      },
+      canAskMoreFollowUps(parentId) {
+        if (!parentId) return false;
+        const asked = this.followUpAskedCountMap[parentId] || 0;
+        const limit = this.getFollowUpLimit(parentId);
+        return asked < limit;
+      },
+      async maybeRequestNextFollowUp(parentId) {
+        if (!parentId) {
+          this.proceedToNextQuestion();
+          return;
+        }
+        if (this.canAskMoreFollowUps(parentId)) {
+          // 避免重复触发并发请求
+          if (this.followUpRequestInFlight[parentId]) {
+            console.log('已有追问请求进行中,跳过重复触发');
+            return;
+          }
+          // 交由 callInterviewInteraction 统一处理并发标记
+          const ok = await this.callInterviewInteraction(parentId);
+          if (!ok) {
+            console.log('未获取到下一条追问或调用失败,进入下一题');
+            this.isFollowUpMode = false;
+            this.isFollowUpQuestion = false;
+            this.currentFollowUpQuestion = null;
+            this.proceedToNextQuestion();
+          }
+        } else {
+          // 已达上限,进入下一题
+          this.isFollowUpMode = false;
+          this.isFollowUpQuestion = false;
+          this.currentFollowUpQuestion = null;
+          this.proceedToNextQuestion();
+        }
+      },
+      // 处理音频播放完成
+      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);
+        this.enterFollowUpMode();
+        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, retryCount = 0, maxRetries = 3) {
+        // 防重入:同一父问题并发保护
+        if (questionId && this.followUpRequestInFlight[questionId]) {
+          console.log('追问请求已在进行中,跳过本次调用');
+          return false;
+        }
+        if (questionId) {
+          this.followUpRequestInFlight[questionId] = true;
+        }
+        const userInfo = JSON.parse(uni.getStorageSync('userInfo'));
+        const appId = uni.getStorageSync('appId');
+        const positionConfigId = JSON.parse(uni.getStorageSync('configData')).id;
+        
+        try {
+          // 显示思考中loading
+          this.showThinkingLoading();
+          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: positionConfigId,
+              application_id: appId
+            },
+            header: {
+              'content-type': 'application/json'
+            }
+          });
+          console.log('面试互动接口返回数据:', res);
+          
+          // 处理4000状态码(视频未转写完成)的情况
+          if (res.statusCode === 400) {
+            if (retryCount < maxRetries) {
+              console.log(`视频转写未完成,${retryCount + 1}次重试中...`);
+              // 等待3秒后重试
+              await new Promise(resolve => setTimeout(resolve, 3000));
+              return this.callInterviewInteraction(questionId, retryCount + 1, maxRetries);
+            } else {
+              console.log('达到最大重试次数,视频转写仍未完成');
+              uni.showToast({
+                title: '视频转写处理中,请稍后再试',
+                icon: 'none',
+                duration: 2000
+              });
+              return false;
+            }
+          }
+          
+          if (res.data.success) {
+            // 成功获取到一条追问,计数 +1(表示“已请求”这条追问)
+            if (questionId) {
+              this.incrementFollowUpCount(questionId);
+            }
+            // 处理本次追问(即便已达到上限,也应该播放本次追问)
+            await this.handleFollowUpQuestion(res.data);
+            this.hideThinkingLoading();
+            return true;
+          } else {
+            console.error('面试互动接口返回错误:', res.data);
+            this.hideThinkingLoading();
+            return false;
+          }
+        } catch (error) {
+          console.error('调用面试互动接口失败:', error);
+          this.hideThinkingLoading();
+          return false;
+        } finally {
+          if (questionId) {
+            this.followUpRequestInFlight[questionId] = false;
+          }
+        }
+      },
+      
+      // 播放追问音频
+      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() {
+      // 检查平台
+      const systemInfo = uni.getSystemInfoSync();
+      
+      // 判断是否在小程序环境中
+      const isMiniProgram = systemInfo.uniPlatform === 'mp-weixin' || 
+                            systemInfo.uniPlatform === 'mp-alipay' || 
+                            systemInfo.uniPlatform === 'mp-baidu';
+      
+      if (isMiniProgram) {
+        // 小程序环境使用小程序的相机API
+        this.useMiniProgramCameraComponent = true;
+        
+        // 创建相机上下文
+        this.cameraContext = uni.createCameraContext();
+        
+        // 确保已获取录音和相机权限
+        uni.getSetting({
+          success: (res) => {
+            // 检查录音权限
+            if (!res.authSetting['scope.record']) {
+              uni.authorize({
+                scope: 'scope.record',
+                success: () => {
+                  console.log('录音权限已获取');
+                },
+                fail: (err) => {
+                  console.error('录音权限获取失败:', err);
+                  this.showPermissionDialog('录音');
+                }
+              });
+            }
+            
+            // 检查相机权限
+            if (!res.authSetting['scope.camera']) {
+              uni.authorize({
+                scope: 'scope.camera',
+                success: () => {
+                  console.log('相机权限已获取');
+                },
+                fail: (err) => {
+                  console.error('相机权限获取失败:', err);
+                  this.showPermissionDialog('相机');
+                }
+              });
+            }
+            
+            // 在iOS上,可能需要额外的权限检查
+            const systemInfo = uni.getSystemInfoSync();
+            if (systemInfo.platform === 'ios') {
+              // 在iOS上,不要使用无效的权限范围
+              // 移除以下代码块
+              /*
+              if (!res.authSetting['scope.camera.record']) {
+                uni.authorize({
+                  scope: 'scope.camera.record',
+                  success: () => {
+                    console.log('相机录制权限已获取');
+                  },
+                  fail: (err) => {
+                    console.error('相机录制权限获取失败:', err);
+                    this.showPermissionDialog('相机录制');
+                  }
+                });
+              }
+              */
+              
+              // 确保同时获取了相机和录音权限
+              if (!res.authSetting['scope.camera'] || !res.authSetting['scope.record']) {
+                console.log('iOS需要同时获取相机和录音权限');
+              }
+            }
+          }
+        });
+      } else {
+        // H5/App环境使用浏览器的API
+        try {
+          // 请求摄像头和麦克风权限并获取媒体流,添加更多约束
+          const constraints = {
+            audio: {
+              echoCancellation: true,
+              noiseSuppression: true,
+              autoGainControl: true
+            },
+            video: {
+              width: { ideal: 640, max: 1280 }, // 控制视频宽度
+              height: { ideal: 480, max: 720 }, // 控制视频高度
+              frameRate: { ideal: 15, max: 24 }, // 控制帧率
+              facingMode: 'user'
+            }
+          };
+          
+          const stream = await navigator.mediaDevices.getUserMedia(constraints);
+          
+          // 保存流以便后续使用
+          this.cameraStream = stream;
+          
+          // 检查音频轨道
+          const audioTracks = stream.getAudioTracks();
+          console.log('音频轨道数量:', audioTracks.length);
+          if (audioTracks.length > 0) {
+            console.log('音频轨道已获取:', audioTracks[0].label);
+            // 确保音频轨道已启用
+            audioTracks[0].enabled = true;
+          } else {
+            console.warn('未检测到音频轨道,尝试单独获取音频');
+            this.tryGetAudioOnly();
+          }
+          
+          // 将流设置到视频元素
+          const videoElement = this.$refs.userCameraVideo;
+          if (videoElement) {
+            videoElement.srcObject = stream;
+            videoElement.muted = true; // 避免回声,但仍然录制声音
+          }
+        } catch (error) {
+          console.error('获取摄像头失败:', error);
+          this.cameraError = error.message || '无法访问摄像头';
+          
+          // 显示错误提示
+          uni.showToast({
+            title: '无法访问摄像头,请检查权限设置',
+            icon: 'none'
+          });
+        }
+      }
+    },
+    
+    // 停止用户摄像头
+    stopUserCamera() {
+      if (this.cameraStream) {
+        // 停止所有轨道
+        this.cameraStream.getTracks().forEach(track => {
+          track.stop();
+        });
+        this.cameraStream = null;
+      }
+    },
+    
+    async fetchData() {
+      this.loading = true
+      this.assistantResponse = ''
+      this.audioTranscript = ''
+      this.processedResponses = []
+      
+      // 显示加载提示
+      uni.showLoading({
+        title: '面试官思考中...',
+        mask: true  // 添加遮罩,防止用户触摸界面
+      })
+      
+      try {
+        // 使用uni.request代替fetch
+        const requestTask = uni.request({
+          url: 'https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions',
+          method: 'POST',
+          header: {
+            'Content-Type': 'application/json',
+            'Authorization': 'Bearer sk-9e1ec73a7d97493b8613c63f06b6110c'
+          },
+          data: {
+            "model": "qwen-omni-turbo",
+            "messages":  [
+              {
+                "role": "user",
+                "content": [
+                  {
+                    "type": "input_audio",
+                    "input_audio": {
+                      "data": "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20250211/tixcef/cherry.wav",
+                      "format": "wav"
+                    }
+                  },
+                  {
+                    "type": "text",
+                    "text": "这段音频在说什么"
+                  }
+                ]
+              }
+            ],
+            "stream":true,
+            "stream_options":{
+                "include_usage":true
+            },
+            "modalities":["text","audio"],
+            "audio":{"voice":"Cherry","format":"wav"}
+          },
+          success: (res) => {
+            console.log('请求成功,响应数据:', res.data);
+            // 检查响应数据是否包含多个JSON对象
+            if (typeof res.data === 'string' && res.data.includes('data: {')) {
+              // 处理包含多个JSON对象的情况
+              const chunks = res.data.split('data: ').filter(chunk => chunk.trim() !== '');
+              chunks.forEach(chunk => {
+                this.handleStreamResponse(chunk);
+              });
+            } else {
+              // 处理单个响应对象的情况
+              this.handleStreamResponse(res.data);
+            }
+            
+            // 模拟获取到数字人视频并播放
+            this.playDigitalHumanVideo();
+          },
+          fail: (err) => {
+            console.error('请求失败:', err);
+            uni.showToast({
+              title: '请求失败,请重试',
+              icon: 'none'
+            });
+          },
+          complete: () => {
+            this.loading = false;
+            // 隐藏加载提示
+            uni.hideLoading();
+          }
+        });
+      } catch (error) {
+        console.error('获取数据失败:', error);
+        this.loading = false;
+        // 隐藏加载提示
+        uni.hideLoading();
+        uni.showToast({
+          title: '系统错误,请重试',
+          icon: 'none'
+        });
+      }
+    },
+    
+    handleStreamResponse(data) {
+      // 处理流式响应数据
+      if (typeof data === 'string') {
+        // 处理字符串格式的响应
+        if (data === '[DONE]') return;
+        
+        try {
+          // 移除可能存在的换行符和多余空格
+          const cleanData = data.trim();
+          // 检查是否是有效的JSON字符串
+          if (cleanData.startsWith('{') && cleanData.endsWith('}')) {
+            const jsonData = JSON.parse(cleanData);
+            this.processStreamChunk(jsonData);
+          }
+        } catch (e) {
+          console.error('解析JSON失败:', e, '原始数据:', data);
+        }
+      } else {
+        // 处理对象格式的响应
+        this.processStreamChunk(data);
+      }
+    },
+    
+    processStreamChunk(chunk) {
+      if (chunk.choices && chunk.choices.length > 0) {
+        const choice = chunk.choices[0];
+        
+        // 处理助手回复内容
+        if (choice.delta && choice.delta.content) {
+          this.assistantResponse += choice.delta.content;
+        }
+        
+        // 处理音频转写内容
+        if (choice.delta && choice.delta.audio && choice.delta.audio.transcript) {
+          this.audioTranscript += choice.delta.audio.transcript;
+        }
+        
+        // 处理角色和音频转写
+        if (choice.delta) {
+          const result = {};
+          
+          if (choice.delta.role) {
+            result.role = choice.delta.role;
+          }
+          
+          if (choice.delta.audio && choice.delta.audio.transcript) {
+            result.transcript = choice.delta.audio.transcript;
+          }
+          
+          if (Object.keys(result).length > 0) {
+            this.processedResponses.push(result);
+          }
+        }
+      }
+    },
+    
+    processResponseData() {
+      // 处理返回的数据
+      this.processedResponses = this.responses.map(item => {
+        const result = {}
+        
+        // 处理角色信息
+        if (item.delta && item.delta.role) {
+          result.role = item.delta.role
+        }
+        
+        // 处理音频转写文本
+        if (item.delta && item.delta.audio && item.delta.audio.transcript) {
+          result.transcript = item.delta.audio.transcript
+        }
+        
+        return result
+      }).filter(item => Object.keys(item).length > 0)
+    },
+    
+    // 播放数字人视频
+    playDigitalHumanVideo() {
+      // 如果还没有加载问题数据,先获取问题数据
+      if (this.videoList.length === 0) {
+        this.fetchQuestions();
+        return;
+      }
+      
+      // 设置当前视频
+      this.videoUrl = this.videoList[this.currentVideoIndex];
+      this.videoPlaying = true;
+      
+      // 使用 uni.createVideoContext 来控制视频
+      this.$nextTick(() => {
+        const videoContext = uni.createVideoContext('myVideo', this);
+        if (videoContext) {
+          videoContext.play();
+          
+          // 设置超时检查,确认视频是否真的在播放
+          setTimeout(() => {
+            if (this.videoPlaying && this.$refs.videoPlayer) {
+              console.log('视频应该正在播放');
+            } else {
+              console.log('视频可能未成功播放,尝试替代方案');
+              this.tryAlternativeVideoPath();
+            }
+          }, 1000);
+        } else {
+          console.error('无法创建视频上下文');
+          this.tryAlternativeVideoPath();
+        }
+      });
+    },
+    
+    // 修改 tryAlternativeVideoPath 方法
+    tryAlternativeVideoPath() {
+      console.log('尝试使用替代路径');
+      
+      // 尝试不同的路径格式
+      const alternativePaths = [
+        './static/demo.mp4',
+        '../static/demo.mp4',
+        'static/demo.mp4',
+        '/static/demo.mp4',
+        // 添加绝对路径
+        `${window.location.origin}/static/demo.mp4`
+      ];
+      
+      // 获取当前路径索引
+      const currentPathIndex = alternativePaths.indexOf(this.videoUrl);
+      const nextPathIndex = (currentPathIndex + 1) % alternativePaths.length;
+      
+      // 设置下一个路径
+      this.videoUrl = alternativePaths[nextPathIndex];
+      console.log('尝试新路径:', this.videoUrl);
+      
+      this.$nextTick(() => {
+        const videoContext = uni.createVideoContext('myVideo', this);
+        if (videoContext) {
+          videoContext.stop();
+          videoContext.play();
+          
+          // 检查是否成功播放
+          setTimeout(() => {
+            if (nextPathIndex === alternativePaths.length - 1 && !this.videoPlaying) {
+              console.log('所有路径均失败,尝试使用uni.getVideoInfo检查视频');
+              this.checkVideoWithAPI();
+            }
+          }, 1000);
+        }
+      });
+    },
+    
+    // 添加新方法:使用uni API检查视频
+    checkVideoWithAPI() {
+      // 尝试使用uni.getVideoInfo API检查视频是否可用
+      uni.getVideoInfo({
+        src: '/static/demo.mp4',
+        success: (res) => {
+          console.log('视频信息获取成功:', res);
+          // 如果能获取到视频信息,再次尝试播放
+          this.videoUrl = '/static/demo.mp4';
+          this.$nextTick(() => {
+            const videoContext = uni.createVideoContext('myVideo', this);
+            if (videoContext) {
+              videoContext.play();
+            }
+          });
+        },
+        fail: (err) => {
+          console.error('视频信息获取失败:', err);
+          // 最后尝试使用uni.chooseVideo API
+          this.fallbackToLocalVideo();
+        }
+      });
+    },
+    
+    // 添加新方法:回退到本地视频
+    fallbackToLocalVideo() {
+      console.log('尝试使用本地视频资源');
+      
+      // 检查平台
+      const platform = uni.getSystemInfoSync().platform;
+      if (platform === 'android' || platform === 'ios') {
+        // 移动端可以尝试使用本地资源
+        this.videoUrl = platform === 'android' ? 'android.resource://package_name/raw/demo' : 'file:///assets/demo.mp4';
+        this.$nextTick(() => {
+          const videoContext = uni.createVideoContext('myVideo', this);
+          if (videoContext) {
+            videoContext.play();
+          }
+        });
+      } else {
+        // 最终回退到静态图片
+        this.videoPlaying = false;
+        uni.showToast({
+          title: '视频加载失败,显示静态图片',
+          icon: 'none'
+        });
+      }
+    },
+    
+    // 修改 handleVideoError 方法
+    handleVideoError(e) {
+      console.error('视频加载错误:', e);
+      
+      // 记录更详细的错误信息
+      if (e && e.detail) {
+        console.error('详细错误信息:', e.detail);
+      }
+      
+      // 检查视频文件是否存在
+      uni.getFileInfo({
+        filePath: this.videoUrl.startsWith('/') ? this.videoUrl.substring(1) : this.videoUrl,
+        success: (res) => {
+          console.log('文件存在,大小:', res.size);
+          // 文件存在但播放失败,可能是格式问题
+          this.tryDifferentFormat();
+        },
+        fail: (err) => {
+          console.error('文件不存在或无法访问:', err);
+          // 尝试不同路径
+          this.tryAlternativeVideoPath();
+        }
+      });
+      
+      // 如果多次尝试后仍然失败,显示错误信息
+      uni.showToast({
+        title: '视频加载失败,请检查文件是否存在',
+        icon: 'none',
+        duration: 2000
+      });
+    },
+
+    // 添加新方法:尝试不同格式
+    tryDifferentFormat() {
+      console.log('尝试不同的视频格式');
+      
+      // 尝试不同的视频格式
+      const formats = [
+        { ext: 'mp4', mime: 'video/mp4' },
+        { ext: 'webm', mime: 'video/webm' },
+        { ext: 'ogg', mime: 'video/ogg' },
+        { ext: 'mov', mime: 'video/quicktime' }
+      ];
+      
+      // 获取当前文件名(不含扩展名)
+      const currentPath = this.videoUrl;
+      const basePath = currentPath.substring(0, currentPath.lastIndexOf('.')) || '/static/demo';
+      
+      // 尝试下一个格式
+      let nextFormat = formats.find(f => !currentPath.endsWith(f.ext));
+      if (nextFormat) {
+        this.videoUrl = `${basePath}.${nextFormat.ext}`;
+        console.log('尝试新格式:', this.videoUrl);
+        
+        this.$nextTick(() => {
+          const videoContext = uni.createVideoContext('myVideo', this);
+          if (videoContext) {
+            videoContext.stop();
+            videoContext.play();
+          }
+        });
+      } else {
+        // 所有格式都尝试过了,使用内置资源
+        this.useBuiltInResource();
+      }
+    },
+
+    // 添加新方法:使用内置资源
+    useBuiltInResource() {
+      console.log('尝试使用内置资源');
+      
+      // 检查平台
+      const platform = uni.getSystemInfoSync().platform;
+      
+      // 根据平台选择合适的视频源
+      if (platform === 'windows') {
+        // Windows平台特定处理
+        // 尝试使用相对于应用根目录的路径
+        const appRoot = process.env.UNI_INPUT_DIR || '';
+        this.videoUrl = `./static/demo.mp4`;
+        
+        // 或者尝试使用file://协议
+        // this.videoUrl = `file:///${appRoot.replace(/\\/g, '/')}/static/demo.mp4`;
+        
+        console.log('Windows平台尝试路径:', this.videoUrl);
+      } else if (platform === 'android' || platform === 'ios') {
+        // 移动端
+        this.useNativeVideo();
+      } else {
+        // Web平台
+        // 尝试使用完整URL
+        const baseUrl = window.location.origin;
+        this.videoUrl = `${baseUrl}/static/demo.mp4`;
+        console.log('Web平台尝试URL:', this.videoUrl);
+      }
+      
+      this.$nextTick(() => {
+        const videoContext = uni.createVideoContext('myVideo', this);
+        if (videoContext) {
+          videoContext.play();
+        }
+      });
+    },
+
+    // 添加新方法:使用原生视频能力
+    useNativeVideo() {
+      console.log('尝试使用原生视频能力');
+      
+      // 在移动端,可以尝试使用原生视频播放器
+      uni.chooseVideo({
+        sourceType: ['album'],
+        success: (res) => {
+          this.videoUrl = res.tempFilePath;
+          this.$nextTick(() => {
+            const videoContext = uni.createVideoContext('myVideo', this);
+            if (videoContext) {
+              videoContext.play();
+            }
+          });
+        },
+        fail: () => {
+          // 如果用户取消选择,回退到静态图片
+          this.videoPlaying = false;
+          /* uni.showToast({
+            title: '无法加载视频,显示静态图片',
+            icon: 'none'
+          }); */
+        }
+      });
+    },
+
+    // 处理视频结束事件
+    handleVideoEnded() {
+      console.log('视频播放结束事件触发');
+      
+      // 获取视频元素和当前时间
+      const videoElement = this.$refs.videoPlayer;
+      if (videoElement) {
+        const currentTime = videoElement.currentTime || 0;
+        const duration = videoElement.duration || 0;
+        
+        // 更严格的检查:只有当前时间非常接近视频总时长时才认为是真正结束
+        if (duration > 0 && (duration - currentTime > 0.5)) {
+          console.log('检测到可能的误触发结束事件,继续播放', currentTime, duration);
+          // 继续播放视频
+          setTimeout(() => {
+            const videoContext = uni.createVideoContext('myVideo', this);
+            if (videoContext) {
+              // 如果距离结束还很远,回到历史位置
+              if (duration - currentTime > 2) {
+                videoContext.seek(this.historyTime || 0);
+              } else {
+                // 如果接近结束但还没完全结束,继续播放
+                videoContext.play();
+              }
+            }
+          }, 100);
+          return;
+        }
+        
+        console.log('视频确认结束,当前时间:', currentTime, '总时长:', duration);
+      }
+      
+      this.videoPlaying = false;
+      
+      // 检查是否是低分提示视频
+      if (this.isPlayingLowScoreVideo) {
+        console.log('低分提示视频播放完成');
+        
+        // 检查重试次数
+        if (this.retryCount < this.maxRetryAttempts) {
+          console.log(`显示重新录制按钮 (重试次数: ${this.retryCount + 1}/${this.maxRetryAttempts})`);
+          
+          // 显示重新录制按钮
+          this.showRerecordButton = true;
+          
+          // 恢复原始问题的字幕
+          if (this.isFollowUpQuestion && this.currentFollowUpQuestion) {
+            this.currentSubtitle = this.currentFollowUpQuestion.question || this.currentFollowUpQuestion.question;
+          } else if (this.originalQuestionSubtitle) {
+            this.currentSubtitle = this.originalQuestionSubtitle;
+          }
+        } else {
+          console.log('已达到最大重试次数,继续下一题');
+          
+          // 重置重试次数
+          this.retryCount = 0;
+          
+          // 继续下一个问题
+          this.proceedToNextQuestion();
+        }
+        
+        // 重置标记
+        this.isPlayingLowScoreVideo = false;
+        this.originalQuestionSubtitle = null;
+        
+        return;
+      }
+      
+      // 检查是否是追问问题视频
+      if (this.isFollowUpQuestion) {
+        console.log('追问问题视频播放完成');
+        
+        // 不重置追问状态,保持显示
+        // this.isFollowUpQuestion = false;
+        // this.currentFollowUpQuestion = null;
+        
+        // 显示"开始回答"按钮,准备回答追问
+        this.showStartRecordingButton = true;
+        this.startCountdown();
+        
+        return;
+      }
+      
+      // 恢复原有的视频结束处理逻辑
+      // 对于所有视频,都显示相应的按钮
+      if (this.currentVideoIndex >= 1) {
+        // 对于问题视频,显示"开始回答"按钮
+        this.showStartRecordingButton = true;
+        this.startCountdown();
+      } else {
+        // 对于介绍视频(第一个视频),显示"开始面试"按钮
+        this.showAnswerButton = true;
+      }
+      
+      // 重置追问状态
+      if (this.isFollowUpQuestion) {
+        this.isFollowUpQuestion = false;
+        this.currentFollowUpQuestion = null;
+      }
+    },
+    
+    // 添加新方法:开始倒计时
+    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);
+    },
+
+    // 添加新方法:清除倒计时
+    clearCountdown() {
+      if (this.countdownTimer) {
+        clearInterval(this.countdownTimer);
+        this.countdownTimer = null;
+      }
+      this.showCountdown = false;
+    },
+
+    // 修改 handleStartRecordingClick 方法,使其可以终止倒计时
+    handleStartRecordingClick() {
+      // 隐藏"开始回答"按钮
+      this.showStartRecordingButton = false;
+      
+      // 如果倒计时正在进行,清除倒计时
+      this.clearCountdown();
+      
+      // 重置等待回答状态
+      this.isWaitingForAnswer = false;
+      
+      // 直接开始录制
+      this.startRecordingAnswer();
+    },
+
+    // 修改 stopRecordingAnswer 方法,添加录制时长检查
+    stopRecordingAnswer() {
+      // 如果倒计时正在进行,先清除倒计时
+      this.clearCountdown();
+      
+      // 重置等待回答状态
+      this.isWaitingForAnswer = false;
+      
+      // 检查录制时长
+      const recordingDuration = this.getRecordingDuration();
+      const minimumDuration = 3; // 最小录制时长(秒),改为3秒
+      const lowScoreDuration = 7; // 低分阈值时长(秒),少于7秒视为低分
+      
+      // 保存录制时长,用于上传
+      this.currentRecordingDuration = recordingDuration;
+      
+      if (recordingDuration < minimumDuration) {
+        // 录制时间过短,显示提示
+        uni.showToast({
+          title: '录制时间过短,请至少录制3秒',
+          icon: 'none',
+          duration: 2000
+        });
+        // 不执行停止录制逻辑,继续录制
+        return;
+      }
+      
+      // 检查是否需要播放低分视频(录制时间少于7秒)
+      if (recordingDuration < lowScoreDuration) {
+        console.log(`录制时间 ${recordingDuration} 秒,少于 ${lowScoreDuration} 秒,将播放低分提示视频`);
+        // 停止录制但不上传
+        this.completeRecordingStop(false);
+        // 直接播放低分视频
+        this.playLowScoreVideo();
+      } else {
+        // 录制时长足够,正常停止录制并上传
+        this.completeRecordingStop(true);
+        this.needPlayLowScoreVideo = false;
+        this.recordingTimeDisplay='00:00'
+      }
+    },
+
+    // 添加新方法:开始录制用户回答
+    startRecordingAnswer() {
+      console.log('开始录制用户回答');
+      this.isRecording = true;
+      
+      // 记录录制开始时间
+      this.recordingStartTime = Date.now();
+      this.recordingTimerCount = 0;
+      
+      // 获取当前问题的推荐录制时长
+      this.maxRecordingTime = this.getCurrentQuestionRecommendedDuration();
+      this.remainingTime = this.maxRecordingTime;
+      
+      // 启动计时器,每秒更新计时
+      this.recordingTimer = setInterval(() => {
+        this.recordingTimerCount++;
+        this.remainingTime = Math.max(0, this.maxRecordingTime - this.recordingTimerCount);
+        
+        // 更新UI显示录制时长和剩余时间
+        this.recordingTimeDisplay = this.formatTime(this.recordingTimerCount)/*  + 
+                                   ' / ' + this.formatTime(this.maxRecordingTime) */;
+        
+        // 更新进度百分比 - 确保值在0-100之间
+        this.progressPercent = Math.min((this.recordingTimerCount / this.maxRecordingTime) * 100, 100);
+        
+        // 检查是否达到最大录制时间
+        if (this.recordingTimerCount >= this.maxRecordingTime) {
+          console.log(`已达到最大录制时间(${this.maxRecordingTime}秒),自动停止录制`);
+          this.stopRecordingAnswer();
+        }
+      }, 1000);
+      
+      // 显示录制中的提示
+      // uni.showLoading({
+      //   title: '正在录制...',
+      //   mask: true
+      // });
+      
+      // 根据平台选择不同的录制方法
+      const systemInfo = uni.getSystemInfoSync();
+      const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith('mp-');
+      
+      if (isMiniProgram) {
+        // 小程序环境使用小程序的录制API
+        this.startMiniProgramRecording();
+      } else {
+        // H5/App环境使用MediaRecorder API
+        this.startBrowserRecording();
+      }
+      
+      // 显示停止录制按钮
+      this.showStopRecordingButton = true;
+    },
+
+    // 添加一个新方法:重置相机组件
+    resetCamera() {
+      console.log('重置相机组件');
+      
+      // 先完全移除相机组件
+      this.useMiniProgramCameraComponent = false;
+      
+      // 释放相机上下文
+      if (this.cameraContext) {
+        this.cameraContext = null;
+      }
+      
+      // 延迟后重新创建相机组件
+      setTimeout(() => {
+        this.useMiniProgramCameraComponent = true;
+        
+        // 再次延迟创建相机上下文,确保组件已完全渲染
+        setTimeout(() => {
+          this.cameraContext = uni.createCameraContext();
+          console.log('相机组件已重置');
+        }, 500);
+      }, 500);
+    },
+
+    // 修改 startMiniProgramRecording 方法
+    startMiniProgramRecording() {
+      console.log('开始小程序录制方法');
+      
+      // 获取平台信息
+      const systemInfo = uni.getSystemInfoSync();
+      const isIOS = systemInfo.platform === 'ios';
+      
+      // 在iOS上,先重置相机
+      if (isIOS) {
+        // 先重置相机组件
+        this.resetCamera();
+        
+        // 延迟执行录制,给相机组件足够的初始化时间
+        setTimeout(() => {
+          this.actualStartRecording(isIOS);
+        }, 1000);
+      } else {
+        // Android直接开始
+        this.actualStartRecording(isIOS);
+      }
+    },
+
+    // 添加新方法:实际开始录制
+    actualStartRecording(isIOS) {
+      if (!this.cameraContext) {
+        this.cameraContext = uni.createCameraContext();
+        console.log('创建新的相机上下文');
+      }
+      
+      // 确保有录音权限
+      uni.getSetting({
+        success: (res) => {
+          const hasRecordAuth = res.authSetting['scope.record'];
+          const hasCameraAuth = res.authSetting['scope.camera'];
+          
+          if (!hasRecordAuth || !hasCameraAuth) {
+            console.warn('缺少必要权限,请求权限');
+            this.requestMiniProgramPermissions();
+            return;
+          }
+          
+          // 在iOS上,先检查相机状态
+          if (isIOS) {
+            console.log('iOS: 检查相机状态');
+            
+            // 使用最简单的选项,设置最大录制时间为当前问题的推荐时长
+            const maxDuration = this.getCurrentQuestionRecommendedDuration() * 1000; // 转换为毫秒
+            const options = {
+              timeout: maxDuration, // 使用当前问题的推荐时长
+              quality: 'low', // 降低质量
+              compressed: true,
+              success: () => {
+                console.log('iOS录制开始成功');
+              },
+              fail: (err) => {
+                console.error('iOS录制失败:', err);
+                
+                // 如果失败,尝试使用不同的方法
+                this.useAlternativeRecordingMethod();
+              }
+            };
+            
+            try {
+              console.log('尝试开始录制');
+              this.recorder = this.cameraContext.startRecord(options);
+            } catch (e) {
+              console.error('开始录制异常:', e);
+              this.useAlternativeRecordingMethod();
+            }
+          } else {
+            // Android使用标准选项,设置最大录制时间为当前问题的推荐时长
+            const maxDuration = this.getCurrentQuestionRecommendedDuration() * 1000; // 转换为毫秒
+            const options = {
+              timeout: maxDuration, // 使用当前问题的推荐时长
+              quality: 'medium',
+              compressed: true,
+              success: () => {
+                console.log('Android录制开始成功');
+              },
+              fail: (err) => {
+                console.error('Android录制失败:', err);
+                uni.showToast({
+                  title: '录制失败,请检查相机权限',
+                  icon: 'none'
+                });
+                this.proceedToNextQuestion();
+              }
+            };
+            
+            this.recorder = this.cameraContext.startRecord(options);
+          }
+        }
+      });
+    },
+
+    // 添加新方法:使用替代录制方法
+    useAlternativeRecordingMethod() {
+      console.log('使用替代录制方法');
+      
+      // 在iOS上,可以尝试使用chooseVideo API作为备选
+      uni.showActionSheet({
+        itemList: ['使用相册中的视频', '跳过此问题'],
+        success: (res) => {
+          if (res.tapIndex === 0) {
+            // 选择相册中的视频
+            uni.chooseVideo({
+              sourceType: ['album'],
+              maxDuration: this.getCurrentQuestionRecommendedDuration(), // 使用当前问题的推荐时长
+              camera: 'front',
+              success: (res) => {
+                console.log('选择视频成功:', res.tempFilePath);
+                // 停止录制状态
+                this.isRecording = false;
+                this.showStopRecordingButton = false;
+                
+                // 上传选择的视频
+                this.uploadRecordedVideo(res.tempFilePath);
+              },
+              fail: () => {
+                console.log('用户取消选择视频');
+                this.proceedToNextQuestion();
+              }
+            });
+          } else {
+            // 跳过此问题
+            console.log('用户选择跳过问题');
+            this.proceedToNextQuestion();
+          }
+        },
+        fail: () => {
+          console.log('操作取消');
+          this.proceedToNextQuestion();
+        }
+      });
+    },
+
+    // 添加新方法:请求小程序权限
+    requestMiniProgramPermissions() {
+      // 请求录音权限
+      uni.authorize({
+        scope: 'scope.record',
+        success: () => {
+          console.log('录音权限已获取');
+          
+          // 请求相机权限
+          uni.authorize({
+            scope: 'scope.camera',
+            success: () => {
+              console.log('相机权限已获取');
+              // 权限都获取到后,开始录制
+              this.startMiniProgramRecording();
+            },
+            fail: (err) => {
+              console.error('相机权限获取失败:', err);
+              this.showPermissionDialog('相机');
+            }
+          });
+        },
+        fail: (err) => {
+          console.error('录音权限获取失败:', err);
+          this.showPermissionDialog('录音');
+        }
+      });
+    },
+
+    // 修改浏览器环境下的录制方法
+    startBrowserRecording() {
+      if (!this.cameraStream) {
+        console.error('没有可用的摄像头流');
+       /* uni.showToast({
+          title: '录制失败,摄像头未就绪',
+          icon: 'none'
+        }); */
+        this.proceedToNextQuestion();
+        return;
+      }
+      
+      try {
+        // 检查流中是否包含音频轨道
+        const hasAudio = this.cameraStream.getAudioTracks().length > 0;
+        if (!hasAudio) {
+          console.warn('警告:媒体流中没有音频轨道,尝试重新获取带音频的媒体流');
+          
+          // 尝试重新获取带音频的媒体流
+          navigator.mediaDevices.getUserMedia({ 
+            audio: {
+              echoCancellation: true,
+              noiseSuppression: true,
+              autoGainControl: true
+            }, 
+            video: true 
+          })
+            .then(newStream => {
+              // 检查新流是否包含音频轨道
+              const audioTracks = newStream.getAudioTracks();
+              if (audioTracks.length > 0) {
+                console.log('成功获取音频轨道:', audioTracks[0].label);
+                
+                // 合并视频和音频轨道
+                const videoTrack = this.cameraStream.getVideoTracks()[0];
+                const audioTrack = newStream.getAudioTracks()[0];
+                
+                // 创建新的媒体流,包含视频和音频轨道
+                const combinedStream = new MediaStream();
+                if (videoTrack) combinedStream.addTrack(videoTrack);
+                if (audioTrack) combinedStream.addTrack(audioTrack);
+                
+                this.cameraStream = combinedStream;
+                
+                // 更新视频元素的源
+                const videoElement = this.$refs.userCameraVideo;
+                if (videoElement) {
+                  videoElement.srcObject = combinedStream;
+                  videoElement.muted = true; // 避免回声,但仍然录制声音
+                }
+                
+                // 继续录制过程
+                this.setupMediaRecorder(combinedStream);
+              } else {
+                console.warn('仍然无法获取音频轨道');
+                // 使用现有流继续
+                this.setupMediaRecorder(this.cameraStream);
+              }
+            })
+            .catch(err => {
+              console.error('获取音频失败:', err);
+              // 使用现有流继续
+              this.setupMediaRecorder(this.cameraStream);
+            });
+        } else {
+          console.log('检测到音频轨道,直接使用');
+          // 已有音频轨道,直接使用
+          this.setupMediaRecorder(this.cameraStream);
+        }
+      } catch (error) {
+        console.error('浏览器录制失败:', error);
+        uni.showToast({
+          title: '录制失败,浏览器可能不支持此功能',
+          icon: 'none'
+        });
+        this.proceedToNextQuestion();
+      }
+    },
+
+    // 修改 setupMediaRecorder 方法
+    setupMediaRecorder(stream) {
+      // 检查流中的轨道
+      const videoTracks = stream.getVideoTracks();
+      const audioTracks = stream.getAudioTracks();
+      
+      console.log('设置MediaRecorder - 视频轨道:', videoTracks.length, '音频轨道:', audioTracks.length);
+      
+      // 尝试使用支持度更广的编码格式
+      let mimeType = '';
+      const supportedTypes = [
+        'video/webm;codecs=vp9,opus',
+        'video/webm;codecs=vp8,opus',
+        'video/webm;codecs=h264,opus',
+        'video/mp4;codecs=h264,aac',
+        'video/webm',
+        'video/mp4'
+      ];
+      
+      for (const type of supportedTypes) {
+        if (MediaRecorder.isTypeSupported(type)) {
+          mimeType = type;
+          console.log('使用支持的MIME类型:', mimeType);
+          break;
+        }
+      }
+      
+      // 创建MediaRecorder实例,设置较低的比特率以减小文件大小
+      const options = {
+        mimeType: mimeType || '',
+        audioBitsPerSecond: 64000,    // 降低音频比特率
+        videoBitsPerSecond: 1000000,  // 降低视频比特率到1Mbps
+      };
+      
+      try {
+        this.mediaRecorder = new MediaRecorder(stream, options);
+        console.log('MediaRecorder创建成功,使用选项:', options);
+      } catch (e) {
+        console.warn('使用指定选项创建MediaRecorder失败,尝试使用默认选项');
+        this.mediaRecorder = new MediaRecorder(stream);
+      }
+      
+      // 存储录制的数据块
+      this.recordedChunks = [];
+      
+      // 监听数据可用事件
+      this.mediaRecorder.ondataavailable = (event) => {
+        if (event.data && event.data.size > 0) {
+          this.recordedChunks.push(event.data);
+          console.log(`收到数据块: ${event.data.size} 字节`);
+        }
+      };
+      
+      // 监听录制停止事件
+      this.mediaRecorder.onstop = async () => {
+        console.log('MediaRecorder停止,数据块数量:', this.recordedChunks.length);
+        
+        if (this.recordedChunks.length === 0) {
+          console.error('没有录制到数据');
+          /* uni.showToast({
+            title: '录制失败,未捕获到数据',
+            icon: 'none'
+          }); */
+          this.proceedToNextQuestion();
+          return;
+        }
+        
+        // 创建Blob对象
+        const mimeType = this.mediaRecorder.mimeType || 'video/webm';
+        const blob = new Blob(this.recordedChunks, { type: mimeType });
+        console.log('创建Blob,原始大小:', blob.size, '类型:', mimeType);
+        
+        // 显示压缩中提示
+        uni.showLoading({
+          title: '正在处理视频...',
+          mask: true
+        });
+        
+        try {
+          // 压缩视频
+          const compressedBlob = await this.compressVideo(blob);
+          
+          // 将Blob转换为File对象
+          const fileName = `answer_${this.currentVideoIndex}_${Date.now()}.webm`;
+          const file = new File([compressedBlob], fileName, { type: mimeType });
+          
+          // 隐藏压缩提示
+          uni.hideLoading();
+          
+          // 上传文件
+          this.uploadRecordedVideo(file);
+        } catch (error) {
+          console.error('视频处理失败:', error);
+          uni.hideLoading();
+          
+          // 如果压缩失败,使用原始视频
+          const fileName = `answer_${this.currentVideoIndex}_${Date.now()}.webm`;
+          const file = new File([blob], fileName, { type: mimeType });
+          this.uploadRecordedVideo(file);
+        }
+      };
+      
+      // 监听错误
+      this.mediaRecorder.onerror = (event) => {
+        console.error('MediaRecorder错误:', event.error);
+      };
+      
+      // 开始录制
+      try {
+        this.mediaRecorder.start(1000); // 每秒触发一次dataavailable事件
+        console.log('MediaRecorder开始录制');
+        
+        // 设置最大录制时间为60秒
+        // 注意:我们已经在startRecordingAnswer方法中设置了全局计时器
+        // 这里作为备份机制,确保即使全局计时器失效,也能停止录制
+        this.mediaRecorderTimeout = setTimeout(() => {
+          if (this.mediaRecorder && this.mediaRecorder.state === 'recording') {
+            console.log('MediaRecorder备份超时机制触发,停止录制');
+            this.mediaRecorder.stop();
+          }
+        }, 300000); // 300秒 (5分钟)
+      } catch (e) {
+        console.error('开始录制失败:', e);
+      }
+    },
+
+    // 添加新方法:获取录制时长
+    getRecordingDuration() {
+      // 如果有明确的录制开始时间,计算实际录制时长
+      if (this.recordingStartTime) {
+        return (Date.now() - this.recordingStartTime) / 1000;
+      }
+      
+      // 如果没有明确记录开始时间,尝试从视频元素获取
+      if (this.mediaRecorder && this.$refs.userCameraVideo) {
+        return this.$refs.userCameraVideo.currentTime || 0;
+      }
+      
+      // 如果无法获取准确时长,返回估计值(如果有计时器)
+      if (this.recordingTimerCount) {
+        return this.recordingTimerCount;
+      }
+      
+      // 默认返回0
+      return 0;
+    },
+
+    // 添加新方法:重置录制
+    resetRecording() {
+      // 保持录制状态,但重置计时器
+      if (this.recordingTimer) {
+        clearTimeout(this.recordingTimer);
+      }
+      
+      // 重置录制开始时间
+      this.recordingStartTime = Date.now();
+      this.recordingTimerCount = 0;
+      
+      // 如果是浏览器环境,需要重置MediaRecorder
+      if (this.mediaRecorder && this.mediaRecorder.state !== 'inactive') {
+        // 停止当前录制
+        this.mediaRecorder.stop();
+        
+        // 清空已录制的数据块
+        this.recordedChunks = [];
+        
+        // 短暂延迟后重新开始录制
+        setTimeout(() => {
+          this.startBrowserRecording();
+        }, 500);
+      } 
+      // 如果是小程序环境,需要重置相机录制
+      else if (this.cameraContext) {
+        // 停止当前录制
+        this.cameraContext.stopRecord({
+          success: () => {
+            console.log('相机录制已停止');
+          },
+          fail: (err) => {
+            console.error('停止相机录制失败:', err);
+          }
+        });
+      }
+      
+      // 显示提示
+      /* uni.showToast({
+        title: '请重新开始回答',
+        icon: 'none',
+        duration: 2000
+      }); */
+    },
+
+    // 修改 completeRecordingStop 方法,确保正确处理追问问题ID
+    completeRecordingStop(uploadVideo = true) {
+      console.log('完成录制停止');
+      
+      // 停止录制计时器
+      if (this.recordingTimer) {
+        clearInterval(this.recordingTimer);
+        this.recordingTimer = null;
+      }
+      
+      // 记录最终录制时长
+      this.finalRecordingDuration = this.recordingTimerCount;
+      
+      // 隐藏停止录制按钮
+      this.showStopRecordingButton = false;
+      
+      // 隐藏录制指示器
+      this.isRecording = false;
+      
+      // 根据平台选择不同的停止录制方法
+      const systemInfo = uni.getSystemInfoSync();
+      const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith('mp-');
+      
+      if (isMiniProgram) {
+        // 小程序环境停止录制
+        if (uploadVideo) {
+          this.stopMiniProgramRecording();
+        } else {
+          // 如果不需要上传,直接停止录制
+          if (this.cameraContext) {
+            this.cameraContext.stopRecord({
+              success: () => {
+                console.log('相机录制已停止,不上传视频');
+              },
+              fail: (err) => {
+                console.error('停止相机录制失败:', err);
+              }
+            });
+          }
+        }
+      } else {
+        // H5/App环境停止录制
+        if (uploadVideo) {
+          this.stopBrowserRecording();
+        } else {
+          // 如果不需要上传,直接停止录制
+          if (this.mediaRecorder && this.mediaRecorder.state !== 'inactive') {
+            this.mediaRecorder.stop();
+            this.recordedChunks = []; // 清空已录制的数据
+          }
+        }
+      }
+      
+      // 记录当前问题ID和类型,确保追问问题使用正确的ID
+      if (this.isFollowUpQuestion && this.currentFollowUpQuestion) {
+        console.log('当前是追问问题,记录追问问题ID:', this.currentFollowUpQuestion.id);
+        this.lastQuestionWasFollowUp = true;
+        this.lastFollowUpQuestionId = this.currentFollowUpQuestion.id;
+      } else {
+        this.lastQuestionWasFollowUp = false;
+        this.lastFollowUpQuestionId = null;
+      }
+    },
+
+    // 修改 stopMiniProgramRecording 方法,确保正确传递追问问题ID
+    stopMiniProgramRecording() {
+      console.log('停止小程序录制');
+      
+      // 检查是否有录制上下文
+      if (!this.cameraContext) {
+        console.error('相机上下文不存在');
+        this.proceedToNextQuestion();
+        return;
+      }
+      
+      // 停止录制
+      this.cameraContext.stopRecord({
+        success: async (res) => {
+          console.log('小程序录制停止成功:', res);
+          
+          // 获取录制的视频文件路径
+          const videoPath = res.tempVideoPath;
+          
+          // 上传视频文件
+          if (videoPath) {
+            // 等待上传完成后再继续
+            await this.uploadRecordedVideo(videoPath);
+          } else {
+            console.error('未获取到录制视频路径');
+            this.proceedToNextQuestion();
+          }
+        },
+        fail: (err) => {
+          console.error('小程序录制停止失败:', err);
+          this.proceedToNextQuestion();
+        }
+      });
+    },
+
+    // 添加新方法:停止浏览器录制
+    stopBrowserRecording() {
+      if (this.mediaRecorder && this.mediaRecorder.state !== 'inactive') {
+        this.mediaRecorder.stop();
+        console.log('浏览器录制停止成功');
+      } else {
+        console.error('MediaRecorder不存在或已经停止');
+        this.proceedToNextQuestion();
+      }
+    },
+
+    // 修改 uploadRecordedVideo 方法,添加记录父问题ID的逻辑
+    uploadRecordedVideo(fileOrPath) {
+     
+      
+      console.log('准备上传视频:', typeof fileOrPath === 'string' ? fileOrPath : fileOrPath.name);
+      console.log('当前问题ID:', this.currentParentQuestionId);
+      console.log('当前问题类型:', this.isFollowUpQuestion);
+      console.log('当前追问问题:', this.currentFollowUpQuestion);
+      
+      // 获取当前问题ID和相关信息
+      let questionId;
+      let isFollowUpQuestionUpload = false;
+      let questionText = '';
+      let questionForm = 0;
+      
+      // 检查当前是否是追问问题
+      if (this.currentFollowUpQuestion && 
+          (this.currentFollowUpQuestion.question_form === 5 || this.isFollowUpQuestion)) {
+        // 使用追问问题的信息
+        questionId = this.currentFollowUpQuestion.id;
+        isFollowUpQuestionUpload = true;
+        questionText = this.currentFollowUpQuestion.question || '';
+        questionForm = 5; // 追问问题类型
+        console.log('正在上传追问问题的回答:', {
+          questionId,
+          questionText,
+          questionForm,
+          isFollowUp: true
+        });
+      } else {
+         // 显示思考中loading
+         this.showThinkingLoading();
+        // 使用常规问题的信息
+        const currentQuestion = this.getCurrentQuestionByIndex(this.currentVideoIndex);
+        if (currentQuestion && currentQuestion.id) {
+          questionId = currentQuestion.id;
+          questionText = currentQuestion.question || '';
+          console.log('正在上传常规问题的回答:', {
+            questionId,
+            questionText,
+            questionForm: 0
+          });
+        } else {
+          questionId = this.getDefaultQuestionId(this.currentVideoIndex);
+          console.log('使用默认问题ID:', questionId);
+        }
+      }
+      
+      // 创建上传任务对象
+      const uploadTask = {
+        id: Date.now().toString(),
+        file: fileOrPath,
+        questionId: questionId,
+        isFollowUp: isFollowUpQuestionUpload,
+        questionText: questionText,
+        questionForm: questionForm,
+        attempts: 0,
+        maxAttempts: 3,
+        parentQuestionId: this.currentParentQuestionId,
+        videoDuration: this.currentRecordingDuration || 0 // 添加视频时长
+      };
+      
+      // 如果不是追问问题,记录当前问题ID作为父问题ID
+      if (!isFollowUpQuestionUpload) {
+        this.currentParentQuestionId = questionId;
+      }
+      
+      // 添加到上传队列
+      this.uploadQueue.push(uploadTask);
+      
+      // 初始化上传进度和状态
+      this.uploadProgress[uploadTask.id] = 0;
+      this.uploadStatus[uploadTask.id] = 'pending';
+      
+      // 显示上传状态提示
+     /* uni.showToast({
+        title: '正在上传回答...',
+        icon: 'loading',
+        duration: 1500
+      }); */
+      
+      // 更新上传状态文本
+      this.updateUploadStatusText();
+      
+      // 如果是追问问题,使用后台上传,不阻塞流程
+      if (isFollowUpQuestionUpload) {
+        console.log('追问问题使用后台上传,不阻塞流程');
+        
+        // 立即执行后续操作,不等待上传完成
+        this.handlePostUploadActions(uploadTask);
+        
+        // 启动后台上传
+        this.startBackgroundUpload(uploadTask);
+        
+        // 返回立即解决的Promise
+        return Promise.resolve();
+      } else {
+        // 常规问题保持原有逻辑,等待上传完成
+        return new Promise((resolve) => {
+          const checkUploadStatus = () => {
+            if (!this.isUploading && this.uploadQueue.length === 0) {
+              // 上传完成后执行后续操作
+              this.handlePostUploadActions(uploadTask);
+              resolve();
+            } else {
+              // 如果还在上传,继续检查
+              setTimeout(checkUploadStatus, 100);
+            }
+          };
+          
+          // 如果当前没有上传任务在进行,开始处理队列
+          if (!this.isUploading) {
+            this.processUploadQueue();
+          }
+          
+          // 开始检查上传状态
+          checkUploadStatus();
+        });
+      }
+    },
+
+    // 添加新方法:启动后台上传
+    startBackgroundUpload(task) {
+      console.log('启动后台上传任务:', task.id);
+      
+      // 标记为后台上传任务
+      task.isBackgroundUpload = true;
+      
+      // 从主上传队列中移除,避免与常规上传冲突
+      const taskIndex = this.uploadQueue.findIndex(t => t.id === task.id);
+      if (taskIndex !== -1) {
+        this.uploadQueue.splice(taskIndex, 1);
+      }
+      
+      // 添加到后台上传队列
+      if (!this.backgroundUploadQueue) {
+        this.backgroundUploadQueue = [];
+      }
+      this.backgroundUploadQueue.push(task);
+      
+      // 启动后台上传处理
+      this.processBackgroundUploadQueue();
+    },
+
+    // 添加新方法:处理后台上传队列
+    processBackgroundUploadQueue() {
+      // 如果后台上传队列为空,结束处理
+      if (!this.backgroundUploadQueue || this.backgroundUploadQueue.length === 0) {
+        return;
+      }
+      
+      // 获取队列中的第一个任务
+      const task = this.backgroundUploadQueue[0];
+      
+      console.log('开始后台上传:', task.id);
+      
+      // 更新任务状态
+      this.uploadStatus[task.id] = 'uploading';
+      this.updateUploadStatusText();
+      
+      // 增加尝试次数
+      task.attempts++;
+      
+      // 根据文件类型选择上传方法
+      if (typeof task.file === 'string') {
+        // 小程序环境,使用uni.uploadFile上传
+        this.uploadFileWithUniBackground(task);
+      } else {
+        // 浏览器环境,使用XMLHttpRequest上传
+        this.uploadFileWithXHRBackground(task);
+      }
+    },
+
+    // 添加新方法:使用XMLHttpRequest后台上传文件
+    uploadFileWithXHRBackground(task) {
+      // 获取用户信息
+      const userInfo = uni.getStorageSync('userInfo');
+      const openid = userInfo ? (JSON.parse(userInfo).openid || '') : '';
+      const tenant_id = JSON.parse(uni.getStorageSync('userInfo')).tenant_id || '1';
+      
+      // 创建FormData
+      const formData = new FormData();
+      formData.append('file', task.file);
+      formData.append('openid', openid);
+      formData.append('tenant_id', tenant_id);
+      formData.append('application_id', uni.getStorageSync('appId'));
+      formData.append('question_id', task.questionId);
+      formData.append('video_duration', task.videoDuration || 0);
+      formData.append('has_audio', 'true');
+      
+      // 创建XMLHttpRequest
+      const xhr = new XMLHttpRequest();
+      
+      // 监听上传进度
+      xhr.upload.onprogress = (event) => {
+        if (event.lengthComputable) {
+          const progress = Math.round((event.loaded / event.total) * 100);
+          this.uploadProgress[task.id] = progress;
+          this.updateUploadStatusText();
+        }
+      };
+      
+      // 监听请求完成
+      xhr.onload = () => {
+        if (xhr.status === 200) {
+          try {
+            const res = JSON.parse(xhr.responseText);
+            console.log('后台上传响应:', res);
+            if (res.code === 2000) {
+              // 获取上传后的视频URL
+              const videoUrl = res.data.url || res.data.photoUrl || '';
+              if (videoUrl) {
+                // 上传成功,更新状态
+                this.uploadStatus[task.id] = 'success';
+                this.updateUploadStatusText();
+                
+                // 提交到面试接口
+                this.submitVideoToInterviewBackground(videoUrl, task);
+              } else {
+                this.handleBackgroundUploadFailure(task, '视频URL获取失败');
+              }
+            } else {
+              this.handleBackgroundUploadFailure(task, res.msg || '上传失败');
+            }
+          } catch (e) {
+            this.handleBackgroundUploadFailure(task, '解析响应失败');
+          }
+        } else {
+          this.handleBackgroundUploadFailure(task, 'HTTP状态: ' + xhr.status);
+        }
+      };
+      
+      // 监听错误
+      xhr.onerror = () => {
+        this.handleBackgroundUploadFailure(task, '网络错误');
+      };
+      
+      // 监听超时
+      xhr.ontimeout = () => {
+        this.handleBackgroundUploadFailure(task, '上传超时');
+      };
+      
+      // 发送请求
+      xhr.open('POST', `${apiBaseUrl}/api/upload/`);
+      xhr.send(formData);
+    },
+
+    // 添加新方法:使用uni.uploadFile后台上传文件
+    uploadFileWithUniBackground(task) {
+      // 获取用户信息
+      const userInfo = uni.getStorageSync('userInfo');
+      const openid = userInfo ? (JSON.parse(userInfo).openid || '') : '';
+      const tenant_id = JSON.parse(uni.getStorageSync('userInfo')).tenant_id || '1';
+      
+      // 创建上传任务
+      const uploadTask = uni.uploadFile({
+        url: `${apiBaseUrl}/api/upload/`,
+        filePath: task.file,
+        name: 'file',
+        formData: {
+          openid: openid,
+          tenant_id: tenant_id,
+          application_id: uni.getStorageSync('appId'),
+          question_id: task.questionId,
+          video_duration: task.videoDuration || 0,
+          has_audio: 'true'
+        },
+        success: (uploadRes) => {
+          try {
+            const res = JSON.parse(uploadRes.data);
+            console.log('后台上传响应:', res);
+            if (res.code === 2000) {
+              // 获取上传后的视频URL
+              const videoUrl = res.data.permanent_link || res.data.url || '';
+              if (videoUrl) {
+                // 上传成功,更新状态
+                this.uploadStatus[task.id] = 'success';
+                this.updateUploadStatusText();
+                
+                // 提交到面试接口
+                this.submitVideoToInterviewBackground(videoUrl, task);
+              } else {
+                this.handleBackgroundUploadFailure(task, '视频URL获取失败');
+              }
+            } else {
+              this.handleBackgroundUploadFailure(task, res.msg || '上传失败');
+            }
+          } catch (e) {
+            this.handleBackgroundUploadFailure(task, '解析响应失败');
+          }
+        },
+        fail: (err) => {
+          this.handleBackgroundUploadFailure(task, err.errMsg || '上传失败');
+        }
+      });
+      
+      // 监听上传进度
+      uploadTask.onProgressUpdate((res) => {
+        this.uploadProgress[task.id] = res.progress;
+        this.updateUploadStatusText();
+      });
+    },
+
+    // 添加新方法:处理后台上传失败
+    handleBackgroundUploadFailure(task, errorMsg) {
+      console.error('后台上传失败:', errorMsg);
+      
+      // 更新任务状态
+      this.uploadStatus[task.id] = 'failed';
+      this.updateUploadStatusText();
+      
+      // 检查是否还有重试机会
+      if (task.attempts < task.maxAttempts) {
+        console.log(`将在5秒后重试后台上传,当前尝试次数: ${task.attempts}/${task.maxAttempts}`);
+        
+        // 5秒后重试
+        setTimeout(() => {
+          // 重置进度
+          this.uploadProgress[task.id] = 0;
+          
+          // 重新开始上传
+          if (typeof task.file !== 'string') {
+            this.uploadFileWithXHRBackground(task);
+          } else {
+            this.uploadFileWithUniBackground(task);
+          }
+        }, 5000);
+      } else {
+        // 超过最大重试次数,移除任务
+        console.log('超过最大重试次数,放弃后台上传');
+        
+        // 从后台上传队列中移除当前任务
+        if (this.backgroundUploadQueue) {
+          const taskIndex = this.backgroundUploadQueue.findIndex(t => t.id === task.id);
+          if (taskIndex !== -1) {
+            this.backgroundUploadQueue.splice(taskIndex, 1);
+          }
+        }
+        
+        // 继续处理队列中的下一个任务
+        this.processBackgroundUploadQueue();
+      }
+    },
+
+    // 添加新方法:后台上传提交到面试接口
+    submitVideoToInterviewBackground(videoUrl, task) {
+      // 准备请求参数
+      const followUpRequestData = {
+        application_id: uni.getStorageSync('appId'),
+        tenant_id: JSON.parse(uni.getStorageSync('userInfo')).tenant_id || '1',
+        video_url: videoUrl,
+        original_question_id: this.parentJobPositionQuestionId, // 使用保存的job_position_question_id
+        follow_up_question: task.questionText,
+        video_duration: task.videoDuration,
+        openid: JSON.parse(uni.getStorageSync('userInfo')).openid || ''
+      };
+      
+      console.log('后台上传提交追问视频:', followUpRequestData);
+      
+      uni.request({
+        url: `${apiBaseUrl}/voice_interview/upload_follow_up_video/`,
+        method: 'POST',
+        data: followUpRequestData,
+        header: {
+          'content-type': 'application/x-www-form-urlencoded'
+        },
+        success: (res) => {
+          if (res.data.code === 200 || res.data.code === 2000) {
+            console.log('后台上传追问视频提交成功');
+            
+            // 从后台上传队列中移除任务
+            if (this.backgroundUploadQueue) {
+              const taskIndex = this.backgroundUploadQueue.findIndex(t => t.id === task.id);
+              if (taskIndex !== -1) {
+                this.backgroundUploadQueue.splice(taskIndex, 1);
+              }
+            }
+            
+            // 继续处理下一个后台上传任务
+            this.processBackgroundUploadQueue();
+          } else {
+            this.handleBackgroundSubmitFailure(task, '提交失败: ' + (res.data.msg || '未知错误'));
+          }
+        },
+        fail: (err) => {
+          console.error('后台上传提交失败:', err);
+          this.handleBackgroundSubmitFailure(task, '提交失败: ' + err.errMsg);
+        }
+      });
+    },
+
+    // 添加新方法:处理后台上传提交失败
+    handleBackgroundSubmitFailure(task, errorMsg) {
+      console.error('后台上传提交失败:', errorMsg);
+      
+      // 检查是否还有重试机会
+      if (task.attempts < task.maxAttempts) {
+        console.log(`将在5秒后重试后台上传提交,当前尝试次数: ${task.attempts}/${task.maxAttempts}`);
+        
+        // 5秒后重试
+        setTimeout(() => {
+          this.submitVideoToInterviewBackground(task.videoUrl, task);
+        }, 5000);
+      } else {
+        // 超过最大重试次数,移除任务
+        console.log('超过最大重试次数,放弃后台上传提交');
+        
+        // 从后台上传队列中移除当前任务
+        if (this.backgroundUploadQueue) {
+          const taskIndex = this.backgroundUploadQueue.findIndex(t => t.id === task.id);
+          if (taskIndex !== -1) {
+            this.backgroundUploadQueue.splice(taskIndex, 1);
+          }
+        }
+        
+        // 继续处理队列中的下一个任务
+        this.processBackgroundUploadQueue();
+      }
+    },
+
+    // 添加新方法:处理上传后的逻辑
+    handlePostUploadActions(task) {
+      // 隐藏思考中loading
+      this.hideThinkingLoading();
+      
+      // 检查是否需要播放低分视频
+      if (this.needPlayLowScoreVideo && this.retryCount < 1) {
+        this.playLowScoreVideo();
+        this.needPlayLowScoreVideo = false;
+      } else {
+        // 如果是追问问题的回答,直接进入下一个问题
+        if (task.isFollowUp) {
+          console.log('追问问题回答完成,进入下一个问题');
+          this.retryCount = 0; // 重置重试次数
+          this.isFollowUpQuestion = false; // 重置追问标记
+          this.currentFollowUpQuestion = null; // 清除当前追问问题信息
+          this.videoUrl=''
+          // 若未达到上限则继续请求下一条追问,否则进入下一题
+          this.maybeRequestNextFollowUp(this.parentJobPositionQuestionId);
+        } else {
+          // 如果是常规问题,记录父问题ID并检查追问问题
+          this.currentParentQuestionId = task.questionId;
+          console.log('检查常规问题的追问,父问题ID:', this.currentParentQuestionId);
+          // 从题目读取追问上限(若后端提供),否则使用默认
+          const currentQuestion = this.getCurrentQuestionByIndex(this.currentVideoIndex);
+          if (currentQuestion && typeof currentQuestion.follow_up_limit !== 'undefined') {
+            this.setFollowUpLimit(this.currentParentQuestionId, currentQuestion.follow_up_limit);
+          } else if (typeof this.defaultFollowUpLimit !== 'undefined') {
+            this.setFollowUpLimit(this.currentParentQuestionId, this.defaultFollowUpLimit);
+          }
+          this.resetFollowUpAskedCount(this.currentParentQuestionId);
+          this.checkAndPlayFollowUpQuestion(this.currentParentQuestionId);
+        }
+      }
+    },
+
+    // 修改 processUploadQueue 方法
+    processUploadQueue() {
+      // 如果队列为空,结束处理
+      if (this.uploadQueue.length === 0) {
+        this.isUploading = false;
+        this.showUploadStatus = false;
+        this.hideThinkingLoading(); // 隐藏思考中loading
+        return;
+      }
+      
+      // 标记为正在上传
+      this.isUploading = true;
+      this.showUploadStatus = true;
+      
+      // 获取队列中的第一个任务
+      const task = this.uploadQueue[0];
+      
+      // 更新任务状态
+      this.uploadStatus[task.id] = 'uploading';
+      this.updateUploadStatusText();
+      
+      // 增加尝试次数
+      task.attempts++;
+      
+      // 根据文件类型选择上传方法
+      if (typeof task.file === 'string') {
+        // 小程序环境,使用uni.uploadFile上传
+        this.uploadFileWithUni(task);
+      } else {
+        // 浏览器环境,使用XMLHttpRequest上传
+        this.uploadFileWithXHR(task);
+      }
+    },
+    
+    // 添加新方法:使用XMLHttpRequest上传文件
+    uploadFileWithXHR(task) {
+      // 获取用户信息
+      const userInfo = uni.getStorageSync('userInfo');
+      const openid = userInfo ? (JSON.parse(userInfo).openid || '') : '';
+      const tenant_id = JSON.parse(uni.getStorageSync('userInfo')).tenant_id || '1';
+      
+      // 创建FormData
+      const formData = new FormData();
+      formData.append('file', task.file);
+      formData.append('openid', openid);
+      formData.append('tenant_id', tenant_id);
+      formData.append('application_id', uni.getStorageSync('appId'));
+      formData.append('question_id', task.questionId);
+      formData.append('video_duration', task.videoDuration);
+      formData.append('has_audio', 'true');
+      
+      // 创建XMLHttpRequest
+      const xhr = new XMLHttpRequest();
+      xhr.open('POST', `${apiBaseUrl}/api/upload/`, true);
+      xhr.timeout = 120000; // 2分钟超时
+      
+      // 监听上传进度
+      xhr.upload.onprogress = (event) => {
+        if (event.lengthComputable) {
+          const percentComplete = Math.round((event.loaded / event.total) * 100);
+          this.uploadProgress[task.id] = percentComplete;
+          this.updateUploadStatusText();
+        }
+      };
+      
+      // 监听请求完成
+      xhr.onload = () => {
+        if (xhr.status === 200) {
+          try {
+            const res = JSON.parse(xhr.responseText);
+            console.log('上传响应:', res);
+            if (res.code === 2000) {
+              // 获取上传后的视频URL
+              const videoUrl = res.data.url || res.data.photoUrl || '';
+              if (videoUrl) {
+                // 上传成功,更新状态
+                this.uploadStatus[task.id] = 'success';
+                this.updateUploadStatusText();
+                
+                // 提交到面试接口
+                this.submitVideoToInterview(videoUrl, task);
+              } else {
+                this.handleUploadFailure(task, '视频URL获取失败');
+              }
+            } else {
+              this.handleUploadFailure(task, res.msg || '上传失败');
+            }
+          } catch (e) {
+            this.handleUploadFailure(task, '解析响应失败');
+          }
+        } else {
+          this.handleUploadFailure(task, 'HTTP状态: ' + xhr.status);
+        }
+      };
+      
+      // 监听错误
+      xhr.onerror = () => {
+        this.handleUploadFailure(task, '网络错误');
+      };
+      
+      // 监听超时
+      xhr.ontimeout = () => {
+        this.handleUploadFailure(task, '上传超时');
+      };
+      
+      // 发送请求
+      xhr.send(formData);
+    },
+    
+    // 添加新方法:使用uni.uploadFile上传文件
+    uploadFileWithUni(task) {
+      // 获取用户信息
+      const userInfo = uni.getStorageSync('userInfo');
+      const openid = userInfo ? (JSON.parse(userInfo).openid || '') : '';
+      const tenant_id = JSON.parse(uni.getStorageSync('userInfo')).tenant_id || '1';
+      
+      // 创建上传任务
+      const uploadTask = uni.uploadFile({
+        url: `${apiBaseUrl}/api/upload/`,
+        filePath: task.file,
+        name: 'file',
+        formData: {
+          openid: openid,
+          tenant_id: tenant_id,
+          application_id: uni.getStorageSync('appId'),
+          question_id: task.questionId,
+          video_duration: 0,
+          has_audio: 'true'
+        },
+        success: (uploadRes) => {
+          try {
+            const res = JSON.parse(uploadRes.data);
+            console.log('上传响应:', res);
+            if (res.code === 2000) {
+              // 获取上传后的视频URL
+              const videoUrl = res.data.permanent_link || res.data.url || '';
+              if (videoUrl) {
+                // 上传成功,更新状态
+                this.uploadStatus[task.id] = 'success';
+                this.updateUploadStatusText();
+                
+                // 提交到面试接口
+                this.submitVideoToInterview(videoUrl, task);
+              } else {
+                this.handleUploadFailure(task, '视频URL获取失败');
+              }
+            } else {
+              this.handleUploadFailure(task, res.msg || '上传失败');
+            }
+          } catch (e) {
+            this.handleUploadFailure(task, '解析响应失败');
+          }
+        },
+        fail: (err) => {
+          this.handleUploadFailure(task, err.errMsg || '上传失败');
+        }
+      });
+      
+      // 监听上传进度
+      uploadTask.onProgressUpdate((res) => {
+        this.uploadProgress[task.id] = res.progress;
+        this.updateUploadStatusText();
+      });
+    },
+    
+    // 添加新方法:处理上传失败
+    handleUploadFailure(task, errorMsg) {
+      console.error('上传失败:', errorMsg);
+      
+      // 更新任务状态
+      this.uploadStatus[task.id] = 'failed';
+      this.updateUploadStatusText();
+      
+      // 检查是否还有重试机会
+      if (task.attempts < task.maxAttempts) {
+        console.log(`将在5秒后重试上传,当前尝试次数: ${task.attempts}/${task.maxAttempts}`);
+        
+        // 5秒后重试
+        setTimeout(() => {
+          // 重置进度
+          this.uploadProgress[task.id] = 0;
+          
+          // 重新开始上传
+          if (typeof task.file !== 'string') {
+            this.uploadFileWithXHR(task);
+          } else {
+            this.uploadFileWithUni(task);
+          }
+        }, 5000);
+      } else {
+        // 超过最大重试次数,移除任务并继续处理队列
+        console.log('超过最大重试次数,放弃上传');
+        
+        // 显示错误提示
+        /* uni.showToast({
+          title: '视频上传失败,请稍后重试',
+          icon: 'none',
+          duration: 2000
+        }); */
+        
+        // 从队列中移除当前任务
+        this.uploadQueue.shift();
+        
+        // 继续处理队列中的下一个任务
+        this.processUploadQueue();
+      }
+    },
+    
+    // 修改 submitVideoToInterview 方法
+    submitVideoToInterview(videoUrl, task) {
+      // 准备请求参数
+      const requestData = {
+        application_id: uni.getStorageSync('appId'),
+        question_id: task.questionId,
+        video_url: videoUrl,
+        tenant_id: JSON.parse(uni.getStorageSync('userInfo')).tenant_id || '1',
+        is_follow_up: task.isFollowUp ? 1 : 0,
+        question_form: task.questionForm,
+        question_text: task.questionText
+      };
+      
+      console.log('提交视频到面试接口', requestData);
+      
+      // 发送请求到面试接口
+      if (task.isFollowUp) {
+        // 追问视频上传
+        const followUpRequestData = {
+          application_id: uni.getStorageSync('appId'),
+          tenant_id: JSON.parse(uni.getStorageSync('userInfo')).tenant_id || '1',
+          video_url: videoUrl,
+          original_question_id: this.parentJobPositionQuestionId, // 使用保存的job_position_question_id
+          follow_up_question: task.questionText,
+          video_duration: task.videoDuration,
+          openid: JSON.parse(uni.getStorageSync('userInfo')).openid || ''
+        };
+        
+        console.log('准备提交追问视频:', followUpRequestData);
+        
+        uni.request({
+          url: `${apiBaseUrl}/voice_interview/upload_follow_up_video/`,
+          method: 'POST',
+          data: followUpRequestData,
+          header: {
+            'content-type': 'application/x-www-form-urlencoded'
+          },
+          success: async (res) => {
+            try {
+              if (res.data.code === 200 || res.data.code === 2000) {
+                if (res.data.data && res.data.data.transcription_status === 'pending') {
+                  // 如果转写状态为pending,5秒后重试
+                  console.log('视频转写进行中,5秒后重试');
+                  setTimeout(() => {
+                    this.checkTranscriptionStatus(task, followUpRequestData);
+                  }, 5000);
+                  return;
+                }
+                
+                console.log('追问视频提交成功');
+                this.isFollowUpMode = false;
+                this.currentVideoIndex = this.mainQuestionIndex;
+                
+                /* uni.showToast({
+                  title: '回答已提交',
+                  icon: 'success',
+                  duration: 1500
+                }); */
+                
+                this.uploadQueue.shift();
+                this.processUploadQueue();
+                
+                this.$nextTick(() => {
+                  if (this.currentVideoIndex < this.videoList.length) {
+                    this.videoUrl = this.videoList[this.currentVideoIndex];
+                    this.videoPlaying = true;
+                    const videoContext = uni.createVideoContext('myVideo', this);
+                    if (videoContext) {
+                      videoContext.play();
+                    }
+                  }
+                });
+              } else {
+                this.handleSubmitFailure(task, '提交失败: ' + (res.data.msg || '未知错误'));
+              }
+            } catch (e) {
+              this.handleSubmitFailure(task, '解析响应失败: ' + e.message);
+            }
+          },
+          fail: (err) => {
+            console.error('提交视频失败:', err);
+            this.handleSubmitFailure(task, '提交失败: ' + err.errMsg);
+          }
+        });
+      } else {
+        // 原有的视频上传逻辑
+        uni.request({
+          url: `${apiBaseUrl}/api/job/upload_video`,
+          method: 'POST',
+          data: requestData,
+          header: {
+            'content-type': 'application/x-www-form-urlencoded'
+          },
+          success: async (res) => {
+            if (res.data.code === 200 || res.data.code === 2000) {
+              console.log('视频提交成功,准备调用面试互动接口');
+              
+              try {
+                // 保存job_position_question_id用于后续追问
+                this.parentJobPositionQuestionId = res.data.data.job_position_question_id;
+                console.log('保存父问题ID:', this.parentJobPositionQuestionId);
+                // 初始化该题的追问上限与已问次数
+                const limitFromServer = res.data.data.follow_up_limit;
+                if (typeof limitFromServer !== 'undefined') {
+                  this.setFollowUpLimit(this.parentJobPositionQuestionId, limitFromServer);
+                } else {
+                  this.setFollowUpLimit(this.parentJobPositionQuestionId, this.defaultFollowUpLimit);
+                }
+                this.resetFollowUpAskedCount(this.parentJobPositionQuestionId);
+                
+                await this.callInterviewInteraction(res.data.data.job_position_question_id);
+                console.log('面试互动接口调用成功');
+              } catch (error) {
+                console.error('面试互动接口调用失败:', error);
+                this.proceedToNextQuestion();
+              }
+              
+              /* uni.showToast({
+                title: '回答已提交',
+                icon: 'success',
+                duration: 1500
+              }); */
+              
+              this.uploadQueue.shift();
+              this.processUploadQueue();
+            } else {
+              this.handleSubmitFailure(task, '提交失败: ' + (res.data.msg || '未知错误'));
+            }
+          },
+          fail: (err) => {
+            console.error('提交视频失败:', err);
+            this.handleSubmitFailure(task, '提交失败: ' + err.errMsg);
+          }
+        });
+      }
+    },
+    
+    // 添加新方法:处理提交失败
+    handleSubmitFailure(task, errorMsg) {
+      console.error('提交失败:', errorMsg);
+      
+      // 更新任务状态
+      this.uploadStatus[task.id] = 'failed';
+      this.updateUploadStatusText();
+      
+      // 检查是否还有重试机会
+      if (task.attempts < task.maxAttempts) {
+        console.log(`将在5秒后重试提交,当前尝试次数: ${task.attempts}/${task.maxAttempts}`);
+        
+        // 5秒后重试
+        setTimeout(() => {
+          // 重新提交
+          this.submitVideoToInterview(task.videoUrl, task);
+        }, 5000);
+      } else {
+        // 超过最大重试次数,移除任务并继续处理队列
+        console.log('超过最大重试次数,放弃提交');
+        
+        // 显示错误提示
+        /* uni.showToast({
+          title: '视频提交失败,请稍后重试',
+          icon: 'none',
+          duration: 2000
+        }); */
+        
+        // 从队列中移除当前任务
+        this.uploadQueue.shift();
+        
+        // 继续处理队列中的下一个任务
+        this.processUploadQueue();
+      }
+    },
+    
+    // 添加检查转写状态的方法
+    checkTranscriptionStatus(task, requestData, retryCount = 0) {
+      const maxRetries = 24; // 最大重试次数(2分钟)
+      const retryInterval = 5000; // 重试间隔时间(5秒)
+      
+      if (retryCount >= maxRetries) {
+        console.log('转写超时,继续下一个问题');
+        this.isFollowUpMode = false;
+        this.currentVideoIndex = this.mainQuestionIndex;
+        
+        this.uploadQueue.shift();
+        this.processUploadQueue();
+        return;
+      }
+      
+      uni.request({
+        url: `${apiBaseUrl}/voice_interview/check_transcription_status/`,
+        method: 'POST',
+        data: {
+          application_id: requestData.application_id,
+          original_question_id: requestData.original_question_id,
+          video_url: requestData.video_url
+        },
+        header: {
+          'content-type': 'application/x-www-form-urlencoded'
+        },
+        success: (res) => {
+          if (res.data.code === 200 || res.data.code === 2000) {
+            if (res.data.data && res.data.data.status === 'completed') {
+              console.log('视频转写完成');
+              this.isFollowUpMode = false;
+              this.currentVideoIndex = this.mainQuestionIndex;
+              
+              this.uploadQueue.shift();
+              this.processUploadQueue();
+              
+              this.$nextTick(() => {
+                if (this.currentVideoIndex < this.videoList.length) {
+                  this.videoUrl = this.videoList[this.currentVideoIndex];
+                  this.videoPlaying = true;
+                  const videoContext = uni.createVideoContext('myVideo', this);
+                  if (videoContext) {
+                    videoContext.play();
+                  }
+                }
+              });
+            } else {
+              // 状态仍为pending,继续重试
+              console.log(`转写进行中,${retryInterval/1000}秒后重试 (${retryCount + 1}/${maxRetries})`);
+              setTimeout(() => {
+                this.checkTranscriptionStatus(task, requestData, retryCount + 1);
+              }, retryInterval);
+            }
+          } else if (res.data.message === "面试视频尚未完成转写" || res.data.success === false) {
+            // 特殊处理转写未完成的情况
+            console.log(`转写未完成,${retryInterval/1000}秒后重试 (${retryCount + 1}/${maxRetries})`);
+            setTimeout(() => {
+              this.checkTranscriptionStatus(task, requestData, retryCount + 1);
+            }, retryInterval);
+          } else {
+            this.handleSubmitFailure(task, '检查转写状态失败: ' + (res.data.msg || '未知错误'));
+          }
+        },
+        fail: (err) => {
+          console.error('检查转写状态失败:', err);
+          // 网络错误时也进行重试
+          console.log(`网络请求失败,${retryInterval/1000}秒后重试 (${retryCount + 1}/${maxRetries})`);
+          setTimeout(() => {
+            this.checkTranscriptionStatus(task, requestData, retryCount + 1);
+          }, retryInterval);
+        }
+      });
+    },
+    
+    // 添加新方法:更新上传状态文本
+    updateUploadStatusText() {
+      // 检查主上传队列
+      let mainQueueText = '';
+      if (this.uploadQueue.length > 0) {
+        const currentTask = this.uploadQueue[0];
+        const progress = this.uploadProgress[currentTask.id] || 0;
+        const status = this.uploadStatus[currentTask.id] || 'pending';
+        
+        let statusText = '';
+        switch (status) {
+          case 'pending':
+            statusText = '等待上传';
+            break;
+          case 'uploading':
+            statusText = `上传中 ${progress}%`;
+            break;
+          case 'success':
+            statusText = '上传成功,提交中...';
+            break;
+          case 'failed':
+            statusText = `上传失败,${currentTask.attempts < currentTask.maxAttempts ? '即将重试' : '已放弃'}`;
+            break;
+        }
+        
+        // 添加问题类型和文本的中文释义
+        const questionTypeText = currentTask.isFollowUp ? '追问' : '问题';
+        const questionShortText = currentTask.questionText ? 
+          (currentTask.questionText.length > 10 ? currentTask.questionText.substring(0, 10) + '...' : currentTask.questionText) : 
+          `${questionTypeText}${currentTask.questionId}`;
+        
+        mainQueueText = `${questionTypeText}「${questionShortText}」:${statusText}`;
+        
+        // 如果队列中有多个任务,显示总数
+        if (this.uploadQueue.length > 1) {
+          mainQueueText += ` (${this.uploadQueue.length}个视频待处理)`;
+        }
+      }
+      
+      // 检查后台上传队列
+      let backgroundQueueText = '';
+      if (this.backgroundUploadQueue && this.backgroundUploadQueue.length > 0) {
+        const currentTask = this.backgroundUploadQueue[0];
+        const progress = this.uploadProgress[currentTask.id] || 0;
+        const status = this.uploadStatus[currentTask.id] || 'pending';
+        
+        let statusText = '';
+        switch (status) {
+          case 'pending':
+            statusText = '等待后台上传';
+            break;
+          case 'uploading':
+            statusText = `后台上传中 ${progress}%`;
+            break;
+          case 'success':
+            statusText = '后台上传成功,提交中...';
+            break;
+          case 'failed':
+            statusText = `后台上传失败,${currentTask.attempts < currentTask.maxAttempts ? '即将重试' : '已放弃'}`;
+            break;
+        }
+        
+        const questionShortText = currentTask.questionText ? 
+          (currentTask.questionText.length > 10 ? currentTask.questionText.substring(0, 10) + '...' : currentTask.questionText) : 
+          `追问${currentTask.questionId}`;
+        
+        backgroundQueueText = `追问「${questionShortText}」:${statusText}`;
+        
+        // 如果后台上传队列中有多个任务,显示总数
+        if (this.backgroundUploadQueue.length > 1) {
+          backgroundQueueText += ` (${this.backgroundUploadQueue.length}个追问待后台上传)`;
+        }
+      }
+      
+      // 合并状态文本
+      if (mainQueueText && backgroundQueueText) {
+        this.uploadStatusText = `${mainQueueText} | ${backgroundQueueText}`;
+      } else if (mainQueueText) {
+        this.uploadStatusText = mainQueueText;
+      } else if (backgroundQueueText) {
+        this.uploadStatusText = backgroundQueueText;
+      } else {
+        this.uploadStatusText = '';
+      }
+    },
+    
+    // 修改 proceedToNextQuestion 方法,确保在切换视频时重置历史时间
+    proceedToNextQuestion() {
+      // 如果正在切换视频,则返回
+      if (this.isVideoSwitching) {
+        console.log('正在切换视频中,请等待...');
+        return;
+      }
+      
+      console.log('继续下一个问题');
+      this.isVideoSwitching = true; // 设置切换状态锁
+      
+      // 停止当前视频播放
+      const currentVideo = uni.createVideoContext('myVideo', this);
+      if (currentVideo) {
+        currentVideo.stop();
+        this.videoPlaying = false;
+      }
+      
+      // 检查是否已经是最后一个视频
+      if (this.currentVideoIndex + 1 >= this.videoList.length) {
+        // 所有视频都播放完毕,显示完成页面或返回
+        console.log('所有视频已播放完毕');
+        
+        // 清理资源
+        this.stopUserCamera();
+        this.clearCountdown();
+        
+        // 获取当前职位ID
+        const currentJobDetail = JSON.parse(uni.getStorageSync('selectedJob'));
+        console.log('当前职位ID:', currentJobDetail);
+        const jobId = currentJobDetail ? currentJobDetail.id : null;
+        
+        this.handleVideoCompletion(jobId);
+        return;
+      }
+      
+      // 清理当前父题的追问中的并发锁
+      if (this.currentParentQuestionId) {
+        this.followUpRequestInFlight[this.currentParentQuestionId] = false;
+      }
+
+      // 增加当前视频索引,切换到下一个视频
+      this.currentVideoIndex++;
+      
+      // 重置历史时间,避免触发异常跳转检测
+      this.historyTime = 0;
+      
+      // 如果还有视频,播放下一个视频
+      if (this.currentVideoIndex < this.videoList.length) {
+        // 确保先更新视频URL
+        this.videoUrl = this.videoList[this.currentVideoIndex];
+        
+        // 使用setTimeout确保DOM更新完成
+        this.$nextTick(() => {
+          this.videoPlaying = true;
+          const videoContext = uni.createVideoContext('myVideo', this);
+          if (videoContext) {
+            videoContext.play();
+          }
+          this.isVideoSwitching = false; // 重置切换状态锁
+        });
+      } else {
+        // 所有视频都播放完毕,显示完成页面或返回
+        console.log('所有视频已播放完毕');
+        
+        // 清理资源
+        this.stopUserCamera();
+        this.clearCountdown();
+        
+        // 获取当前职位ID
+        const currentJobDetail = JSON.parse(uni.getStorageSync('selectedJob'));
+        console.log('当前职位ID:', currentJobDetail);
+        const jobId = currentJobDetail ? currentJobDetail.id : null;
+        
+        console.log('当前职位ID:', jobId);
+        
+        // 延迟后根据职位ID跳转到不同页面
+        setTimeout(() => {
+          this.isVideoSwitching = false; // 重置切换状态锁
+          // 如果职位ID为9,跳转到interview-question页面
+          if (jobId === 9) {
+            uni.navigateTo({
+              url: '/pages/interview-question/interview-question',
+              success: () => {
+                console.log('成功跳转到interview-question页面');
+              },
+              fail: (err) => {
+                console.error('跳转到interview-question页面失败:', err);
+                // 如果跳转失败,尝试使用redirectTo
+                uni.redirectTo({
+                  url: '/pages/interview-question/interview-question',
+                  fail: (redirectErr) => {
+                    console.error('重定向到interview-question页面也失败:', redirectErr);
+                    // 如果所有跳转方式都失败,尝试返回上一页
+                    uni.navigateBack({
+                      delta: 1
+                    });
+                  }
+                });
+              }
+            });
+          } else {
+            // 其他职位ID跳转到camera页面
+            uni.navigateTo({
+              url: '/pages/camera/camera',
+              success: () => {
+                console.log('成功跳转到camera页面');
+              },
+              fail: (err) => {
+                console.error('跳转到camera页面失败:', err);
+                
+                // 如果跳转失败,尝试使用redirectTo
+                uni.redirectTo({
+                  url: '/pages/camera/camera',
+                  fail: (redirectErr) => {
+                    console.error('重定向到camera页面也失败:', redirectErr);
+                    
+                    // 最后尝试使用switchTab(如果camera是tabBar页面)
+                    uni.switchTab({
+                      url: '/pages/camera/camera',
+                      fail: (switchErr) => {
+                        console.error('所有跳转方式都失败:', switchErr);
+                        
+                        // 如果所有跳转方式都失败,尝试返回上一页
+                        uni.navigateBack({
+                          delta: 1
+                        });
+                      }
+                    });
+                  }
+                });
+              }
+            });
+          }
+        }, 0);
+      }
+    },
+
+    // 修改 handleAnswerButtonClick 方法,确保在切换视频时重置历史时间
+    handleAnswerButtonClick() {
+      console.log('点击开始回答按钮');
+      
+      // 隐藏开始回答按钮
+      this.showAnswerButton = false;
+      
+      // 增加当前视频索引,切换到下一个视频
+      this.currentVideoIndex++;
+      
+      // 重置历史时间,避免触发异常跳转检测
+      this.historyTime = 0;
+      
+      // 如果还有视频,播放下一个视频
+      if (this.currentVideoIndex < this.videoList.length) {
+        this.videoUrl = this.videoList[this.currentVideoIndex];
+        this.videoPlaying = true;
+        
+        this.$nextTick(() => {
+          const videoContext = uni.createVideoContext('myVideo', this);
+          if (videoContext) {
+            videoContext.play();
+          }
+        });
+      }
+    },
+
+    // 处理相机错误
+    handleCameraError(e) {
+      console.error('相机错误:', e);
+      
+      // 获取平台信息
+      const systemInfo = uni.getSystemInfoSync();
+      const isIOS = systemInfo.platform === 'ios';
+      
+      if (isIOS) {
+        console.log('iOS相机错误,尝试重新初始化');
+        
+        // 显示提示
+        uni.showToast({
+          title: '相机初始化中...',
+          icon: 'loading',
+          duration: 2000
+        });
+        
+        // 重置相机
+        this.resetCamera();
+        
+        // 如果正在录制,停止录制
+        if (this.isRecording) {
+          this.isRecording = false;
+          this.showStopRecordingButton = false;
+          
+          // 提供替代选项
+          setTimeout(() => {
+            this.useAlternativeRecordingMethod();
+          }, 1000);
+        }
+      } else {
+        // 显示错误提示
+        uni.showToast({
+          title: '相机初始化失败,请检查权限设置',
+          icon: 'none'
+        });
+        
+        // 尝试备用选项
+        this.tryFallbackOptions();
+      }
+    },
+
+    // 添加新方法:尝试备用选项
+    tryFallbackOptions() {
+      // 检查环境
+      const systemInfo = uni.getSystemInfoSync();
+      
+      // 在小程序环境中使用小程序API
+      if (systemInfo.uniPlatform === 'mp-weixin' || systemInfo.uniPlatform === 'mp-alipay') {
+        this.useMiniProgramCamera();
+      } 
+      // 在H5环境中显示静态图像
+      else {
+        this.showStaticCameraPlaceholder();
+      }
+    },
+
+    // 添加新方法:使用小程序相机API
+    useMiniProgramCamera() {
+      console.log('尝试使用小程序相机组件');
+      // 这里需要在模板中添加小程序相机组件
+      // 并设置一个标志来控制显示
+      this.useMiniProgramCameraComponent = true;
+    },
+
+    // 添加新方法:显示静态图像
+    showStaticCameraPlaceholder() {
+      console.log('显示静态摄像头占位图');
+      // 创建一个图像元素
+      const img = document.createElement('img');
+      img.src = '/static/images/camera-placeholder.png'; // 确保有这个图片资源
+      img.className = 'static-camera-image';
+      img.style.width = '100%';
+      img.style.height = '100%';
+      img.style.objectFit = 'cover';
+      
+      // 获取容器并添加图像
+      const container = this.$refs.userCameraVideo.parentNode;
+      container.appendChild(img);
+    },
+
+    // 修改 handleTimeUpdate 方法
+    handleTimeUpdate(e) {
+      // 获取当前视频播放时间
+      const currentTime = e.detail.currentTime || e.target.currentTime;
+      
+      // 如果正在录制,更新录制时间显示
+      if (this.isRecording && this.recordingTimerCount) {
+        this.recordingTimeDisplay = this.formatTime(this.recordingTimerCount);
+      }
+      
+      // 如果正在播放低分提示视频,使用专门的字幕数组
+      if (this.isPlayingLowScoreVideo) {
+        if (this.lowScoreVideoSubtitles && this.lowScoreVideoSubtitles.length > 0) {
+          const subtitle = this.lowScoreVideoSubtitles[0]; // 使用第一个字幕
+          this.currentSubtitle = subtitle.text;
+        }
+        return;
+      }
+      
+      // 获取当前视频对应的字幕数组
+      let currentSubtitles = null;
+      
+      if (this.isFollowUpQuestion && this.currentFollowUpQuestion) {
+        // 追问问题字幕处理
+        const subtitleKey = `followUpSubtitles_${this.currentFollowUpQuestion.id}`;
+        currentSubtitles = this[subtitleKey] || [{
+          startTime: 0,
+          endTime: 30,
+          text: this.currentFollowUpQuestion.question || 
+                this.currentFollowUpQuestion.question
+        }];
+      } else {
+        // 常规问题字幕处理
+        if (this.currentVideoIndex === 0) {
+          currentSubtitles = this.subtitles;
+        } else {
+          const subtitleArrayName = `question${this.currentVideoIndex}Subtitles`;
+          currentSubtitles = this[subtitleArrayName];
+        }
+      }
+      
+      // 确保字幕持续显示
+      if (currentSubtitles && currentSubtitles.length > 0) {
+        // 找到当前时间对应的字幕
+        const subtitle = currentSubtitles.find(sub => 
+          currentTime >= sub.startTime && currentTime <= sub.endTime
+        ) || currentSubtitles[0]; // 如果找不到对应时间的字幕,使用第一个字幕
+        
+        // 只显示字幕文本
+        if (subtitle) {
+          this.currentSubtitle = subtitle.text;
+        }
+      }
+      
+      // 更新历史时间和时间戳
+      this.historyTime = currentTime;
+      this.lastUpdateTime = Date.now();
+    },
+
+    // Add a new method to handle the "Start Recording" button click
+    handleStartRecordingClick() {
+      // 隐藏"开始回答"按钮
+      this.showStartRecordingButton = false;
+      
+      // 如果倒计时正在进行,清除倒计时
+      this.clearCountdown();
+      
+      // 重置等待回答状态
+      this.isWaitingForAnswer = false;
+      
+      // 直接开始录制
+      this.startRecordingAnswer();
+    },
+
+    // 修改 checkAudioPermission 方法,确保在录制前获取音频权限
+    checkAudioPermission() {
+      // 在小程序环境中
+      const systemInfo = uni.getSystemInfoSync();
+      const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith('mp-');
+      
+      if (isMiniProgram) {
+        // 小程序环境下的权限请求
+        uni.getSetting({
+          success: (res) => {
+            if (!res.authSetting['scope.record']) {
+              uni.authorize({
+                scope: 'scope.record',
+                success: () => {
+                  console.log('录音权限已获取');
+                },
+                fail: (err) => {
+                  console.error('录音权限获取失败:', err);
+                  this.showPermissionDialog('录音');
+                }
+              });
+            }
+            
+            if (!res.authSetting['scope.camera']) {
+              uni.authorize({
+                scope: 'scope.camera',
+                success: () => {
+                  console.log('相机权限已获取');
+                },
+                fail: (err) => {
+                  console.error('相机权限获取失败:', err);
+                  this.showPermissionDialog('相机');
+                }
+              });
+            }
+          }
+        });
+      } else {
+        // 浏览器环境下的权限请求
+        // ... 保持原有代码不变
+      }
+    },
+
+    // 添加新方法:测试音频输入
+    testAudioInput() {
+      if (!this.cameraStream) {
+        console.warn('没有可用的媒体流,无法测试音频');
+        return;
+      }
+      
+      const audioTracks = this.cameraStream.getAudioTracks();
+      if (audioTracks.length === 0) {
+        console.warn('没有检测到音频轨道,尝试重新获取');
+        this.tryGetAudioOnly();
+        return;
+      }
+      
+      console.log('音频轨道信息:', audioTracks[0].getSettings());
+      
+      // 创建音频上下文和分析器
+      try {
+        const AudioContext = window.AudioContext || window.webkitAudioContext;
+        if (!AudioContext) {
+          console.warn('浏览器不支持AudioContext');
+          return;
+        }
+        
+        const audioContext = new AudioContext();
+        const analyser = audioContext.createAnalyser();
+        const microphone = audioContext.createMediaStreamSource(this.cameraStream);
+        microphone.connect(analyser);
+        
+        // 设置分析器
+        analyser.fftSize = 256;
+        const bufferLength = analyser.frequencyBinCount;
+        const dataArray = new Uint8Array(bufferLength);
+        
+        // 检测音频输入
+        let silenceCounter = 0;
+        const checkAudio = () => {
+          if (this.isRecording) return; // 如果正在录制,停止检测
+          
+          analyser.getByteFrequencyData(dataArray);
+          
+          // 计算平均音量
+          let sum = 0;
+          for (let i = 0; i < bufferLength; i++) {
+            sum += dataArray[i];
+          }
+          const average = sum / bufferLength;
+          
+          if (average > 10) {
+            console.log('检测到音频输入,音量:', average);
+            silenceCounter = 0;
+          } else {
+            silenceCounter++;
+            if (silenceCounter > 10) {
+              console.warn('持续检测不到音频输入,可能麦克风未正常工作');
+              silenceCounter = 0;
+            }
+          }
+          
+          // 继续检测
+          requestAnimationFrame(checkAudio);
+        };
+        
+        // 开始检测
+        checkAudio();
+      } catch (e) {
+        console.error('音频测试失败:', e);
+      }
+    },
+
+    // 添加新方法:尝试单独获取音频
+    tryGetAudioOnly() {
+      navigator.mediaDevices.getUserMedia({ audio: true })
+        .then(audioStream => {
+          // 如果已有视频流,合并音频和视频轨道
+          if (this.cameraStream) {
+            const videoTrack = this.cameraStream.getVideoTracks()[0];
+            const audioTrack = audioStream.getAudioTracks()[0];
+            
+            // 创建新的媒体流,包含视频和音频轨道
+            const combinedStream = new MediaStream();
+            if (videoTrack) combinedStream.addTrack(videoTrack);
+            if (audioTrack) combinedStream.addTrack(audioTrack);
+            
+            // 更新摄像头流
+            this.cameraStream = combinedStream;
+            
+            // 更新视频元素的源
+            const videoElement = this.$refs.userCameraVideo;
+            if (videoElement) {
+              videoElement.srcObject = combinedStream;
+              videoElement.muted = true; // 避免回声,但仍然录制声音
+            }
+            
+            console.log('成功合并音频和视频轨道');
+          } else {
+            console.warn('没有视频流可合并');
+          }
+        })
+        .catch(err => {
+          console.error('单独获取音频失败:', err);
+        });
+    },
+
+    // 添加新方法:显示权限对话框
+    showPermissionDialog(permissionType) {
+      uni.showModal({
+        title: '需要权限',
+        content: `请允许使用${permissionType}权限,否则可能影响面试功能`,
+        confirmText: '去设置',
+        success: (res) => {
+          if (res.confirm) {
+            uni.openSetting({
+              success: (settingRes) => {
+                console.log('设置页面打开成功', settingRes);
+              }
+            });
+          }
+        }
+      });
+    },
+
+    // 添加重试上传方法
+    retryVideoUpload() {
+      if (this.lastVideoToRetry) {
+        // 隐藏重试按钮
+        this.showRetryButton = false;
+        
+        // 显示加载提示
+        uni.showLoading({
+          title: '正在重新提交...',
+          mask: true
+        });
+        
+        // 重新提交视频
+        this.submitVideoToInterview(this.lastVideoToRetry);
+      } else {
+        uni.showToast({
+          title: '没有可重试的视频',
+          icon: 'none'
+        });
+      }
+    },
+
+    // 添加一个新方法用于压缩视频
+    async compressVideo(videoBlob) {
+      // 如果视频大小小于某个阈值,直接返回原视频
+      if (videoBlob.size < 5 * 1024 * 1024) { // 小于5MB
+        return videoBlob;
+      }
+      
+      console.log('开始压缩视频,原始大小:', videoBlob.size);
+      
+      // 创建一个视频元素来加载视频
+      const videoElement = document.createElement('video');
+      videoElement.muted = true;
+      videoElement.autoplay = false;
+      
+      // 创建一个canvas元素用于绘制视频帧
+      const canvas = document.createElement('canvas');
+      const ctx = canvas.getContext('2d');
+      
+      // 设置视频源
+      videoElement.src = URL.createObjectURL(videoBlob);
+      
+      return new Promise((resolve) => {
+        videoElement.onloadedmetadata = () => {
+          // 设置canvas尺寸为视频的一半
+          const width = Math.floor(videoElement.videoWidth / 2);
+          const height = Math.floor(videoElement.videoHeight / 2);
+          canvas.width = width;
+          canvas.height = height;
+          
+          // 创建MediaRecorder来录制canvas
+          const stream = canvas.captureStream(15); // 15fps
+          
+          // 如果原视频有音轨,添加到新流中
+          if (videoElement.captureStream) {
+            const originalStream = videoElement.captureStream();
+            const audioTracks = originalStream.getAudioTracks();
+            if (audioTracks.length > 0) {
+              stream.addTrack(audioTracks[0]);
+            }
+          }
+          
+          // 设置较低的比特率
+          const options = {
+            mimeType: 'video/webm;codecs=vp8,opus',
+            audioBitsPerSecond: 64000,
+            videoBitsPerSecond: 800000 // 800kbps
+          };
+          
+          const mediaRecorder = new MediaRecorder(stream, options);
+          const chunks = [];
+          
+          mediaRecorder.ondataavailable = (e) => {
+            if (e.data.size > 0) {
+              chunks.push(e.data);
+            }
+          };
+          
+          mediaRecorder.onstop = () => {
+            const compressedBlob = new Blob(chunks, { type: 'video/webm' });
+            console.log('视频压缩完成,压缩后大小:', compressedBlob.size);
+            resolve(compressedBlob);
+          };
+          
+          // 开始播放视频并录制
+          videoElement.onplay = () => {
+            mediaRecorder.start(10);
+            
+            // 绘制视频帧到canvas
+            const drawFrame = () => {
+              if (videoElement.paused || videoElement.ended) {
+                mediaRecorder.stop();
+                return;
+              }
+              
+              ctx.drawImage(videoElement, 0, 0, width, height);
+              requestAnimationFrame(drawFrame);
+            };
+            
+            drawFrame();
+          };
+          
+          videoElement.play();
+        };
+      });
+    },
+
+    // 修改 checkIOSCameraRecordPermission 方法
+    checkIOSCameraRecordPermission() {
+      const systemInfo = uni.getSystemInfoSync();
+      if (systemInfo.platform !== 'ios') return;
+      
+      // 在iOS上,需要同时请求相机和录音权限
+      uni.getSetting({
+        success: (res) => {
+          // 检查相机权限
+          if (!res.authSetting['scope.camera']) {
+            uni.authorize({
+              scope: 'scope.camera',
+              success: () => {
+                console.log('iOS相机权限已获取');
+              },
+              fail: (err) => {
+                console.error('iOS相机权限获取失败:', err);
+                this.showPermissionDialog('相机');
+              }
+            });
+          }
+          
+          // 检查录音权限
+          if (!res.authSetting['scope.record']) {
+            uni.authorize({
+              scope: 'scope.record',
+              success: () => {
+                console.log('iOS录音权限已获取');
+              },
+              fail: (err) => {
+                console.error('iOS录音权限获取失败:', err);
+                this.showPermissionDialog('录音');
+              }
+            });
+          }
+        }
+      });
+    },
+
+    // 添加新方法:检查并修复渲染问题
+    checkAndFixRenderingIssues() {
+      // 检查全局对象,防止渲染错误
+      try {
+        // 检查是否有全局变量u
+        if (typeof u !== 'undefined' && u) {
+          // 检查currentQuestion属性
+          if (!u.currentQuestion) {
+            console.log('修复: 创建缺失的currentQuestion对象');
+            u.currentQuestion = {};
+          }
+          // 确保isImportant属性存在
+          if (u.currentQuestion && typeof u.currentQuestion.isImportant === 'undefined') {
+            console.log('修复: 设置缺失的isImportant属性');
+            u.currentQuestion.isImportant = false;
+          }
+        }
+      } catch (e) {
+        console.log('防御性检查异常:', e);
+      }
+    },
+
+    // 添加格式化时间的辅助方法
+    formatTime(seconds) {
+      if (!seconds && seconds !== 0) return '03:30'; // 默认显示03:30
+      const minutes = Math.floor(seconds / 60);
+      const remainingSeconds = seconds % 60;
+      return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;
+    },
+
+    // 添加获取问题数据的方法
+    fetchQuestions() {
+      this.loading = true;
+      
+      // 获取tenant_id,如果没有则使用默认值1
+      const tenant_id = JSON.parse(uni.getStorageSync('userInfo')).tenant_id || '1';
+      
+      // 获取当前选择的职位ID
+      let position_id = 1; // 默认值
+      try {
+        const selectedJob = JSON.parse(uni.getStorageSync('selectedJob') || '{}');
+        if (selectedJob && selectedJob.id) {
+          position_id = selectedJob.id;
+          console.log('使用选择的职位ID获取问题:', position_id);
+        } else {
+          console.warn('未找到选择的职位信息,使用默认职位ID:', position_id);
+        }
+      } catch (e) {
+        console.error('解析职位信息失败:', e);
+      }
+      
+      // 构建完整的请求URL,便于调试
+      const timestamp = Date.now();
+      const requestUrl = `${apiBaseUrl}/api/wechat/open_questions/?position_id=${position_id}&tenant_id=${tenant_id}&question_form=0&_t=${timestamp}`;
+      console.log('完整的请求URL:', requestUrl);
+      
+      uni.request({
+        url: requestUrl,
+        method: 'GET',
+        success: (res) => {
+          if (res.data && res.data.code === 2000 && res.data.data && res.data.data.items) {
+            console.log('获取问题数据成功:', res.data.data.items);
+            
+            // 存储问题数据
+            this.questions = res.data.data.items;
+            
+            // 处理视频列表和字幕
+            this.processQuestionData();
+            
+            // 播放介绍视频
+            this.playIntroVideo();
+          } else {
+            console.error('获取问题数据失败:', res.data);
+            uni.showToast({
+              title: '获取问题数据失败',
+              icon: 'none'
+            });
+            
+          /*   // 使用默认视频和字幕
+            this.useDefaultVideosAndSubtitles(); */
+          }
+        },
+        fail: (err) => {
+          console.error('请求问题数据失败:', err);
+          uni.showToast({
+            title: '网络错误,请检查网络连接',
+            icon: 'none'
+          });
+          
+         /*  // 使用默认视频和字幕
+          this.useDefaultVideosAndSubtitles(); */
+        },
+        complete: () => {
+          this.loading = false;
+        }
+      });
+    },
+
+    // 处理问题数据,提取视频URL和字幕
+    processQuestionData() {
+      // 清空视频列表和字幕
+      this.videoList = [];
+      
+      // 首先添加介绍视频
+      this.videoList.push(this.introVideoUrl);
+      
+      // 获取配置数据中的开场白
+        const configStr = uni.getStorageSync('configData');
+        let openingSpeech = [];
+        
+        if (configStr) {
+          try {
+            const configData = JSON.parse(configStr);
+            if (configData && configData.digital_human_opening_speech) {
+              // 检查是否为数组格式
+              if (Array.isArray(configData.digital_human_opening_speech)) {
+                // 将配置数据转换为字幕格式
+                openingSpeech = configData.digital_human_opening_speech.map((item, index, arr) => {
+                  const startTime = index === 0 ? 0 : arr[index - 1].end_time || index * 5;
+                  const endTime = item.end_time || (index + 1) * 5;
+                  return {
+                    startTime,
+                    endTime,
+                    text: item.content
+                  };
+                });
+              } else if (typeof configData.digital_human_opening_speech === 'string') {
+                // 使用新的方法处理字符串类型的开场白
+                openingSpeech = this.convertStringToSubtitles(configData.digital_human_opening_speech);
+              }
+            }
+          } catch (error) {
+            console.error('解析configData失败:', error);
+          }
+        }
+  
+      // 如果成功获取到开场白配置则使用配置的内容,否则使用默认字幕
+      this.subtitles = openingSpeech.length > 0 ? openingSpeech : [
+        {
+          startTime: 0,
+          endTime: 5,
+          text: '你好,我是本次面试的面试官,欢迎参加本公司的线上面试!'
+        },
+        {
+          startTime: 5,
+          endTime: 13,
+          text: '面试预计需要15分钟,请你提前安排在网络良好、光线亮度合适、且相对安静的环境参加这次面试'
+        },
+        {
+          startTime: 13,
+          endTime: 20,
+          text: '以免影响本次面试的结果。如果你在面试过程中遇到问题,请与我们的招聘人员联系。'
+        }
+      ];
+      console.log('处理后的字幕数据:', this.subtitles);
+      // 按照sequence_number排序问题
+      const sortedQuestions = [...this.questions].sort((a, b) => a.sequence_number - b.sequence_number);
+      
+      // 只处理前5个问题(或者更少,如果问题总数不足5个)
+      const questionsToUse = sortedQuestions.slice(0, 5);
+      
+      // 为每个问题添加视频URL和字幕
+      questionsToUse.forEach((question, index) => {
+        if (question.digital_human_video_url) {
+          this.videoList.push(question.digital_human_video_url);
+          
+          // 创建字幕映射,只保留文本
+          const subtitleArray = [{
+            startTime: 0,
+            endTime: 30, // 延长字幕显示时间到30秒
+            text: question.question || question.question
+          }];
+          
+          const videoIndex = this.videoList.length - 1;
+          this[`question${videoIndex}Subtitles`] = subtitleArray;
+          
+          // 存储字幕映射
+          this.subtitleMap[question.digital_human_video_url] = subtitleArray;
+        }
+      });
+      
+      // 如果没有获取到任何问题视频,使用默认视频
+      if (this.videoList.length <= 1) {
+    /*     this.useDefaultVideosAndSubtitles(); */
+      } else {
+        console.log('处理后的视频列表:', this.videoList);
+        console.log('处理后的字幕:', this.subtitles);
+      }
+    },
+
+    // 将字符串类型的文本转换为字幕格式
+    convertStringToSubtitles(text) {
+      if (!text || typeof text !== 'string') {
+        return [];
+      }
+      
+      // 按照标点符号分割文本,保留标点符号
+      const sentences = text.split(/([。!?!?])/)
+        .filter(part => part.trim() !== '')
+        .reduce((acc, part, index, arr) => {
+          if (index % 2 === 0) {
+            // 文本部分
+            const nextPart = arr[index + 1] || '';
+            acc.push(part + nextPart);
+          }
+          return acc;
+        }, [])
+        .filter(sentence => sentence.trim().length > 0);
+      
+      // 如果没有明显的分句标点,按长度分割
+      if (sentences.length <= 1) {
+        const maxLength = 30; // 每段最大字符数
+        const textParts = [];
+        for (let i = 0; i < text.length; i += maxLength) {
+          textParts.push(text.substring(i, i + maxLength));
+        }
+        sentences.splice(0, sentences.length, ...textParts);
+      }
+      
+      // 为每个句子分配时间戳
+      let currentStartTime = 0;
+      return sentences.map((sentence) => {
+        const duration = Math.max(3, Math.ceil(sentence.length / 6)); // 根据文本长度计算时长
+        const startTime = currentStartTime;
+        const endTime = startTime + duration;
+        currentStartTime = endTime;
+        return {
+          startTime,
+          endTime,
+          text: sentence.trim()
+        };
+      });
+    },
+
+    // 使用默认视频和字幕(作为备用)
+    useDefaultVideosAndSubtitles() {
+      console.log('使用默认视频和字幕');
+      
+      // 设置默认字幕
+      this.subtitles = [
+        {
+          startTime: 0,
+          endTime: 5,
+          text: '你好,我是本次面试的面试官,欢迎参加本公司的线上面试!'
+        },
+        {
+          startTime: 5,
+          endTime: 13,
+          text: '面试预计需要15分钟,请你提前安排在网络良好、光线亮度合适、且相对安静的环境参加这次面试'
+        },
+        {
+          startTime: 13,
+          endTime: 20,
+          text: '以免影响本次面试的结果。如果你在面试过程中遇到问题,请与我们的招聘人员联系。'
+        }
+      ];
+      
+      // 设置默认问题字幕
+      this.question1Subtitles = [{
+        startTime: 0,
+        endTime: 10,
+        text: '请结合您的基本信息与过往履历进行简单的自我介绍,并讲一讲您有哪些优势胜任本岗位:'
+      }];
+      
+      this.question2Subtitles = [{
+        startTime: 0,
+        endTime: 4,
+        text: '在工作中,你如何确保个人防护装备的正确使用?'
+      }];
+      
+      this.question3Subtitles = [{
+        startTime: 0,
+        endTime: 4,
+        text: '描述一次你与团队合作改善生产流程的经历。'
+      }];
+      
+      this.question4Subtitles = [{
+        startTime: 0,
+        endTime: 6,
+        text: '你在团队合作中曾遇到过哪些挑战?如何解决团队内部的分歧?'
+      }];
+      
+      this.question5Subtitles = [{
+        startTime: 0,
+        endTime: 5,
+        text: '您已完成本次面试全部题目,请问您对于这个岗位还有什么想要了解的吗?'
+      }];
+    },
+
+    // 播放介绍视频
+    playIntroVideo() {
+      // 设置第一个视频(介绍视频)
+      this.videoUrl = this.videoList[0];
+      this.videoPlaying = true;
+      
+      this.$nextTick(() => {
+        const videoContext = uni.createVideoContext('myVideo', this);
+        if (videoContext) {
+          videoContext.play();
+        }
+      });
+    },
+
+    // 添加新方法:获取默认问题ID
+    getDefaultQuestionId(videoIndex) {
+      // 根据视频索引映射到默认问题ID
+      switch(videoIndex) {
+        case 1: // 第一个问题
+          return 10;
+        case 2: // 第二个问题
+          return 11;
+        case 3: // 第三个问题
+          return 12;
+        case 4: // 第四个问题
+          return 13;
+        default:
+          return 10; // 默认值
+      }
+    },
+
+    // 添加新方法:根据索引获取当前问题
+    getCurrentQuestionByIndex(videoIndex) {
+      // 视频索引减1,因为第一个视频是介绍视频
+      const questionIndex = videoIndex - 1;
+      
+      // 按照sequence_number排序问题
+      const sortedQuestions = [...this.questions].sort((a, b) => a.sequence_number - b.sequence_number);
+      
+      // 检查索引是否有效
+      if (questionIndex >= 0 && questionIndex < sortedQuestions.length) {
+        return sortedQuestions[questionIndex];
+      }
+      
+      return null;
+    },
+
+    // 添加新方法:获取当前问题的推荐录制时长
+    getCurrentQuestionRecommendedDuration() {
+      const currentQuestion = this.getCurrentQuestionByIndex(this.currentVideoIndex);
+      if (currentQuestion && currentQuestion.recommended_duration) {
+        // 如果问题有推荐时长,使用推荐时长(转换为秒)
+        const recommendedDuration = parseInt(currentQuestion.recommended_duration);
+        console.log(`使用问题推荐时长: ${recommendedDuration}秒`);
+        return recommendedDuration;
+      }
+      
+      // 如果没有推荐时长,使用默认值300秒(5分钟)
+      console.log('使用默认录制时长: 300秒');
+      return 300;
+    },
+
+
+
+    // 添加新方法:重置录制状态,准备重新回答
+    resetForRerecording() {
+      console.log('重置录制状态,准备重新回答');
+      
+      // 重置录制状态
+      this.isRecording = false;
+      this.showStopRecordingButton = false;
+      
+      // 显示"开始回答"按钮
+      this.showStartRecordingButton = true;
+      
+      // 清除倒计时
+      this.clearCountdown();
+      
+      // 重置录制计时器
+      if (this.recordingTimer) {
+        clearInterval(this.recordingTimer);
+        this.recordingTimer = null;
+      }
+      
+      // 重置录制时间显示
+      this.recordingTimerCount = 0;
+      this.recordingTimeDisplay = '00:00 ';/* / 05:00 */
+      
+      // 重新获取当前问题的推荐录制时长
+      this.maxRecordingTime = this.getCurrentQuestionRecommendedDuration();
+      this.remainingTime = this.maxRecordingTime;
+      
+      // 如果是浏览器环境,停止MediaRecorder
+      if (this.mediaRecorder && this.mediaRecorder.state !== 'inactive') {
+        this.mediaRecorder.stop();
+        this.recordedChunks = [];
+      }
+      
+      // 如果是小程序环境,停止相机录制
+      if (this.cameraContext) {
+        this.cameraContext.stopRecord({
+          success: () => {
+            console.log('相机录制已停止');
+          },
+          fail: (err) => {
+            console.error('停止相机录制失败:', err);
+          }
+        });
+      }
+      
+      // 重置问题重试次数映射
+      this.questionRetryMap = {};
+    },
+
+    // 修改 playLowScoreVideo 方法,优化字幕显示并添加重试次数限制
+    playLowScoreVideo() {
+      console.log('播放低分提示视频');
+      
+      // 获取当前问题的重试次数
+      const currentQuestionId = this.getCurrentQuestionByIndex(this.currentVideoIndex)?.id;
+      if (!currentQuestionId) {
+        console.error('无法获取当前问题ID');
+        return;
+      }
+      
+      // 初始化或增加重试次数
+      if (!this.questionRetryMap[currentQuestionId]) {
+        this.questionRetryMap[currentQuestionId] = 1;
+      } else {
+        this.questionRetryMap[currentQuestionId]++;
+      }
+      
+      // 检查是否超过最大重试次数
+      if (this.questionRetryMap[currentQuestionId] > this.maxQuestionRetries) {
+        console.log(`问题 ${currentQuestionId} 已超过最大重试次数,自动进入下一题`);
+        // 重置低分视频状态
+        this.isPlayingLowScoreVideo = false;
+        // 重置追问相关状态
+        this.isFollowUpQuestion = false;
+        this.currentFollowUpQuestion = null;
+        this.followUpQuestion = '';
+        this.parentQuestion = '';
+        // 增加视频索引,进入下一题
+        this.currentVideoIndex++;
+        // 检查是否还有下一题
+        if (this.currentVideoIndex < this.videoList.length) {
+          // 获取下一题的字幕
+          const nextQuestion = this.getCurrentQuestionByIndex(this.currentVideoIndex);
+          if (nextQuestion) {
+            this.currentSubtitle = nextQuestion.question || nextQuestion.question;
+          }
+          // 播放下一题的视频
+          this.videoUrl = this.videoList[this.currentVideoIndex];
+          this.videoPlaying = true;
+          this.$nextTick(() => {
+            const videoContext = uni.createVideoContext('myVideo', this);
+            if (videoContext) {
+              videoContext.play();
+            }
+          });
+        } else {
+          // 如果没有下一题,结束面试
+          this.finishInterview();
+        }
+        return;
+      }
+      
+      // 标记正在播放低分提示视频
+      this.isPlayingLowScoreVideo = true;
+      
+      // 隐藏其他按钮
+      this.showStartRecordingButton = false;
+      this.showStopRecordingButton = false;
+      this.showRerecordButton = false;
+      
+      // 设置视频URL
+      this.videoUrl = this.lowScoreVideoUrl;
+      this.videoPlaying = true;
+      
+      // 保存当前问题的字幕
+      const currentQuestion = this.getCurrentQuestionByIndex(this.currentVideoIndex);
+      const originalSubtitle = currentQuestion ? (currentQuestion.question || currentQuestion.question) : this.currentSubtitle;
+      
+      // 清除现有字幕
+      this.currentSubtitle = '';
+      
+      // 使用 nextTick 确保 DOM 更新后再播放视频
+      this.$nextTick(() => {
+        const videoContext = uni.createVideoContext('myVideo', this);
+        if (videoContext) {
+          videoContext.play();
+          
+          // 视频开始播放后短暂延迟显示字幕,确保用户注意到
+          setTimeout(() => {
+            // 设置低分提示视频的字幕
+            this.currentSubtitle = '我未听清楚您在说什么,请您再说一遍!';
+            
+            // 创建专门的字幕数组用于低分提示视频
+            this.lowScoreVideoSubtitles = [
+              {
+                startTime: 0,
+                endTime: 30,
+                text: '我未听清楚您在说什么,请您再说一遍!',
+                translation: 'I didn\'t quite catch what you said, could you please repeat it?'
+              }
+            ];
+          }, 500);
+        }
+      });
+      
+      // 保存原始字幕信息到实例属性,以便在视频结束时恢复
+      this.originalQuestionSubtitle = originalSubtitle;
+    },
+
+    // 添加新方法:处理重新录制按钮点击
+    handleRerecordButtonClick() {
+      console.log('点击重新录制按钮');
+      
+      // 增加重试计数
+      this.retryCount++;
+      console.log(`当前重试次数: ${this.retryCount}/${this.maxRetryAttempts}`);
+      
+      // 隐藏重新录制按钮
+      this.showRerecordButton = false;
+      
+      // 直接调用开始录制的方法
+      this.handleStartRecordingClick();
+    },
+
+    // 页面卸载时关闭WebSocket连接
+    onUnload() {
+      console.log('页面卸载,关闭WebSocket连接');
+      this.cleanupPersonDetectionWebSocket();
+      // 清理其他资源
+      this.stopUserCamera();
+      this.clearCountdown();
+      
+      // 清理录制相关定时器
+      if (this.recordingTimer) {
+        clearInterval(this.recordingTimer);
+        this.recordingTimer = null;
+      }
+      
+      // 停止MediaRecorder
+      if (this.mediaRecorder && this.mediaRecorder.state !== 'inactive') {
+        this.mediaRecorder.stop();
+      }
+      
+      // 关闭屏幕常亮
+      uni.setKeepScreenOn({
+        keepScreenOn: false
+      });
+    },
+
+    // 页面隐藏时关闭WebSocket连接
+    onHide() {
+      console.log('页面隐藏,关闭WebSocket连接');
+      
+      // 完全关闭WebSocket连接和相关定时器
+      this.cleanupPersonDetectionWebSocket();
+      
+      // 如果正在录制,给用户提示
+      if (this.isRecording) {
+        console.log('页面隐藏时正在录制,录制将继续');
+        // 可以选择暂停录制或者给用户提示
+        uni.showToast({
+          title: '请不要离开面试页面',
+          icon: 'none',
+          duration: 2000
+        });
+      }
+    },
+
+    // 页面显示时重新初始化WebSocket连接
+    onShow() {
+      console.log('identity-verify页面onShow');
+      console.log('当前本地存储中的职位信息:', uni.getStorageSync('selectedJob'));
+      
+      // 每次页面显示时重新获取问题
+      this.fetchQuestions();
+     // this.fetchFollowUpQuestions(); // 添加获取追问问题的调用
+      
+      // 重新初始化WebSocket连接(仅在小程序环境中)
+      const systemInfo = uni.getSystemInfoSync();
+      const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith('mp-');
+      if (isMiniProgram) {
+        // 如果WebSocket未连接,重新初始化
+        if (!this.personDetectionSocket) {
+          console.log('重新初始化WebSocket连接');
+          this.initPersonDetectionWebSocket();
+        }
+        // 如果WebSocket已连接但检测定时器被停止,重新启动检测
+        else if (!this.personDetectionInterval) {
+          console.log('重新启动人脸检测定时器');
+          this.startPersonDetectionInterval();
+        }
+      }
+	   uni.hideHomeButton(); // 隐藏左上角返回按钮
+    },
+
+    // 添加新方法:阻止视频控制
+    preventVideoControl(e) {
+      // 阻止默认行为和事件冒泡
+      e.preventDefault();
+      e.stopPropagation();
+      console.log('阻止视频控制操作');
+      return false;
+    },
+
+    // 添加获取追问问题的方法
+    fetchFollowUpQuestions() {
+      // 获取tenant_id,如果没有则使用默认值1
+      const tenant_id = JSON.parse(uni.getStorageSync('userInfo')).tenant_id || '1';
+      
+      // 获取当前选择的职位ID
+      let position_id = 1; // 默认值
+      try {
+        const selectedJob = JSON.parse(uni.getStorageSync('selectedJob') || '{}');
+        if (selectedJob && selectedJob.id) {
+          position_id = selectedJob.id;
+          console.log('使用选择的职位ID获取追问问题:', position_id);
+        } else {
+          console.warn('未找到选择的职位信息,使用默认职位ID:', position_id);
+        }
+      } catch (e) {
+        console.error('解析职位信息失败:', e);
+      }
+      
+      // 构建完整的请求URL,便于调试
+      const timestamp = Date.now();
+      const requestUrl = `${apiBaseUrl}/api/wechat/open_questions/?position_id=${position_id}&tenant_id=${tenant_id}&question_form=5&_t=${timestamp}`;
+      console.log('获取追问问题的请求URL:', requestUrl);
+      
+      uni.request({
+        url: requestUrl,
+        method: 'GET',
+        success: (res) => {
+          if (res.data && res.data.code === 2000 && res.data.data && res.data.data.items) {
+            console.log('获取追问问题数据成功:', res.data.data.items);
+            
+            // 存储追问问题数据,并确保每个问题都有question_form=5标记
+            this.followUpQuestions = res.data.data.items.map(item => ({
+              ...item,
+              question_form: 5 // 确保每个追问问题都有正确的question_form值
+            }));
+            
+            // 处理追问问题数据,建立与父问题的关联
+            this.processFollowUpQuestions();
+          } else {
+            console.error('获取追问问题数据失败:', res.data);
+            // 初始化为空数组,避免undefined错误
+            this.followUpQuestions = [];
+          }
+        },
+        fail: (err) => {
+          console.error('请求追问问题数据失败:', err);
+          // 初始化为空数组,避免undefined错误
+          this.followUpQuestions = [];
+        }
+      });
+    },
+
+    // 改进处理追问问题数据的方法
+    processFollowUpQuestions() {
+      if (!this.followUpQuestions || this.followUpQuestions.length === 0) {
+        console.log('没有追问问题数据');
+        this.followUpQuestions = []; // 确保是数组
+        return;
+      }
+      
+      console.log('处理追问问题数据,总数:', this.followUpQuestions.length);
+      
+      // 过滤掉没有parent_question_id的追问问题
+      this.followUpQuestions = this.followUpQuestions.filter(q => q.parent_question_id);
+      
+      // 可以在这里进行额外的数据处理,如按照parent_question_id分组等
+      const parentQuestionIds = new Set();
+      this.followUpQuestions.forEach(question => {
+        if (question.parent_question_id) {
+          parentQuestionIds.add(question.parent_question_id);
+        }
+      });
+      
+      console.log('有追问的父问题ID:', Array.from(parentQuestionIds));
+      
+      // 初始化已播放追问记录对象
+      this.hasPlayedFollowUp = {};
+    },
+
+    // 修改检查并播放追问问题的方法
+    checkAndPlayFollowUpQuestion(parentQuestionId) {
+      console.log('检查是否有追问问题,父问题ID:', parentQuestionId);
+      
+      // 如果正在等待用户回答,不进行任何操作
+      if (this.isWaitingForAnswer) {
+        console.log('正在等待用户回答,暂不处理追问');
+        return;
+      }
+      
+      // 超过追问上限则直接进入下一题
+      if (!this.canAskMoreFollowUps(parentQuestionId)) {
+        console.log('追问次数已达上限,进入下一题');
+        this.proceedToNextQuestion();
+        return;
+      }
+
+      if (!parentQuestionId) {
+        console.warn('没有父问题ID,无法检查追问问题');
+        this.proceedToNextQuestion();
+        return;
+      }
+
+      // 如果已经播放过这个问题的追问,则直接进入下一个问题
+      if (this.hasPlayedFollowUp[parentQuestionId]) {
+        console.log('已经播放过此问题的追问,直接进入下一个问题');
+        this.retryCount = 0;
+        this.proceedToNextQuestion();
+        return;
+      }
+
+      // 查找对应的追问问题
+      const followUpQuestion = this.followUpQuestions.find(q => 
+        q.parent_question_id === parentQuestionId && 
+        q.digital_human_video_url && 
+        q.question_form === 5
+      );
+
+      if (followUpQuestion) {
+        console.log('找到追问问题:', followUpQuestion);
+        
+        // 检查录制时长
+        const recordingDuration = this.getRecordingDuration();
+        const lowScoreDuration = 7; // 低分阈值时长(秒),少于7秒视为低分
+        const minDuration = 3; // 最小录制时长阈值(秒)
+        
+        // 如果录制时间少于最小时长或者在最小时长和低分阈值之间,播放"未听清楚"提示视频
+        if (recordingDuration < lowScoreDuration) {
+          let message = recordingDuration < minDuration ? 
+            `录制时间 ${recordingDuration} 秒,少于最小时长 ${minDuration} 秒` :
+            `录制时间 ${recordingDuration} 秒,少于标准时长 ${lowScoreDuration} 秒`;
+          console.log(message + ',将播放低分提示视频');
+          
+          // 增加重试次数
+          this.retryCount++;
+          
+          // 设置需要播放低分提示视频
+          this.needPlayLowScoreVideo = true;
+          
+          // 播放低分提示视频
+          this.playLowScoreVideo();
+          return;
+        }
+        
+        // 如果录制时长足够,重置重试次数
+        this.retryCount = 0;
+        
+        // 标记此追问已播放
+        this.hasPlayedFollowUp[parentQuestionId] = true;
+        
+        // 标记当前是追问问题
+        this.isFollowUpQuestion = true;
+        
+        // 记录当前父问题ID
+        this.currentParentQuestionId = parentQuestionId;
+        
+        // 保存当前追问问题的完整信息
+        this.currentFollowUpQuestion = followUpQuestion;
+        
+        // 播放追问问题视频
+        this.playFollowUpQuestionVideo(followUpQuestion);
+      } else {
+        console.log('没有找到对应的追问问题,继续下一个问题');
+        this.retryCount = 0;
+        this.proceedToNextQuestion();
+      }
+    },
+
+    // 修改播放追问问题视频的方法
+    playFollowUpQuestionVideo(followUpQuestion) {
+      console.log('播放追问问题视频:', followUpQuestion.digital_human_video_url);
+      
+      // 保存父问题内容
+      this.parentQuestion = this.currentSubtitle;
+      
+      this.videoUrl = followUpQuestion.digital_human_video_url;
+      this.videoPlaying = true;
+      this.isFollowUpQuestion = true;
+      this.currentFollowUpQuestion = followUpQuestion;
+      
+      // 设置追问问题的字幕
+      const followUpSubtitles = [{
+        startTime: 0,
+        endTime: 60, // 延长显示时间到60秒
+        text: followUpQuestion.question || followUpQuestion.question
+      }];
+      
+      const subtitleKey = `followUpSubtitles_${followUpQuestion.id}`;
+      this[subtitleKey] = followUpSubtitles;
+      
+      this.$nextTick(() => {
+        const videoContext = uni.createVideoContext('myVideo', this);
+        if (videoContext) {
+          videoContext.play();
+          
+          // 更新当前字幕为追问内容
+          this.currentSubtitle = followUpSubtitles[0].text;
+        }
+      });
+    },
+
+    // 添加作废面试的方法
+    invalidateInterview() {
+      // 停止录制(如果正在录制)
+      if (this.isRecording) {
+        this.stopRecordingAnswer();
+      }
+      
+      // 清除所有计时器
+      if (this.recordingTimer) {
+        clearInterval(this.recordingTimer);
+      }
+      
+      // 重置状态
+      this.isRecording = false;
+      this.showStopRecordingButton = false;
+      this.showStartRecordingButton = false;
+      
+      // 显示作废提示
+      // uni.showToast({
+      //   title: 'Interview invalidated',
+      //   icon: 'none',
+      //   duration: 2000
+      // });
+      
+      // 延迟后返回上一页
+      setTimeout(() => {
+        uni.switchTab({
+        url: '/pages/index/index'
+      });
+      }, 500);
+    },
+
+    initPersonDetectionWebSocket() {
+      if (this.personDetectionSocket) {
+        this.cleanupPersonDetectionWebSocket();
+      }
+
+      try {
+        this.personDetectionSocket = uni.connectSocket({
+          url: `${personDetectionWsUrl}/ws/interview-room/room_${uni.getStorageSync('appId')}/${uni.getStorageSync('appId')}/`,
+          success: () => {
+            console.log('WebSocket connection initiated');
+          },
+          fail: (error) => {
+            console.error('WebSocket connection failed:', error);
+          }
+        });
+
+        this.personDetectionSocket.onOpen(() => {
+          console.log('WebSocket connection opened');
+          this.startPersonDetectionInterval();
+        });
+
+        this.personDetectionSocket.onError((error) => {
+          console.error('WebSocket error:', error);
+          this.cleanupPersonDetectionWebSocket();
+        });
+
+        this.personDetectionSocket.onClose(() => {
+          console.log('WebSocket connection closed');
+          this.cleanupPersonDetectionWebSocket();
+        });
+
+        this.personDetectionSocket.onMessage((res) => {
+          try {
+            const data = JSON.parse(res.data);
+          /*   console.log('data1', data); */
+            if (data.type === 'person_detection_result') {
+              this.handlePersonDetectionResult(data);
+            }
+          } catch (error) {
+            console.error('Error parsing WebSocket message:', error);
+          }
+        });
+      } catch (error) {
+        console.error('Error initializing WebSocket:', error);
+        this.cleanupPersonDetectionWebSocket();
+      }
+    },
+
+    startPersonDetectionInterval() {
+      if (this.personDetectionInterval) {
+        clearInterval(this.personDetectionInterval);
+      }
+
+      this.personDetectionInterval = setInterval(() => {
+        try {
+          if (!this.personDetectionSocket || !this.cameraContext) {
+            console.warn('人脸检测:相机上下文或WebSocket连接未就绪');
+            return;
+          }
+
+          this.cameraContext.takePhoto({
+            quality: 'low',
+            success: (res) => {
+              try {
+                const tempFilePath = res.tempImagePath;
+                if (!tempFilePath) {
+                  console.warn('人脸检测:未获取到有效的图片路径');
+                 
+                }
+                uni.getFileSystemManager().readFile({
+                  filePath: tempFilePath,
+                  encoding: 'base64',
+                  success: (res) => {
+                    try {
+                      const base64Image = res.data;
+                      if (!this.personDetectionSocket || this.personDetectionSocket.readyState !== 1) {
+                        console.warn('人脸检测:WebSocket连接已断开或未就绪');
+                        return;
+                      }
+                      this.personDetectionSocket.send({
+                        data: JSON.stringify({
+                          type: 'person_detection',
+                          image_data: base64Image
+                        })
+                      });
+                    } catch (wsError) {
+                      console.error('人脸检测:发送WebSocket数据时出错:', wsError);
+                    }
+                  },
+                  fail: (error) => {
+                    console.error('人脸检测:读取图片文件失败:', error);
+                  }
+                });
+              } catch (fileError) {
+                console.error('人脸检测:处理图片文件时出错:', fileError);
+              }
+            },
+            fail: (error) => {
+              console.error('人脸检测:拍照失败:', error);
+            }
+          });
+        } catch (mainError) {
+          console.error('人脸检测:主流程执行出错:', mainError);
+        }
+      }, 5000);
+    },
+
+    cleanupPersonDetectionWebSocket() {
+      if (this.personDetectionInterval) {
+        clearInterval(this.personDetectionInterval);
+        this.personDetectionInterval = null;
+      }
+
+      if (this.personDetectionSocket) {
+        try {
+          this.personDetectionSocket.close();
+        } catch (error) {
+          console.error('Error closing WebSocket:', error);
+        }
+        this.personDetectionSocket = null;
+      }
+    },
+
+    handlePersonDetectionResult(data) {
+      console.log('data', data);
+      /* console.log(data.data.detection.has_person);
+      console.log(data.data.identity.status);//identity_verified */
+      
+      /* // 首先检查是否有人
+      if (!data.data.detection.has_person) {
+        this.showPageWarning = true;
+        uni.showToast({
+          title: '请勿离开摄像头',
+          icon: 'none',
+          duration: 3000
+        });
+        // 添加震动反馈
+        uni.vibrateLong({
+          success: function () {
+            console.log('Vibration successful');
+          },
+          fail: function (err) {
+            console.error('Vibration failed:', err);
+          }
+        });
+        setTimeout(() => {
+          this.showPageWarning = false;
+        }, 3000);
+      }
+      // 然后检查身份验证状态
+      else */ if (data.data.identity.status == "no_face") {
+         this.showPageWarning = true;
+        uni.showToast({/* data.data.identity.message */
+          title: '请保持面部完整出现在镜头内',
+          icon: 'none',
+          duration: 3000
+        });
+        uni.vibrateLong({
+          success: function () {
+            console.log('Vibration successful');
+          },
+          fail: function (err) {
+            console.error('Vibration failed:', err);
+          }
+        });
+        setTimeout(() => {
+          this.showPageWarning = false;
+        }, 3000);
+      }
+    },
+
+    // 进入追问模式
+    enterFollowUpMode() {
+      this.isFollowUpMode = true;
+      this.mainQuestionIndex = this.currentVideoIndex; // 保存当前主问题的索引
+      console.log('进入追问模式,保存主问题索引:', this.mainQuestionIndex);
+    },
+
+    // 修改 handleFollowUpQuestion 方法
+    async handleFollowUpQuestion(questionData) {
+      console.log('处理追问:', questionData);
+      this.enterFollowUpMode();
+      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]);
+          }
+        });
+      }
+    },
+
+    // 显示面试官思考中loading
+    showThinkingLoading() {
+      this.isThinking = true;
+      uni.showLoading({
+        title: '面试官正在思考中',
+        mask: false
+      });
+    },
+    
+    // 隐藏面试官思考中loading
+    hideThinkingLoading() {
+      this.isThinking = false;
+      uni.hideLoading();
+      if (this.thinkingTimer) {
+        clearTimeout(this.thinkingTimer);
+        this.thinkingTimer = null;
+      }
+    },
+
+    // 处理视频完成
+    handleVideoCompletion(jobId) {
+      this.isVideoSwitching = false; // 重置切换状态锁
+      
+      // 延迟执行跳转,确保资源清理完成
+     /*  setTimeout(() => { */
+        // 如果职位ID为9,跳转到interview-question页面
+        if (jobId === 9) {
+          uni.navigateTo({
+            url: '/pages/interview-question/interview-question',
+            success: () => {
+              console.log('成功跳转到interview-question页面');
+            },
+            fail: (err) => {
+              console.error('跳转到interview-question页面失败:', err);
+              // 如果跳转失败,尝试使用redirectTo
+              uni.redirectTo({
+                url: '/pages/interview-question/interview-question',
+                fail: (redirectErr) => {
+                  console.error('重定向到interview-question页面也失败:', redirectErr);
+                  // 如果所有跳转方式都失败,尝试返回上一页
+                  uni.navigateBack({
+                    delta: 1
+                  });
+                }
+              });
+            }
+          });
+        } else {
+          // 其他职位ID跳转到camera页面
+          uni.navigateTo({
+            url: '/pages/camera/camera',
+            success: () => {
+              console.log('成功跳转到camera页面');
+            },
+            fail: (err) => {
+              console.error('跳转到camera页面失败:', err);
+              
+              // 如果跳转失败,尝试使用redirectTo
+              uni.redirectTo({
+                url: '/pages/camera/camera',
+                fail: (redirectErr) => {
+                  console.error('重定向到camera页面也失败:', redirectErr);
+                  
+                  // 最后尝试使用switchTab(如果camera是tabBar页面)
+                  uni.switchTab({
+                    url: '/pages/camera/camera',
+                    fail: (switchErr) => {
+                      console.error('所有跳转方式都失败:', switchErr);
+                      
+                      // 如果所有跳转方式都失败,尝试返回上一页
+                      uni.navigateBack({
+                        delta: 1
+                      });
+                    }
+                  });
+                }
+              });
+            }
+          });
+        }
+      /* }, 200); */
+    },
+  },
+  computed: {
+    // 计算进度比例
+    progressRatio() {
+      return this.recordingTimerCount / this.maxRecordingTime;
+    },
+    // 右半圆旋转角度
+    half1Turn() {
+      // 初始状态为0度,小于50%时,右半圆按比例旋转
+      if (this.progressRatio <= 0.5) {
+        return this.progressRatio * 2 * 180;
+      } else {
+        // 大于50%时,右半圆固定在180度
+        return 180;
+      }
+    },
+    // 左半圆旋转角度
+    half2Turn() {
+      // 小于50%时,左半圆固定在0度
+      if (this.progressRatio <= 0.5) {
+        return 0;
+      } else {
+        // 大于50%时,左半圆按超出50%的比例旋转
+        return (this.progressRatio - 0.5) * 2 * 180;
+      }
+    },
+    // 修改进度百分比的计算方式
+    progressPercent() {
+      // 将时间进度转换为百分比(0-100)
+      return Math.min(Math.round((this.recordingTimerCount / this.maxRecordingTime) * 100), 100);
+    },
+    // 添加总题数计算属性
+    totalQuestions() {
+      // 获取问题总数,不包括介绍视频
+      return this.questions.length || 5; // 如果没有问题数据,默认显示5
+    }
+  }
+}
+</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%;
+  margin: 0 auto;
+  height: 100vh;
+  display: flex;
+  flex-direction: column;
+  background-color: #f5f5f5;
+  transition: all 0.3s ease;
+  position: relative;
+}
+
+.page-warning {
+  animation: page-warning-flash 1s ease-in-out infinite;
+}
+
+@keyframes page-warning-flash {
+  0% { 
+    background-color: rgba(255, 0, 0, 0.2);
+    box-shadow: 0 0 20px rgba(255, 0, 0, 0.3);
+  }
+  50% { 
+    background-color: rgba(255, 0, 0, 0.1);
+    box-shadow: 0 0 10px rgba(255, 0, 0, 0.2);
+  }
+  100% { 
+    background-color: rgba(255, 0, 0, 0.2);
+    box-shadow: 0 0 20px rgba(255, 0, 0, 0.3);
+  }
+}
+
+.digital-human-container {
+  position: relative;
+  width: 100%;
+  height: 100vh;
+  overflow: hidden;
+  background-color: #f0f0f0;
+}
+
+.digital-human-video {
+  width: 100%;
+  height: 100%;
+  margin-top: 32px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+/* 用户摄像头容器样式 */
+.user-camera-container {
+  position: absolute;
+  top: 100px;
+  right: 5px;
+  width: 110px;
+  height: 160px;
+  border-radius: 4px;
+  overflow: hidden;
+  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
+  z-index: 20;
+  transition: all 0.3s ease;
+}
+
+.camera-warning {
+  animation: camera-warning-flash 1s ease-in-out infinite;
+  border: 4px solid #ff0000;
+}
+
+@keyframes camera-warning-flash {
+  0% { 
+    border-color: #ff0000;
+    box-shadow: 0 0 15px rgba(255, 0, 0, 0.8);
+  }
+  50% { 
+    border-color: rgba(255, 0, 0, 0.3);
+    box-shadow: 0 0 5px rgba(255, 0, 0, 0.4);
+  }
+  100% { 
+    border-color: #ff0000;
+    box-shadow: 0 0 15px rgba(255, 0, 0, 0.8);
+  }
+}
+
+/* 用户摄像头视频样式 */
+.user-camera-video {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+  background-color: #333;
+}
+
+.video-player {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+  outline: none; /* 移除视频获得焦点时的轮廓 */
+  -webkit-tap-highlight-color: transparent; /* 移除移动设备上的点击高亮 */
+}
+
+/* 隐藏视频控制条 */
+video::-webkit-media-controls {
+  display: none !important;
+}
+
+video::-webkit-media-controls-enclosure {
+  display: none !important;
+}
+
+video::-webkit-media-controls-panel {
+  display: none !important;
+}
+
+video::-webkit-media-controls-play-button {
+  display: none !important;
+}
+
+video::-webkit-media-controls-timeline {
+  display: none !important;
+}
+
+video::-webkit-media-controls-current-time-display {
+  display: none !important;
+}
+
+video::-webkit-media-controls-time-remaining-display {
+  display: none !important;
+}
+
+video::-webkit-media-controls-mute-button {
+  display: none !important;
+}
+
+video::-webkit-media-controls-volume-slider {
+  display: none !important;
+}
+
+video::-webkit-media-controls-fullscreen-button {
+  display: none !important;
+}
+
+/* 修改字幕覆盖层样式,使其与图片中的样式一致 */
+.subtitle-overlay {
+  position: absolute;
+  bottom: 180px;
+  left: 10%;
+  width: 80%;
+  padding: 0; /* 移除内边距,由内部元素控制 */
+  border-radius: 15px;
+  background-color: rgba(255, 255, 255, 0.9);
+  color: #333;
+  text-align: left;
+  font-size: 16px;
+  line-height: 1.5;
+  z-index: 10;
+  margin: 0 auto;
+  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+  display: flex;
+  flex-direction: column;
+  overflow: hidden; /* 确保圆角效果 */
+}
+
+/* 添加题号header样式 */
+.subtitle-header {
+/*   background-color: rgba(0, 0, 0, 0.05); */
+  padding: 8px 20px;
+  /* border-bottom: 1px solid rgba(0, 0, 0, 0.05); */
+}
+
+.question-tag {
+  font-size: 14px;
+  color: #666;
+  font-weight: 500;
+}
+
+/* 调整主字幕样式 */
+.subtitle-main {
+  padding: 15px 20px ;
+  font-weight: 500;
+}
+
+/* 移除之前的题号显示器 */
+.question-counter {
+  display: none;
+}
+
+.control-panel {
+  padding: 15px;
+  display: flex;
+  justify-content: center;
+}
+
+.control-button {
+  padding: 10px 20px;
+  background-color: #4CAF50;
+  color: white;
+  border: none;
+  border-radius: 4px;
+  cursor: pointer;
+}
+
+.loading {
+  text-align: center;
+  margin: 20px 0;
+  font-size: 16px;
+}
+
+.response-container {
+  margin-top: 20px;
+  padding: 0 20px;
+  display: none; /* 默认隐藏调试信息 */
+}
+
+/* 当showDebugInfo为true时显示 */
+.showDebugInfo .response-container {
+  display: block;
+}
+
+.response-item {
+  padding: 10px;
+  border: 1px solid #eee;
+  border-radius: 4px;
+  margin-bottom: 10px;
+  background-color: #f9f9f9;
+}
+
+.response-content {
+  display: flex;
+  flex-direction: column;
+}
+
+.answer-button-container {
+  position: absolute;
+  bottom: 50px; /* 将按钮放在底部而不是75%的位置 */
+  left: 50%;
+  transform: translateX(-50%); /* 只在X轴上平移,保持水平居中 */
+  z-index: 20;
+}
+
+/* 修改回答按钮样式 */
+.answer-button {
+  width: 120px;
+  height: 40px; /* 改为矩形按钮 */
+  border-radius: 20px; /* 圆角矩形 */
+  background-color: #ffffff; /* 白色背景 */
+  color: #333; /* 深色文字 */
+  font-size: 16px;
+  border: none;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  cursor: pointer;
+  animation: none; /* 移除脉动动画 */
+}
+
+.stop-recording-button-container {
+  position: absolute;
+  bottom: 50px; /* 统一与其他按钮的位置 */
+  left: 50%;
+  transform: translateX(-50%);
+  z-index: 20;
+}
+
+.stop-recording-button {
+  width: 120px;
+  height: 40px; /* 改为矩形按钮 */
+  border-radius: 20px; /* 圆角矩形 */
+  background-color: #0039b3; /* 白色背景 */
+  color: #fff;/* 深色文字 */
+  font-size: 16px;
+  border: none;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  cursor: pointer;
+  animation: none; /* 移除脉动动画 */
+}
+
+.recording-indicator {
+  position: fixed;
+  bottom: 20px;
+  left: 17%;
+  transform: translateX(-50%);
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+ /*  background-color: rgba(0, 0, 0, 0.6); */
+  padding: 10px 15px;
+  border-radius: 10px;
+  z-index: 100;
+}
+
+.timer-text {
+  color: #05dc8b;
+  font-size: 14px;
+  margin-top: 5px;
+}
+
+.start-recording-button-container {
+  position: absolute;
+  bottom: 50px; /* 统一与其他按钮的位置 */
+  left: 50%;
+  transform: translateX(-50%);
+  z-index: 101;
+}
+
+.start-recording-button {
+  width: 120px;
+  height: 40px; /* 改为矩形按钮 */
+  border-radius: 20px; /* 圆角矩形 */
+  background-color: #ffffff; /* 白色背景 */
+  color: #333; /* 深色文字 */
+  font-size: 16px;
+  border: none;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  cursor: pointer;
+  animation: none; /* 移除脉动动画 */
+}
+
+.retry-button-container {
+  position: absolute;
+  bottom: 30px; /* 统一与其他按钮的位置 */
+  left: 50%;
+  transform: translateX(-50%);
+  z-index: 20;
+}
+
+.retry-button {
+  padding: 10px 20px;
+  background-color: #ffffff; /* 白色背景 */
+  color: #333; /* 深色文字 */
+  font-size: 16px;
+  border: none;
+  border-radius: 20px; /* 圆角矩形 */
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
+  cursor: pointer;
+}
+
+.retry-button:hover {
+  background-color: #2980b9;
+}
+
+/* 录制时长显示 */
+.recording-timer {
+  position: absolute;
+  top: 20px;
+  left: 130px; /* 放在录制指示器旁边 */
+  background-color: rgba(0, 0, 0, 0.6);
+  padding: 5px 10px;
+  border-radius: 15px;
+  z-index: 20;
+  display: flex;
+  flex-direction: column;
+}
+
+.timer-text {
+  color: #000;
+  font-size: 14px;
+  font-family: monospace; /* 使用等宽字体,使时间显示更稳定 */
+}
+
+.remaining-time {
+  color: white;
+  font-size: 12px;
+  margin-top: 2px;
+}
+
+.remaining-time.warning {
+  color: #ff6b6b; /* 剩余时间少时显示红色 */
+  animation: blink 1s infinite; /* 使用闪烁动画提醒用户 */
+}
+
+/* 添加上传状态指示器 */
+.upload-status-indicator {
+  position: absolute;
+  top: 20px;
+  left: 130px; /* 放在录制指示器旁边 */
+  background-color: rgba(0, 0, 0, 0.6);
+  padding: 5px 10px;
+  border-radius: 15px;
+  z-index: 20;
+}
+
+.upload-status-content {
+  display: flex;
+  align-items: center;
+}
+
+.upload-status-icon {
+  width: 12px;
+  height: 12px;
+  border-radius: 50%;
+  margin-right: 8px;
+}
+
+.upload-status-text {
+  color: white;
+  font-size: 14px;
+}
+
+.uploading {
+  background-color: #e74c3c;
+}
+
+/* 添加倒计时蒙层样式 */
+.countdown-overlay {
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background-color: rgba(0, 0, 0, 0.7);
+  z-index: 100;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.countdown-content {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+
+.countdown-number {
+  font-size: 80px;
+  color: #ffffff;
+  font-weight: bold;
+  margin-bottom: 20px;
+}
+
+.countdown-text {
+  font-size: 24px;
+  color: #ffffff;
+}
+
+/* 添加GIF播放器样式 */
+.gif-player {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: 5; /* 确保GIF在视频上方但在字幕和按钮下方 */
+}
+
+/* 重新录制按钮容器样式 */
+.rerecord-button-container {
+  position: absolute;
+  bottom: 50px; /* 统一与其他按钮的位置 */
+  left: 50%;
+  transform: translateX(-50%);
+  z-index: 20;
+}
+
+/* 重新录制按钮样式 */
+.rerecord-button {
+  width: 120px;
+  height: 40px;
+  border-radius: 20px;
+  background-color: #ffffff;
+  color: #333;
+  font-size: 16px;
+  border: none;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  cursor: pointer;
+}
+
+.rerecord-button:hover {
+  background-color: #f0f0f0;
+}
+
+/* 添加视频蒙层样式 */
+.video-overlay {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background-color: transparent; /* 完全透明 */
+  z-index: 6; /* 确保在视频之上,但在按钮和字幕之下 */
+  pointer-events: auto; /* 允许捕获点击事件 */
+}
+
+/* 调整其他元素的z-index以确保正确的层级关系 */
+.subtitle-overlay {
+  /* ... 现有样式 ... */
+  z-index: 10; /* 确保字幕在蒙层之上 */
+}
+
+.answer-button-container,
+.stop-recording-button-container,
+.start-recording-button-container,
+.retry-button-container,
+.rerecord-button-container {
+  /* ... 现有样式 ... */
+  z-index: 999; /* 确保按钮在蒙层之上 */
+}
+
+.user-camera-container {
+  /* ... 现有样式 ... */
+  z-index: 20; /* 确保摄像头窗口在蒙层之上 */
+}
+
+.recording-indicator {
+  /* ... 现有样式 ... */
+  z-index: 20; /* 确保录制指示器在蒙层之上 */
+}
+
+/* 环形进度条样式 */
+.circle-progress-container {
+  width: 60px;
+  height: 60px;
+  position: relative;
+  margin: 0 auto 10px;
+}
+
+.circle-progress {
+  width: 100%;
+  height: 100%;
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  position: relative;
+  transform: rotate(-90deg); /* 从顶部开始进度 */
+}
+
+.circle-progress-inner {
+  width: 80%;
+  height: 80%;
+  background-color: rgba(255, 255, 255);
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  transform: rotate(90deg); /* 修正文本方向 */
+}
+
+.progress-text {
+  font-size: 14px;
+  font-weight: bold;
+   color: #05dc8b;
+}
+
+/* 添加题号显示 */
+.question-counter {
+  position: absolute;
+  top: 20px;
+  right: 130px; /* 调整位置,避免与用户摄像头重叠 */
+  background-color: rgba(255, 255, 255, 0.9);
+  padding: 6px 12px;
+  border-radius: 15px;
+  z-index: 20;
+  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
+  display: flex;
+  align-items: center;
+}
+
+.question-number {
+  color: #333;
+  font-size: 14px;
+  font-weight: 500;
+}
+
+/* 追问问题容器样式 */
+.followup-container {
+  width: 100%;
+}
+
+/* 追问分隔线 */
+.followup-divider {
+  height: 1px;
+  background-color: rgba(0, 0, 0, 0.05);
+  margin: 0;
+}
+
+/* 追问内容样式 */
+.followup-content {
+  padding: 12px 20px;
+  display: flex;
+  align-items: flex-start;
+  gap: 8px;
+}
+
+/* 追问标签样式 */
+.followup-label {
+  color: #fb752f;
+  font-size: 14px;
+  font-weight: 500;
+}
+
+/* 追问文本样式 */
+.followup-text {
+  color: #333;
+  font-size: 14px;
+  line-height: 1.5;
+  flex: 1;
+}
+
+/* 调整主字幕样式,确保有足够空间 */
+.subtitle-main {
+  padding:15px 20px ;
+  font-weight: 500;
+  border-bottom: none; /* 移除底部边框,由追问分隔线处理 */
+}
+
+/* 父问题样式 */
+.parent-question {
+  padding: 15px 20px;
+  font-weight: 500;
+  color: #333;
+}
+
+/* 追问容器样式调整 */
+.followup-container {
+  width: 100%;
+ /*  background-color: rgba(0, 0, 0, 0.02);  *//* 轻微的背景色区分 */
+}
+
+/* 分隔线样式 */
+.followup-divider {
+  height: 1px;
+  background-color: rgba(0, 0, 0, 0.05);
+  margin: 0;
+}
+
+/* 追问内容样式 */
+.followup-content {
+  padding: 12px 20px;
+  display: flex;
+  align-items: flex-start;
+  gap: 8px;
+}
+
+/* 追问标签样式 */
+.followup-label {
+  color: #fb752f;
+  font-size: 14px;
+  font-weight: 500;
+}
+
+/* 追问文本样式 */
+.followup-text {
+  color: #333;
+  font-size: 14px;
+  line-height: 1.5;
+  flex: 1;
+}
+.custom-navbar {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  height: 44px;
+  background-color: #ffffff;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  z-index: 999;
+}
+.navbar-title {
+  font-size: 16px;
+  font-weight: bold;
+}
+.content {
+  margin-top: 44px;
+  padding-top: var(--status-bar-height);
+}
+</style>

+ 1 - 0
unpackage/dist/dev/mp-weixin/app.js

@@ -24,6 +24,7 @@ if (!Math) {
   "./pages/uploadResume/uploadResume.js";
   "./pages/posture-guide/posture-guide.js";
   "./pages/interview_retake/interview_retake.js";
+  "./pages/demo/demo.js";
 }
 const _sfc_main = {
   onLaunch: function() {

+ 2 - 1
unpackage/dist/dev/mp-weixin/app.json

@@ -20,7 +20,8 @@
     "pages/followUp/followUp",
     "pages/uploadResume/uploadResume",
     "pages/posture-guide/posture-guide",
-    "pages/interview_retake/interview_retake"
+    "pages/interview_retake/interview_retake",
+    "pages/demo/demo"
   ],
   "window": {
     "navigationBarTextStyle": "black",

+ 3815 - 0
unpackage/dist/dev/mp-weixin/pages/demo/demo.js

@@ -0,0 +1,3815 @@
+"use strict";
+const common_vendor = require("../../common/vendor.js");
+const common_config = require("../../common/config.js");
+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: [],
+      assistantResponse: "",
+      audioTranscript: "",
+      videoPlaying: false,
+      showDebugInfo: false,
+      // 设置为true可以显示调试信息
+      videoUrl: "",
+      // 修改为空字符串,将通过API获取
+      showReplayButton: false,
+      cameraStream: null,
+      // 存储摄像头流
+      cameraError: null,
+      // 存储摄像头错误信息
+      useMiniProgramCameraComponent: false,
+      // 添加小程序相机组件标志
+      cameraContext: null,
+      // 添加相机上下文
+      currentSubtitle: "",
+      currentTranslation: "",
+      // 添加翻译文本
+      subtitles: [],
+      // 修改为空数组,将通过API获取
+      // 移除硬编码的字幕数组
+      // secondVideoSubtitles: [...],
+      // thirdVideoSubtitles: [...],
+      // 等等...
+      showAnswerButton: false,
+      // 控制答题按钮显示
+      currentVideoIndex: 0,
+      // 当前播放的视频索引
+      videoList: [],
+      // 修改为空数组,将通过API获取
+      // 其他属性保持不变...
+      questions: [],
+      // 添加新属性存储API返回的问题数据
+      introVideoUrl: (() => {
+        const DEFAULT_VIDEO_URL = "https://data.qicai321.com/minlong/ee4d9cce-c3d5-4350-8c6e-684283827897.mp4";
+        try {
+          const configStr = common_vendor.index.getStorageSync("configData");
+          if (!configStr)
+            return DEFAULT_VIDEO_URL;
+          const config = JSON.parse(configStr);
+          return config.digital_human_opening_video_url || DEFAULT_VIDEO_URL;
+        } catch (error) {
+          console.warn("解析配置数据失败:", error);
+          return DEFAULT_VIDEO_URL;
+        }
+      })(),
+      //'https://data.qicai321.com/minlong/ee4d9cce-c3d5-4350-8c6e-684283827897.mp4', // 保留介绍视频
+      isRecording: false,
+      recordingTimer: null,
+      showStopRecordingButton: false,
+      mediaRecorder: null,
+      recordedChunks: [],
+      recorder: null,
+      lastUploadedVideoUrl: "",
+      showStartRecordingButton: false,
+      showRetryButton: false,
+      // 控制重试按钮显示
+      lastVideoToRetry: null,
+      // 存储上次失败的视频URL,用于重试
+      recordingStartTime: null,
+      // 录制开始时间
+      recordingTimerCount: 0,
+      // 录制计时器计数
+      recordingTimeDisplay: "00:00",
+      // 格式化的录制时间显示
+      // 添加上传队列相关数据
+      uploadQueue: [],
+      // 存储待上传的视频
+      backgroundUploadQueue: [],
+      // 存储后台上传的视频
+      isUploading: false,
+      // 标记是否正在上传
+      uploadProgress: {},
+      // 存储每个视频的上传进度
+      uploadStatus: {},
+      // 存储每个视频的上传状态
+      showUploadStatus: false,
+      // 是否显示上传状态指示器
+      uploadStatusText: "",
+      // 上传状态文本
+      mediaRecorderTimeout: null,
+      // 用于存储MediaRecorder的超时机制
+      maxRecordingTime: 300,
+      // 最大录制时间(秒)- 从60秒改为300秒(5分钟)
+      remainingTime: 300,
+      // 剩余录制时间(秒)- 从60秒改为300秒
+      countdownValue: 10,
+      // 倒计时数值
+      showCountdown: false,
+      // 是否显示倒计时蒙层
+      countdownTimer: null,
+      showGif: false,
+      // 控制是否显示GIF
+      gifUrl: "",
+      // GIF图片的URL
+      globalSocketTask: null,
+      // 添加全局 WebSocket 连接对象
+      lowScoreVideoUrl: (() => {
+        var _a;
+        const DEFAULT_VIDEO_URL = "https://data.qicai321.com/minlong/latentsync/0530e7f5-1957-422d-8f34-ba4a92608081_result.mp4";
+        try {
+          const configStr = common_vendor.index.getStorageSync("configData");
+          if (!configStr)
+            return DEFAULT_VIDEO_URL;
+          const config = JSON.parse(configStr);
+          return ((_a = config.digital_human) == null ? void 0 : _a.middle_video_url) || DEFAULT_VIDEO_URL;
+        } catch (error) {
+          console.warn("解析配置数据失败:", error);
+          return DEFAULT_VIDEO_URL;
+        }
+      })(),
+      //'https://data.qicai321.com/minlong/latentsync/0530e7f5-1957-422d-8f34-ba4a92608081_result.mp4', // 低分提示视频URL
+      showRerecordButton: false,
+      // 控制重新录制按钮显示
+      isPlayingLowScoreVideo: false,
+      // 标记是否正在播放低分提示视频
+      lowScoreVideoSubtitles: [
+        {
+          startTime: 0,
+          endTime: 10,
+          // 假设视频长度为10秒,可根据实际情况调整
+          text: "我未听清楚您在说什么,请您再说一遍!"
+        }
+      ],
+      // 用于存储低分提示视频的字幕
+      retryCount: 0,
+      // 添加重试次数计数器
+      maxRetryAttempts: 2,
+      // 最大重试次数限制
+      needPlayLowScoreVideo: false,
+      // 是否需要播放低分视频
+      finalRecordingDuration: 0,
+      // 最终录制时长
+      historyTime: 0,
+      // 添加历史时间记录
+      followUpQuestions: [],
+      // 存储追问问题数据
+      currentParentQuestionId: null,
+      // 当前父问题ID
+      hasPlayedFollowUp: {},
+      // 记录已播放的追问,格式: {questionId: true}
+      isFollowUpQuestion: false,
+      // 标记当前是否正在播放追问问题
+      currentFollowUpQuestion: null,
+      // 添加当前追问问题的完整信息
+      lastQuestionWasFollowUp: false,
+      lastFollowUpQuestionId: null,
+      // 追问次数控制
+      defaultFollowUpLimit: 1,
+      // 默认每个主题目最多2次追问
+      followUpLimitMap: {},
+      // { parentJobPositionQuestionId: limit }
+      followUpAskedCountMap: {},
+      // { parentJobPositionQuestionId: askedCount }
+      followUpRequestInFlight: {},
+      // { parentJobPositionQuestionId: boolean }
+      lastUpdateTime: Date.now(),
+      // 添加最后更新时间戳
+      subtitleMap: {},
+      // 用于存储字幕和翻译的映射
+      progressPercent: 0,
+      // 录制进度百分比
+      progressColor: "#05dc8b",
+      // 进度条颜色
+      progressBgColor: "rgba(0, 0, 0,0.3)",
+      // 进度条背景色
+      parentQuestion: "",
+      // 添加父问题存储
+      screenCaptureCount: 0,
+      // 添加截屏次数记录
+      personDetectionSocket: null,
+      // WebSocket对象
+      personDetectionInterval: null,
+      // 定时器对象
+      showCameraWarning: false,
+      // 添加新的数据属性
+      showPageWarning: false,
+      // 添加新的数据属性
+      followUpQuestion: "",
+      // 追问问题
+      followUpAudioUrl: "",
+      // 追问音频URL
+      audioContext: null,
+      // 音频上下文
+      followUpQuestions: [],
+      // 追问问题列表
+      currentFollowUpIndex: -1,
+      // 当前追问问题索引
+      showSubtitleText: false,
+      // 是否显示字幕
+      subtitleText: "",
+      // 字幕文本
+      isAudioPlaying: false,
+      isWaitingForAnswer: false,
+      // 添加新的状态来控制是否在等待用户回答
+      currentRecordingDuration: 0,
+      // 添加当前录制时长
+      parentJobPositionQuestionId: null,
+      // 添加父问题的job_position_question_id
+      isFollowUpMode: false,
+      // 是否处于追问模式
+      mainQuestionIndex: 0,
+      // 当前主问题的索引
+      isVideoSwitching: false,
+      // 添加视频切换状态锁
+      originalQuestionSubtitle: null,
+      // 保存原始字幕信息
+      isThinking: false,
+      // 面试官思考中状态
+      thinkingTimer: null,
+      // 思考计时器
+      questionRetryMap: {},
+      // 用于跟踪每个问题的重试次数
+      maxQuestionRetries: 2,
+      // 每个问题最大重试次数
+      statusBarHeight: 0
+    };
+  },
+  onLoad() {
+    this.statusBarHeight = common_vendor.index.getSystemInfoSync().statusBarHeight || 0;
+  },
+  mounted() {
+    this.fetchQuestions();
+    this.checkAudioPermission();
+    this.initCamera();
+    this.checkIOSCameraRecordPermission();
+    this.checkAndFixRenderingIssues();
+    setTimeout(() => {
+      if (this.cameraStream && !this.useMiniProgramCameraComponent) {
+        this.testAudioInput();
+      }
+    }, 3e3);
+    this.historyTime = 0;
+    common_vendor.index.setKeepScreenOn({
+      keepScreenOn: true
+    });
+    common_vendor.index.onUserCaptureScreen(() => {
+      console.log("User captured screen");
+      this.screenCaptureCount++;
+      if (this.screenCaptureCount === 1) {
+        common_vendor.index.showModal({
+          title: "Warning",
+          content: "检测到屏幕截图。如果你再次捕捉屏幕,你的面试将无效.",
+          showCancel: false,
+          confirmText: "OK"
+        });
+      } else if (this.screenCaptureCount >= 2) {
+        common_vendor.index.showModal({
+          title: "Interview Invalid",
+          content: "由于多次屏幕截图,您的面试已无效。请联系招聘人员寻求帮助.",
+          showCancel: false,
+          confirmText: "OK",
+          success: () => {
+            this.invalidateInterview();
+          }
+        });
+      }
+    });
+    const systemInfo = common_vendor.index.getSystemInfoSync();
+    const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith("mp-");
+    console.log("isMiniProgram", isMiniProgram);
+    if (isMiniProgram) {
+      this.initPersonDetectionWebSocket();
+    }
+  },
+  beforeDestroy() {
+    common_vendor.index.offUserCaptureScreen();
+    this.cleanupPersonDetectionWebSocket();
+  },
+  methods: {
+    // ===== 追问次数控制:工具方法 =====
+    getFollowUpLimit(parentId) {
+      if (!parentId)
+        return this.defaultFollowUpLimit;
+      return this.followUpLimitMap[parentId] || this.defaultFollowUpLimit;
+    },
+    setFollowUpLimit(parentId, limit) {
+      if (!parentId)
+        return;
+      const parsed = parseInt(limit);
+      this.followUpLimitMap[parentId] = Number.isFinite(parsed) && parsed > 0 ? parsed : this.defaultFollowUpLimit;
+    },
+    resetFollowUpAskedCount(parentId) {
+      if (!parentId)
+        return;
+      this.followUpAskedCountMap[parentId] = 0;
+    },
+    incrementFollowUpCount(parentId) {
+      if (!parentId)
+        return;
+      const current = this.followUpAskedCountMap[parentId] || 0;
+      this.followUpAskedCountMap[parentId] = current + 1;
+    },
+    canAskMoreFollowUps(parentId) {
+      if (!parentId)
+        return false;
+      const asked = this.followUpAskedCountMap[parentId] || 0;
+      const limit = this.getFollowUpLimit(parentId);
+      return asked < limit;
+    },
+    async maybeRequestNextFollowUp(parentId) {
+      if (!parentId) {
+        this.proceedToNextQuestion();
+        return;
+      }
+      if (this.canAskMoreFollowUps(parentId)) {
+        if (this.followUpRequestInFlight[parentId]) {
+          console.log("已有追问请求进行中,跳过重复触发");
+          return;
+        }
+        const ok = await this.callInterviewInteraction(parentId);
+        if (!ok) {
+          console.log("未获取到下一条追问或调用失败,进入下一题");
+          this.isFollowUpMode = false;
+          this.isFollowUpQuestion = false;
+          this.currentFollowUpQuestion = null;
+          this.proceedToNextQuestion();
+        }
+      } else {
+        this.isFollowUpMode = false;
+        this.isFollowUpQuestion = false;
+        this.currentFollowUpQuestion = null;
+        this.proceedToNextQuestion();
+      }
+    },
+    // 处理音频播放完成
+    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);
+      this.enterFollowUpMode();
+      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, retryCount = 0, maxRetries = 3) {
+      if (questionId && this.followUpRequestInFlight[questionId]) {
+        console.log("追问请求已在进行中,跳过本次调用");
+        return false;
+      }
+      if (questionId) {
+        this.followUpRequestInFlight[questionId] = true;
+      }
+      const userInfo = JSON.parse(common_vendor.index.getStorageSync("userInfo"));
+      const appId = common_vendor.index.getStorageSync("appId");
+      const positionConfigId = JSON.parse(common_vendor.index.getStorageSync("configData")).id;
+      try {
+        this.showThinkingLoading();
+        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: positionConfigId,
+            application_id: appId
+          },
+          header: {
+            "content-type": "application/json"
+          }
+        });
+        console.log("面试互动接口返回数据:", res);
+        if (res.statusCode === 400) {
+          if (retryCount < maxRetries) {
+            console.log(`视频转写未完成,${retryCount + 1}次重试中...`);
+            await new Promise((resolve) => setTimeout(resolve, 3e3));
+            return this.callInterviewInteraction(questionId, retryCount + 1, maxRetries);
+          } else {
+            console.log("达到最大重试次数,视频转写仍未完成");
+            common_vendor.index.showToast({
+              title: "视频转写处理中,请稍后再试",
+              icon: "none",
+              duration: 2e3
+            });
+            return false;
+          }
+        }
+        if (res.data.success) {
+          if (questionId) {
+            this.incrementFollowUpCount(questionId);
+          }
+          await this.handleFollowUpQuestion(res.data);
+          this.hideThinkingLoading();
+          return true;
+        } else {
+          console.error("面试互动接口返回错误:", res.data);
+          this.hideThinkingLoading();
+          return false;
+        }
+      } catch (error) {
+        console.error("调用面试互动接口失败:", error);
+        this.hideThinkingLoading();
+        return false;
+      } finally {
+        if (questionId) {
+          this.followUpRequestInFlight[questionId] = false;
+        }
+      }
+    },
+    // 播放追问音频
+    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;
+          });
+          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();
+            reject(res);
+            this.stopAndDestroyAudio();
+          });
+          console.log("设置音频源:", this.followUpAudioUrl);
+          innerAudioContext.src = this.followUpAudioUrl;
+        } catch (error) {
+          console.error("创建或播放音频失败:", error);
+          this.isAudioPlaying = false;
+          common_vendor.index.hideLoading();
+          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("音频可以播放");
+      });
+      audioContext.onTimeUpdate(() => {
+        console.log("音频播放进度:", audioContext.currentTime);
+      });
+      audioContext.onEnded(() => {
+        console.log("追问音频播放完成");
+        this.cleanupAudioContext();
+        resolve();
+      });
+      audioContext.onError((res) => {
+        console.error("音频播放错误:", res);
+        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();
+      const isMiniProgram = systemInfo.uniPlatform === "mp-weixin" || systemInfo.uniPlatform === "mp-alipay" || systemInfo.uniPlatform === "mp-baidu";
+      if (isMiniProgram) {
+        this.useMiniProgramCameraComponent = true;
+        this.cameraContext = common_vendor.index.createCameraContext();
+        common_vendor.index.getSetting({
+          success: (res) => {
+            if (!res.authSetting["scope.record"]) {
+              common_vendor.index.authorize({
+                scope: "scope.record",
+                success: () => {
+                  console.log("录音权限已获取");
+                },
+                fail: (err) => {
+                  console.error("录音权限获取失败:", err);
+                  this.showPermissionDialog("录音");
+                }
+              });
+            }
+            if (!res.authSetting["scope.camera"]) {
+              common_vendor.index.authorize({
+                scope: "scope.camera",
+                success: () => {
+                  console.log("相机权限已获取");
+                },
+                fail: (err) => {
+                  console.error("相机权限获取失败:", err);
+                  this.showPermissionDialog("相机");
+                }
+              });
+            }
+            const systemInfo2 = common_vendor.index.getSystemInfoSync();
+            if (systemInfo2.platform === "ios") {
+              if (!res.authSetting["scope.camera"] || !res.authSetting["scope.record"]) {
+                console.log("iOS需要同时获取相机和录音权限");
+              }
+            }
+          }
+        });
+      } else {
+        try {
+          const constraints = {
+            audio: {
+              echoCancellation: true,
+              noiseSuppression: true,
+              autoGainControl: true
+            },
+            video: {
+              width: { ideal: 640, max: 1280 },
+              // 控制视频宽度
+              height: { ideal: 480, max: 720 },
+              // 控制视频高度
+              frameRate: { ideal: 15, max: 24 },
+              // 控制帧率
+              facingMode: "user"
+            }
+          };
+          const stream = await navigator.mediaDevices.getUserMedia(constraints);
+          this.cameraStream = stream;
+          const audioTracks = stream.getAudioTracks();
+          console.log("音频轨道数量:", audioTracks.length);
+          if (audioTracks.length > 0) {
+            console.log("音频轨道已获取:", audioTracks[0].label);
+            audioTracks[0].enabled = true;
+          } else {
+            console.warn("未检测到音频轨道,尝试单独获取音频");
+            this.tryGetAudioOnly();
+          }
+          const videoElement = this.$refs.userCameraVideo;
+          if (videoElement) {
+            videoElement.srcObject = stream;
+            videoElement.muted = true;
+          }
+        } catch (error) {
+          console.error("获取摄像头失败:", error);
+          this.cameraError = error.message || "无法访问摄像头";
+          common_vendor.index.showToast({
+            title: "无法访问摄像头,请检查权限设置",
+            icon: "none"
+          });
+        }
+      }
+    },
+    // 停止用户摄像头
+    stopUserCamera() {
+      if (this.cameraStream) {
+        this.cameraStream.getTracks().forEach((track) => {
+          track.stop();
+        });
+        this.cameraStream = null;
+      }
+    },
+    async fetchData() {
+      this.loading = true;
+      this.assistantResponse = "";
+      this.audioTranscript = "";
+      this.processedResponses = [];
+      common_vendor.index.showLoading({
+        title: "面试官思考中...",
+        mask: true
+        // 添加遮罩,防止用户触摸界面
+      });
+      try {
+        const requestTask = common_vendor.index.request({
+          url: "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions",
+          method: "POST",
+          header: {
+            "Content-Type": "application/json",
+            "Authorization": "Bearer sk-9e1ec73a7d97493b8613c63f06b6110c"
+          },
+          data: {
+            "model": "qwen-omni-turbo",
+            "messages": [
+              {
+                "role": "user",
+                "content": [
+                  {
+                    "type": "input_audio",
+                    "input_audio": {
+                      "data": "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20250211/tixcef/cherry.wav",
+                      "format": "wav"
+                    }
+                  },
+                  {
+                    "type": "text",
+                    "text": "这段音频在说什么"
+                  }
+                ]
+              }
+            ],
+            "stream": true,
+            "stream_options": {
+              "include_usage": true
+            },
+            "modalities": ["text", "audio"],
+            "audio": { "voice": "Cherry", "format": "wav" }
+          },
+          success: (res) => {
+            console.log("请求成功,响应数据:", res.data);
+            if (typeof res.data === "string" && res.data.includes("data: {")) {
+              const chunks = res.data.split("data: ").filter((chunk) => chunk.trim() !== "");
+              chunks.forEach((chunk) => {
+                this.handleStreamResponse(chunk);
+              });
+            } else {
+              this.handleStreamResponse(res.data);
+            }
+            this.playDigitalHumanVideo();
+          },
+          fail: (err) => {
+            console.error("请求失败:", err);
+            common_vendor.index.showToast({
+              title: "请求失败,请重试",
+              icon: "none"
+            });
+          },
+          complete: () => {
+            this.loading = false;
+            common_vendor.index.hideLoading();
+          }
+        });
+      } catch (error) {
+        console.error("获取数据失败:", error);
+        this.loading = false;
+        common_vendor.index.hideLoading();
+        common_vendor.index.showToast({
+          title: "系统错误,请重试",
+          icon: "none"
+        });
+      }
+    },
+    handleStreamResponse(data) {
+      if (typeof data === "string") {
+        if (data === "[DONE]")
+          return;
+        try {
+          const cleanData = data.trim();
+          if (cleanData.startsWith("{") && cleanData.endsWith("}")) {
+            const jsonData = JSON.parse(cleanData);
+            this.processStreamChunk(jsonData);
+          }
+        } catch (e) {
+          console.error("解析JSON失败:", e, "原始数据:", data);
+        }
+      } else {
+        this.processStreamChunk(data);
+      }
+    },
+    processStreamChunk(chunk) {
+      if (chunk.choices && chunk.choices.length > 0) {
+        const choice = chunk.choices[0];
+        if (choice.delta && choice.delta.content) {
+          this.assistantResponse += choice.delta.content;
+        }
+        if (choice.delta && choice.delta.audio && choice.delta.audio.transcript) {
+          this.audioTranscript += choice.delta.audio.transcript;
+        }
+        if (choice.delta) {
+          const result = {};
+          if (choice.delta.role) {
+            result.role = choice.delta.role;
+          }
+          if (choice.delta.audio && choice.delta.audio.transcript) {
+            result.transcript = choice.delta.audio.transcript;
+          }
+          if (Object.keys(result).length > 0) {
+            this.processedResponses.push(result);
+          }
+        }
+      }
+    },
+    processResponseData() {
+      this.processedResponses = this.responses.map((item) => {
+        const result = {};
+        if (item.delta && item.delta.role) {
+          result.role = item.delta.role;
+        }
+        if (item.delta && item.delta.audio && item.delta.audio.transcript) {
+          result.transcript = item.delta.audio.transcript;
+        }
+        return result;
+      }).filter((item) => Object.keys(item).length > 0);
+    },
+    // 播放数字人视频
+    playDigitalHumanVideo() {
+      if (this.videoList.length === 0) {
+        this.fetchQuestions();
+        return;
+      }
+      this.videoUrl = this.videoList[this.currentVideoIndex];
+      this.videoPlaying = true;
+      this.$nextTick(() => {
+        const videoContext = common_vendor.index.createVideoContext("myVideo", this);
+        if (videoContext) {
+          videoContext.play();
+          setTimeout(() => {
+            if (this.videoPlaying && this.$refs.videoPlayer) {
+              console.log("视频应该正在播放");
+            } else {
+              console.log("视频可能未成功播放,尝试替代方案");
+              this.tryAlternativeVideoPath();
+            }
+          }, 1e3);
+        } else {
+          console.error("无法创建视频上下文");
+          this.tryAlternativeVideoPath();
+        }
+      });
+    },
+    // 修改 tryAlternativeVideoPath 方法
+    tryAlternativeVideoPath() {
+      console.log("尝试使用替代路径");
+      const alternativePaths = [
+        "./static/demo.mp4",
+        "../static/demo.mp4",
+        "static/demo.mp4",
+        "/static/demo.mp4",
+        // 添加绝对路径
+        `${window.location.origin}/static/demo.mp4`
+      ];
+      const currentPathIndex = alternativePaths.indexOf(this.videoUrl);
+      const nextPathIndex = (currentPathIndex + 1) % alternativePaths.length;
+      this.videoUrl = alternativePaths[nextPathIndex];
+      console.log("尝试新路径:", this.videoUrl);
+      this.$nextTick(() => {
+        const videoContext = common_vendor.index.createVideoContext("myVideo", this);
+        if (videoContext) {
+          videoContext.stop();
+          videoContext.play();
+          setTimeout(() => {
+            if (nextPathIndex === alternativePaths.length - 1 && !this.videoPlaying) {
+              console.log("所有路径均失败,尝试使用uni.getVideoInfo检查视频");
+              this.checkVideoWithAPI();
+            }
+          }, 1e3);
+        }
+      });
+    },
+    // 添加新方法:使用uni API检查视频
+    checkVideoWithAPI() {
+      common_vendor.index.getVideoInfo({
+        src: "/static/demo.mp4",
+        success: (res) => {
+          console.log("视频信息获取成功:", res);
+          this.videoUrl = "/static/demo.mp4";
+          this.$nextTick(() => {
+            const videoContext = common_vendor.index.createVideoContext("myVideo", this);
+            if (videoContext) {
+              videoContext.play();
+            }
+          });
+        },
+        fail: (err) => {
+          console.error("视频信息获取失败:", err);
+          this.fallbackToLocalVideo();
+        }
+      });
+    },
+    // 添加新方法:回退到本地视频
+    fallbackToLocalVideo() {
+      console.log("尝试使用本地视频资源");
+      const platform = common_vendor.index.getSystemInfoSync().platform;
+      if (platform === "android" || platform === "ios") {
+        this.videoUrl = platform === "android" ? "android.resource://package_name/raw/demo" : "file:///assets/demo.mp4";
+        this.$nextTick(() => {
+          const videoContext = common_vendor.index.createVideoContext("myVideo", this);
+          if (videoContext) {
+            videoContext.play();
+          }
+        });
+      } else {
+        this.videoPlaying = false;
+        common_vendor.index.showToast({
+          title: "视频加载失败,显示静态图片",
+          icon: "none"
+        });
+      }
+    },
+    // 修改 handleVideoError 方法
+    handleVideoError(e) {
+      console.error("视频加载错误:", e);
+      if (e && e.detail) {
+        console.error("详细错误信息:", e.detail);
+      }
+      common_vendor.index.getFileInfo({
+        filePath: this.videoUrl.startsWith("/") ? this.videoUrl.substring(1) : this.videoUrl,
+        success: (res) => {
+          console.log("文件存在,大小:", res.size);
+          this.tryDifferentFormat();
+        },
+        fail: (err) => {
+          console.error("文件不存在或无法访问:", err);
+          this.tryAlternativeVideoPath();
+        }
+      });
+      common_vendor.index.showToast({
+        title: "视频加载失败,请检查文件是否存在",
+        icon: "none",
+        duration: 2e3
+      });
+    },
+    // 添加新方法:尝试不同格式
+    tryDifferentFormat() {
+      console.log("尝试不同的视频格式");
+      const formats = [
+        { ext: "mp4", mime: "video/mp4" },
+        { ext: "webm", mime: "video/webm" },
+        { ext: "ogg", mime: "video/ogg" },
+        { ext: "mov", mime: "video/quicktime" }
+      ];
+      const currentPath = this.videoUrl;
+      const basePath = currentPath.substring(0, currentPath.lastIndexOf(".")) || "/static/demo";
+      let nextFormat = formats.find((f) => !currentPath.endsWith(f.ext));
+      if (nextFormat) {
+        this.videoUrl = `${basePath}.${nextFormat.ext}`;
+        console.log("尝试新格式:", this.videoUrl);
+        this.$nextTick(() => {
+          const videoContext = common_vendor.index.createVideoContext("myVideo", this);
+          if (videoContext) {
+            videoContext.stop();
+            videoContext.play();
+          }
+        });
+      } else {
+        this.useBuiltInResource();
+      }
+    },
+    // 添加新方法:使用内置资源
+    useBuiltInResource() {
+      console.log("尝试使用内置资源");
+      const platform = common_vendor.index.getSystemInfoSync().platform;
+      if (platform === "windows") {
+        process.env.UNI_INPUT_DIR || "";
+        this.videoUrl = `./static/demo.mp4`;
+        console.log("Windows平台尝试路径:", this.videoUrl);
+      } else if (platform === "android" || platform === "ios") {
+        this.useNativeVideo();
+      } else {
+        const baseUrl = window.location.origin;
+        this.videoUrl = `${baseUrl}/static/demo.mp4`;
+        console.log("Web平台尝试URL:", this.videoUrl);
+      }
+      this.$nextTick(() => {
+        const videoContext = common_vendor.index.createVideoContext("myVideo", this);
+        if (videoContext) {
+          videoContext.play();
+        }
+      });
+    },
+    // 添加新方法:使用原生视频能力
+    useNativeVideo() {
+      console.log("尝试使用原生视频能力");
+      common_vendor.index.chooseVideo({
+        sourceType: ["album"],
+        success: (res) => {
+          this.videoUrl = res.tempFilePath;
+          this.$nextTick(() => {
+            const videoContext = common_vendor.index.createVideoContext("myVideo", this);
+            if (videoContext) {
+              videoContext.play();
+            }
+          });
+        },
+        fail: () => {
+          this.videoPlaying = false;
+        }
+      });
+    },
+    // 处理视频结束事件
+    handleVideoEnded() {
+      console.log("视频播放结束事件触发");
+      const videoElement = this.$refs.videoPlayer;
+      if (videoElement) {
+        const currentTime = videoElement.currentTime || 0;
+        const duration = videoElement.duration || 0;
+        if (duration > 0 && duration - currentTime > 0.5) {
+          console.log("检测到可能的误触发结束事件,继续播放", currentTime, duration);
+          setTimeout(() => {
+            const videoContext = common_vendor.index.createVideoContext("myVideo", this);
+            if (videoContext) {
+              if (duration - currentTime > 2) {
+                videoContext.seek(this.historyTime || 0);
+              } else {
+                videoContext.play();
+              }
+            }
+          }, 100);
+          return;
+        }
+        console.log("视频确认结束,当前时间:", currentTime, "总时长:", duration);
+      }
+      this.videoPlaying = false;
+      if (this.isPlayingLowScoreVideo) {
+        console.log("低分提示视频播放完成");
+        if (this.retryCount < this.maxRetryAttempts) {
+          console.log(`显示重新录制按钮 (重试次数: ${this.retryCount + 1}/${this.maxRetryAttempts})`);
+          this.showRerecordButton = true;
+          if (this.isFollowUpQuestion && this.currentFollowUpQuestion) {
+            this.currentSubtitle = this.currentFollowUpQuestion.question || this.currentFollowUpQuestion.question;
+          } else if (this.originalQuestionSubtitle) {
+            this.currentSubtitle = this.originalQuestionSubtitle;
+          }
+        } else {
+          console.log("已达到最大重试次数,继续下一题");
+          this.retryCount = 0;
+          this.proceedToNextQuestion();
+        }
+        this.isPlayingLowScoreVideo = false;
+        this.originalQuestionSubtitle = null;
+        return;
+      }
+      if (this.isFollowUpQuestion) {
+        console.log("追问问题视频播放完成");
+        this.showStartRecordingButton = true;
+        this.startCountdown();
+        return;
+      }
+      if (this.currentVideoIndex >= 1) {
+        this.showStartRecordingButton = true;
+        this.startCountdown();
+      } else {
+        this.showAnswerButton = true;
+      }
+      if (this.isFollowUpQuestion) {
+        this.isFollowUpQuestion = false;
+        this.currentFollowUpQuestion = null;
+      }
+    },
+    // 添加新方法:开始倒计时
+    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();
+        }
+      }, 1e3);
+    },
+    // 添加新方法:清除倒计时
+    clearCountdown() {
+      if (this.countdownTimer) {
+        clearInterval(this.countdownTimer);
+        this.countdownTimer = null;
+      }
+      this.showCountdown = false;
+    },
+    // 修改 handleStartRecordingClick 方法,使其可以终止倒计时
+    handleStartRecordingClick() {
+      this.showStartRecordingButton = false;
+      this.clearCountdown();
+      this.isWaitingForAnswer = false;
+      this.startRecordingAnswer();
+    },
+    // 修改 stopRecordingAnswer 方法,添加录制时长检查
+    stopRecordingAnswer() {
+      this.clearCountdown();
+      this.isWaitingForAnswer = false;
+      const recordingDuration = this.getRecordingDuration();
+      const minimumDuration = 3;
+      const lowScoreDuration = 7;
+      this.currentRecordingDuration = recordingDuration;
+      if (recordingDuration < minimumDuration) {
+        common_vendor.index.showToast({
+          title: "录制时间过短,请至少录制3秒",
+          icon: "none",
+          duration: 2e3
+        });
+        return;
+      }
+      if (recordingDuration < lowScoreDuration) {
+        console.log(`录制时间 ${recordingDuration} 秒,少于 ${lowScoreDuration} 秒,将播放低分提示视频`);
+        this.completeRecordingStop(false);
+        this.playLowScoreVideo();
+      } else {
+        this.completeRecordingStop(true);
+        this.needPlayLowScoreVideo = false;
+        this.recordingTimeDisplay = "00:00";
+      }
+    },
+    // 添加新方法:开始录制用户回答
+    startRecordingAnswer() {
+      console.log("开始录制用户回答");
+      this.isRecording = true;
+      this.recordingStartTime = Date.now();
+      this.recordingTimerCount = 0;
+      this.maxRecordingTime = this.getCurrentQuestionRecommendedDuration();
+      this.remainingTime = this.maxRecordingTime;
+      this.recordingTimer = setInterval(() => {
+        this.recordingTimerCount++;
+        this.remainingTime = Math.max(0, this.maxRecordingTime - this.recordingTimerCount);
+        this.recordingTimeDisplay = this.formatTime(this.recordingTimerCount);
+        this.progressPercent = Math.min(this.recordingTimerCount / this.maxRecordingTime * 100, 100);
+        if (this.recordingTimerCount >= this.maxRecordingTime) {
+          console.log(`已达到最大录制时间(${this.maxRecordingTime}秒),自动停止录制`);
+          this.stopRecordingAnswer();
+        }
+      }, 1e3);
+      const systemInfo = common_vendor.index.getSystemInfoSync();
+      const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith("mp-");
+      if (isMiniProgram) {
+        this.startMiniProgramRecording();
+      } else {
+        this.startBrowserRecording();
+      }
+      this.showStopRecordingButton = true;
+    },
+    // 添加一个新方法:重置相机组件
+    resetCamera() {
+      console.log("重置相机组件");
+      this.useMiniProgramCameraComponent = false;
+      if (this.cameraContext) {
+        this.cameraContext = null;
+      }
+      setTimeout(() => {
+        this.useMiniProgramCameraComponent = true;
+        setTimeout(() => {
+          this.cameraContext = common_vendor.index.createCameraContext();
+          console.log("相机组件已重置");
+        }, 500);
+      }, 500);
+    },
+    // 修改 startMiniProgramRecording 方法
+    startMiniProgramRecording() {
+      console.log("开始小程序录制方法");
+      const systemInfo = common_vendor.index.getSystemInfoSync();
+      const isIOS = systemInfo.platform === "ios";
+      if (isIOS) {
+        this.resetCamera();
+        setTimeout(() => {
+          this.actualStartRecording(isIOS);
+        }, 1e3);
+      } else {
+        this.actualStartRecording(isIOS);
+      }
+    },
+    // 添加新方法:实际开始录制
+    actualStartRecording(isIOS) {
+      if (!this.cameraContext) {
+        this.cameraContext = common_vendor.index.createCameraContext();
+        console.log("创建新的相机上下文");
+      }
+      common_vendor.index.getSetting({
+        success: (res) => {
+          const hasRecordAuth = res.authSetting["scope.record"];
+          const hasCameraAuth = res.authSetting["scope.camera"];
+          if (!hasRecordAuth || !hasCameraAuth) {
+            console.warn("缺少必要权限,请求权限");
+            this.requestMiniProgramPermissions();
+            return;
+          }
+          if (isIOS) {
+            console.log("iOS: 检查相机状态");
+            const maxDuration = this.getCurrentQuestionRecommendedDuration() * 1e3;
+            const options = {
+              timeout: maxDuration,
+              // 使用当前问题的推荐时长
+              quality: "low",
+              // 降低质量
+              compressed: true,
+              success: () => {
+                console.log("iOS录制开始成功");
+              },
+              fail: (err) => {
+                console.error("iOS录制失败:", err);
+                this.useAlternativeRecordingMethod();
+              }
+            };
+            try {
+              console.log("尝试开始录制");
+              this.recorder = this.cameraContext.startRecord(options);
+            } catch (e) {
+              console.error("开始录制异常:", e);
+              this.useAlternativeRecordingMethod();
+            }
+          } else {
+            const maxDuration = this.getCurrentQuestionRecommendedDuration() * 1e3;
+            const options = {
+              timeout: maxDuration,
+              // 使用当前问题的推荐时长
+              quality: "medium",
+              compressed: true,
+              success: () => {
+                console.log("Android录制开始成功");
+              },
+              fail: (err) => {
+                console.error("Android录制失败:", err);
+                common_vendor.index.showToast({
+                  title: "录制失败,请检查相机权限",
+                  icon: "none"
+                });
+                this.proceedToNextQuestion();
+              }
+            };
+            this.recorder = this.cameraContext.startRecord(options);
+          }
+        }
+      });
+    },
+    // 添加新方法:使用替代录制方法
+    useAlternativeRecordingMethod() {
+      console.log("使用替代录制方法");
+      common_vendor.index.showActionSheet({
+        itemList: ["使用相册中的视频", "跳过此问题"],
+        success: (res) => {
+          if (res.tapIndex === 0) {
+            common_vendor.index.chooseVideo({
+              sourceType: ["album"],
+              maxDuration: this.getCurrentQuestionRecommendedDuration(),
+              // 使用当前问题的推荐时长
+              camera: "front",
+              success: (res2) => {
+                console.log("选择视频成功:", res2.tempFilePath);
+                this.isRecording = false;
+                this.showStopRecordingButton = false;
+                this.uploadRecordedVideo(res2.tempFilePath);
+              },
+              fail: () => {
+                console.log("用户取消选择视频");
+                this.proceedToNextQuestion();
+              }
+            });
+          } else {
+            console.log("用户选择跳过问题");
+            this.proceedToNextQuestion();
+          }
+        },
+        fail: () => {
+          console.log("操作取消");
+          this.proceedToNextQuestion();
+        }
+      });
+    },
+    // 添加新方法:请求小程序权限
+    requestMiniProgramPermissions() {
+      common_vendor.index.authorize({
+        scope: "scope.record",
+        success: () => {
+          console.log("录音权限已获取");
+          common_vendor.index.authorize({
+            scope: "scope.camera",
+            success: () => {
+              console.log("相机权限已获取");
+              this.startMiniProgramRecording();
+            },
+            fail: (err) => {
+              console.error("相机权限获取失败:", err);
+              this.showPermissionDialog("相机");
+            }
+          });
+        },
+        fail: (err) => {
+          console.error("录音权限获取失败:", err);
+          this.showPermissionDialog("录音");
+        }
+      });
+    },
+    // 修改浏览器环境下的录制方法
+    startBrowserRecording() {
+      if (!this.cameraStream) {
+        console.error("没有可用的摄像头流");
+        this.proceedToNextQuestion();
+        return;
+      }
+      try {
+        const hasAudio = this.cameraStream.getAudioTracks().length > 0;
+        if (!hasAudio) {
+          console.warn("警告:媒体流中没有音频轨道,尝试重新获取带音频的媒体流");
+          navigator.mediaDevices.getUserMedia({
+            audio: {
+              echoCancellation: true,
+              noiseSuppression: true,
+              autoGainControl: true
+            },
+            video: true
+          }).then((newStream) => {
+            const audioTracks = newStream.getAudioTracks();
+            if (audioTracks.length > 0) {
+              console.log("成功获取音频轨道:", audioTracks[0].label);
+              const videoTrack = this.cameraStream.getVideoTracks()[0];
+              const audioTrack = newStream.getAudioTracks()[0];
+              const combinedStream = new MediaStream();
+              if (videoTrack)
+                combinedStream.addTrack(videoTrack);
+              if (audioTrack)
+                combinedStream.addTrack(audioTrack);
+              this.cameraStream = combinedStream;
+              const videoElement = this.$refs.userCameraVideo;
+              if (videoElement) {
+                videoElement.srcObject = combinedStream;
+                videoElement.muted = true;
+              }
+              this.setupMediaRecorder(combinedStream);
+            } else {
+              console.warn("仍然无法获取音频轨道");
+              this.setupMediaRecorder(this.cameraStream);
+            }
+          }).catch((err) => {
+            console.error("获取音频失败:", err);
+            this.setupMediaRecorder(this.cameraStream);
+          });
+        } else {
+          console.log("检测到音频轨道,直接使用");
+          this.setupMediaRecorder(this.cameraStream);
+        }
+      } catch (error) {
+        console.error("浏览器录制失败:", error);
+        common_vendor.index.showToast({
+          title: "录制失败,浏览器可能不支持此功能",
+          icon: "none"
+        });
+        this.proceedToNextQuestion();
+      }
+    },
+    // 修改 setupMediaRecorder 方法
+    setupMediaRecorder(stream) {
+      const videoTracks = stream.getVideoTracks();
+      const audioTracks = stream.getAudioTracks();
+      console.log("设置MediaRecorder - 视频轨道:", videoTracks.length, "音频轨道:", audioTracks.length);
+      let mimeType = "";
+      const supportedTypes = [
+        "video/webm;codecs=vp9,opus",
+        "video/webm;codecs=vp8,opus",
+        "video/webm;codecs=h264,opus",
+        "video/mp4;codecs=h264,aac",
+        "video/webm",
+        "video/mp4"
+      ];
+      for (const type of supportedTypes) {
+        if (MediaRecorder.isTypeSupported(type)) {
+          mimeType = type;
+          console.log("使用支持的MIME类型:", mimeType);
+          break;
+        }
+      }
+      const options = {
+        mimeType: mimeType || "",
+        audioBitsPerSecond: 64e3,
+        // 降低音频比特率
+        videoBitsPerSecond: 1e6
+        // 降低视频比特率到1Mbps
+      };
+      try {
+        this.mediaRecorder = new MediaRecorder(stream, options);
+        console.log("MediaRecorder创建成功,使用选项:", options);
+      } catch (e) {
+        console.warn("使用指定选项创建MediaRecorder失败,尝试使用默认选项");
+        this.mediaRecorder = new MediaRecorder(stream);
+      }
+      this.recordedChunks = [];
+      this.mediaRecorder.ondataavailable = (event) => {
+        if (event.data && event.data.size > 0) {
+          this.recordedChunks.push(event.data);
+          console.log(`收到数据块: ${event.data.size} 字节`);
+        }
+      };
+      this.mediaRecorder.onstop = async () => {
+        console.log("MediaRecorder停止,数据块数量:", this.recordedChunks.length);
+        if (this.recordedChunks.length === 0) {
+          console.error("没有录制到数据");
+          this.proceedToNextQuestion();
+          return;
+        }
+        const mimeType2 = this.mediaRecorder.mimeType || "video/webm";
+        const blob = new Blob(this.recordedChunks, { type: mimeType2 });
+        console.log("创建Blob,原始大小:", blob.size, "类型:", mimeType2);
+        common_vendor.index.showLoading({
+          title: "正在处理视频...",
+          mask: true
+        });
+        try {
+          const compressedBlob = await this.compressVideo(blob);
+          const fileName = `answer_${this.currentVideoIndex}_${Date.now()}.webm`;
+          const file = new File([compressedBlob], fileName, { type: mimeType2 });
+          common_vendor.index.hideLoading();
+          this.uploadRecordedVideo(file);
+        } catch (error) {
+          console.error("视频处理失败:", error);
+          common_vendor.index.hideLoading();
+          const fileName = `answer_${this.currentVideoIndex}_${Date.now()}.webm`;
+          const file = new File([blob], fileName, { type: mimeType2 });
+          this.uploadRecordedVideo(file);
+        }
+      };
+      this.mediaRecorder.onerror = (event) => {
+        console.error("MediaRecorder错误:", event.error);
+      };
+      try {
+        this.mediaRecorder.start(1e3);
+        console.log("MediaRecorder开始录制");
+        this.mediaRecorderTimeout = setTimeout(() => {
+          if (this.mediaRecorder && this.mediaRecorder.state === "recording") {
+            console.log("MediaRecorder备份超时机制触发,停止录制");
+            this.mediaRecorder.stop();
+          }
+        }, 3e5);
+      } catch (e) {
+        console.error("开始录制失败:", e);
+      }
+    },
+    // 添加新方法:获取录制时长
+    getRecordingDuration() {
+      if (this.recordingStartTime) {
+        return (Date.now() - this.recordingStartTime) / 1e3;
+      }
+      if (this.mediaRecorder && this.$refs.userCameraVideo) {
+        return this.$refs.userCameraVideo.currentTime || 0;
+      }
+      if (this.recordingTimerCount) {
+        return this.recordingTimerCount;
+      }
+      return 0;
+    },
+    // 添加新方法:重置录制
+    resetRecording() {
+      if (this.recordingTimer) {
+        clearTimeout(this.recordingTimer);
+      }
+      this.recordingStartTime = Date.now();
+      this.recordingTimerCount = 0;
+      if (this.mediaRecorder && this.mediaRecorder.state !== "inactive") {
+        this.mediaRecorder.stop();
+        this.recordedChunks = [];
+        setTimeout(() => {
+          this.startBrowserRecording();
+        }, 500);
+      } else if (this.cameraContext) {
+        this.cameraContext.stopRecord({
+          success: () => {
+            console.log("相机录制已停止");
+          },
+          fail: (err) => {
+            console.error("停止相机录制失败:", err);
+          }
+        });
+      }
+    },
+    // 修改 completeRecordingStop 方法,确保正确处理追问问题ID
+    completeRecordingStop(uploadVideo = true) {
+      console.log("完成录制停止");
+      if (this.recordingTimer) {
+        clearInterval(this.recordingTimer);
+        this.recordingTimer = null;
+      }
+      this.finalRecordingDuration = this.recordingTimerCount;
+      this.showStopRecordingButton = false;
+      this.isRecording = false;
+      const systemInfo = common_vendor.index.getSystemInfoSync();
+      const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith("mp-");
+      if (isMiniProgram) {
+        if (uploadVideo) {
+          this.stopMiniProgramRecording();
+        } else {
+          if (this.cameraContext) {
+            this.cameraContext.stopRecord({
+              success: () => {
+                console.log("相机录制已停止,不上传视频");
+              },
+              fail: (err) => {
+                console.error("停止相机录制失败:", err);
+              }
+            });
+          }
+        }
+      } else {
+        if (uploadVideo) {
+          this.stopBrowserRecording();
+        } else {
+          if (this.mediaRecorder && this.mediaRecorder.state !== "inactive") {
+            this.mediaRecorder.stop();
+            this.recordedChunks = [];
+          }
+        }
+      }
+      if (this.isFollowUpQuestion && this.currentFollowUpQuestion) {
+        console.log("当前是追问问题,记录追问问题ID:", this.currentFollowUpQuestion.id);
+        this.lastQuestionWasFollowUp = true;
+        this.lastFollowUpQuestionId = this.currentFollowUpQuestion.id;
+      } else {
+        this.lastQuestionWasFollowUp = false;
+        this.lastFollowUpQuestionId = null;
+      }
+    },
+    // 修改 stopMiniProgramRecording 方法,确保正确传递追问问题ID
+    stopMiniProgramRecording() {
+      console.log("停止小程序录制");
+      if (!this.cameraContext) {
+        console.error("相机上下文不存在");
+        this.proceedToNextQuestion();
+        return;
+      }
+      this.cameraContext.stopRecord({
+        success: async (res) => {
+          console.log("小程序录制停止成功:", res);
+          const videoPath = res.tempVideoPath;
+          if (videoPath) {
+            await this.uploadRecordedVideo(videoPath);
+          } else {
+            console.error("未获取到录制视频路径");
+            this.proceedToNextQuestion();
+          }
+        },
+        fail: (err) => {
+          console.error("小程序录制停止失败:", err);
+          this.proceedToNextQuestion();
+        }
+      });
+    },
+    // 添加新方法:停止浏览器录制
+    stopBrowserRecording() {
+      if (this.mediaRecorder && this.mediaRecorder.state !== "inactive") {
+        this.mediaRecorder.stop();
+        console.log("浏览器录制停止成功");
+      } else {
+        console.error("MediaRecorder不存在或已经停止");
+        this.proceedToNextQuestion();
+      }
+    },
+    // 修改 uploadRecordedVideo 方法,添加记录父问题ID的逻辑
+    uploadRecordedVideo(fileOrPath) {
+      console.log("准备上传视频:", typeof fileOrPath === "string" ? fileOrPath : fileOrPath.name);
+      console.log("当前问题ID:", this.currentParentQuestionId);
+      console.log("当前问题类型:", this.isFollowUpQuestion);
+      console.log("当前追问问题:", this.currentFollowUpQuestion);
+      let questionId;
+      let isFollowUpQuestionUpload = false;
+      let questionText = "";
+      let questionForm = 0;
+      if (this.currentFollowUpQuestion && (this.currentFollowUpQuestion.question_form === 5 || this.isFollowUpQuestion)) {
+        questionId = this.currentFollowUpQuestion.id;
+        isFollowUpQuestionUpload = true;
+        questionText = this.currentFollowUpQuestion.question || "";
+        questionForm = 5;
+        console.log("正在上传追问问题的回答:", {
+          questionId,
+          questionText,
+          questionForm,
+          isFollowUp: true
+        });
+      } else {
+        this.showThinkingLoading();
+        const currentQuestion = this.getCurrentQuestionByIndex(this.currentVideoIndex);
+        if (currentQuestion && currentQuestion.id) {
+          questionId = currentQuestion.id;
+          questionText = currentQuestion.question || "";
+          console.log("正在上传常规问题的回答:", {
+            questionId,
+            questionText,
+            questionForm: 0
+          });
+        } else {
+          questionId = this.getDefaultQuestionId(this.currentVideoIndex);
+          console.log("使用默认问题ID:", questionId);
+        }
+      }
+      const uploadTask = {
+        id: Date.now().toString(),
+        file: fileOrPath,
+        questionId,
+        isFollowUp: isFollowUpQuestionUpload,
+        questionText,
+        questionForm,
+        attempts: 0,
+        maxAttempts: 3,
+        parentQuestionId: this.currentParentQuestionId,
+        videoDuration: this.currentRecordingDuration || 0
+        // 添加视频时长
+      };
+      if (!isFollowUpQuestionUpload) {
+        this.currentParentQuestionId = questionId;
+      }
+      this.uploadQueue.push(uploadTask);
+      this.uploadProgress[uploadTask.id] = 0;
+      this.uploadStatus[uploadTask.id] = "pending";
+      this.updateUploadStatusText();
+      if (isFollowUpQuestionUpload) {
+        console.log("追问问题使用后台上传,不阻塞流程");
+        this.handlePostUploadActions(uploadTask);
+        this.startBackgroundUpload(uploadTask);
+        return Promise.resolve();
+      } else {
+        return new Promise((resolve) => {
+          const checkUploadStatus = () => {
+            if (!this.isUploading && this.uploadQueue.length === 0) {
+              this.handlePostUploadActions(uploadTask);
+              resolve();
+            } else {
+              setTimeout(checkUploadStatus, 100);
+            }
+          };
+          if (!this.isUploading) {
+            this.processUploadQueue();
+          }
+          checkUploadStatus();
+        });
+      }
+    },
+    // 添加新方法:启动后台上传
+    startBackgroundUpload(task) {
+      console.log("启动后台上传任务:", task.id);
+      task.isBackgroundUpload = true;
+      const taskIndex = this.uploadQueue.findIndex((t) => t.id === task.id);
+      if (taskIndex !== -1) {
+        this.uploadQueue.splice(taskIndex, 1);
+      }
+      if (!this.backgroundUploadQueue) {
+        this.backgroundUploadQueue = [];
+      }
+      this.backgroundUploadQueue.push(task);
+      this.processBackgroundUploadQueue();
+    },
+    // 添加新方法:处理后台上传队列
+    processBackgroundUploadQueue() {
+      if (!this.backgroundUploadQueue || this.backgroundUploadQueue.length === 0) {
+        return;
+      }
+      const task = this.backgroundUploadQueue[0];
+      console.log("开始后台上传:", task.id);
+      this.uploadStatus[task.id] = "uploading";
+      this.updateUploadStatusText();
+      task.attempts++;
+      if (typeof task.file === "string") {
+        this.uploadFileWithUniBackground(task);
+      } else {
+        this.uploadFileWithXHRBackground(task);
+      }
+    },
+    // 添加新方法:使用XMLHttpRequest后台上传文件
+    uploadFileWithXHRBackground(task) {
+      const userInfo = common_vendor.index.getStorageSync("userInfo");
+      const openid = userInfo ? JSON.parse(userInfo).openid || "" : "";
+      const tenant_id = JSON.parse(common_vendor.index.getStorageSync("userInfo")).tenant_id || "1";
+      const formData = new FormData();
+      formData.append("file", task.file);
+      formData.append("openid", openid);
+      formData.append("tenant_id", tenant_id);
+      formData.append("application_id", common_vendor.index.getStorageSync("appId"));
+      formData.append("question_id", task.questionId);
+      formData.append("video_duration", task.videoDuration || 0);
+      formData.append("has_audio", "true");
+      const xhr = new XMLHttpRequest();
+      xhr.upload.onprogress = (event) => {
+        if (event.lengthComputable) {
+          const progress = Math.round(event.loaded / event.total * 100);
+          this.uploadProgress[task.id] = progress;
+          this.updateUploadStatusText();
+        }
+      };
+      xhr.onload = () => {
+        if (xhr.status === 200) {
+          try {
+            const res = JSON.parse(xhr.responseText);
+            console.log("后台上传响应:", res);
+            if (res.code === 2e3) {
+              const videoUrl = res.data.url || res.data.photoUrl || "";
+              if (videoUrl) {
+                this.uploadStatus[task.id] = "success";
+                this.updateUploadStatusText();
+                this.submitVideoToInterviewBackground(videoUrl, task);
+              } else {
+                this.handleBackgroundUploadFailure(task, "视频URL获取失败");
+              }
+            } else {
+              this.handleBackgroundUploadFailure(task, res.msg || "上传失败");
+            }
+          } catch (e) {
+            this.handleBackgroundUploadFailure(task, "解析响应失败");
+          }
+        } else {
+          this.handleBackgroundUploadFailure(task, "HTTP状态: " + xhr.status);
+        }
+      };
+      xhr.onerror = () => {
+        this.handleBackgroundUploadFailure(task, "网络错误");
+      };
+      xhr.ontimeout = () => {
+        this.handleBackgroundUploadFailure(task, "上传超时");
+      };
+      xhr.open("POST", `${common_config.apiBaseUrl}/api/upload/`);
+      xhr.send(formData);
+    },
+    // 添加新方法:使用uni.uploadFile后台上传文件
+    uploadFileWithUniBackground(task) {
+      const userInfo = common_vendor.index.getStorageSync("userInfo");
+      const openid = userInfo ? JSON.parse(userInfo).openid || "" : "";
+      const tenant_id = JSON.parse(common_vendor.index.getStorageSync("userInfo")).tenant_id || "1";
+      const uploadTask = common_vendor.index.uploadFile({
+        url: `${common_config.apiBaseUrl}/api/upload/`,
+        filePath: task.file,
+        name: "file",
+        formData: {
+          openid,
+          tenant_id,
+          application_id: common_vendor.index.getStorageSync("appId"),
+          question_id: task.questionId,
+          video_duration: task.videoDuration || 0,
+          has_audio: "true"
+        },
+        success: (uploadRes) => {
+          try {
+            const res = JSON.parse(uploadRes.data);
+            console.log("后台上传响应:", res);
+            if (res.code === 2e3) {
+              const videoUrl = res.data.permanent_link || res.data.url || "";
+              if (videoUrl) {
+                this.uploadStatus[task.id] = "success";
+                this.updateUploadStatusText();
+                this.submitVideoToInterviewBackground(videoUrl, task);
+              } else {
+                this.handleBackgroundUploadFailure(task, "视频URL获取失败");
+              }
+            } else {
+              this.handleBackgroundUploadFailure(task, res.msg || "上传失败");
+            }
+          } catch (e) {
+            this.handleBackgroundUploadFailure(task, "解析响应失败");
+          }
+        },
+        fail: (err) => {
+          this.handleBackgroundUploadFailure(task, err.errMsg || "上传失败");
+        }
+      });
+      uploadTask.onProgressUpdate((res) => {
+        this.uploadProgress[task.id] = res.progress;
+        this.updateUploadStatusText();
+      });
+    },
+    // 添加新方法:处理后台上传失败
+    handleBackgroundUploadFailure(task, errorMsg) {
+      console.error("后台上传失败:", errorMsg);
+      this.uploadStatus[task.id] = "failed";
+      this.updateUploadStatusText();
+      if (task.attempts < task.maxAttempts) {
+        console.log(`将在5秒后重试后台上传,当前尝试次数: ${task.attempts}/${task.maxAttempts}`);
+        setTimeout(() => {
+          this.uploadProgress[task.id] = 0;
+          if (typeof task.file !== "string") {
+            this.uploadFileWithXHRBackground(task);
+          } else {
+            this.uploadFileWithUniBackground(task);
+          }
+        }, 5e3);
+      } else {
+        console.log("超过最大重试次数,放弃后台上传");
+        if (this.backgroundUploadQueue) {
+          const taskIndex = this.backgroundUploadQueue.findIndex((t) => t.id === task.id);
+          if (taskIndex !== -1) {
+            this.backgroundUploadQueue.splice(taskIndex, 1);
+          }
+        }
+        this.processBackgroundUploadQueue();
+      }
+    },
+    // 添加新方法:后台上传提交到面试接口
+    submitVideoToInterviewBackground(videoUrl, task) {
+      const followUpRequestData = {
+        application_id: common_vendor.index.getStorageSync("appId"),
+        tenant_id: JSON.parse(common_vendor.index.getStorageSync("userInfo")).tenant_id || "1",
+        video_url: videoUrl,
+        original_question_id: this.parentJobPositionQuestionId,
+        // 使用保存的job_position_question_id
+        follow_up_question: task.questionText,
+        video_duration: task.videoDuration,
+        openid: JSON.parse(common_vendor.index.getStorageSync("userInfo")).openid || ""
+      };
+      console.log("后台上传提交追问视频:", followUpRequestData);
+      common_vendor.index.request({
+        url: `${common_config.apiBaseUrl}/voice_interview/upload_follow_up_video/`,
+        method: "POST",
+        data: followUpRequestData,
+        header: {
+          "content-type": "application/x-www-form-urlencoded"
+        },
+        success: (res) => {
+          if (res.data.code === 200 || res.data.code === 2e3) {
+            console.log("后台上传追问视频提交成功");
+            if (this.backgroundUploadQueue) {
+              const taskIndex = this.backgroundUploadQueue.findIndex((t) => t.id === task.id);
+              if (taskIndex !== -1) {
+                this.backgroundUploadQueue.splice(taskIndex, 1);
+              }
+            }
+            this.processBackgroundUploadQueue();
+          } else {
+            this.handleBackgroundSubmitFailure(task, "提交失败: " + (res.data.msg || "未知错误"));
+          }
+        },
+        fail: (err) => {
+          console.error("后台上传提交失败:", err);
+          this.handleBackgroundSubmitFailure(task, "提交失败: " + err.errMsg);
+        }
+      });
+    },
+    // 添加新方法:处理后台上传提交失败
+    handleBackgroundSubmitFailure(task, errorMsg) {
+      console.error("后台上传提交失败:", errorMsg);
+      if (task.attempts < task.maxAttempts) {
+        console.log(`将在5秒后重试后台上传提交,当前尝试次数: ${task.attempts}/${task.maxAttempts}`);
+        setTimeout(() => {
+          this.submitVideoToInterviewBackground(task.videoUrl, task);
+        }, 5e3);
+      } else {
+        console.log("超过最大重试次数,放弃后台上传提交");
+        if (this.backgroundUploadQueue) {
+          const taskIndex = this.backgroundUploadQueue.findIndex((t) => t.id === task.id);
+          if (taskIndex !== -1) {
+            this.backgroundUploadQueue.splice(taskIndex, 1);
+          }
+        }
+        this.processBackgroundUploadQueue();
+      }
+    },
+    // 添加新方法:处理上传后的逻辑
+    handlePostUploadActions(task) {
+      this.hideThinkingLoading();
+      if (this.needPlayLowScoreVideo && this.retryCount < 1) {
+        this.playLowScoreVideo();
+        this.needPlayLowScoreVideo = false;
+      } else {
+        if (task.isFollowUp) {
+          console.log("追问问题回答完成,进入下一个问题");
+          this.retryCount = 0;
+          this.isFollowUpQuestion = false;
+          this.currentFollowUpQuestion = null;
+          this.videoUrl = "";
+          this.maybeRequestNextFollowUp(this.parentJobPositionQuestionId);
+        } else {
+          this.currentParentQuestionId = task.questionId;
+          console.log("检查常规问题的追问,父问题ID:", this.currentParentQuestionId);
+          const currentQuestion = this.getCurrentQuestionByIndex(this.currentVideoIndex);
+          if (currentQuestion && typeof currentQuestion.follow_up_limit !== "undefined") {
+            this.setFollowUpLimit(this.currentParentQuestionId, currentQuestion.follow_up_limit);
+          } else if (typeof this.defaultFollowUpLimit !== "undefined") {
+            this.setFollowUpLimit(this.currentParentQuestionId, this.defaultFollowUpLimit);
+          }
+          this.resetFollowUpAskedCount(this.currentParentQuestionId);
+          this.checkAndPlayFollowUpQuestion(this.currentParentQuestionId);
+        }
+      }
+    },
+    // 修改 processUploadQueue 方法
+    processUploadQueue() {
+      if (this.uploadQueue.length === 0) {
+        this.isUploading = false;
+        this.showUploadStatus = false;
+        this.hideThinkingLoading();
+        return;
+      }
+      this.isUploading = true;
+      this.showUploadStatus = true;
+      const task = this.uploadQueue[0];
+      this.uploadStatus[task.id] = "uploading";
+      this.updateUploadStatusText();
+      task.attempts++;
+      if (typeof task.file === "string") {
+        this.uploadFileWithUni(task);
+      } else {
+        this.uploadFileWithXHR(task);
+      }
+    },
+    // 添加新方法:使用XMLHttpRequest上传文件
+    uploadFileWithXHR(task) {
+      const userInfo = common_vendor.index.getStorageSync("userInfo");
+      const openid = userInfo ? JSON.parse(userInfo).openid || "" : "";
+      const tenant_id = JSON.parse(common_vendor.index.getStorageSync("userInfo")).tenant_id || "1";
+      const formData = new FormData();
+      formData.append("file", task.file);
+      formData.append("openid", openid);
+      formData.append("tenant_id", tenant_id);
+      formData.append("application_id", common_vendor.index.getStorageSync("appId"));
+      formData.append("question_id", task.questionId);
+      formData.append("video_duration", task.videoDuration);
+      formData.append("has_audio", "true");
+      const xhr = new XMLHttpRequest();
+      xhr.open("POST", `${common_config.apiBaseUrl}/api/upload/`, true);
+      xhr.timeout = 12e4;
+      xhr.upload.onprogress = (event) => {
+        if (event.lengthComputable) {
+          const percentComplete = Math.round(event.loaded / event.total * 100);
+          this.uploadProgress[task.id] = percentComplete;
+          this.updateUploadStatusText();
+        }
+      };
+      xhr.onload = () => {
+        if (xhr.status === 200) {
+          try {
+            const res = JSON.parse(xhr.responseText);
+            console.log("上传响应:", res);
+            if (res.code === 2e3) {
+              const videoUrl = res.data.url || res.data.photoUrl || "";
+              if (videoUrl) {
+                this.uploadStatus[task.id] = "success";
+                this.updateUploadStatusText();
+                this.submitVideoToInterview(videoUrl, task);
+              } else {
+                this.handleUploadFailure(task, "视频URL获取失败");
+              }
+            } else {
+              this.handleUploadFailure(task, res.msg || "上传失败");
+            }
+          } catch (e) {
+            this.handleUploadFailure(task, "解析响应失败");
+          }
+        } else {
+          this.handleUploadFailure(task, "HTTP状态: " + xhr.status);
+        }
+      };
+      xhr.onerror = () => {
+        this.handleUploadFailure(task, "网络错误");
+      };
+      xhr.ontimeout = () => {
+        this.handleUploadFailure(task, "上传超时");
+      };
+      xhr.send(formData);
+    },
+    // 添加新方法:使用uni.uploadFile上传文件
+    uploadFileWithUni(task) {
+      const userInfo = common_vendor.index.getStorageSync("userInfo");
+      const openid = userInfo ? JSON.parse(userInfo).openid || "" : "";
+      const tenant_id = JSON.parse(common_vendor.index.getStorageSync("userInfo")).tenant_id || "1";
+      const uploadTask = common_vendor.index.uploadFile({
+        url: `${common_config.apiBaseUrl}/api/upload/`,
+        filePath: task.file,
+        name: "file",
+        formData: {
+          openid,
+          tenant_id,
+          application_id: common_vendor.index.getStorageSync("appId"),
+          question_id: task.questionId,
+          video_duration: 0,
+          has_audio: "true"
+        },
+        success: (uploadRes) => {
+          try {
+            const res = JSON.parse(uploadRes.data);
+            console.log("上传响应:", res);
+            if (res.code === 2e3) {
+              const videoUrl = res.data.permanent_link || res.data.url || "";
+              if (videoUrl) {
+                this.uploadStatus[task.id] = "success";
+                this.updateUploadStatusText();
+                this.submitVideoToInterview(videoUrl, task);
+              } else {
+                this.handleUploadFailure(task, "视频URL获取失败");
+              }
+            } else {
+              this.handleUploadFailure(task, res.msg || "上传失败");
+            }
+          } catch (e) {
+            this.handleUploadFailure(task, "解析响应失败");
+          }
+        },
+        fail: (err) => {
+          this.handleUploadFailure(task, err.errMsg || "上传失败");
+        }
+      });
+      uploadTask.onProgressUpdate((res) => {
+        this.uploadProgress[task.id] = res.progress;
+        this.updateUploadStatusText();
+      });
+    },
+    // 添加新方法:处理上传失败
+    handleUploadFailure(task, errorMsg) {
+      console.error("上传失败:", errorMsg);
+      this.uploadStatus[task.id] = "failed";
+      this.updateUploadStatusText();
+      if (task.attempts < task.maxAttempts) {
+        console.log(`将在5秒后重试上传,当前尝试次数: ${task.attempts}/${task.maxAttempts}`);
+        setTimeout(() => {
+          this.uploadProgress[task.id] = 0;
+          if (typeof task.file !== "string") {
+            this.uploadFileWithXHR(task);
+          } else {
+            this.uploadFileWithUni(task);
+          }
+        }, 5e3);
+      } else {
+        console.log("超过最大重试次数,放弃上传");
+        this.uploadQueue.shift();
+        this.processUploadQueue();
+      }
+    },
+    // 修改 submitVideoToInterview 方法
+    submitVideoToInterview(videoUrl, task) {
+      const requestData = {
+        application_id: common_vendor.index.getStorageSync("appId"),
+        question_id: task.questionId,
+        video_url: videoUrl,
+        tenant_id: JSON.parse(common_vendor.index.getStorageSync("userInfo")).tenant_id || "1",
+        is_follow_up: task.isFollowUp ? 1 : 0,
+        question_form: task.questionForm,
+        question_text: task.questionText
+      };
+      console.log("提交视频到面试接口", requestData);
+      if (task.isFollowUp) {
+        const followUpRequestData = {
+          application_id: common_vendor.index.getStorageSync("appId"),
+          tenant_id: JSON.parse(common_vendor.index.getStorageSync("userInfo")).tenant_id || "1",
+          video_url: videoUrl,
+          original_question_id: this.parentJobPositionQuestionId,
+          // 使用保存的job_position_question_id
+          follow_up_question: task.questionText,
+          video_duration: task.videoDuration,
+          openid: JSON.parse(common_vendor.index.getStorageSync("userInfo")).openid || ""
+        };
+        console.log("准备提交追问视频:", followUpRequestData);
+        common_vendor.index.request({
+          url: `${common_config.apiBaseUrl}/voice_interview/upload_follow_up_video/`,
+          method: "POST",
+          data: followUpRequestData,
+          header: {
+            "content-type": "application/x-www-form-urlencoded"
+          },
+          success: async (res) => {
+            try {
+              if (res.data.code === 200 || res.data.code === 2e3) {
+                if (res.data.data && res.data.data.transcription_status === "pending") {
+                  console.log("视频转写进行中,5秒后重试");
+                  setTimeout(() => {
+                    this.checkTranscriptionStatus(task, followUpRequestData);
+                  }, 5e3);
+                  return;
+                }
+                console.log("追问视频提交成功");
+                this.isFollowUpMode = false;
+                this.currentVideoIndex = this.mainQuestionIndex;
+                this.uploadQueue.shift();
+                this.processUploadQueue();
+                this.$nextTick(() => {
+                  if (this.currentVideoIndex < this.videoList.length) {
+                    this.videoUrl = this.videoList[this.currentVideoIndex];
+                    this.videoPlaying = true;
+                    const videoContext = common_vendor.index.createVideoContext("myVideo", this);
+                    if (videoContext) {
+                      videoContext.play();
+                    }
+                  }
+                });
+              } else {
+                this.handleSubmitFailure(task, "提交失败: " + (res.data.msg || "未知错误"));
+              }
+            } catch (e) {
+              this.handleSubmitFailure(task, "解析响应失败: " + e.message);
+            }
+          },
+          fail: (err) => {
+            console.error("提交视频失败:", err);
+            this.handleSubmitFailure(task, "提交失败: " + err.errMsg);
+          }
+        });
+      } else {
+        common_vendor.index.request({
+          url: `${common_config.apiBaseUrl}/api/job/upload_video`,
+          method: "POST",
+          data: requestData,
+          header: {
+            "content-type": "application/x-www-form-urlencoded"
+          },
+          success: async (res) => {
+            if (res.data.code === 200 || res.data.code === 2e3) {
+              console.log("视频提交成功,准备调用面试互动接口");
+              try {
+                this.parentJobPositionQuestionId = res.data.data.job_position_question_id;
+                console.log("保存父问题ID:", this.parentJobPositionQuestionId);
+                const limitFromServer = res.data.data.follow_up_limit;
+                if (typeof limitFromServer !== "undefined") {
+                  this.setFollowUpLimit(this.parentJobPositionQuestionId, limitFromServer);
+                } else {
+                  this.setFollowUpLimit(this.parentJobPositionQuestionId, this.defaultFollowUpLimit);
+                }
+                this.resetFollowUpAskedCount(this.parentJobPositionQuestionId);
+                await this.callInterviewInteraction(res.data.data.job_position_question_id);
+                console.log("面试互动接口调用成功");
+              } catch (error) {
+                console.error("面试互动接口调用失败:", error);
+                this.proceedToNextQuestion();
+              }
+              this.uploadQueue.shift();
+              this.processUploadQueue();
+            } else {
+              this.handleSubmitFailure(task, "提交失败: " + (res.data.msg || "未知错误"));
+            }
+          },
+          fail: (err) => {
+            console.error("提交视频失败:", err);
+            this.handleSubmitFailure(task, "提交失败: " + err.errMsg);
+          }
+        });
+      }
+    },
+    // 添加新方法:处理提交失败
+    handleSubmitFailure(task, errorMsg) {
+      console.error("提交失败:", errorMsg);
+      this.uploadStatus[task.id] = "failed";
+      this.updateUploadStatusText();
+      if (task.attempts < task.maxAttempts) {
+        console.log(`将在5秒后重试提交,当前尝试次数: ${task.attempts}/${task.maxAttempts}`);
+        setTimeout(() => {
+          this.submitVideoToInterview(task.videoUrl, task);
+        }, 5e3);
+      } else {
+        console.log("超过最大重试次数,放弃提交");
+        this.uploadQueue.shift();
+        this.processUploadQueue();
+      }
+    },
+    // 添加检查转写状态的方法
+    checkTranscriptionStatus(task, requestData, retryCount = 0) {
+      const maxRetries = 24;
+      const retryInterval = 5e3;
+      if (retryCount >= maxRetries) {
+        console.log("转写超时,继续下一个问题");
+        this.isFollowUpMode = false;
+        this.currentVideoIndex = this.mainQuestionIndex;
+        this.uploadQueue.shift();
+        this.processUploadQueue();
+        return;
+      }
+      common_vendor.index.request({
+        url: `${common_config.apiBaseUrl}/voice_interview/check_transcription_status/`,
+        method: "POST",
+        data: {
+          application_id: requestData.application_id,
+          original_question_id: requestData.original_question_id,
+          video_url: requestData.video_url
+        },
+        header: {
+          "content-type": "application/x-www-form-urlencoded"
+        },
+        success: (res) => {
+          if (res.data.code === 200 || res.data.code === 2e3) {
+            if (res.data.data && res.data.data.status === "completed") {
+              console.log("视频转写完成");
+              this.isFollowUpMode = false;
+              this.currentVideoIndex = this.mainQuestionIndex;
+              this.uploadQueue.shift();
+              this.processUploadQueue();
+              this.$nextTick(() => {
+                if (this.currentVideoIndex < this.videoList.length) {
+                  this.videoUrl = this.videoList[this.currentVideoIndex];
+                  this.videoPlaying = true;
+                  const videoContext = common_vendor.index.createVideoContext("myVideo", this);
+                  if (videoContext) {
+                    videoContext.play();
+                  }
+                }
+              });
+            } else {
+              console.log(`转写进行中,${retryInterval / 1e3}秒后重试 (${retryCount + 1}/${maxRetries})`);
+              setTimeout(() => {
+                this.checkTranscriptionStatus(task, requestData, retryCount + 1);
+              }, retryInterval);
+            }
+          } else if (res.data.message === "面试视频尚未完成转写" || res.data.success === false) {
+            console.log(`转写未完成,${retryInterval / 1e3}秒后重试 (${retryCount + 1}/${maxRetries})`);
+            setTimeout(() => {
+              this.checkTranscriptionStatus(task, requestData, retryCount + 1);
+            }, retryInterval);
+          } else {
+            this.handleSubmitFailure(task, "检查转写状态失败: " + (res.data.msg || "未知错误"));
+          }
+        },
+        fail: (err) => {
+          console.error("检查转写状态失败:", err);
+          console.log(`网络请求失败,${retryInterval / 1e3}秒后重试 (${retryCount + 1}/${maxRetries})`);
+          setTimeout(() => {
+            this.checkTranscriptionStatus(task, requestData, retryCount + 1);
+          }, retryInterval);
+        }
+      });
+    },
+    // 添加新方法:更新上传状态文本
+    updateUploadStatusText() {
+      let mainQueueText = "";
+      if (this.uploadQueue.length > 0) {
+        const currentTask = this.uploadQueue[0];
+        const progress = this.uploadProgress[currentTask.id] || 0;
+        const status = this.uploadStatus[currentTask.id] || "pending";
+        let statusText = "";
+        switch (status) {
+          case "pending":
+            statusText = "等待上传";
+            break;
+          case "uploading":
+            statusText = `上传中 ${progress}%`;
+            break;
+          case "success":
+            statusText = "上传成功,提交中...";
+            break;
+          case "failed":
+            statusText = `上传失败,${currentTask.attempts < currentTask.maxAttempts ? "即将重试" : "已放弃"}`;
+            break;
+        }
+        const questionTypeText = currentTask.isFollowUp ? "追问" : "问题";
+        const questionShortText = currentTask.questionText ? currentTask.questionText.length > 10 ? currentTask.questionText.substring(0, 10) + "..." : currentTask.questionText : `${questionTypeText}${currentTask.questionId}`;
+        mainQueueText = `${questionTypeText}「${questionShortText}」:${statusText}`;
+        if (this.uploadQueue.length > 1) {
+          mainQueueText += ` (${this.uploadQueue.length}个视频待处理)`;
+        }
+      }
+      let backgroundQueueText = "";
+      if (this.backgroundUploadQueue && this.backgroundUploadQueue.length > 0) {
+        const currentTask = this.backgroundUploadQueue[0];
+        const progress = this.uploadProgress[currentTask.id] || 0;
+        const status = this.uploadStatus[currentTask.id] || "pending";
+        let statusText = "";
+        switch (status) {
+          case "pending":
+            statusText = "等待后台上传";
+            break;
+          case "uploading":
+            statusText = `后台上传中 ${progress}%`;
+            break;
+          case "success":
+            statusText = "后台上传成功,提交中...";
+            break;
+          case "failed":
+            statusText = `后台上传失败,${currentTask.attempts < currentTask.maxAttempts ? "即将重试" : "已放弃"}`;
+            break;
+        }
+        const questionShortText = currentTask.questionText ? currentTask.questionText.length > 10 ? currentTask.questionText.substring(0, 10) + "..." : currentTask.questionText : `追问${currentTask.questionId}`;
+        backgroundQueueText = `追问「${questionShortText}」:${statusText}`;
+        if (this.backgroundUploadQueue.length > 1) {
+          backgroundQueueText += ` (${this.backgroundUploadQueue.length}个追问待后台上传)`;
+        }
+      }
+      if (mainQueueText && backgroundQueueText) {
+        this.uploadStatusText = `${mainQueueText} | ${backgroundQueueText}`;
+      } else if (mainQueueText) {
+        this.uploadStatusText = mainQueueText;
+      } else if (backgroundQueueText) {
+        this.uploadStatusText = backgroundQueueText;
+      } else {
+        this.uploadStatusText = "";
+      }
+    },
+    // 修改 proceedToNextQuestion 方法,确保在切换视频时重置历史时间
+    proceedToNextQuestion() {
+      if (this.isVideoSwitching) {
+        console.log("正在切换视频中,请等待...");
+        return;
+      }
+      console.log("继续下一个问题");
+      this.isVideoSwitching = true;
+      const currentVideo = common_vendor.index.createVideoContext("myVideo", this);
+      if (currentVideo) {
+        currentVideo.stop();
+        this.videoPlaying = false;
+      }
+      if (this.currentVideoIndex + 1 >= this.videoList.length) {
+        console.log("所有视频已播放完毕");
+        this.stopUserCamera();
+        this.clearCountdown();
+        const currentJobDetail = JSON.parse(common_vendor.index.getStorageSync("selectedJob"));
+        console.log("当前职位ID:", currentJobDetail);
+        const jobId = currentJobDetail ? currentJobDetail.id : null;
+        this.handleVideoCompletion(jobId);
+        return;
+      }
+      if (this.currentParentQuestionId) {
+        this.followUpRequestInFlight[this.currentParentQuestionId] = false;
+      }
+      this.currentVideoIndex++;
+      this.historyTime = 0;
+      if (this.currentVideoIndex < this.videoList.length) {
+        this.videoUrl = this.videoList[this.currentVideoIndex];
+        this.$nextTick(() => {
+          this.videoPlaying = true;
+          const videoContext = common_vendor.index.createVideoContext("myVideo", this);
+          if (videoContext) {
+            videoContext.play();
+          }
+          this.isVideoSwitching = false;
+        });
+      } else {
+        console.log("所有视频已播放完毕");
+        this.stopUserCamera();
+        this.clearCountdown();
+        const currentJobDetail = JSON.parse(common_vendor.index.getStorageSync("selectedJob"));
+        console.log("当前职位ID:", currentJobDetail);
+        const jobId = currentJobDetail ? currentJobDetail.id : null;
+        console.log("当前职位ID:", jobId);
+        setTimeout(() => {
+          this.isVideoSwitching = false;
+          if (jobId === 9) {
+            common_vendor.index.navigateTo({
+              url: "/pages/interview-question/interview-question",
+              success: () => {
+                console.log("成功跳转到interview-question页面");
+              },
+              fail: (err) => {
+                console.error("跳转到interview-question页面失败:", err);
+                common_vendor.index.redirectTo({
+                  url: "/pages/interview-question/interview-question",
+                  fail: (redirectErr) => {
+                    console.error("重定向到interview-question页面也失败:", redirectErr);
+                    common_vendor.index.navigateBack({
+                      delta: 1
+                    });
+                  }
+                });
+              }
+            });
+          } else {
+            common_vendor.index.navigateTo({
+              url: "/pages/camera/camera",
+              success: () => {
+                console.log("成功跳转到camera页面");
+              },
+              fail: (err) => {
+                console.error("跳转到camera页面失败:", err);
+                common_vendor.index.redirectTo({
+                  url: "/pages/camera/camera",
+                  fail: (redirectErr) => {
+                    console.error("重定向到camera页面也失败:", redirectErr);
+                    common_vendor.index.switchTab({
+                      url: "/pages/camera/camera",
+                      fail: (switchErr) => {
+                        console.error("所有跳转方式都失败:", switchErr);
+                        common_vendor.index.navigateBack({
+                          delta: 1
+                        });
+                      }
+                    });
+                  }
+                });
+              }
+            });
+          }
+        }, 0);
+      }
+    },
+    // 修改 handleAnswerButtonClick 方法,确保在切换视频时重置历史时间
+    handleAnswerButtonClick() {
+      console.log("点击开始回答按钮");
+      this.showAnswerButton = false;
+      this.currentVideoIndex++;
+      this.historyTime = 0;
+      if (this.currentVideoIndex < this.videoList.length) {
+        this.videoUrl = this.videoList[this.currentVideoIndex];
+        this.videoPlaying = true;
+        this.$nextTick(() => {
+          const videoContext = common_vendor.index.createVideoContext("myVideo", this);
+          if (videoContext) {
+            videoContext.play();
+          }
+        });
+      }
+    },
+    // 处理相机错误
+    handleCameraError(e) {
+      console.error("相机错误:", e);
+      const systemInfo = common_vendor.index.getSystemInfoSync();
+      const isIOS = systemInfo.platform === "ios";
+      if (isIOS) {
+        console.log("iOS相机错误,尝试重新初始化");
+        common_vendor.index.showToast({
+          title: "相机初始化中...",
+          icon: "loading",
+          duration: 2e3
+        });
+        this.resetCamera();
+        if (this.isRecording) {
+          this.isRecording = false;
+          this.showStopRecordingButton = false;
+          setTimeout(() => {
+            this.useAlternativeRecordingMethod();
+          }, 1e3);
+        }
+      } else {
+        common_vendor.index.showToast({
+          title: "相机初始化失败,请检查权限设置",
+          icon: "none"
+        });
+        this.tryFallbackOptions();
+      }
+    },
+    // 添加新方法:尝试备用选项
+    tryFallbackOptions() {
+      const systemInfo = common_vendor.index.getSystemInfoSync();
+      if (systemInfo.uniPlatform === "mp-weixin" || systemInfo.uniPlatform === "mp-alipay") {
+        this.useMiniProgramCamera();
+      } else {
+        this.showStaticCameraPlaceholder();
+      }
+    },
+    // 添加新方法:使用小程序相机API
+    useMiniProgramCamera() {
+      console.log("尝试使用小程序相机组件");
+      this.useMiniProgramCameraComponent = true;
+    },
+    // 添加新方法:显示静态图像
+    showStaticCameraPlaceholder() {
+      console.log("显示静态摄像头占位图");
+      const img = document.createElement("img");
+      img.src = "/static/images/camera-placeholder.png";
+      img.className = "static-camera-image";
+      img.style.width = "100%";
+      img.style.height = "100%";
+      img.style.objectFit = "cover";
+      const container = this.$refs.userCameraVideo.parentNode;
+      container.appendChild(img);
+    },
+    // 修改 handleTimeUpdate 方法
+    handleTimeUpdate(e) {
+      const currentTime = e.detail.currentTime || e.target.currentTime;
+      if (this.isRecording && this.recordingTimerCount) {
+        this.recordingTimeDisplay = this.formatTime(this.recordingTimerCount);
+      }
+      if (this.isPlayingLowScoreVideo) {
+        if (this.lowScoreVideoSubtitles && this.lowScoreVideoSubtitles.length > 0) {
+          const subtitle = this.lowScoreVideoSubtitles[0];
+          this.currentSubtitle = subtitle.text;
+        }
+        return;
+      }
+      let currentSubtitles = null;
+      if (this.isFollowUpQuestion && this.currentFollowUpQuestion) {
+        const subtitleKey = `followUpSubtitles_${this.currentFollowUpQuestion.id}`;
+        currentSubtitles = this[subtitleKey] || [{
+          startTime: 0,
+          endTime: 30,
+          text: this.currentFollowUpQuestion.question || this.currentFollowUpQuestion.question
+        }];
+      } else {
+        if (this.currentVideoIndex === 0) {
+          currentSubtitles = this.subtitles;
+        } else {
+          const subtitleArrayName = `question${this.currentVideoIndex}Subtitles`;
+          currentSubtitles = this[subtitleArrayName];
+        }
+      }
+      if (currentSubtitles && currentSubtitles.length > 0) {
+        const subtitle = currentSubtitles.find(
+          (sub) => currentTime >= sub.startTime && currentTime <= sub.endTime
+        ) || currentSubtitles[0];
+        if (subtitle) {
+          this.currentSubtitle = subtitle.text;
+        }
+      }
+      this.historyTime = currentTime;
+      this.lastUpdateTime = Date.now();
+    },
+    // Add a new method to handle the "Start Recording" button click
+    handleStartRecordingClick() {
+      this.showStartRecordingButton = false;
+      this.clearCountdown();
+      this.isWaitingForAnswer = false;
+      this.startRecordingAnswer();
+    },
+    // 修改 checkAudioPermission 方法,确保在录制前获取音频权限
+    checkAudioPermission() {
+      const systemInfo = common_vendor.index.getSystemInfoSync();
+      const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith("mp-");
+      if (isMiniProgram) {
+        common_vendor.index.getSetting({
+          success: (res) => {
+            if (!res.authSetting["scope.record"]) {
+              common_vendor.index.authorize({
+                scope: "scope.record",
+                success: () => {
+                  console.log("录音权限已获取");
+                },
+                fail: (err) => {
+                  console.error("录音权限获取失败:", err);
+                  this.showPermissionDialog("录音");
+                }
+              });
+            }
+            if (!res.authSetting["scope.camera"]) {
+              common_vendor.index.authorize({
+                scope: "scope.camera",
+                success: () => {
+                  console.log("相机权限已获取");
+                },
+                fail: (err) => {
+                  console.error("相机权限获取失败:", err);
+                  this.showPermissionDialog("相机");
+                }
+              });
+            }
+          }
+        });
+      }
+    },
+    // 添加新方法:测试音频输入
+    testAudioInput() {
+      if (!this.cameraStream) {
+        console.warn("没有可用的媒体流,无法测试音频");
+        return;
+      }
+      const audioTracks = this.cameraStream.getAudioTracks();
+      if (audioTracks.length === 0) {
+        console.warn("没有检测到音频轨道,尝试重新获取");
+        this.tryGetAudioOnly();
+        return;
+      }
+      console.log("音频轨道信息:", audioTracks[0].getSettings());
+      try {
+        const AudioContext = window.AudioContext || window.webkitAudioContext;
+        if (!AudioContext) {
+          console.warn("浏览器不支持AudioContext");
+          return;
+        }
+        const audioContext = new AudioContext();
+        const analyser = audioContext.createAnalyser();
+        const microphone = audioContext.createMediaStreamSource(this.cameraStream);
+        microphone.connect(analyser);
+        analyser.fftSize = 256;
+        const bufferLength = analyser.frequencyBinCount;
+        const dataArray = new Uint8Array(bufferLength);
+        let silenceCounter = 0;
+        const checkAudio = () => {
+          if (this.isRecording)
+            return;
+          analyser.getByteFrequencyData(dataArray);
+          let sum = 0;
+          for (let i = 0; i < bufferLength; i++) {
+            sum += dataArray[i];
+          }
+          const average = sum / bufferLength;
+          if (average > 10) {
+            console.log("检测到音频输入,音量:", average);
+            silenceCounter = 0;
+          } else {
+            silenceCounter++;
+            if (silenceCounter > 10) {
+              console.warn("持续检测不到音频输入,可能麦克风未正常工作");
+              silenceCounter = 0;
+            }
+          }
+          requestAnimationFrame(checkAudio);
+        };
+        checkAudio();
+      } catch (e) {
+        console.error("音频测试失败:", e);
+      }
+    },
+    // 添加新方法:尝试单独获取音频
+    tryGetAudioOnly() {
+      navigator.mediaDevices.getUserMedia({ audio: true }).then((audioStream) => {
+        if (this.cameraStream) {
+          const videoTrack = this.cameraStream.getVideoTracks()[0];
+          const audioTrack = audioStream.getAudioTracks()[0];
+          const combinedStream = new MediaStream();
+          if (videoTrack)
+            combinedStream.addTrack(videoTrack);
+          if (audioTrack)
+            combinedStream.addTrack(audioTrack);
+          this.cameraStream = combinedStream;
+          const videoElement = this.$refs.userCameraVideo;
+          if (videoElement) {
+            videoElement.srcObject = combinedStream;
+            videoElement.muted = true;
+          }
+          console.log("成功合并音频和视频轨道");
+        } else {
+          console.warn("没有视频流可合并");
+        }
+      }).catch((err) => {
+        console.error("单独获取音频失败:", err);
+      });
+    },
+    // 添加新方法:显示权限对话框
+    showPermissionDialog(permissionType) {
+      common_vendor.index.showModal({
+        title: "需要权限",
+        content: `请允许使用${permissionType}权限,否则可能影响面试功能`,
+        confirmText: "去设置",
+        success: (res) => {
+          if (res.confirm) {
+            common_vendor.index.openSetting({
+              success: (settingRes) => {
+                console.log("设置页面打开成功", settingRes);
+              }
+            });
+          }
+        }
+      });
+    },
+    // 添加重试上传方法
+    retryVideoUpload() {
+      if (this.lastVideoToRetry) {
+        this.showRetryButton = false;
+        common_vendor.index.showLoading({
+          title: "正在重新提交...",
+          mask: true
+        });
+        this.submitVideoToInterview(this.lastVideoToRetry);
+      } else {
+        common_vendor.index.showToast({
+          title: "没有可重试的视频",
+          icon: "none"
+        });
+      }
+    },
+    // 添加一个新方法用于压缩视频
+    async compressVideo(videoBlob) {
+      if (videoBlob.size < 5 * 1024 * 1024) {
+        return videoBlob;
+      }
+      console.log("开始压缩视频,原始大小:", videoBlob.size);
+      const videoElement = document.createElement("video");
+      videoElement.muted = true;
+      videoElement.autoplay = false;
+      const canvas = document.createElement("canvas");
+      const ctx = canvas.getContext("2d");
+      videoElement.src = URL.createObjectURL(videoBlob);
+      return new Promise((resolve) => {
+        videoElement.onloadedmetadata = () => {
+          const width = Math.floor(videoElement.videoWidth / 2);
+          const height = Math.floor(videoElement.videoHeight / 2);
+          canvas.width = width;
+          canvas.height = height;
+          const stream = canvas.captureStream(15);
+          if (videoElement.captureStream) {
+            const originalStream = videoElement.captureStream();
+            const audioTracks = originalStream.getAudioTracks();
+            if (audioTracks.length > 0) {
+              stream.addTrack(audioTracks[0]);
+            }
+          }
+          const options = {
+            mimeType: "video/webm;codecs=vp8,opus",
+            audioBitsPerSecond: 64e3,
+            videoBitsPerSecond: 8e5
+            // 800kbps
+          };
+          const mediaRecorder = new MediaRecorder(stream, options);
+          const chunks = [];
+          mediaRecorder.ondataavailable = (e) => {
+            if (e.data.size > 0) {
+              chunks.push(e.data);
+            }
+          };
+          mediaRecorder.onstop = () => {
+            const compressedBlob = new Blob(chunks, { type: "video/webm" });
+            console.log("视频压缩完成,压缩后大小:", compressedBlob.size);
+            resolve(compressedBlob);
+          };
+          videoElement.onplay = () => {
+            mediaRecorder.start(10);
+            const drawFrame = () => {
+              if (videoElement.paused || videoElement.ended) {
+                mediaRecorder.stop();
+                return;
+              }
+              ctx.drawImage(videoElement, 0, 0, width, height);
+              requestAnimationFrame(drawFrame);
+            };
+            drawFrame();
+          };
+          videoElement.play();
+        };
+      });
+    },
+    // 修改 checkIOSCameraRecordPermission 方法
+    checkIOSCameraRecordPermission() {
+      const systemInfo = common_vendor.index.getSystemInfoSync();
+      if (systemInfo.platform !== "ios")
+        return;
+      common_vendor.index.getSetting({
+        success: (res) => {
+          if (!res.authSetting["scope.camera"]) {
+            common_vendor.index.authorize({
+              scope: "scope.camera",
+              success: () => {
+                console.log("iOS相机权限已获取");
+              },
+              fail: (err) => {
+                console.error("iOS相机权限获取失败:", err);
+                this.showPermissionDialog("相机");
+              }
+            });
+          }
+          if (!res.authSetting["scope.record"]) {
+            common_vendor.index.authorize({
+              scope: "scope.record",
+              success: () => {
+                console.log("iOS录音权限已获取");
+              },
+              fail: (err) => {
+                console.error("iOS录音权限获取失败:", err);
+                this.showPermissionDialog("录音");
+              }
+            });
+          }
+        }
+      });
+    },
+    // 添加新方法:检查并修复渲染问题
+    checkAndFixRenderingIssues() {
+      try {
+        if (typeof u !== "undefined" && u) {
+          if (!u.currentQuestion) {
+            console.log("修复: 创建缺失的currentQuestion对象");
+            u.currentQuestion = {};
+          }
+          if (u.currentQuestion && typeof u.currentQuestion.isImportant === "undefined") {
+            console.log("修复: 设置缺失的isImportant属性");
+            u.currentQuestion.isImportant = false;
+          }
+        }
+      } catch (e) {
+        console.log("防御性检查异常:", e);
+      }
+    },
+    // 添加格式化时间的辅助方法
+    formatTime(seconds) {
+      if (!seconds && seconds !== 0)
+        return "03:30";
+      const minutes = Math.floor(seconds / 60);
+      const remainingSeconds = seconds % 60;
+      return `${minutes.toString().padStart(2, "0")}:${remainingSeconds.toString().padStart(2, "0")}`;
+    },
+    // 添加获取问题数据的方法
+    fetchQuestions() {
+      this.loading = true;
+      const tenant_id = JSON.parse(common_vendor.index.getStorageSync("userInfo")).tenant_id || "1";
+      let position_id = 1;
+      try {
+        const selectedJob = JSON.parse(common_vendor.index.getStorageSync("selectedJob") || "{}");
+        if (selectedJob && selectedJob.id) {
+          position_id = selectedJob.id;
+          console.log("使用选择的职位ID获取问题:", position_id);
+        } else {
+          console.warn("未找到选择的职位信息,使用默认职位ID:", position_id);
+        }
+      } catch (e) {
+        console.error("解析职位信息失败:", e);
+      }
+      const timestamp = Date.now();
+      const requestUrl = `${common_config.apiBaseUrl}/api/wechat/open_questions/?position_id=${position_id}&tenant_id=${tenant_id}&question_form=0&_t=${timestamp}`;
+      console.log("完整的请求URL:", requestUrl);
+      common_vendor.index.request({
+        url: requestUrl,
+        method: "GET",
+        success: (res) => {
+          if (res.data && res.data.code === 2e3 && res.data.data && res.data.data.items) {
+            console.log("获取问题数据成功:", res.data.data.items);
+            this.questions = res.data.data.items;
+            this.processQuestionData();
+            this.playIntroVideo();
+          } else {
+            console.error("获取问题数据失败:", res.data);
+            common_vendor.index.showToast({
+              title: "获取问题数据失败",
+              icon: "none"
+            });
+          }
+        },
+        fail: (err) => {
+          console.error("请求问题数据失败:", err);
+          common_vendor.index.showToast({
+            title: "网络错误,请检查网络连接",
+            icon: "none"
+          });
+        },
+        complete: () => {
+          this.loading = false;
+        }
+      });
+    },
+    // 处理问题数据,提取视频URL和字幕
+    processQuestionData() {
+      this.videoList = [];
+      this.videoList.push(this.introVideoUrl);
+      const configStr = common_vendor.index.getStorageSync("configData");
+      let openingSpeech = [];
+      if (configStr) {
+        try {
+          const configData = JSON.parse(configStr);
+          if (configData && configData.digital_human_opening_speech) {
+            if (Array.isArray(configData.digital_human_opening_speech)) {
+              openingSpeech = configData.digital_human_opening_speech.map((item, index, arr) => {
+                const startTime = index === 0 ? 0 : arr[index - 1].end_time || index * 5;
+                const endTime = item.end_time || (index + 1) * 5;
+                return {
+                  startTime,
+                  endTime,
+                  text: item.content
+                };
+              });
+            } else if (typeof configData.digital_human_opening_speech === "string") {
+              openingSpeech = this.convertStringToSubtitles(configData.digital_human_opening_speech);
+            }
+          }
+        } catch (error) {
+          console.error("解析configData失败:", error);
+        }
+      }
+      this.subtitles = openingSpeech.length > 0 ? openingSpeech : [
+        {
+          startTime: 0,
+          endTime: 5,
+          text: "你好,我是本次面试的面试官,欢迎参加本公司的线上面试!"
+        },
+        {
+          startTime: 5,
+          endTime: 13,
+          text: "面试预计需要15分钟,请你提前安排在网络良好、光线亮度合适、且相对安静的环境参加这次面试"
+        },
+        {
+          startTime: 13,
+          endTime: 20,
+          text: "以免影响本次面试的结果。如果你在面试过程中遇到问题,请与我们的招聘人员联系。"
+        }
+      ];
+      console.log("处理后的字幕数据:", this.subtitles);
+      const sortedQuestions = [...this.questions].sort((a, b) => a.sequence_number - b.sequence_number);
+      const questionsToUse = sortedQuestions.slice(0, 5);
+      questionsToUse.forEach((question, index) => {
+        if (question.digital_human_video_url) {
+          this.videoList.push(question.digital_human_video_url);
+          const subtitleArray = [{
+            startTime: 0,
+            endTime: 30,
+            // 延长字幕显示时间到30秒
+            text: question.question || question.question
+          }];
+          const videoIndex = this.videoList.length - 1;
+          this[`question${videoIndex}Subtitles`] = subtitleArray;
+          this.subtitleMap[question.digital_human_video_url] = subtitleArray;
+        }
+      });
+      if (this.videoList.length <= 1)
+        ;
+      else {
+        console.log("处理后的视频列表:", this.videoList);
+        console.log("处理后的字幕:", this.subtitles);
+      }
+    },
+    // 将字符串类型的文本转换为字幕格式
+    convertStringToSubtitles(text) {
+      if (!text || typeof text !== "string") {
+        return [];
+      }
+      const sentences = text.split(/([。!?!?])/).filter((part) => part.trim() !== "").reduce((acc, part, index, arr) => {
+        if (index % 2 === 0) {
+          const nextPart = arr[index + 1] || "";
+          acc.push(part + nextPart);
+        }
+        return acc;
+      }, []).filter((sentence) => sentence.trim().length > 0);
+      if (sentences.length <= 1) {
+        const maxLength = 30;
+        const textParts = [];
+        for (let i = 0; i < text.length; i += maxLength) {
+          textParts.push(text.substring(i, i + maxLength));
+        }
+        sentences.splice(0, sentences.length, ...textParts);
+      }
+      let currentStartTime = 0;
+      return sentences.map((sentence) => {
+        const duration = Math.max(3, Math.ceil(sentence.length / 6));
+        const startTime = currentStartTime;
+        const endTime = startTime + duration;
+        currentStartTime = endTime;
+        return {
+          startTime,
+          endTime,
+          text: sentence.trim()
+        };
+      });
+    },
+    // 使用默认视频和字幕(作为备用)
+    useDefaultVideosAndSubtitles() {
+      console.log("使用默认视频和字幕");
+      this.subtitles = [
+        {
+          startTime: 0,
+          endTime: 5,
+          text: "你好,我是本次面试的面试官,欢迎参加本公司的线上面试!"
+        },
+        {
+          startTime: 5,
+          endTime: 13,
+          text: "面试预计需要15分钟,请你提前安排在网络良好、光线亮度合适、且相对安静的环境参加这次面试"
+        },
+        {
+          startTime: 13,
+          endTime: 20,
+          text: "以免影响本次面试的结果。如果你在面试过程中遇到问题,请与我们的招聘人员联系。"
+        }
+      ];
+      this.question1Subtitles = [{
+        startTime: 0,
+        endTime: 10,
+        text: "请结合您的基本信息与过往履历进行简单的自我介绍,并讲一讲您有哪些优势胜任本岗位:"
+      }];
+      this.question2Subtitles = [{
+        startTime: 0,
+        endTime: 4,
+        text: "在工作中,你如何确保个人防护装备的正确使用?"
+      }];
+      this.question3Subtitles = [{
+        startTime: 0,
+        endTime: 4,
+        text: "描述一次你与团队合作改善生产流程的经历。"
+      }];
+      this.question4Subtitles = [{
+        startTime: 0,
+        endTime: 6,
+        text: "你在团队合作中曾遇到过哪些挑战?如何解决团队内部的分歧?"
+      }];
+      this.question5Subtitles = [{
+        startTime: 0,
+        endTime: 5,
+        text: "您已完成本次面试全部题目,请问您对于这个岗位还有什么想要了解的吗?"
+      }];
+    },
+    // 播放介绍视频
+    playIntroVideo() {
+      this.videoUrl = this.videoList[0];
+      this.videoPlaying = true;
+      this.$nextTick(() => {
+        const videoContext = common_vendor.index.createVideoContext("myVideo", this);
+        if (videoContext) {
+          videoContext.play();
+        }
+      });
+    },
+    // 添加新方法:获取默认问题ID
+    getDefaultQuestionId(videoIndex) {
+      switch (videoIndex) {
+        case 1:
+          return 10;
+        case 2:
+          return 11;
+        case 3:
+          return 12;
+        case 4:
+          return 13;
+        default:
+          return 10;
+      }
+    },
+    // 添加新方法:根据索引获取当前问题
+    getCurrentQuestionByIndex(videoIndex) {
+      const questionIndex = videoIndex - 1;
+      const sortedQuestions = [...this.questions].sort((a, b) => a.sequence_number - b.sequence_number);
+      if (questionIndex >= 0 && questionIndex < sortedQuestions.length) {
+        return sortedQuestions[questionIndex];
+      }
+      return null;
+    },
+    // 添加新方法:获取当前问题的推荐录制时长
+    getCurrentQuestionRecommendedDuration() {
+      const currentQuestion = this.getCurrentQuestionByIndex(this.currentVideoIndex);
+      if (currentQuestion && currentQuestion.recommended_duration) {
+        const recommendedDuration = parseInt(currentQuestion.recommended_duration);
+        console.log(`使用问题推荐时长: ${recommendedDuration}秒`);
+        return recommendedDuration;
+      }
+      console.log("使用默认录制时长: 300秒");
+      return 300;
+    },
+    // 添加新方法:重置录制状态,准备重新回答
+    resetForRerecording() {
+      console.log("重置录制状态,准备重新回答");
+      this.isRecording = false;
+      this.showStopRecordingButton = false;
+      this.showStartRecordingButton = true;
+      this.clearCountdown();
+      if (this.recordingTimer) {
+        clearInterval(this.recordingTimer);
+        this.recordingTimer = null;
+      }
+      this.recordingTimerCount = 0;
+      this.recordingTimeDisplay = "00:00 ";
+      this.maxRecordingTime = this.getCurrentQuestionRecommendedDuration();
+      this.remainingTime = this.maxRecordingTime;
+      if (this.mediaRecorder && this.mediaRecorder.state !== "inactive") {
+        this.mediaRecorder.stop();
+        this.recordedChunks = [];
+      }
+      if (this.cameraContext) {
+        this.cameraContext.stopRecord({
+          success: () => {
+            console.log("相机录制已停止");
+          },
+          fail: (err) => {
+            console.error("停止相机录制失败:", err);
+          }
+        });
+      }
+      this.questionRetryMap = {};
+    },
+    // 修改 playLowScoreVideo 方法,优化字幕显示并添加重试次数限制
+    playLowScoreVideo() {
+      var _a;
+      console.log("播放低分提示视频");
+      const currentQuestionId = (_a = this.getCurrentQuestionByIndex(this.currentVideoIndex)) == null ? void 0 : _a.id;
+      if (!currentQuestionId) {
+        console.error("无法获取当前问题ID");
+        return;
+      }
+      if (!this.questionRetryMap[currentQuestionId]) {
+        this.questionRetryMap[currentQuestionId] = 1;
+      } else {
+        this.questionRetryMap[currentQuestionId]++;
+      }
+      if (this.questionRetryMap[currentQuestionId] > this.maxQuestionRetries) {
+        console.log(`问题 ${currentQuestionId} 已超过最大重试次数,自动进入下一题`);
+        this.isPlayingLowScoreVideo = false;
+        this.isFollowUpQuestion = false;
+        this.currentFollowUpQuestion = null;
+        this.followUpQuestion = "";
+        this.parentQuestion = "";
+        this.currentVideoIndex++;
+        if (this.currentVideoIndex < this.videoList.length) {
+          const nextQuestion = this.getCurrentQuestionByIndex(this.currentVideoIndex);
+          if (nextQuestion) {
+            this.currentSubtitle = nextQuestion.question || nextQuestion.question;
+          }
+          this.videoUrl = this.videoList[this.currentVideoIndex];
+          this.videoPlaying = true;
+          this.$nextTick(() => {
+            const videoContext = common_vendor.index.createVideoContext("myVideo", this);
+            if (videoContext) {
+              videoContext.play();
+            }
+          });
+        } else {
+          this.finishInterview();
+        }
+        return;
+      }
+      this.isPlayingLowScoreVideo = true;
+      this.showStartRecordingButton = false;
+      this.showStopRecordingButton = false;
+      this.showRerecordButton = false;
+      this.videoUrl = this.lowScoreVideoUrl;
+      this.videoPlaying = true;
+      const currentQuestion = this.getCurrentQuestionByIndex(this.currentVideoIndex);
+      const originalSubtitle = currentQuestion ? currentQuestion.question || currentQuestion.question : this.currentSubtitle;
+      this.currentSubtitle = "";
+      this.$nextTick(() => {
+        const videoContext = common_vendor.index.createVideoContext("myVideo", this);
+        if (videoContext) {
+          videoContext.play();
+          setTimeout(() => {
+            this.currentSubtitle = "我未听清楚您在说什么,请您再说一遍!";
+            this.lowScoreVideoSubtitles = [
+              {
+                startTime: 0,
+                endTime: 30,
+                text: "我未听清楚您在说什么,请您再说一遍!",
+                translation: "I didn't quite catch what you said, could you please repeat it?"
+              }
+            ];
+          }, 500);
+        }
+      });
+      this.originalQuestionSubtitle = originalSubtitle;
+    },
+    // 添加新方法:处理重新录制按钮点击
+    handleRerecordButtonClick() {
+      console.log("点击重新录制按钮");
+      this.retryCount++;
+      console.log(`当前重试次数: ${this.retryCount}/${this.maxRetryAttempts}`);
+      this.showRerecordButton = false;
+      this.handleStartRecordingClick();
+    },
+    // 页面卸载时关闭WebSocket连接
+    onUnload() {
+      console.log("页面卸载,关闭WebSocket连接");
+      this.cleanupPersonDetectionWebSocket();
+      this.stopUserCamera();
+      this.clearCountdown();
+      if (this.recordingTimer) {
+        clearInterval(this.recordingTimer);
+        this.recordingTimer = null;
+      }
+      if (this.mediaRecorder && this.mediaRecorder.state !== "inactive") {
+        this.mediaRecorder.stop();
+      }
+      common_vendor.index.setKeepScreenOn({
+        keepScreenOn: false
+      });
+    },
+    // 页面隐藏时关闭WebSocket连接
+    onHide() {
+      console.log("页面隐藏,关闭WebSocket连接");
+      this.cleanupPersonDetectionWebSocket();
+      if (this.isRecording) {
+        console.log("页面隐藏时正在录制,录制将继续");
+        common_vendor.index.showToast({
+          title: "请不要离开面试页面",
+          icon: "none",
+          duration: 2e3
+        });
+      }
+    },
+    // 页面显示时重新初始化WebSocket连接
+    onShow() {
+      console.log("identity-verify页面onShow");
+      console.log("当前本地存储中的职位信息:", common_vendor.index.getStorageSync("selectedJob"));
+      this.fetchQuestions();
+      const systemInfo = common_vendor.index.getSystemInfoSync();
+      const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith("mp-");
+      if (isMiniProgram) {
+        if (!this.personDetectionSocket) {
+          console.log("重新初始化WebSocket连接");
+          this.initPersonDetectionWebSocket();
+        } else if (!this.personDetectionInterval) {
+          console.log("重新启动人脸检测定时器");
+          this.startPersonDetectionInterval();
+        }
+      }
+      common_vendor.index.hideHomeButton();
+    },
+    // 添加新方法:阻止视频控制
+    preventVideoControl(e) {
+      e.preventDefault();
+      e.stopPropagation();
+      console.log("阻止视频控制操作");
+      return false;
+    },
+    // 添加获取追问问题的方法
+    fetchFollowUpQuestions() {
+      const tenant_id = JSON.parse(common_vendor.index.getStorageSync("userInfo")).tenant_id || "1";
+      let position_id = 1;
+      try {
+        const selectedJob = JSON.parse(common_vendor.index.getStorageSync("selectedJob") || "{}");
+        if (selectedJob && selectedJob.id) {
+          position_id = selectedJob.id;
+          console.log("使用选择的职位ID获取追问问题:", position_id);
+        } else {
+          console.warn("未找到选择的职位信息,使用默认职位ID:", position_id);
+        }
+      } catch (e) {
+        console.error("解析职位信息失败:", e);
+      }
+      const timestamp = Date.now();
+      const requestUrl = `${common_config.apiBaseUrl}/api/wechat/open_questions/?position_id=${position_id}&tenant_id=${tenant_id}&question_form=5&_t=${timestamp}`;
+      console.log("获取追问问题的请求URL:", requestUrl);
+      common_vendor.index.request({
+        url: requestUrl,
+        method: "GET",
+        success: (res) => {
+          if (res.data && res.data.code === 2e3 && res.data.data && res.data.data.items) {
+            console.log("获取追问问题数据成功:", res.data.data.items);
+            this.followUpQuestions = res.data.data.items.map((item) => ({
+              ...item,
+              question_form: 5
+              // 确保每个追问问题都有正确的question_form值
+            }));
+            this.processFollowUpQuestions();
+          } else {
+            console.error("获取追问问题数据失败:", res.data);
+            this.followUpQuestions = [];
+          }
+        },
+        fail: (err) => {
+          console.error("请求追问问题数据失败:", err);
+          this.followUpQuestions = [];
+        }
+      });
+    },
+    // 改进处理追问问题数据的方法
+    processFollowUpQuestions() {
+      if (!this.followUpQuestions || this.followUpQuestions.length === 0) {
+        console.log("没有追问问题数据");
+        this.followUpQuestions = [];
+        return;
+      }
+      console.log("处理追问问题数据,总数:", this.followUpQuestions.length);
+      this.followUpQuestions = this.followUpQuestions.filter((q) => q.parent_question_id);
+      const parentQuestionIds = /* @__PURE__ */ new Set();
+      this.followUpQuestions.forEach((question) => {
+        if (question.parent_question_id) {
+          parentQuestionIds.add(question.parent_question_id);
+        }
+      });
+      console.log("有追问的父问题ID:", Array.from(parentQuestionIds));
+      this.hasPlayedFollowUp = {};
+    },
+    // 修改检查并播放追问问题的方法
+    checkAndPlayFollowUpQuestion(parentQuestionId) {
+      console.log("检查是否有追问问题,父问题ID:", parentQuestionId);
+      if (this.isWaitingForAnswer) {
+        console.log("正在等待用户回答,暂不处理追问");
+        return;
+      }
+      if (!this.canAskMoreFollowUps(parentQuestionId)) {
+        console.log("追问次数已达上限,进入下一题");
+        this.proceedToNextQuestion();
+        return;
+      }
+      if (!parentQuestionId) {
+        console.warn("没有父问题ID,无法检查追问问题");
+        this.proceedToNextQuestion();
+        return;
+      }
+      if (this.hasPlayedFollowUp[parentQuestionId]) {
+        console.log("已经播放过此问题的追问,直接进入下一个问题");
+        this.retryCount = 0;
+        this.proceedToNextQuestion();
+        return;
+      }
+      const followUpQuestion = this.followUpQuestions.find(
+        (q) => q.parent_question_id === parentQuestionId && q.digital_human_video_url && q.question_form === 5
+      );
+      if (followUpQuestion) {
+        console.log("找到追问问题:", followUpQuestion);
+        const recordingDuration = this.getRecordingDuration();
+        const lowScoreDuration = 7;
+        const minDuration = 3;
+        if (recordingDuration < lowScoreDuration) {
+          let message = recordingDuration < minDuration ? `录制时间 ${recordingDuration} 秒,少于最小时长 ${minDuration} 秒` : `录制时间 ${recordingDuration} 秒,少于标准时长 ${lowScoreDuration} 秒`;
+          console.log(message + ",将播放低分提示视频");
+          this.retryCount++;
+          this.needPlayLowScoreVideo = true;
+          this.playLowScoreVideo();
+          return;
+        }
+        this.retryCount = 0;
+        this.hasPlayedFollowUp[parentQuestionId] = true;
+        this.isFollowUpQuestion = true;
+        this.currentParentQuestionId = parentQuestionId;
+        this.currentFollowUpQuestion = followUpQuestion;
+        this.playFollowUpQuestionVideo(followUpQuestion);
+      } else {
+        console.log("没有找到对应的追问问题,继续下一个问题");
+        this.retryCount = 0;
+        this.proceedToNextQuestion();
+      }
+    },
+    // 修改播放追问问题视频的方法
+    playFollowUpQuestionVideo(followUpQuestion) {
+      console.log("播放追问问题视频:", followUpQuestion.digital_human_video_url);
+      this.parentQuestion = this.currentSubtitle;
+      this.videoUrl = followUpQuestion.digital_human_video_url;
+      this.videoPlaying = true;
+      this.isFollowUpQuestion = true;
+      this.currentFollowUpQuestion = followUpQuestion;
+      const followUpSubtitles = [{
+        startTime: 0,
+        endTime: 60,
+        // 延长显示时间到60秒
+        text: followUpQuestion.question || followUpQuestion.question
+      }];
+      const subtitleKey = `followUpSubtitles_${followUpQuestion.id}`;
+      this[subtitleKey] = followUpSubtitles;
+      this.$nextTick(() => {
+        const videoContext = common_vendor.index.createVideoContext("myVideo", this);
+        if (videoContext) {
+          videoContext.play();
+          this.currentSubtitle = followUpSubtitles[0].text;
+        }
+      });
+    },
+    // 添加作废面试的方法
+    invalidateInterview() {
+      if (this.isRecording) {
+        this.stopRecordingAnswer();
+      }
+      if (this.recordingTimer) {
+        clearInterval(this.recordingTimer);
+      }
+      this.isRecording = false;
+      this.showStopRecordingButton = false;
+      this.showStartRecordingButton = false;
+      setTimeout(() => {
+        common_vendor.index.switchTab({
+          url: "/pages/index/index"
+        });
+      }, 500);
+    },
+    initPersonDetectionWebSocket() {
+      if (this.personDetectionSocket) {
+        this.cleanupPersonDetectionWebSocket();
+      }
+      try {
+        this.personDetectionSocket = common_vendor.index.connectSocket({
+          url: `${common_config.personDetectionWsUrl}/ws/interview-room/room_${common_vendor.index.getStorageSync("appId")}/${common_vendor.index.getStorageSync("appId")}/`,
+          success: () => {
+            console.log("WebSocket connection initiated");
+          },
+          fail: (error) => {
+            console.error("WebSocket connection failed:", error);
+          }
+        });
+        this.personDetectionSocket.onOpen(() => {
+          console.log("WebSocket connection opened");
+          this.startPersonDetectionInterval();
+        });
+        this.personDetectionSocket.onError((error) => {
+          console.error("WebSocket error:", error);
+          this.cleanupPersonDetectionWebSocket();
+        });
+        this.personDetectionSocket.onClose(() => {
+          console.log("WebSocket connection closed");
+          this.cleanupPersonDetectionWebSocket();
+        });
+        this.personDetectionSocket.onMessage((res) => {
+          try {
+            const data = JSON.parse(res.data);
+            if (data.type === "person_detection_result") {
+              this.handlePersonDetectionResult(data);
+            }
+          } catch (error) {
+            console.error("Error parsing WebSocket message:", error);
+          }
+        });
+      } catch (error) {
+        console.error("Error initializing WebSocket:", error);
+        this.cleanupPersonDetectionWebSocket();
+      }
+    },
+    startPersonDetectionInterval() {
+      if (this.personDetectionInterval) {
+        clearInterval(this.personDetectionInterval);
+      }
+      this.personDetectionInterval = setInterval(() => {
+        try {
+          if (!this.personDetectionSocket || !this.cameraContext) {
+            console.warn("人脸检测:相机上下文或WebSocket连接未就绪");
+            return;
+          }
+          this.cameraContext.takePhoto({
+            quality: "low",
+            success: (res) => {
+              try {
+                const tempFilePath = res.tempImagePath;
+                if (!tempFilePath) {
+                  console.warn("人脸检测:未获取到有效的图片路径");
+                }
+                common_vendor.index.getFileSystemManager().readFile({
+                  filePath: tempFilePath,
+                  encoding: "base64",
+                  success: (res2) => {
+                    try {
+                      const base64Image = res2.data;
+                      if (!this.personDetectionSocket || this.personDetectionSocket.readyState !== 1) {
+                        console.warn("人脸检测:WebSocket连接已断开或未就绪");
+                        return;
+                      }
+                      this.personDetectionSocket.send({
+                        data: JSON.stringify({
+                          type: "person_detection",
+                          image_data: base64Image
+                        })
+                      });
+                    } catch (wsError) {
+                      console.error("人脸检测:发送WebSocket数据时出错:", wsError);
+                    }
+                  },
+                  fail: (error) => {
+                    console.error("人脸检测:读取图片文件失败:", error);
+                  }
+                });
+              } catch (fileError) {
+                console.error("人脸检测:处理图片文件时出错:", fileError);
+              }
+            },
+            fail: (error) => {
+              console.error("人脸检测:拍照失败:", error);
+            }
+          });
+        } catch (mainError) {
+          console.error("人脸检测:主流程执行出错:", mainError);
+        }
+      }, 5e3);
+    },
+    cleanupPersonDetectionWebSocket() {
+      if (this.personDetectionInterval) {
+        clearInterval(this.personDetectionInterval);
+        this.personDetectionInterval = null;
+      }
+      if (this.personDetectionSocket) {
+        try {
+          this.personDetectionSocket.close();
+        } catch (error) {
+          console.error("Error closing WebSocket:", error);
+        }
+        this.personDetectionSocket = null;
+      }
+    },
+    handlePersonDetectionResult(data) {
+      console.log("data", data);
+      if (data.data.identity.status == "no_face") {
+        this.showPageWarning = true;
+        common_vendor.index.showToast({
+          /* data.data.identity.message */
+          title: "请保持面部完整出现在镜头内",
+          icon: "none",
+          duration: 3e3
+        });
+        common_vendor.index.vibrateLong({
+          success: function() {
+            console.log("Vibration successful");
+          },
+          fail: function(err) {
+            console.error("Vibration failed:", err);
+          }
+        });
+        setTimeout(() => {
+          this.showPageWarning = false;
+        }, 3e3);
+      }
+    },
+    // 进入追问模式
+    enterFollowUpMode() {
+      this.isFollowUpMode = true;
+      this.mainQuestionIndex = this.currentVideoIndex;
+      console.log("进入追问模式,保存主问题索引:", this.mainQuestionIndex);
+    },
+    // 修改 handleFollowUpQuestion 方法
+    async handleFollowUpQuestion(questionData) {
+      console.log("处理追问:", questionData);
+      this.enterFollowUpMode();
+      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);
+      }
+    },
+    // 播放追问音频
+    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;
+          });
+          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.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]);
+          }
+        });
+      }
+    },
+    // 显示面试官思考中loading
+    showThinkingLoading() {
+      this.isThinking = true;
+      common_vendor.index.showLoading({
+        title: "面试官正在思考中",
+        mask: false
+      });
+    },
+    // 隐藏面试官思考中loading
+    hideThinkingLoading() {
+      this.isThinking = false;
+      common_vendor.index.hideLoading();
+      if (this.thinkingTimer) {
+        clearTimeout(this.thinkingTimer);
+        this.thinkingTimer = null;
+      }
+    },
+    // 处理视频完成
+    handleVideoCompletion(jobId) {
+      this.isVideoSwitching = false;
+      if (jobId === 9) {
+        common_vendor.index.navigateTo({
+          url: "/pages/interview-question/interview-question",
+          success: () => {
+            console.log("成功跳转到interview-question页面");
+          },
+          fail: (err) => {
+            console.error("跳转到interview-question页面失败:", err);
+            common_vendor.index.redirectTo({
+              url: "/pages/interview-question/interview-question",
+              fail: (redirectErr) => {
+                console.error("重定向到interview-question页面也失败:", redirectErr);
+                common_vendor.index.navigateBack({
+                  delta: 1
+                });
+              }
+            });
+          }
+        });
+      } else {
+        common_vendor.index.navigateTo({
+          url: "/pages/camera/camera",
+          success: () => {
+            console.log("成功跳转到camera页面");
+          },
+          fail: (err) => {
+            console.error("跳转到camera页面失败:", err);
+            common_vendor.index.redirectTo({
+              url: "/pages/camera/camera",
+              fail: (redirectErr) => {
+                console.error("重定向到camera页面也失败:", redirectErr);
+                common_vendor.index.switchTab({
+                  url: "/pages/camera/camera",
+                  fail: (switchErr) => {
+                    console.error("所有跳转方式都失败:", switchErr);
+                    common_vendor.index.navigateBack({
+                      delta: 1
+                    });
+                  }
+                });
+              }
+            });
+          }
+        });
+      }
+    }
+  },
+  computed: {
+    // 计算进度比例
+    progressRatio() {
+      return this.recordingTimerCount / this.maxRecordingTime;
+    },
+    // 右半圆旋转角度
+    half1Turn() {
+      if (this.progressRatio <= 0.5) {
+        return this.progressRatio * 2 * 180;
+      } else {
+        return 180;
+      }
+    },
+    // 左半圆旋转角度
+    half2Turn() {
+      if (this.progressRatio <= 0.5) {
+        return 0;
+      } else {
+        return (this.progressRatio - 0.5) * 2 * 180;
+      }
+    },
+    // 修改进度百分比的计算方式
+    progressPercent() {
+      return Math.min(Math.round(this.recordingTimerCount / this.maxRecordingTime * 100), 100);
+    },
+    // 添加总题数计算属性
+    totalQuestions() {
+      return this.questions.length || 5;
+    }
+  }
+};
+function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
+  return common_vendor.e({
+    a: $data.statusBarHeight + "px",
+    b: $data.videoUrl,
+    c: common_vendor.o((...args) => $options.handleVideoError && $options.handleVideoError(...args)),
+    d: common_vendor.o((...args) => $options.handleVideoEnded && $options.handleVideoEnded(...args)),
+    e: common_vendor.o((...args) => $options.handleTimeUpdate && $options.handleTimeUpdate(...args)),
+    f: common_vendor.o((...args) => $options.preventVideoControl && $options.preventVideoControl(...args)),
+    g: common_vendor.o((...args) => $options.preventVideoControl && $options.preventVideoControl(...args)),
+    h: $data.showAnswerButton
+  }, $data.showAnswerButton ? {
+    i: common_vendor.o((...args) => $options.handleAnswerButtonClick && $options.handleAnswerButtonClick(...args))
+  } : {}, {
+    j: $data.currentSubtitle || $data.showSubtitleText && $data.subtitleText
+  }, $data.currentSubtitle || $data.showSubtitleText && $data.subtitleText ? common_vendor.e({
+    k: $data.currentVideoIndex > 0
+  }, $data.currentVideoIndex > 0 ? {
+    l: common_vendor.t($data.currentVideoIndex),
+    m: common_vendor.t($options.totalQuestions)
+  } : {}, {
+    n: !$data.isFollowUpQuestion
+  }, !$data.isFollowUpQuestion ? {
+    o: common_vendor.t($data.currentSubtitle)
+  } : {
+    p: common_vendor.t($data.parentQuestion),
+    q: common_vendor.t($data.subtitleText || $data.currentSubtitle)
+  }) : {}, {
+    r: $data.useMiniProgramCameraComponent
+  }, $data.useMiniProgramCameraComponent ? {
+    s: common_vendor.o((...args) => $options.handleCameraError && $options.handleCameraError(...args))
+  } : {}, {
+    t: $data.showPageWarning ? 1 : "",
+    v: $data.loading
+  }, $data.loading ? {} : {}, {
+    w: $data.showDebugInfo
+  }, $data.showDebugInfo ? common_vendor.e({
+    x: $data.assistantResponse
+  }, $data.assistantResponse ? {
+    y: common_vendor.t($data.assistantResponse)
+  } : {}, {
+    z: $data.audioTranscript
+  }, $data.audioTranscript ? {
+    A: common_vendor.t($data.audioTranscript)
+  } : {}, {
+    B: common_vendor.f($data.processedResponses, (item, index, i0) => {
+      return common_vendor.e({
+        a: item.role
+      }, item.role ? {
+        b: common_vendor.t(item.role)
+      } : {}, {
+        c: item.transcript
+      }, item.transcript ? {
+        d: common_vendor.t(item.transcript)
+      } : {}, {
+        e: index
+      });
+    })
+  }) : {}, {
+    C: $data.showStopRecordingButton
+  }, $data.showStopRecordingButton ? {
+    D: common_vendor.o((...args) => $options.stopRecordingAnswer && $options.stopRecordingAnswer(...args))
+  } : {}, {
+    E: $data.isRecording
+  }, $data.isRecording ? {
+    F: common_vendor.t($data.recordingTimeDisplay),
+    G: `conic-gradient(${$data.progressColor} ${$options.progressPercent}%, ${$data.progressBgColor} 0%)`
+  } : {}, {
+    H: $data.showStartRecordingButton
+  }, $data.showStartRecordingButton ? {
+    I: common_vendor.o((...args) => $options.handleStartRecordingClick && $options.handleStartRecordingClick(...args))
+  } : {}, {
+    J: $data.showRetryButton
+  }, $data.showRetryButton ? {
+    K: common_vendor.o((...args) => $options.retryVideoUpload && $options.retryVideoUpload(...args))
+  } : {}, {
+    L: $data.showCountdown
+  }, $data.showCountdown ? {
+    M: common_vendor.t($data.countdownValue)
+  } : {}, {
+    N: $data.showRerecordButton
+  }, $data.showRerecordButton ? {
+    O: common_vendor.o((...args) => $options.handleRerecordButtonClick && $options.handleRerecordButtonClick(...args))
+  } : {}, {
+    P: $data.showPageWarning ? 1 : ""
+  });
+}
+const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-d10efb47"]]);
+wx.createPage(MiniProgramPage);

+ 5 - 0
unpackage/dist/dev/mp-weixin/pages/demo/demo.json

@@ -0,0 +1,5 @@
+{
+  "navigationBarTitleText": "",
+  "navigationStyle": "custom",
+  "usingComponents": {}
+}

文件差异内容过多而无法显示
+ 0 - 0
unpackage/dist/dev/mp-weixin/pages/demo/demo.wxml


+ 656 - 0
unpackage/dist/dev/mp-weixin/pages/demo/demo.wxss

@@ -0,0 +1,656 @@
+
+.subtitle-container.data-v-d10efb47 {
+  position: fixed;
+  bottom: 20%;
+  left: 0;
+  right: 0;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  z-index: 1000;
+}
+.subtitle-text.data-v-d10efb47 {
+  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-d10efb47 0.5s ease-in-out;
+}
+@keyframes fadeIn-d10efb47 {
+from {
+    opacity: 0;
+    transform: translateY(20px);
+}
+to {
+    opacity: 1;
+    transform: translateY(0);
+}
+}
+.identity-verify-container.data-v-d10efb47 {
+  padding: 0;
+  max-width: 100%;
+  margin: 0 auto;
+  height: 100vh;
+  display: flex;
+  flex-direction: column;
+  background-color: #f5f5f5;
+  transition: all 0.3s ease;
+  position: relative;
+}
+.page-warning.data-v-d10efb47 {
+  animation: page-warning-flash-d10efb47 1s ease-in-out infinite;
+}
+@keyframes page-warning-flash-d10efb47 {
+0% { 
+    background-color: rgba(255, 0, 0, 0.2);
+    box-shadow: 0 0 20px rgba(255, 0, 0, 0.3);
+}
+50% { 
+    background-color: rgba(255, 0, 0, 0.1);
+    box-shadow: 0 0 10px rgba(255, 0, 0, 0.2);
+}
+100% { 
+    background-color: rgba(255, 0, 0, 0.2);
+    box-shadow: 0 0 20px rgba(255, 0, 0, 0.3);
+}
+}
+.digital-human-container.data-v-d10efb47 {
+  position: relative;
+  width: 100%;
+  height: 100vh;
+  overflow: hidden;
+  background-color: #f0f0f0;
+}
+.digital-human-video.data-v-d10efb47 {
+  width: 100%;
+  height: 100%;
+  margin-top: 32px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+/* 用户摄像头容器样式 */
+.user-camera-container.data-v-d10efb47 {
+  position: absolute;
+  top: 100px;
+  right: 5px;
+  width: 110px;
+  height: 160px;
+  border-radius: 4px;
+  overflow: hidden;
+  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
+  z-index: 20;
+  transition: all 0.3s ease;
+}
+.camera-warning.data-v-d10efb47 {
+  animation: camera-warning-flash-d10efb47 1s ease-in-out infinite;
+  border: 4px solid #ff0000;
+}
+@keyframes camera-warning-flash-d10efb47 {
+0% { 
+    border-color: #ff0000;
+    box-shadow: 0 0 15px rgba(255, 0, 0, 0.8);
+}
+50% { 
+    border-color: rgba(255, 0, 0, 0.3);
+    box-shadow: 0 0 5px rgba(255, 0, 0, 0.4);
+}
+100% { 
+    border-color: #ff0000;
+    box-shadow: 0 0 15px rgba(255, 0, 0, 0.8);
+}
+}
+
+/* 用户摄像头视频样式 */
+.user-camera-video.data-v-d10efb47 {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+  background-color: #333;
+}
+.video-player.data-v-d10efb47 {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+  outline: none; /* 移除视频获得焦点时的轮廓 */
+  -webkit-tap-highlight-color: transparent; /* 移除移动设备上的点击高亮 */
+}
+
+/* 隐藏视频控制条 */
+video.data-v-d10efb47::-webkit-media-controls {
+  display: none !important;
+}
+video.data-v-d10efb47::-webkit-media-controls-enclosure {
+  display: none !important;
+}
+video.data-v-d10efb47::-webkit-media-controls-panel {
+  display: none !important;
+}
+video.data-v-d10efb47::-webkit-media-controls-play-button {
+  display: none !important;
+}
+video.data-v-d10efb47::-webkit-media-controls-timeline {
+  display: none !important;
+}
+video.data-v-d10efb47::-webkit-media-controls-current-time-display {
+  display: none !important;
+}
+video.data-v-d10efb47::-webkit-media-controls-time-remaining-display {
+  display: none !important;
+}
+video.data-v-d10efb47::-webkit-media-controls-mute-button {
+  display: none !important;
+}
+video.data-v-d10efb47::-webkit-media-controls-volume-slider {
+  display: none !important;
+}
+video.data-v-d10efb47::-webkit-media-controls-fullscreen-button {
+  display: none !important;
+}
+
+/* 修改字幕覆盖层样式,使其与图片中的样式一致 */
+.subtitle-overlay.data-v-d10efb47 {
+  position: absolute;
+  bottom: 180px;
+  left: 10%;
+  width: 80%;
+  padding: 0; /* 移除内边距,由内部元素控制 */
+  border-radius: 15px;
+  background-color: rgba(255, 255, 255, 0.9);
+  color: #333;
+  text-align: left;
+  font-size: 16px;
+  line-height: 1.5;
+  z-index: 10;
+  margin: 0 auto;
+  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+  display: flex;
+  flex-direction: column;
+  overflow: hidden; /* 确保圆角效果 */
+}
+
+/* 添加题号header样式 */
+.subtitle-header.data-v-d10efb47 {
+/*   background-color: rgba(0, 0, 0, 0.05); */
+  padding: 8px 20px;
+  /* border-bottom: 1px solid rgba(0, 0, 0, 0.05); */
+}
+.question-tag.data-v-d10efb47 {
+  font-size: 14px;
+  color: #666;
+  font-weight: 500;
+}
+
+/* 调整主字幕样式 */
+.subtitle-main.data-v-d10efb47 {
+  padding: 15px 20px ;
+  font-weight: 500;
+}
+
+/* 移除之前的题号显示器 */
+.question-counter.data-v-d10efb47 {
+  display: none;
+}
+.control-panel.data-v-d10efb47 {
+  padding: 15px;
+  display: flex;
+  justify-content: center;
+}
+.control-button.data-v-d10efb47 {
+  padding: 10px 20px;
+  background-color: #4CAF50;
+  color: white;
+  border: none;
+  border-radius: 4px;
+  cursor: pointer;
+}
+.loading.data-v-d10efb47 {
+  text-align: center;
+  margin: 20px 0;
+  font-size: 16px;
+}
+.response-container.data-v-d10efb47 {
+  margin-top: 20px;
+  padding: 0 20px;
+  display: none; /* 默认隐藏调试信息 */
+}
+
+/* 当showDebugInfo为true时显示 */
+.showDebugInfo .response-container.data-v-d10efb47 {
+  display: block;
+}
+.response-item.data-v-d10efb47 {
+  padding: 10px;
+  border: 1px solid #eee;
+  border-radius: 4px;
+  margin-bottom: 10px;
+  background-color: #f9f9f9;
+}
+.response-content.data-v-d10efb47 {
+  display: flex;
+  flex-direction: column;
+}
+.answer-button-container.data-v-d10efb47 {
+  position: absolute;
+  bottom: 50px; /* 将按钮放在底部而不是75%的位置 */
+  left: 50%;
+  transform: translateX(-50%); /* 只在X轴上平移,保持水平居中 */
+  z-index: 20;
+}
+
+/* 修改回答按钮样式 */
+.answer-button.data-v-d10efb47 {
+  width: 120px;
+  height: 40px; /* 改为矩形按钮 */
+  border-radius: 20px; /* 圆角矩形 */
+  background-color: #ffffff; /* 白色背景 */
+  color: #333; /* 深色文字 */
+  font-size: 16px;
+  border: none;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  cursor: pointer;
+  animation: none; /* 移除脉动动画 */
+}
+.stop-recording-button-container.data-v-d10efb47 {
+  position: absolute;
+  bottom: 50px; /* 统一与其他按钮的位置 */
+  left: 50%;
+  transform: translateX(-50%);
+  z-index: 20;
+}
+.stop-recording-button.data-v-d10efb47 {
+  width: 120px;
+  height: 40px; /* 改为矩形按钮 */
+  border-radius: 20px; /* 圆角矩形 */
+  background-color: #0039b3; /* 白色背景 */
+  color: #fff;/* 深色文字 */
+  font-size: 16px;
+  border: none;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  cursor: pointer;
+  animation: none; /* 移除脉动动画 */
+}
+.recording-indicator.data-v-d10efb47 {
+  position: fixed;
+  bottom: 20px;
+  left: 17%;
+  transform: translateX(-50%);
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+ /*  background-color: rgba(0, 0, 0, 0.6); */
+  padding: 10px 15px;
+  border-radius: 10px;
+  z-index: 100;
+}
+.timer-text.data-v-d10efb47 {
+  color: #05dc8b;
+  font-size: 14px;
+  margin-top: 5px;
+}
+.start-recording-button-container.data-v-d10efb47 {
+  position: absolute;
+  bottom: 50px; /* 统一与其他按钮的位置 */
+  left: 50%;
+  transform: translateX(-50%);
+  z-index: 101;
+}
+.start-recording-button.data-v-d10efb47 {
+  width: 120px;
+  height: 40px; /* 改为矩形按钮 */
+  border-radius: 20px; /* 圆角矩形 */
+  background-color: #ffffff; /* 白色背景 */
+  color: #333; /* 深色文字 */
+  font-size: 16px;
+  border: none;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  cursor: pointer;
+  animation: none; /* 移除脉动动画 */
+}
+.retry-button-container.data-v-d10efb47 {
+  position: absolute;
+  bottom: 30px; /* 统一与其他按钮的位置 */
+  left: 50%;
+  transform: translateX(-50%);
+  z-index: 20;
+}
+.retry-button.data-v-d10efb47 {
+  padding: 10px 20px;
+  background-color: #ffffff; /* 白色背景 */
+  color: #333; /* 深色文字 */
+  font-size: 16px;
+  border: none;
+  border-radius: 20px; /* 圆角矩形 */
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
+  cursor: pointer;
+}
+.retry-button.data-v-d10efb47:hover {
+  background-color: #2980b9;
+}
+
+/* 录制时长显示 */
+.recording-timer.data-v-d10efb47 {
+  position: absolute;
+  top: 20px;
+  left: 130px; /* 放在录制指示器旁边 */
+  background-color: rgba(0, 0, 0, 0.6);
+  padding: 5px 10px;
+  border-radius: 15px;
+  z-index: 20;
+  display: flex;
+  flex-direction: column;
+}
+.timer-text.data-v-d10efb47 {
+  color: #000;
+  font-size: 14px;
+  font-family: monospace; /* 使用等宽字体,使时间显示更稳定 */
+}
+.remaining-time.data-v-d10efb47 {
+  color: white;
+  font-size: 12px;
+  margin-top: 2px;
+}
+.remaining-time.warning.data-v-d10efb47 {
+  color: #ff6b6b; /* 剩余时间少时显示红色 */
+  animation: blink 1s infinite; /* 使用闪烁动画提醒用户 */
+}
+
+/* 添加上传状态指示器 */
+.upload-status-indicator.data-v-d10efb47 {
+  position: absolute;
+  top: 20px;
+  left: 130px; /* 放在录制指示器旁边 */
+  background-color: rgba(0, 0, 0, 0.6);
+  padding: 5px 10px;
+  border-radius: 15px;
+  z-index: 20;
+}
+.upload-status-content.data-v-d10efb47 {
+  display: flex;
+  align-items: center;
+}
+.upload-status-icon.data-v-d10efb47 {
+  width: 12px;
+  height: 12px;
+  border-radius: 50%;
+  margin-right: 8px;
+}
+.upload-status-text.data-v-d10efb47 {
+  color: white;
+  font-size: 14px;
+}
+.uploading.data-v-d10efb47 {
+  background-color: #e74c3c;
+}
+
+/* 添加倒计时蒙层样式 */
+.countdown-overlay.data-v-d10efb47 {
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background-color: rgba(0, 0, 0, 0.7);
+  z-index: 100;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+.countdown-content.data-v-d10efb47 {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+.countdown-number.data-v-d10efb47 {
+  font-size: 80px;
+  color: #ffffff;
+  font-weight: bold;
+  margin-bottom: 20px;
+}
+.countdown-text.data-v-d10efb47 {
+  font-size: 24px;
+  color: #ffffff;
+}
+
+/* 添加GIF播放器样式 */
+.gif-player.data-v-d10efb47 {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: 5; /* 确保GIF在视频上方但在字幕和按钮下方 */
+}
+
+/* 重新录制按钮容器样式 */
+.rerecord-button-container.data-v-d10efb47 {
+  position: absolute;
+  bottom: 50px; /* 统一与其他按钮的位置 */
+  left: 50%;
+  transform: translateX(-50%);
+  z-index: 20;
+}
+
+/* 重新录制按钮样式 */
+.rerecord-button.data-v-d10efb47 {
+  width: 120px;
+  height: 40px;
+  border-radius: 20px;
+  background-color: #ffffff;
+  color: #333;
+  font-size: 16px;
+  border: none;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  cursor: pointer;
+}
+.rerecord-button.data-v-d10efb47:hover {
+  background-color: #f0f0f0;
+}
+
+/* 添加视频蒙层样式 */
+.video-overlay.data-v-d10efb47 {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background-color: transparent; /* 完全透明 */
+  z-index: 6; /* 确保在视频之上,但在按钮和字幕之下 */
+  pointer-events: auto; /* 允许捕获点击事件 */
+}
+
+/* 调整其他元素的z-index以确保正确的层级关系 */
+.subtitle-overlay.data-v-d10efb47 {
+  /* ... 现有样式 ... */
+  z-index: 10; /* 确保字幕在蒙层之上 */
+}
+.answer-button-container.data-v-d10efb47,
+.stop-recording-button-container.data-v-d10efb47,
+.start-recording-button-container.data-v-d10efb47,
+.retry-button-container.data-v-d10efb47,
+.rerecord-button-container.data-v-d10efb47 {
+  /* ... 现有样式 ... */
+  z-index: 999; /* 确保按钮在蒙层之上 */
+}
+.user-camera-container.data-v-d10efb47 {
+  /* ... 现有样式 ... */
+  z-index: 20; /* 确保摄像头窗口在蒙层之上 */
+}
+.recording-indicator.data-v-d10efb47 {
+  /* ... 现有样式 ... */
+  z-index: 20; /* 确保录制指示器在蒙层之上 */
+}
+
+/* 环形进度条样式 */
+.circle-progress-container.data-v-d10efb47 {
+  width: 60px;
+  height: 60px;
+  position: relative;
+  margin: 0 auto 10px;
+}
+.circle-progress.data-v-d10efb47 {
+  width: 100%;
+  height: 100%;
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  position: relative;
+  transform: rotate(-90deg); /* 从顶部开始进度 */
+}
+.circle-progress-inner.data-v-d10efb47 {
+  width: 80%;
+  height: 80%;
+  background-color: rgba(255, 255, 255);
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  transform: rotate(90deg); /* 修正文本方向 */
+}
+.progress-text.data-v-d10efb47 {
+  font-size: 14px;
+  font-weight: bold;
+   color: #05dc8b;
+}
+
+/* 添加题号显示 */
+.question-counter.data-v-d10efb47 {
+  position: absolute;
+  top: 20px;
+  right: 130px; /* 调整位置,避免与用户摄像头重叠 */
+  background-color: rgba(255, 255, 255, 0.9);
+  padding: 6px 12px;
+  border-radius: 15px;
+  z-index: 20;
+  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
+  display: flex;
+  align-items: center;
+}
+.question-number.data-v-d10efb47 {
+  color: #333;
+  font-size: 14px;
+  font-weight: 500;
+}
+
+/* 追问问题容器样式 */
+.followup-container.data-v-d10efb47 {
+  width: 100%;
+}
+
+/* 追问分隔线 */
+.followup-divider.data-v-d10efb47 {
+  height: 1px;
+  background-color: rgba(0, 0, 0, 0.05);
+  margin: 0;
+}
+
+/* 追问内容样式 */
+.followup-content.data-v-d10efb47 {
+  padding: 12px 20px;
+  display: flex;
+  align-items: flex-start;
+  gap: 8px;
+}
+
+/* 追问标签样式 */
+.followup-label.data-v-d10efb47 {
+  color: #fb752f;
+  font-size: 14px;
+  font-weight: 500;
+}
+
+/* 追问文本样式 */
+.followup-text.data-v-d10efb47 {
+  color: #333;
+  font-size: 14px;
+  line-height: 1.5;
+  flex: 1;
+}
+
+/* 调整主字幕样式,确保有足够空间 */
+.subtitle-main.data-v-d10efb47 {
+  padding:15px 20px ;
+  font-weight: 500;
+  border-bottom: none; /* 移除底部边框,由追问分隔线处理 */
+}
+
+/* 父问题样式 */
+.parent-question.data-v-d10efb47 {
+  padding: 15px 20px;
+  font-weight: 500;
+  color: #333;
+}
+
+/* 追问容器样式调整 */
+.followup-container.data-v-d10efb47 {
+  width: 100%;
+ /*  background-color: rgba(0, 0, 0, 0.02);  *//* 轻微的背景色区分 */
+}
+
+/* 分隔线样式 */
+.followup-divider.data-v-d10efb47 {
+  height: 1px;
+  background-color: rgba(0, 0, 0, 0.05);
+  margin: 0;
+}
+
+/* 追问内容样式 */
+.followup-content.data-v-d10efb47 {
+  padding: 12px 20px;
+  display: flex;
+  align-items: flex-start;
+  gap: 8px;
+}
+
+/* 追问标签样式 */
+.followup-label.data-v-d10efb47 {
+  color: #fb752f;
+  font-size: 14px;
+  font-weight: 500;
+}
+
+/* 追问文本样式 */
+.followup-text.data-v-d10efb47 {
+  color: #333;
+  font-size: 14px;
+  line-height: 1.5;
+  flex: 1;
+}
+.custom-navbar.data-v-d10efb47 {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  height: 44px;
+  background-color: #ffffff;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  z-index: 999;
+}
+.navbar-title.data-v-d10efb47 {
+  font-size: 16px;
+  font-weight: bold;
+}
+.content.data-v-d10efb47 {
+  margin-top: 44px;
+  padding-top: var(--status-bar-height);
+}

+ 1 - 1
unpackage/dist/dev/mp-weixin/project.config.json

@@ -8,7 +8,7 @@
     "urlCheck": false,
     "es6": true,
     "postcss": false,
-    "minified": true,
+    "minified": false,
     "newFeature": true,
     "bigPackageSizeSupport": true,
     "babelSetting": {

+ 7 - 0
unpackage/dist/dev/mp-weixin/project.private.config.json

@@ -7,6 +7,13 @@
   "condition": {
     "miniprogram": {
       "list": [
+        {
+          "name": "pages/demo/demo",
+          "pathName": "pages/demo/demo",
+          "query": "",
+          "launchMode": "default",
+          "scene": null
+        },
         {
           "name": "pages/interview-notice",
           "pathName": "pages/interview-notice/interview-notice",

部分文件因为文件数量过多而无法显示