yangg 1 mēnesi atpakaļ
vecāks
revīzija
230996112f

+ 1 - 1
common/config.js

@@ -2,7 +2,7 @@
 //线上 https://minlong.raycos.com.cn
 //测试 http://192.168.66.187:8083
 //https://backend.qicai321.com
-export const apiBaseUrl = 'http://192.168.66.187:8083';
+export const apiBaseUrl = 'https://backend.qicai321.com';
 
 // You can add other global configuration settings here
 export const appVersion = '1.0.0';

+ 6 - 0
pages.json

@@ -114,6 +114,12 @@
 			{
 				"navigationBarTitleText" : ""
 			}
+		},
+		{
+			"path": "pages/followUp/followUp",
+			"style": {
+				"navigationStyle": "custom"
+			}
 		}
 	],
 	

+ 3292 - 0
pages/followUp/followUp.vue

@@ -0,0 +1,3292 @@
+<template>
+  <div class="identity-verify-container">
+    <div class="digital-human-container">
+      <!-- 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"
+          @play="handleVideoPlay"
+          @timeupdate="handleTimeUpdate">
+        </video>
+         <div class="answer-button-container" v-if="showAnswerButton">
+          <button class="answer-button" @click="handleAnswerButtonClick">
+            开始回答
+          </button>
+        </div>
+        <!-- 添加字幕覆盖层 :data-time="formatTime(recordingTimerCount) || '03:30'"-->
+        <div class="subtitle-overlay" v-if="currentSubtitle" >
+          {{ currentSubtitle }}
+        </div>
+        
+        <!-- 添加答题按钮 -->
+       
+      </div>
+      
+      <!-- 用户摄像头视频显示区域 -->
+      <div class="user-camera-container">
+        <!-- 在小程序环境中使用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">
+      <div class="recording-dot"></div>
+		<span class="recording-text">正在录制...</span>
+	    <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>
+</template>
+
+<script>
+import { apiBaseUrl } from '@/common/config.js';
+export default {
+  name: 'IdentityVerify',
+  data() {
+    return {
+      loading: false,
+      responses: [],
+      processedResponses: [],
+      assistantResponse: '',
+      audioTranscript: '',
+      videoPlaying: false,
+      showDebugInfo: false, // 设置为true可以显示调试信息
+      videoUrl: '', // 修改为空字符串,将通过API获取
+      showReplayButton: false,
+      cameraStream: null, // 存储摄像头流
+      cameraError: null, // 存储摄像头错误信息
+      useMiniProgramCameraComponent: false, // 添加小程序相机组件标志
+      cameraContext: null, // 添加相机上下文
+      currentSubtitle: '',
+      subtitles: [], // 修改为空数组,将通过API获取
+      // 移除硬编码的字幕数组
+      // secondVideoSubtitles: [...],
+      // thirdVideoSubtitles: [...],
+      // 等等...
+      showAnswerButton: false, // 控制答题按钮显示
+      currentVideoIndex: 0, // 当前播放的视频索引
+      videoList: [], // 修改为空数组,将通过API获取
+      // 其他属性保持不变...
+      questions: [], // 添加新属性存储API返回的问题数据
+      introVideoUrl: 'http://121.36.251.245:9000/minlong/tenant_1/general_uploads/880a117c8fcc4196b0d8c0750608d373.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: [], // 存储待上传的视频
+      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
+      additionalQuestions: [], // 存储追加问题
+      currentQuestionIndex: 0, // 当前问题索引
+    }
+  },
+  mounted() {
+    /* this.fetchData() */
+    // this.fetchQuestions(); // 移除获取问题数据的方法调用
+    this.checkAudioPermission();
+    this.initCamera();
+    this.checkIOSCameraRecordPermission();
+    
+    // 添加防御性检查,避免渲染错误
+    this.checkAndFixRenderingIssues();
+    
+    // 添加音频测试
+    setTimeout(() => {
+      if (this.cameraStream && !this.useMiniProgramCameraComponent) {
+        this.testAudioInput();
+      }
+    }, 3000);
+    uni.setKeepScreenOn({
+      keepScreenOn: true
+    });
+    
+    // 获取追加问题
+    this.fetchAdditionalQuestions();
+  },
+  beforeDestroy() {
+    // 组件销毁前停止摄像头
+    this.stopUserCamera();
+    
+    // 清除倒计时定时器
+    this.clearCountdown();
+  },
+  methods: {
+    // 初始化相机
+    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 = []
+      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);
+          },
+          complete: () => {
+            this.loading = false;
+          }
+        });
+      } catch (error) {
+        console.error('获取数据失败:', error);
+        this.loading = false;
+      }
+    },
+    
+    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('视频播放结束');
+      this.videoPlaying = false;
+      
+      // 对于所有视频,都显示相应的按钮
+      this.showStartRecordingButton = true;
+      this.startCountdown();
+    },
+    
+    // 添加新方法:开始倒计时
+    startCountdown() {
+      // 显示倒计时蒙层
+      this.showCountdown = true;
+      this.countdownValue = 10;
+      
+      // 开始倒计时
+      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;
+    },
+
+    // 修改 handleStartRecordingClick 方法,使其可以终止倒计时
+    handleStartRecordingClick() {
+      // 隐藏"开始回答"按钮
+      this.showStartRecordingButton = false;
+      
+      // 如果倒计时正在进行,清除倒计时
+      this.clearCountdown();
+      
+      // 直接开始录制
+      this.startRecordingAnswer();
+    },
+
+    // 修改 stopRecordingAnswer 方法,确保清除倒计时
+    stopRecordingAnswer() {
+      // 如果倒计时正在进行,先清除倒计时
+      this.clearCountdown();
+      
+      // 检查录制时长
+      const recordingDuration = this.getRecordingDuration();
+      const minimumDuration = 5; // 最小录制时长(秒)
+      
+      if (recordingDuration < minimumDuration) {
+        // 录制时间过短,显示提示
+        uni.showToast({
+          title: '录制时间过短,请至少录制5秒',
+          icon: 'none',
+          duration: 2000
+        });
+        // 不执行停止录制逻辑,继续录制
+        return;
+      }
+      
+      // 录制时长足够,直接停止
+      this.completeRecordingStop();
+    },
+
+    // 添加新方法:开始录制用户回答
+    startRecordingAnswer() {
+      console.log('开始录制用户回答');
+      this.isRecording = true;
+      
+      // 记录录制开始时间
+      this.recordingStartTime = Date.now();
+      this.recordingTimerCount = 0;
+      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);
+        
+        // 检查是否达到最大录制时间
+        if (this.recordingTimerCount >= this.maxRecordingTime) {
+          console.log('已达到最大录制时间(60秒),自动停止录制');
+          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: 检查相机状态');
+            
+            // 使用最简单的选项,设置最大录制时间为5分钟
+            const options = {
+              timeout: 300000, // 300秒超时 (5分钟)
+              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使用标准选项,设置最大录制时间为5分钟
+            const options = {
+              timeout: 300000, // 300秒超时 (5分钟)
+              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: 300, // 从60秒改为300秒
+              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);
+      }
+    },
+
+    // 添加新方法:停止录制用户回答
+    stopRecordingAnswer() {
+      console.log('停止录制用户回答');
+      
+      // 如果倒计时正在进行,先清除倒计时
+      if (this.countdownTimer) {
+        clearInterval(this.countdownTimer);
+        this.countdownTimer = null;
+        this.showCountdown = false;
+      }
+      
+      // 检查录制时长
+      const recordingDuration = this.getRecordingDuration();
+      const minimumDuration = 5; // 最小录制时长(秒),从3秒改为5秒
+      
+      if (recordingDuration < minimumDuration) {
+        // 录制时间过短,显示提示
+        uni.showToast({
+          title: '录制时间过短,请至少录制5秒',
+          icon: 'none',
+          duration: 2000
+        });
+        // 不执行停止录制逻辑,继续录制
+        return;
+      }
+      
+      // 录制时长足够,直接停止
+      this.completeRecordingStop();
+    },
+
+    // 添加新方法:获取录制时长
+    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('重置录制:停止当前录制成功');
+            // 短暂延迟后重新开始录制
+            setTimeout(() => {
+              this.startMiniProgramRecording();
+            }, 500);
+          },
+          fail: (err) => {
+            console.error('重置录制:停止当前录制失败', err);
+            // 尝试直接重新开始录制
+            this.startMiniProgramRecording();
+          }
+        });
+      }
+      
+      // 显示提示
+      uni.showToast({
+        title: '请重新开始回答',
+        icon: 'none',
+        duration: 2000
+      });
+    },
+
+    // 添加新方法:完成录制停止流程
+    completeRecordingStop() {
+      this.isRecording = false;
+      
+      // 清除定时器
+      if (this.recordingTimer) {
+        clearInterval(this.recordingTimer);
+        this.recordingTimer = null;
+      }
+      
+      // 清除MediaRecorder超时定时器
+      if (this.mediaRecorderTimeout) {
+        clearTimeout(this.mediaRecorderTimeout);
+        this.mediaRecorderTimeout = null;
+      }
+      
+      // 隐藏录制中提示
+      uni.hideLoading();
+      
+      // 隐藏停止录制按钮
+      this.showStopRecordingButton = false;
+      
+      // 根据平台选择不同的停止录制方法
+      const systemInfo = uni.getSystemInfoSync();
+      const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith('mp-');
+      
+      if (isMiniProgram) {
+        // 小程序环境停止录制
+        this.stopMiniProgramRecording();
+      } else {
+        // H5/App环境停止录制
+        this.stopBrowserRecording();
+      }
+    },
+
+    // 修改 stopMiniProgramRecording 方法
+    stopMiniProgramRecording() {
+      if (!this.cameraContext) {
+        console.error('相机上下文不存在');
+        this.proceedToNextQuestion();
+        return;
+      }
+      
+      const systemInfo = uni.getSystemInfoSync();
+      const isIOS = systemInfo.platform === 'ios';
+      
+      // 在iOS上添加额外的错误处理
+      const stopOptions = {
+        success: (res) => {
+          console.log('小程序录像停止成功:', res);
+          // 获取临时文件路径
+          const tempFilePath = res.tempVideoPath;
+          if (!tempFilePath) {
+            console.error('未获取到视频文件路径');
+            uni.showToast({
+              title: '录制失败,未获取到视频文件',
+              icon: 'none'
+            });
+            this.proceedToNextQuestion();
+            return;
+          }
+          
+          // 在iOS上,检查文件是否存在
+          if (isIOS) {
+            uni.getFileInfo({
+              filePath: tempFilePath,
+              success: () => {
+                // 文件存在,上传视频
+                this.uploadRecordedVideo(tempFilePath);
+              },
+              fail: (err) => {
+                console.error('视频文件不存在:', err);
+                uni.showToast({
+                  title: '录制失败,视频文件不存在',
+                  icon: 'none'
+                });
+                this.proceedToNextQuestion();
+              }
+            });
+          } else {
+            // Android直接上传
+            this.uploadRecordedVideo(tempFilePath);
+          }
+        },
+        fail: (err) => {
+          console.error('小程序录像停止失败:', err);
+          uni.showToast({
+            title: '录制失败',
+            icon: 'none'
+          });
+          this.proceedToNextQuestion();
+        }
+      };
+      
+      // 停止录制
+      this.cameraContext.stopRecord(stopOptions);
+    },
+
+    // 添加新方法:停止浏览器录制
+    stopBrowserRecording() {
+      if (this.mediaRecorder && this.mediaRecorder.state !== 'inactive') {
+        this.mediaRecorder.stop();
+        console.log('浏览器录制停止成功');
+      } else {
+        console.error('MediaRecorder不存在或已经停止');
+        this.proceedToNextQuestion();
+      }
+    },
+
+    // 修改上传录制的视频方法
+    uploadRecordedVideo(fileOrPath) {
+      console.log('准备上传视频:', typeof fileOrPath === 'string' ? fileOrPath : fileOrPath.name);
+      
+      // 获取当前问题ID
+      let questionId;
+      
+      // 获取当前正在回答的问题
+      const currentQuestion = this.additionalQuestions[this.currentVideoIndex];
+      
+      if (currentQuestion && currentQuestion.id) {
+        // 直接使用API返回的问题ID
+        questionId = currentQuestion.id;
+        console.log(`使用API返回的问题ID: ${questionId}, 问题: ${currentQuestion.question}`);
+      } else {
+        // 如果没有找到对应的问题,使用默认ID
+        questionId = this.getDefaultQuestionId(this.currentVideoIndex);
+        console.log(`未找到当前问题,使用默认ID: ${questionId}`);
+      }
+      
+      console.log('上传视频对应的问题ID:', questionId);
+      
+      // 创建上传任务对象
+      const uploadTask = {
+        id: Date.now().toString(), // 生成唯一ID
+        file: fileOrPath,
+        questionId: questionId,
+        attempts: 0, // 上传尝试次数
+        maxAttempts: 3, // 最大尝试次数
+      };
+      
+      // 添加到上传队列
+      this.uploadQueue.push(uploadTask);
+      
+      // 初始化上传进度和状态
+      this.uploadProgress[uploadTask.id] = 0;
+      this.uploadStatus[uploadTask.id] = 'pending'; // pending, uploading, success, failed
+      
+      // 显示简短的上传状态提示
+      uni.showToast({
+        title: '已完成回答',
+        icon: 'none',
+        duration: 1500
+      });
+      
+      // 更新上传状态文本
+      this.updateUploadStatusText();
+      
+      // 如果当前没有上传任务在进行,开始处理队列
+      if (!this.isUploading) {
+        this.processUploadQueue();
+      }
+      
+      // 立即进入下一个问题,不等待上传完成
+      this.proceedToNextQuestion();
+    },
+    
+    // 添加新方法:处理上传队列
+    processUploadQueue() {
+      // 如果队列为空,结束处理
+      if (this.uploadQueue.length === 0) {
+        this.isUploading = false;
+        this.showUploadStatus = false;
+        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') {
+        // 浏览器环境,使用XMLHttpRequest上传
+        this.uploadFileWithXHR(task);
+      } else {
+        // 小程序环境,使用uni.uploadFile上传
+        this.uploadFileWithUni(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', 0);
+      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 = null) {
+      console.log('提交视频URL到面试接口:', videoUrl);
+      
+      // 确定问题ID
+      let questionId;
+      if (task) {
+        questionId = task.questionId;
+      } else {
+        // 根据当前视频索引获取问题ID
+        if (this.currentVideoIndex >= 1 && this.questions.length > 0) {
+          // 获取当前正在回答的问题
+          const currentQuestion = this.getCurrentQuestionByIndex(this.currentVideoIndex);
+          
+          if (currentQuestion && currentQuestion.id) {
+            // 直接使用API返回的问题ID
+            questionId = currentQuestion.id;
+            console.log(`使用API返回的问题ID: ${questionId}, 问题: ${currentQuestion.question}`);
+          } else {
+            // 如果没有找到对应的问题,使用默认ID
+            questionId = this.getDefaultQuestionId(this.currentVideoIndex);
+            console.log(`未找到当前问题,使用默认ID: ${questionId}`);
+          }
+        } else {
+          // 使用旧的映射逻辑作为备用
+          questionId = this.getDefaultQuestionId(this.currentVideoIndex);
+          console.log(`使用备用问题ID: ${questionId} (问题索引: ${this.currentVideoIndex})`);
+        }
+      }
+      
+      // 准备请求参数
+      const requestData = {
+        application_id: uni.getStorageSync('appId'),
+        question_id: questionId,
+        video_url: videoUrl,
+        tenant_id: JSON.parse(uni.getStorageSync('userInfo')).tenant_id || '1'
+      };
+      
+      console.log('提交面试请求参数:', requestData);
+      
+      // 发送请求到面试接口
+      uni.request({
+        url: `${apiBaseUrl}/api/job/upload_video`,
+        method: 'POST',
+        data: requestData,
+        header: {
+          'content-type': 'application/x-www-form-urlencoded'
+        },
+        success: (res) => {
+          console.log('面试接口提交成功:', res);
+          
+          if (res.data.code === 0 || res.data.code === 2000) {
+            // 提交成功
+            if (task) {
+              // 从队列中移除当前任务
+              this.uploadQueue.shift();
+              
+              // 显示简短的成功提示
+              // uni.showToast({
+              //   title: '视频提交成功',
+              //   icon: 'success',
+              //   duration: 1500
+              // });
+              
+              // 继续处理队列中的下一个任务
+              this.processUploadQueue();
+            } else {
+              // 兼容旧代码的处理逻辑
+              uni.showToast({
+                title: '回答已提交',
+                icon: 'success'
+              });
+              
+              // 保存最后上传的视频URL
+              this.lastUploadedVideoUrl = videoUrl;
+              
+              // 隐藏重试按钮(如果之前显示了)
+              this.showRetryButton = false;
+              this.lastVideoToRetry = null;
+            }
+          } else {
+            // 提交失败
+            if (task) {
+              this.handleSubmitFailure(task, res.data.msg || '提交失败');
+            } else {
+              // 兼容旧代码的处理逻辑
+              uni.showToast({
+                title: res.data.msg || '提交失败,请重试',
+                icon: 'none'
+              });
+              
+              // 保存失败的视频URL,用于重试
+              this.lastVideoToRetry = videoUrl;
+              
+              // 显示重试按钮
+              this.showRetryButton = true;
+            }
+          }
+        },
+        fail: (err) => {
+          console.error('面试接口提交失败:', err);
+          
+          if (task) {
+            this.handleSubmitFailure(task, err.errMsg || '网络错误');
+          } else {
+            // 兼容旧代码的处理逻辑
+            uni.hideLoading();
+            uni.showToast({
+              title: '网络错误,请重试',
+              icon: 'none'
+            });
+            
+            // 保存失败的视频URL,用于重试
+            this.lastVideoToRetry = videoUrl;
+            
+            // 显示重试按钮
+            this.showRetryButton = true;
+          }
+        }
+      });
+    },
+    
+    // 添加新方法:处理提交失败
+    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();
+      }
+    },
+    
+    // 添加新方法:更新上传状态文本
+    updateUploadStatusText() {
+      if (this.uploadQueue.length === 0) {
+        this.uploadStatusText = '';
+        return;
+      }
+      
+      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;
+      }
+      
+      this.uploadStatusText = `问题${currentTask.questionId - 9}:${statusText}`;
+      
+      // 如果队列中有多个任务,显示总数
+      if (this.uploadQueue.length > 1) {
+        this.uploadStatusText += ` (${this.uploadQueue.length}个视频待处理)`;
+      }
+    },
+    
+    // 修改 proceedToNextQuestion 方法
+    proceedToNextQuestion() {
+      // 检查是否已完成所有追加问题
+      if (this.currentVideoIndex >= this.additionalQuestions.length - 1) {
+        // 完成所有追加问题后,跳转到相机页面
+        uni.navigateTo({
+          url: '/pages/camera/camera'
+        });
+        return;
+      }
+      
+      // 切换到下一个视频
+      this.currentVideoIndex++;
+      if (this.currentVideoIndex < this.videoList.length) {
+        // 还有下一段视频,播放它
+        this.videoUrl = this.videoList[this.currentVideoIndex];
+        this.videoPlaying = true;
+        
+        // 重置当前字幕
+        this.currentSubtitle = '';
+        
+        // 使用 nextTick 确保 DOM 更新后再播放视频
+        this.$nextTick(() => {
+          const videoContext = uni.createVideoContext('myVideo', this);
+          if (videoContext) {
+            videoContext.play();
+          }
+        });
+      } else {
+        // 所有视频都播放完毕,可以进行下一步操作
+        uni.showToast({
+          title: '追加问题已完成',
+          icon: 'success',
+          duration: 2000
+        });
+        
+        // 跳转到相机页面
+        setTimeout(() => {
+          uni.navigateTo({
+            url: '/pages/camera/camera'
+          });
+        }, 2000);
+      }
+    },
+
+    // 修改 handleAnswerButtonClick 方法
+    handleAnswerButtonClick() {
+      // 隐藏答题按钮
+      this.showAnswerButton = false;
+      
+     /*  // 重置GIF状态
+      this.showGif = false;
+      this.gifUrl = ''; */
+      
+      // 直接进入下一个问题
+      this.proceedToNextQuestion();
+    },
+
+    // 处理相机错误
+    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.target.currentTime;
+      
+      // 如果正在录制,更新录制时间显示
+      if (this.isRecording && this.recordingTimerCount) {
+        this.recordingTimeDisplay = this.formatTime(this.recordingTimerCount);
+      }
+      
+      // 从当前追加问题中获取字幕
+      if (this.currentVideoIndex >= 0 && this.currentVideoIndex < this.additionalQuestions.length) {
+        const currentQuestion = this.additionalQuestions[this.currentVideoIndex];
+        
+        if (currentQuestion && currentQuestion.subtitles) {
+          // 查找当前时间应该显示的字幕
+          const subtitle = currentQuestion.subtitles.find(
+            sub => currentTime >= sub.startTime && currentTime < sub.endTime
+          );
+          
+          // 更新当前字幕
+          this.currentSubtitle = subtitle ? subtitle.text : '';
+        } else {
+          // 如果没有字幕数据,直接显示问题文本
+          this.currentSubtitle = currentQuestion.question || '';
+        }
+      } else {
+        // 清空字幕
+        this.currentSubtitle = '';
+      }
+    },
+
+    // Add a new method to handle the "Start Recording" button click
+    handleStartRecordingClick() {
+      // 隐藏"开始回答"按钮
+      this.showStartRecordingButton = false;
+      
+      // 如果倒计时正在进行,清除倒计时
+      this.clearCountdown();
+      
+      // 直接开始录制
+      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(100);
+            
+            // 绘制视频帧到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);
+      
+      // 为介绍视频设置字幕
+      this.subtitles = [
+        {
+          startTime: 0,
+          endTime: 5,
+          text: '你好,我是本次面试的面试官,欢迎参加本公司的线上面试!'
+        },
+        {
+          startTime: 5,
+          endTime: 13,
+          text: '面试预计需要15分钟,请你提前安排在网络良好、光线亮度合适、且相对安静的环境参加这次面试'
+        },
+        {
+          startTime: 13,
+          endTime: 20,
+          text: '以免影响本次面试的结果。如果你在面试过程中遇到问题,请与我们的招聘人员联系。'
+        }
+      ];
+      
+      // 按照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 => {
+        // 如果有视频URL,添加到视频列表
+        if (question.digital_human_video_url) {
+          this.videoList.push(question.digital_human_video_url);
+          
+          // 为这个问题创建字幕数组
+          const subtitleArray = [{
+            startTime: 0,
+            endTime: 10, // 默认10秒,可以根据实际情况调整
+            text: question.digital_human_video_subtitle || question.question
+          }];
+          
+          // 根据问题的序号存储字幕
+          const index = this.videoList.length - 1; // 减1是因为我们已经添加了视频URL
+          
+          // 动态创建字幕数组属性
+          this[`question${index}Subtitles`] = subtitleArray;
+        }
+      });
+      
+      // 如果没有获取到任何问题视频,使用默认视频
+      if (this.videoList.length <= 1) {
+    /*     this.useDefaultVideosAndSubtitles(); */
+      } else {
+        console.log('处理后的视频列表:', this.videoList);
+        console.log('处理后的字幕:', this.subtitles);
+      }
+    },
+
+    // 使用默认视频和字幕(作为备用)
+    useDefaultVideosAndSubtitles() {
+      console.log('使用默认视频和字幕');
+      
+      // 设置默认视频列表
+     /*  this.videoList = [
+        this.introVideoUrl, // 介绍视频
+        'http://121.36.251.245:9000/minlong/tenant_1/general_uploads/e465e23d377b4456bbb3b755d3ad9500.mp4',
+        'http://121.36.251.245:9000/minlong/tenant_1/general_uploads/9bc84230d2a14978b4ea0a97e4102a15.mp4',
+        'http://121.36.251.245:9000/minlong/tenant_1/general_uploads/9b48e824432f451d9e27e12b884d9074.mp4',
+        'http://121.36.251.245:9000/minlong/tenant_1/general_uploads/52f1445b400345e1a673b3c7f05e5cc1.mp4',
+        'http://121.36.251.245:9000/minlong/tenant_1/general_uploads/abdaa6fda8494e3a8613304743ed0433.mp4'
+      ]; */
+      
+      // 设置默认字幕
+      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) {
+      // 检查索引是否有效
+      if (videoIndex >= 0 && videoIndex < this.additionalQuestions.length) {
+        return this.additionalQuestions[videoIndex];
+      }
+      
+      return null;
+    },
+
+    onShow() {
+      console.log('followUp页面onShow');
+      console.log('当前本地存储中的职位信息:', uni.getStorageSync('selectedJob'));
+      
+      // 每次页面显示时重新获取追加问题
+      this.fetchAdditionalQuestions();
+    },
+
+    // 获取追加问题
+    fetchAdditionalQuestions() {
+      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 requestUrl = `${apiBaseUrl}/api/job/additional_questions?position_id=${position_id}&tenant_id=${tenant_id}&count=2`;
+      
+      uni.request({
+        url: requestUrl,
+        method: 'GET',
+        success: (res) => {
+          if (res.data && res.data.code === 2000 && Array.isArray(res.data.data)) {
+            console.log('获取追加问题成功:', res.data.data);
+            
+            // 处理问题数据,添加视频URL和字幕
+            this.additionalQuestions = res.data.data.map(question => ({
+              ...question,
+              videoUrl: question.digital_human_video_url,
+              subtitles: [{
+                startTime: 0,
+                endTime: 60, // 增加字幕显示时间到60秒,确保覆盖整个视频
+                text: question.digital_human_video_subtitle || question.question || '请回答问题'
+              }]
+            }));
+            
+            // 初始化视频列表
+            this.initializeVideoList();
+          } else {
+            console.error('获取追加问题失败:', res.data);
+            uni.showToast({
+              title: '获取追加问题失败',
+              icon: 'none'
+            });
+          }
+        },
+        fail: (err) => {
+          console.error('请求追加问题失败:', err);
+          uni.showToast({
+            title: '网络错误,请检查网络连接',
+            icon: 'none'
+          });
+        },
+        complete: () => {
+          this.loading = false;
+        }
+      });
+    },
+
+    // 初始化视频列表
+    initializeVideoList() {
+      // 清空现有视频列表
+      this.videoList = [];
+      
+      // 添加追加问题的视频
+      this.additionalQuestions.forEach(question => {
+        if (question.videoUrl) {
+          this.videoList.push(question.videoUrl);
+        }
+      });
+      
+      // 如果有视频,开始播放第一个
+      if (this.videoList.length > 0) {
+        this.videoUrl = this.videoList[0];
+        this.currentVideoIndex = 0;
+        this.playCurrentVideo();
+      }
+    },
+
+    // 播放当前视频
+    playCurrentVideo() {
+      if (this.currentVideoIndex < this.videoList.length) {
+        this.videoUrl = this.videoList[this.currentVideoIndex];
+        this.videoPlaying = true;
+        
+        // 获取当前问题
+        const currentQuestion = this.additionalQuestions[this.currentVideoIndex];
+        
+        // 设置当前字幕 - 直接设置问题文本作为字幕
+        if (currentQuestion) {
+          this.currentSubtitle = currentQuestion.question || 
+                                currentQuestion.digital_human_video_subtitle || 
+                                '请回答问题';
+        }
+        
+        this.$nextTick(() => {
+          const videoContext = uni.createVideoContext('myVideo', this);
+          if (videoContext) {
+            videoContext.play();
+          }
+        });
+      }
+    },
+
+    // 添加 handleVideoPlay 方法
+    handleVideoPlay() {
+      console.log('视频开始播放');
+      
+      // 设置当前问题的字幕
+      if (this.currentVideoIndex >= 0 && this.currentVideoIndex < this.additionalQuestions.length) {
+        const currentQuestion = this.additionalQuestions[this.currentVideoIndex];
+        if (currentQuestion) {
+          this.currentSubtitle = currentQuestion.question || 
+                                currentQuestion.digital_human_video_subtitle || 
+                                '请回答问题';
+        }
+      }
+    }
+  }
+}
+</script>
+
+<style scoped>
+.identity-verify-container {
+  padding: 0;
+  max-width: 100%;
+  margin: 0 auto;
+  height: 100vh;
+  display: flex;
+  flex-direction: column;
+  background-color: #f5f5f5;
+}
+
+.digital-human-container {
+  position: relative;
+  width: 100%;
+  height: 100vh;
+  overflow: hidden;
+  background-color: #f0f0f0;
+}
+
+.digital-human-video {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+/* 用户摄像头容器样式 */
+.user-camera-container {
+  position: absolute;
+  top: 50px;
+  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;
+ 
+}
+
+/* 用户摄像头视频样式 */
+.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: 5%; /* 从左侧留出5%的空间 */
+  width: 80%; /* 宽度设为90%,两侧各留5%实现居中 */
+  padding: 15px 20px; /* 增加左右内边距 */
+  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); /* 添加轻微阴影 */
+}
+
+/* 添加计时器样式,右侧显示橙色圆点和时间 */
+.subtitle-overlay::after {
+  content: attr(data-time);
+  position: absolute;
+  right: 20px;
+  bottom: 15px;
+  color: #333;
+  font-size: 14px;
+}
+
+.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: #e74c3c; /* 白色背景 */
+  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; /* 移除脉动动画 */
+}
+
+.recording-indicator {
+  position: absolute;
+  top: 20px;
+  left: 20px;
+  display: flex;
+  align-items: center;
+  background-color: rgba(255, 255, 255, 0.9); /* 改为白色半透明背景 */
+  padding: 5px 10px;
+  border-radius: 15px;
+  z-index: 20;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+}
+
+.recording-dot {
+  width: 12px;
+  height: 12px;
+  background-color: #ff6b00; /* 改为橙色,与图片中的颜色一致 */
+  border-radius: 50%;
+  margin-right: 8px;
+  animation: blink 1s infinite;
+}
+
+.recording-text {
+  color: #333; /* 改为深色文字 */
+  font-size: 14px;
+}
+
+.timer-text {
+  color: #333; /* 改为深色文字 */
+  font-size: 14px;
+  margin-left: 8px;
+}
+
+.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在视频上方但在字幕和按钮下方 */
+}
+</style>

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

@@ -20,6 +20,7 @@ if (!Math) {
   "./pages/test/test.js";
   "./pages/Personal/Personal.js";
   "./pages/job-detail/job-detail.js";
+  "./pages/followUp/followUp.js";
 }
 const _sfc_main = {
   onLaunch: function() {

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

@@ -16,7 +16,8 @@
     "pages/agreement/agreement",
     "pages/test/test",
     "pages/Personal/Personal",
-    "pages/job-detail/job-detail"
+    "pages/job-detail/job-detail",
+    "pages/followUp/followUp"
   ],
   "window": {
     "navigationBarTextStyle": "black",

+ 1 - 1
unpackage/dist/dev/mp-weixin/common/config.js

@@ -1,3 +1,3 @@
 "use strict";
-const apiBaseUrl = "http://192.168.66.187:8083";
+const apiBaseUrl = "https://backend.qicai321.com";
 exports.apiBaseUrl = apiBaseUrl;

+ 30 - 11
unpackage/dist/dev/mp-weixin/pages/camera/camera.js

@@ -63,7 +63,9 @@ const _sfc_main = {
       scrollTop: 0,
       // 控制 scroll-view 的滚动位置
       _clickTimer: null,
-      _isClicking: false
+      _isClicking: false,
+      showPromptModal: false
+      // 添加新的数据属性
     };
   },
   computed: {
@@ -532,21 +534,34 @@ const _sfc_main = {
     // 处理继续按钮点击
     handleContinue() {
       if (this.currentGroupIndex < this.questionGroups.length - 1) {
-        this.currentGroupIndex++;
-        this.questions = this.questionGroups[this.currentGroupIndex];
-        this.currentQuestionIndex = 0;
-        this.showContinueButton = false;
-        this.currentScrollId = "question-0";
-        this.scrollTop = 0;
-        this.selectedOption = null;
-        this.selectedOptions = [];
-        this.showResult = false;
+        if (this.currentGroupIndex === 0) {
+          this.showPromptModal = true;
+        } else {
+          this.proceedToNextGroup();
+        }
       } else {
         common_vendor.index.navigateTo({
           url: "/pages/interview-question/interview-question"
         });
       }
     },
+    // 添加新的方法处理弹窗确认
+    handlePromptConfirm() {
+      this.showPromptModal = false;
+      this.proceedToNextGroup();
+    },
+    // 添加新的方法处理组切换逻辑
+    proceedToNextGroup() {
+      this.currentGroupIndex++;
+      this.questions = this.questionGroups[this.currentGroupIndex];
+      this.currentQuestionIndex = 0;
+      this.showContinueButton = false;
+      this.currentScrollId = "question-0";
+      this.scrollTop = 0;
+      this.selectedOption = null;
+      this.selectedOptions = [];
+      this.showResult = false;
+    },
     // 保存当前题目的答案
     saveAnswer() {
       let answer;
@@ -722,7 +737,7 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
       } : {}, {
         j: qIndex === $data.currentQuestionIndex && question.questionType === 2
       }, qIndex === $data.currentQuestionIndex && question.questionType === 2 ? {
-        k: common_vendor.t("提交答案"),
+        k: common_vendor.t("下一题"),
         l: common_vendor.o(($event) => $options.nextQuestion(), question.id),
         m: $data.selectedOptions.length === 0
       } : {}, {
@@ -759,6 +774,10 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
     v: !$data.loading && $data.loadError
   }, !$data.loading && $data.loadError ? {
     w: common_vendor.o((...args) => $options.fetchInterviewData && $options.fetchInterviewData(...args))
+  } : {}, {
+    x: $data.showPromptModal
+  }, $data.showPromptModal ? {
+    y: common_vendor.o((...args) => $options.handlePromptConfirm && $options.handlePromptConfirm(...args))
   } : {});
 }
 const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]);

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
unpackage/dist/dev/mp-weixin/pages/camera/camera.wxml


+ 51 - 0
unpackage/dist/dev/mp-weixin/pages/camera/camera.wxss

@@ -575,3 +575,54 @@
 		width: 90%;
 		text-align: center;
 }
+
+	/* 添加新的样式 */
+.prompt-modal {
+		position: fixed;
+		top: 0;
+		left: 0;
+		right: 0;
+		bottom: 0;
+		background-color: rgba(0, 0, 0, 0.5);
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		z-index: 1000;
+}
+.prompt-content {
+		width: 85%;
+		background-color: #ffffff;
+		border-radius: 20rpx;
+		padding: 40rpx;
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+}
+.prompt-title {
+		font-size: 36rpx;
+		font-weight: bold;
+		color: #333;
+		margin-bottom: 30rpx;
+}
+.prompt-text {
+		font-size: 28rpx;
+		color: #666;
+		line-height: 1.6;
+		margin-bottom: 20rpx;
+		text-align: justify;
+}
+.bold-text {
+		font-weight: bold;
+		color: #333;
+}
+.prompt-button {
+		background-color: #0039b3;
+		color: #ffffff;
+		border-radius: 10rpx;
+		font-size: 30rpx;
+		height: 80rpx;
+		line-height: 80rpx;
+		width: 60%;
+		text-align: center;
+		margin-top: 30rpx;
+}

+ 2071 - 0
unpackage/dist/dev/mp-weixin/pages/followUp/followUp.js

@@ -0,0 +1,2071 @@
+"use strict";
+const common_vendor = require("../../common/vendor.js");
+const common_config = require("../../common/config.js");
+const _sfc_main = {
+  name: "IdentityVerify",
+  data() {
+    return {
+      loading: false,
+      responses: [],
+      processedResponses: [],
+      assistantResponse: "",
+      audioTranscript: "",
+      videoPlaying: false,
+      showDebugInfo: false,
+      // 设置为true可以显示调试信息
+      videoUrl: "",
+      // 修改为空字符串,将通过API获取
+      showReplayButton: false,
+      cameraStream: null,
+      // 存储摄像头流
+      cameraError: null,
+      // 存储摄像头错误信息
+      useMiniProgramCameraComponent: false,
+      // 添加小程序相机组件标志
+      cameraContext: null,
+      // 添加相机上下文
+      currentSubtitle: "",
+      subtitles: [],
+      // 修改为空数组,将通过API获取
+      // 移除硬编码的字幕数组
+      // secondVideoSubtitles: [...],
+      // thirdVideoSubtitles: [...],
+      // 等等...
+      showAnswerButton: false,
+      // 控制答题按钮显示
+      currentVideoIndex: 0,
+      // 当前播放的视频索引
+      videoList: [],
+      // 修改为空数组,将通过API获取
+      // 其他属性保持不变...
+      questions: [],
+      // 添加新属性存储API返回的问题数据
+      introVideoUrl: "http://121.36.251.245:9000/minlong/tenant_1/general_uploads/880a117c8fcc4196b0d8c0750608d373.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: [],
+      // 存储待上传的视频
+      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
+      additionalQuestions: [],
+      // 存储追加问题
+      currentQuestionIndex: 0
+      // 当前问题索引
+    };
+  },
+  mounted() {
+    this.checkAudioPermission();
+    this.initCamera();
+    this.checkIOSCameraRecordPermission();
+    this.checkAndFixRenderingIssues();
+    setTimeout(() => {
+      if (this.cameraStream && !this.useMiniProgramCameraComponent) {
+        this.testAudioInput();
+      }
+    }, 3e3);
+    common_vendor.index.setKeepScreenOn({
+      keepScreenOn: true
+    });
+    this.fetchAdditionalQuestions();
+  },
+  beforeDestroy() {
+    this.stopUserCamera();
+    this.clearCountdown();
+  },
+  methods: {
+    // 初始化相机
+    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 = [];
+      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);
+          },
+          complete: () => {
+            this.loading = false;
+          }
+        });
+      } catch (error) {
+        console.error("获取数据失败:", error);
+        this.loading = false;
+      }
+    },
+    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;
+          common_vendor.index.showToast({
+            title: "无法加载视频,显示静态图片",
+            icon: "none"
+          });
+        }
+      });
+    },
+    // 处理视频结束事件
+    handleVideoEnded() {
+      console.log("视频播放结束");
+      this.videoPlaying = false;
+      this.showStartRecordingButton = true;
+      this.startCountdown();
+    },
+    // 添加新方法:开始倒计时
+    startCountdown() {
+      this.showCountdown = true;
+      this.countdownValue = 10;
+      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;
+    },
+    // 修改 handleStartRecordingClick 方法,使其可以终止倒计时
+    handleStartRecordingClick() {
+      this.showStartRecordingButton = false;
+      this.clearCountdown();
+      this.startRecordingAnswer();
+    },
+    // 修改 stopRecordingAnswer 方法,确保清除倒计时
+    stopRecordingAnswer() {
+      this.clearCountdown();
+      const recordingDuration = this.getRecordingDuration();
+      const minimumDuration = 5;
+      if (recordingDuration < minimumDuration) {
+        common_vendor.index.showToast({
+          title: "录制时间过短,请至少录制5秒",
+          icon: "none",
+          duration: 2e3
+        });
+        return;
+      }
+      this.completeRecordingStop();
+    },
+    // 添加新方法:开始录制用户回答
+    startRecordingAnswer() {
+      console.log("开始录制用户回答");
+      this.isRecording = true;
+      this.recordingStartTime = Date.now();
+      this.recordingTimerCount = 0;
+      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.formatTime(this.maxRecordingTime);
+        if (this.recordingTimerCount >= this.maxRecordingTime) {
+          console.log("已达到最大录制时间(60秒),自动停止录制");
+          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 options = {
+              timeout: 3e5,
+              // 300秒超时 (5分钟)
+              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 options = {
+              timeout: 3e5,
+              // 300秒超时 (5分钟)
+              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: 300,
+              // 从60秒改为300秒
+              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("没有可用的摄像头流");
+        common_vendor.index.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);
+        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("没有录制到数据");
+          common_vendor.index.showToast({
+            title: "录制失败,未捕获到数据",
+            icon: "none"
+          });
+          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);
+      }
+    },
+    // 添加新方法:停止录制用户回答
+    stopRecordingAnswer() {
+      console.log("停止录制用户回答");
+      if (this.countdownTimer) {
+        clearInterval(this.countdownTimer);
+        this.countdownTimer = null;
+        this.showCountdown = false;
+      }
+      const recordingDuration = this.getRecordingDuration();
+      const minimumDuration = 5;
+      if (recordingDuration < minimumDuration) {
+        common_vendor.index.showToast({
+          title: "录制时间过短,请至少录制5秒",
+          icon: "none",
+          duration: 2e3
+        });
+        return;
+      }
+      this.completeRecordingStop();
+    },
+    // 添加新方法:获取录制时长
+    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("重置录制:停止当前录制成功");
+            setTimeout(() => {
+              this.startMiniProgramRecording();
+            }, 500);
+          },
+          fail: (err) => {
+            console.error("重置录制:停止当前录制失败", err);
+            this.startMiniProgramRecording();
+          }
+        });
+      }
+      common_vendor.index.showToast({
+        title: "请重新开始回答",
+        icon: "none",
+        duration: 2e3
+      });
+    },
+    // 添加新方法:完成录制停止流程
+    completeRecordingStop() {
+      this.isRecording = false;
+      if (this.recordingTimer) {
+        clearInterval(this.recordingTimer);
+        this.recordingTimer = null;
+      }
+      if (this.mediaRecorderTimeout) {
+        clearTimeout(this.mediaRecorderTimeout);
+        this.mediaRecorderTimeout = null;
+      }
+      common_vendor.index.hideLoading();
+      this.showStopRecordingButton = false;
+      const systemInfo = common_vendor.index.getSystemInfoSync();
+      const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith("mp-");
+      if (isMiniProgram) {
+        this.stopMiniProgramRecording();
+      } else {
+        this.stopBrowserRecording();
+      }
+    },
+    // 修改 stopMiniProgramRecording 方法
+    stopMiniProgramRecording() {
+      if (!this.cameraContext) {
+        console.error("相机上下文不存在");
+        this.proceedToNextQuestion();
+        return;
+      }
+      const systemInfo = common_vendor.index.getSystemInfoSync();
+      const isIOS = systemInfo.platform === "ios";
+      const stopOptions = {
+        success: (res) => {
+          console.log("小程序录像停止成功:", res);
+          const tempFilePath = res.tempVideoPath;
+          if (!tempFilePath) {
+            console.error("未获取到视频文件路径");
+            common_vendor.index.showToast({
+              title: "录制失败,未获取到视频文件",
+              icon: "none"
+            });
+            this.proceedToNextQuestion();
+            return;
+          }
+          if (isIOS) {
+            common_vendor.index.getFileInfo({
+              filePath: tempFilePath,
+              success: () => {
+                this.uploadRecordedVideo(tempFilePath);
+              },
+              fail: (err) => {
+                console.error("视频文件不存在:", err);
+                common_vendor.index.showToast({
+                  title: "录制失败,视频文件不存在",
+                  icon: "none"
+                });
+                this.proceedToNextQuestion();
+              }
+            });
+          } else {
+            this.uploadRecordedVideo(tempFilePath);
+          }
+        },
+        fail: (err) => {
+          console.error("小程序录像停止失败:", err);
+          common_vendor.index.showToast({
+            title: "录制失败",
+            icon: "none"
+          });
+          this.proceedToNextQuestion();
+        }
+      };
+      this.cameraContext.stopRecord(stopOptions);
+    },
+    // 添加新方法:停止浏览器录制
+    stopBrowserRecording() {
+      if (this.mediaRecorder && this.mediaRecorder.state !== "inactive") {
+        this.mediaRecorder.stop();
+        console.log("浏览器录制停止成功");
+      } else {
+        console.error("MediaRecorder不存在或已经停止");
+        this.proceedToNextQuestion();
+      }
+    },
+    // 修改上传录制的视频方法
+    uploadRecordedVideo(fileOrPath) {
+      console.log("准备上传视频:", typeof fileOrPath === "string" ? fileOrPath : fileOrPath.name);
+      let questionId;
+      const currentQuestion = this.additionalQuestions[this.currentVideoIndex];
+      if (currentQuestion && currentQuestion.id) {
+        questionId = currentQuestion.id;
+        console.log(`使用API返回的问题ID: ${questionId}, 问题: ${currentQuestion.question}`);
+      } else {
+        questionId = this.getDefaultQuestionId(this.currentVideoIndex);
+        console.log(`未找到当前问题,使用默认ID: ${questionId}`);
+      }
+      console.log("上传视频对应的问题ID:", questionId);
+      const uploadTask = {
+        id: Date.now().toString(),
+        // 生成唯一ID
+        file: fileOrPath,
+        questionId,
+        attempts: 0,
+        // 上传尝试次数
+        maxAttempts: 3
+        // 最大尝试次数
+      };
+      this.uploadQueue.push(uploadTask);
+      this.uploadProgress[uploadTask.id] = 0;
+      this.uploadStatus[uploadTask.id] = "pending";
+      common_vendor.index.showToast({
+        title: "已完成回答",
+        icon: "none",
+        duration: 1500
+      });
+      this.updateUploadStatusText();
+      if (!this.isUploading) {
+        this.processUploadQueue();
+      }
+      this.proceedToNextQuestion();
+    },
+    // 添加新方法:处理上传队列
+    processUploadQueue() {
+      if (this.uploadQueue.length === 0) {
+        this.isUploading = false;
+        this.showUploadStatus = false;
+        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.uploadFileWithXHR(task);
+      } else {
+        this.uploadFileWithUni(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", 0);
+      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("超过最大重试次数,放弃上传");
+        common_vendor.index.showToast({
+          title: "视频上传失败,请稍后重试",
+          icon: "none",
+          duration: 2e3
+        });
+        this.uploadQueue.shift();
+        this.processUploadQueue();
+      }
+    },
+    // 修改 submitVideoToInterview 方法
+    submitVideoToInterview(videoUrl, task = null) {
+      console.log("提交视频URL到面试接口:", videoUrl);
+      let questionId;
+      if (task) {
+        questionId = task.questionId;
+      } else {
+        if (this.currentVideoIndex >= 1 && this.questions.length > 0) {
+          const currentQuestion = this.getCurrentQuestionByIndex(this.currentVideoIndex);
+          if (currentQuestion && currentQuestion.id) {
+            questionId = currentQuestion.id;
+            console.log(`使用API返回的问题ID: ${questionId}, 问题: ${currentQuestion.question}`);
+          } else {
+            questionId = this.getDefaultQuestionId(this.currentVideoIndex);
+            console.log(`未找到当前问题,使用默认ID: ${questionId}`);
+          }
+        } else {
+          questionId = this.getDefaultQuestionId(this.currentVideoIndex);
+          console.log(`使用备用问题ID: ${questionId} (问题索引: ${this.currentVideoIndex})`);
+        }
+      }
+      const requestData = {
+        application_id: common_vendor.index.getStorageSync("appId"),
+        question_id: questionId,
+        video_url: videoUrl,
+        tenant_id: JSON.parse(common_vendor.index.getStorageSync("userInfo")).tenant_id || "1"
+      };
+      console.log("提交面试请求参数:", requestData);
+      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: (res) => {
+          console.log("面试接口提交成功:", res);
+          if (res.data.code === 0 || res.data.code === 2e3) {
+            if (task) {
+              this.uploadQueue.shift();
+              this.processUploadQueue();
+            } else {
+              common_vendor.index.showToast({
+                title: "回答已提交",
+                icon: "success"
+              });
+              this.lastUploadedVideoUrl = videoUrl;
+              this.showRetryButton = false;
+              this.lastVideoToRetry = null;
+            }
+          } else {
+            if (task) {
+              this.handleSubmitFailure(task, res.data.msg || "提交失败");
+            } else {
+              common_vendor.index.showToast({
+                title: res.data.msg || "提交失败,请重试",
+                icon: "none"
+              });
+              this.lastVideoToRetry = videoUrl;
+              this.showRetryButton = true;
+            }
+          }
+        },
+        fail: (err) => {
+          console.error("面试接口提交失败:", err);
+          if (task) {
+            this.handleSubmitFailure(task, err.errMsg || "网络错误");
+          } else {
+            common_vendor.index.hideLoading();
+            common_vendor.index.showToast({
+              title: "网络错误,请重试",
+              icon: "none"
+            });
+            this.lastVideoToRetry = videoUrl;
+            this.showRetryButton = true;
+          }
+        }
+      });
+    },
+    // 添加新方法:处理提交失败
+    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("超过最大重试次数,放弃提交");
+        common_vendor.index.showToast({
+          title: "视频提交失败,请稍后重试",
+          icon: "none",
+          duration: 2e3
+        });
+        this.uploadQueue.shift();
+        this.processUploadQueue();
+      }
+    },
+    // 添加新方法:更新上传状态文本
+    updateUploadStatusText() {
+      if (this.uploadQueue.length === 0) {
+        this.uploadStatusText = "";
+        return;
+      }
+      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;
+      }
+      this.uploadStatusText = `问题${currentTask.questionId - 9}:${statusText}`;
+      if (this.uploadQueue.length > 1) {
+        this.uploadStatusText += ` (${this.uploadQueue.length}个视频待处理)`;
+      }
+    },
+    // 修改 proceedToNextQuestion 方法
+    proceedToNextQuestion() {
+      if (this.currentVideoIndex >= this.additionalQuestions.length - 1) {
+        common_vendor.index.navigateTo({
+          url: "/pages/camera/camera"
+        });
+        return;
+      }
+      this.currentVideoIndex++;
+      if (this.currentVideoIndex < this.videoList.length) {
+        this.videoUrl = this.videoList[this.currentVideoIndex];
+        this.videoPlaying = true;
+        this.currentSubtitle = "";
+        this.$nextTick(() => {
+          const videoContext = common_vendor.index.createVideoContext("myVideo", this);
+          if (videoContext) {
+            videoContext.play();
+          }
+        });
+      } else {
+        common_vendor.index.showToast({
+          title: "追加问题已完成",
+          icon: "success",
+          duration: 2e3
+        });
+        setTimeout(() => {
+          common_vendor.index.navigateTo({
+            url: "/pages/camera/camera"
+          });
+        }, 2e3);
+      }
+    },
+    // 修改 handleAnswerButtonClick 方法
+    handleAnswerButtonClick() {
+      this.showAnswerButton = false;
+      this.proceedToNextQuestion();
+    },
+    // 处理相机错误
+    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.target.currentTime;
+      if (this.isRecording && this.recordingTimerCount) {
+        this.recordingTimeDisplay = this.formatTime(this.recordingTimerCount);
+      }
+      if (this.currentVideoIndex >= 0 && this.currentVideoIndex < this.additionalQuestions.length) {
+        const currentQuestion = this.additionalQuestions[this.currentVideoIndex];
+        if (currentQuestion && currentQuestion.subtitles) {
+          const subtitle = currentQuestion.subtitles.find(
+            (sub) => currentTime >= sub.startTime && currentTime < sub.endTime
+          );
+          this.currentSubtitle = subtitle ? subtitle.text : "";
+        } else {
+          this.currentSubtitle = currentQuestion.question || "";
+        }
+      } else {
+        this.currentSubtitle = "";
+      }
+    },
+    // Add a new method to handle the "Start Recording" button click
+    handleStartRecordingClick() {
+      this.showStartRecordingButton = false;
+      this.clearCountdown();
+      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(100);
+            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);
+      this.subtitles = [
+        {
+          startTime: 0,
+          endTime: 5,
+          text: "你好,我是本次面试的面试官,欢迎参加本公司的线上面试!"
+        },
+        {
+          startTime: 5,
+          endTime: 13,
+          text: "面试预计需要15分钟,请你提前安排在网络良好、光线亮度合适、且相对安静的环境参加这次面试"
+        },
+        {
+          startTime: 13,
+          endTime: 20,
+          text: "以免影响本次面试的结果。如果你在面试过程中遇到问题,请与我们的招聘人员联系。"
+        }
+      ];
+      const sortedQuestions = [...this.questions].sort((a, b) => a.sequence_number - b.sequence_number);
+      const questionsToUse = sortedQuestions.slice(0, 5);
+      questionsToUse.forEach((question) => {
+        if (question.digital_human_video_url) {
+          this.videoList.push(question.digital_human_video_url);
+          const subtitleArray = [{
+            startTime: 0,
+            endTime: 10,
+            // 默认10秒,可以根据实际情况调整
+            text: question.digital_human_video_subtitle || question.question
+          }];
+          const index = this.videoList.length - 1;
+          this[`question${index}Subtitles`] = subtitleArray;
+        }
+      });
+      if (this.videoList.length <= 1)
+        ;
+      else {
+        console.log("处理后的视频列表:", this.videoList);
+        console.log("处理后的字幕:", this.subtitles);
+      }
+    },
+    // 使用默认视频和字幕(作为备用)
+    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) {
+      if (videoIndex >= 0 && videoIndex < this.additionalQuestions.length) {
+        return this.additionalQuestions[videoIndex];
+      }
+      return null;
+    },
+    onShow() {
+      console.log("followUp页面onShow");
+      console.log("当前本地存储中的职位信息:", common_vendor.index.getStorageSync("selectedJob"));
+      this.fetchAdditionalQuestions();
+    },
+    // 获取追加问题
+    fetchAdditionalQuestions() {
+      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 requestUrl = `${common_config.apiBaseUrl}/api/job/additional_questions?position_id=${position_id}&tenant_id=${tenant_id}&count=2`;
+      common_vendor.index.request({
+        url: requestUrl,
+        method: "GET",
+        success: (res) => {
+          if (res.data && res.data.code === 2e3 && Array.isArray(res.data.data)) {
+            console.log("获取追加问题成功:", res.data.data);
+            this.additionalQuestions = res.data.data.map((question) => ({
+              ...question,
+              videoUrl: question.digital_human_video_url,
+              subtitles: [{
+                startTime: 0,
+                endTime: 60,
+                // 增加字幕显示时间到60秒,确保覆盖整个视频
+                text: question.digital_human_video_subtitle || question.question || "请回答问题"
+              }]
+            }));
+            this.initializeVideoList();
+          } 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;
+        }
+      });
+    },
+    // 初始化视频列表
+    initializeVideoList() {
+      this.videoList = [];
+      this.additionalQuestions.forEach((question) => {
+        if (question.videoUrl) {
+          this.videoList.push(question.videoUrl);
+        }
+      });
+      if (this.videoList.length > 0) {
+        this.videoUrl = this.videoList[0];
+        this.currentVideoIndex = 0;
+        this.playCurrentVideo();
+      }
+    },
+    // 播放当前视频
+    playCurrentVideo() {
+      if (this.currentVideoIndex < this.videoList.length) {
+        this.videoUrl = this.videoList[this.currentVideoIndex];
+        this.videoPlaying = true;
+        const currentQuestion = this.additionalQuestions[this.currentVideoIndex];
+        if (currentQuestion) {
+          this.currentSubtitle = currentQuestion.question || currentQuestion.digital_human_video_subtitle || "请回答问题";
+        }
+        this.$nextTick(() => {
+          const videoContext = common_vendor.index.createVideoContext("myVideo", this);
+          if (videoContext) {
+            videoContext.play();
+          }
+        });
+      }
+    },
+    // 添加 handleVideoPlay 方法
+    handleVideoPlay() {
+      console.log("视频开始播放");
+      if (this.currentVideoIndex >= 0 && this.currentVideoIndex < this.additionalQuestions.length) {
+        const currentQuestion = this.additionalQuestions[this.currentVideoIndex];
+        if (currentQuestion) {
+          this.currentSubtitle = currentQuestion.question || currentQuestion.digital_human_video_subtitle || "请回答问题";
+        }
+      }
+    }
+  }
+};
+function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
+  return common_vendor.e({
+    a: $data.videoUrl,
+    b: common_vendor.o((...args) => $options.handleVideoError && $options.handleVideoError(...args)),
+    c: common_vendor.o((...args) => $options.handleVideoEnded && $options.handleVideoEnded(...args)),
+    d: common_vendor.o((...args) => $options.handleVideoPlay && $options.handleVideoPlay(...args)),
+    e: common_vendor.o((...args) => $options.handleTimeUpdate && $options.handleTimeUpdate(...args)),
+    f: $data.showAnswerButton
+  }, $data.showAnswerButton ? {
+    g: common_vendor.o((...args) => $options.handleAnswerButtonClick && $options.handleAnswerButtonClick(...args))
+  } : {}, {
+    h: $data.currentSubtitle
+  }, $data.currentSubtitle ? {
+    i: common_vendor.t($data.currentSubtitle)
+  } : {}, {
+    j: $data.useMiniProgramCameraComponent
+  }, $data.useMiniProgramCameraComponent ? {
+    k: common_vendor.o((...args) => $options.handleCameraError && $options.handleCameraError(...args))
+  } : {}, {
+    l: $data.loading
+  }, $data.loading ? {} : {}, {
+    m: $data.showDebugInfo
+  }, $data.showDebugInfo ? common_vendor.e({
+    n: $data.assistantResponse
+  }, $data.assistantResponse ? {
+    o: common_vendor.t($data.assistantResponse)
+  } : {}, {
+    p: $data.audioTranscript
+  }, $data.audioTranscript ? {
+    q: common_vendor.t($data.audioTranscript)
+  } : {}, {
+    r: 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
+      });
+    })
+  }) : {}, {
+    s: $data.showStopRecordingButton
+  }, $data.showStopRecordingButton ? {
+    t: common_vendor.o((...args) => $options.stopRecordingAnswer && $options.stopRecordingAnswer(...args))
+  } : {}, {
+    v: $data.isRecording
+  }, $data.isRecording ? {
+    w: common_vendor.t($data.recordingTimeDisplay || "00:00 / 05:00")
+  } : {}, {
+    x: $data.showStartRecordingButton
+  }, $data.showStartRecordingButton ? {
+    y: common_vendor.o((...args) => $options.handleStartRecordingClick && $options.handleStartRecordingClick(...args))
+  } : {}, {
+    z: $data.showRetryButton
+  }, $data.showRetryButton ? {
+    A: common_vendor.o((...args) => $options.retryVideoUpload && $options.retryVideoUpload(...args))
+  } : {}, {
+    B: $data.showCountdown
+  }, $data.showCountdown ? {
+    C: common_vendor.t($data.countdownValue)
+  } : {});
+}
+const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-5095da88"]]);
+wx.createPage(MiniProgramPage);

+ 4 - 0
unpackage/dist/dev/mp-weixin/pages/followUp/followUp.json

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

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
unpackage/dist/dev/mp-weixin/pages/followUp/followUp.wxml


+ 363 - 0
unpackage/dist/dev/mp-weixin/pages/followUp/followUp.wxss

@@ -0,0 +1,363 @@
+
+.identity-verify-container.data-v-5095da88 {
+  padding: 0;
+  max-width: 100%;
+  margin: 0 auto;
+  height: 100vh;
+  display: flex;
+  flex-direction: column;
+  background-color: #f5f5f5;
+}
+.digital-human-container.data-v-5095da88 {
+  position: relative;
+  width: 100%;
+  height: 100vh;
+  overflow: hidden;
+  background-color: #f0f0f0;
+}
+.digital-human-video.data-v-5095da88 {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+/* 用户摄像头容器样式 */
+.user-camera-container.data-v-5095da88 {
+  position: absolute;
+  top: 50px;
+  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;
+}
+
+/* 用户摄像头视频样式 */
+.user-camera-video.data-v-5095da88 {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+  background-color: #333;
+}
+.video-player.data-v-5095da88 {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+  outline: none; /* 移除视频获得焦点时的轮廓 */
+  -webkit-tap-highlight-color: transparent; /* 移除移动设备上的点击高亮 */
+}
+
+/* 隐藏视频控制条 */
+video.data-v-5095da88::-webkit-media-controls {
+  display: none !important;
+}
+video.data-v-5095da88::-webkit-media-controls-enclosure {
+  display: none !important;
+}
+video.data-v-5095da88::-webkit-media-controls-panel {
+  display: none !important;
+}
+video.data-v-5095da88::-webkit-media-controls-play-button {
+  display: none !important;
+}
+video.data-v-5095da88::-webkit-media-controls-timeline {
+  display: none !important;
+}
+video.data-v-5095da88::-webkit-media-controls-current-time-display {
+  display: none !important;
+}
+video.data-v-5095da88::-webkit-media-controls-time-remaining-display {
+  display: none !important;
+}
+video.data-v-5095da88::-webkit-media-controls-mute-button {
+  display: none !important;
+}
+video.data-v-5095da88::-webkit-media-controls-volume-slider {
+  display: none !important;
+}
+video.data-v-5095da88::-webkit-media-controls-fullscreen-button {
+  display: none !important;
+}
+
+/* 修改字幕覆盖层样式,使其与图片中的样式一致 */
+.subtitle-overlay.data-v-5095da88 {
+  position: absolute;
+  bottom: 180px; /* 调整位置,使其更靠近底部 */
+  left: 5%; /* 从左侧留出5%的空间 */
+  width: 80%; /* 宽度设为90%,两侧各留5%实现居中 */
+  padding: 15px 20px; /* 增加左右内边距 */
+  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); /* 添加轻微阴影 */
+}
+
+/* 添加计时器样式,右侧显示橙色圆点和时间 */
+.subtitle-overlay.data-v-5095da88::after {
+  content: attr(data-time);
+  position: absolute;
+  right: 20px;
+  bottom: 15px;
+  color: #333;
+  font-size: 14px;
+}
+.control-panel.data-v-5095da88 {
+  padding: 15px;
+  display: flex;
+  justify-content: center;
+}
+.control-button.data-v-5095da88 {
+  padding: 10px 20px;
+  background-color: #4CAF50;
+  color: white;
+  border: none;
+  border-radius: 4px;
+  cursor: pointer;
+}
+.loading.data-v-5095da88 {
+  text-align: center;
+  margin: 20px 0;
+  font-size: 16px;
+}
+.response-container.data-v-5095da88 {
+  margin-top: 20px;
+  padding: 0 20px;
+  display: none; /* 默认隐藏调试信息 */
+}
+
+/* 当showDebugInfo为true时显示 */
+.showDebugInfo .response-container.data-v-5095da88 {
+  display: block;
+}
+.response-item.data-v-5095da88 {
+  padding: 10px;
+  border: 1px solid #eee;
+  border-radius: 4px;
+  margin-bottom: 10px;
+  background-color: #f9f9f9;
+}
+.response-content.data-v-5095da88 {
+  display: flex;
+  flex-direction: column;
+}
+.answer-button-container.data-v-5095da88 {
+  position: absolute;
+  bottom: 50px; /* 将按钮放在底部而不是75%的位置 */
+  left: 50%;
+  transform: translateX(-50%); /* 只在X轴上平移,保持水平居中 */
+  z-index: 20;
+}
+
+/* 修改回答按钮样式 */
+.answer-button.data-v-5095da88 {
+  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-5095da88 {
+  position: absolute;
+  bottom: 50px; /* 统一与其他按钮的位置 */
+  left: 50%;
+  transform: translateX(-50%);
+  z-index: 20;
+}
+.stop-recording-button.data-v-5095da88 {
+  width: 120px;
+  height: 40px; /* 改为矩形按钮 */
+  border-radius: 20px; /* 圆角矩形 */
+  background-color: #e74c3c; /* 白色背景 */
+  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; /* 移除脉动动画 */
+}
+.recording-indicator.data-v-5095da88 {
+  position: absolute;
+  top: 20px;
+  left: 20px;
+  display: flex;
+  align-items: center;
+  background-color: rgba(255, 255, 255, 0.9); /* 改为白色半透明背景 */
+  padding: 5px 10px;
+  border-radius: 15px;
+  z-index: 20;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+}
+.recording-dot.data-v-5095da88 {
+  width: 12px;
+  height: 12px;
+  background-color: #ff6b00; /* 改为橙色,与图片中的颜色一致 */
+  border-radius: 50%;
+  margin-right: 8px;
+  animation: blink 1s infinite;
+}
+.recording-text.data-v-5095da88 {
+  color: #333; /* 改为深色文字 */
+  font-size: 14px;
+}
+.timer-text.data-v-5095da88 {
+  color: #333; /* 改为深色文字 */
+  font-size: 14px;
+  margin-left: 8px;
+}
+.start-recording-button-container.data-v-5095da88 {
+  position: absolute;
+  bottom: 50px; /* 统一与其他按钮的位置 */
+  left: 50%;
+  transform: translateX(-50%);
+  z-index: 101;
+}
+.start-recording-button.data-v-5095da88 {
+  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-5095da88 {
+  position: absolute;
+  bottom: 30px; /* 统一与其他按钮的位置 */
+  left: 50%;
+  transform: translateX(-50%);
+  z-index: 20;
+}
+.retry-button.data-v-5095da88 {
+  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-5095da88:hover {
+  background-color: #2980b9;
+}
+
+/* 录制时长显示 */
+.recording-timer.data-v-5095da88 {
+  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-5095da88 {
+  color: #000;
+  font-size: 14px;
+  font-family: monospace; /* 使用等宽字体,使时间显示更稳定 */
+}
+.remaining-time.data-v-5095da88 {
+  color: white;
+  font-size: 12px;
+  margin-top: 2px;
+}
+.remaining-time.warning.data-v-5095da88 {
+  color: #ff6b6b; /* 剩余时间少时显示红色 */
+  animation: blink 1s infinite; /* 使用闪烁动画提醒用户 */
+}
+
+/* 添加上传状态指示器 */
+.upload-status-indicator.data-v-5095da88 {
+  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-5095da88 {
+  display: flex;
+  align-items: center;
+}
+.upload-status-icon.data-v-5095da88 {
+  width: 12px;
+  height: 12px;
+  border-radius: 50%;
+  margin-right: 8px;
+}
+.upload-status-text.data-v-5095da88 {
+  color: white;
+  font-size: 14px;
+}
+.uploading.data-v-5095da88 {
+  background-color: #e74c3c;
+}
+
+/* 添加倒计时蒙层样式 */
+.countdown-overlay.data-v-5095da88 {
+  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-5095da88 {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+.countdown-number.data-v-5095da88 {
+  font-size: 80px;
+  color: #ffffff;
+  font-weight: bold;
+  margin-bottom: 20px;
+}
+.countdown-text.data-v-5095da88 {
+  font-size: 24px;
+  color: #ffffff;
+}
+
+/* 添加GIF播放器样式 */
+.gif-player.data-v-5095da88 {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: 5; /* 确保GIF在视频上方但在字幕和按钮下方 */
+}

+ 516 - 192
unpackage/dist/dev/mp-weixin/pages/identity-verify/identity-verify.js

@@ -25,6 +25,8 @@ const _sfc_main = {
       cameraContext: null,
       // 添加相机上下文
       currentSubtitle: "",
+      currentTranslation: "",
+      // 添加翻译文本
       subtitles: [],
       // 修改为空数组,将通过API获取
       // 移除硬编码的字幕数组
@@ -86,12 +88,56 @@ const _sfc_main = {
       countdownTimer: null,
       showGif: false,
       // 控制是否显示GIF
-      gifUrl: ""
+      gifUrl: "",
       // GIF图片的URL
+      globalSocketTask: null,
+      // 添加全局 WebSocket 连接对象
+      lowScoreVideoUrl: "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,
+      lastUpdateTime: Date.now(),
+      // 添加最后更新时间戳
+      subtitleMap: {}
+      // 用于存储字幕和翻译的映射
     };
   },
   mounted() {
     this.fetchQuestions();
+    this.fetchFollowUpQuestions();
     this.checkAudioPermission();
     this.initCamera();
     this.checkIOSCameraRecordPermission();
@@ -101,6 +147,7 @@ const _sfc_main = {
         this.testAudioInput();
       }
     }, 3e3);
+    this.historyTime = 0;
     common_vendor.index.setKeepScreenOn({
       keepScreenOn: true
     });
@@ -511,8 +558,49 @@ const _sfc_main = {
     },
     // 处理视频结束事件
     handleVideoEnded() {
-      console.log("视频播放结束");
+      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;
+        } else {
+          console.log("已达到最大重试次数,继续下一题");
+          this.retryCount = 0;
+          this.proceedToNextQuestion();
+        }
+        this.isPlayingLowScoreVideo = false;
+        this.currentSubtitle = "";
+        return;
+      }
+      if (this.isFollowUpQuestion) {
+        console.log("追问问题视频播放完成");
+        this.isFollowUpQuestion = false;
+        this.showStartRecordingButton = true;
+        this.startCountdown();
+        return;
+      }
       if (this.currentVideoIndex >= 1) {
         this.showStartRecordingButton = true;
         this.startCountdown();
@@ -547,20 +635,27 @@ const _sfc_main = {
       this.clearCountdown();
       this.startRecordingAnswer();
     },
-    // 修改 stopRecordingAnswer 方法,确保清除倒计时
+    // 修改 stopRecordingAnswer 方法,添加录制时长检查
     stopRecordingAnswer() {
       this.clearCountdown();
       const recordingDuration = this.getRecordingDuration();
-      const minimumDuration = 5;
+      const minimumDuration = 3;
+      const lowScoreDuration = 7;
       if (recordingDuration < minimumDuration) {
         common_vendor.index.showToast({
-          title: "录制时间过短,请至少录制5秒",
+          title: "录制时间过短,请至少录制3秒",
           icon: "none",
           duration: 2e3
         });
         return;
       }
       this.completeRecordingStop();
+      if (recordingDuration < lowScoreDuration) {
+        console.log(`录制时间 ${recordingDuration} 秒,少于 ${lowScoreDuration} 秒,将播放低分提示视频`);
+        this.needPlayLowScoreVideo = true;
+      } else {
+        this.needPlayLowScoreVideo = false;
+      }
     },
     // 添加新方法:开始录制用户回答
     startRecordingAnswer() {
@@ -574,7 +669,7 @@ const _sfc_main = {
         this.remainingTime = Math.max(0, this.maxRecordingTime - this.recordingTimerCount);
         this.recordingTimeDisplay = this.formatTime(this.recordingTimerCount) + " / " + this.formatTime(this.maxRecordingTime);
         if (this.recordingTimerCount >= this.maxRecordingTime) {
-          console.log("已达到最大录制时间(60秒),自动停止录制");
+          console.log("已达到最大录制时间(5分钟),自动停止录制");
           this.stopRecordingAnswer();
         }
       }, 1e3);
@@ -895,16 +990,23 @@ const _sfc_main = {
         this.showCountdown = false;
       }
       const recordingDuration = this.getRecordingDuration();
-      const minimumDuration = 5;
+      const minimumDuration = 3;
+      const lowScoreDuration = 7;
       if (recordingDuration < minimumDuration) {
         common_vendor.index.showToast({
-          title: "录制时间过短,请至少录制5秒",
+          title: "录制时间过短,请至少录制3秒",
           icon: "none",
           duration: 2e3
         });
         return;
       }
       this.completeRecordingStop();
+      if (recordingDuration < lowScoreDuration) {
+        console.log(`录制时间 ${recordingDuration} 秒,少于 ${lowScoreDuration} 秒,将播放低分提示视频`);
+        this.needPlayLowScoreVideo = true;
+      } else {
+        this.needPlayLowScoreVideo = false;
+      }
     },
     // 添加新方法:获取录制时长
     getRecordingDuration() {
@@ -935,14 +1037,10 @@ const _sfc_main = {
       } else if (this.cameraContext) {
         this.cameraContext.stopRecord({
           success: () => {
-            console.log("重置录制:停止当前录制成功");
-            setTimeout(() => {
-              this.startMiniProgramRecording();
-            }, 500);
+            console.log("相机录制已停止");
           },
           fail: (err) => {
-            console.error("重置录制:停止当前录制失败", err);
-            this.startMiniProgramRecording();
+            console.error("停止相机录制失败:", err);
           }
         });
       }
@@ -952,19 +1050,16 @@ const _sfc_main = {
         duration: 2e3
       });
     },
-    // 添加新方法:完成录制停止流程
+    // 修改 completeRecordingStop 方法,确保正确处理追问问题ID
     completeRecordingStop() {
-      this.isRecording = false;
+      console.log("完成录制停止");
       if (this.recordingTimer) {
         clearInterval(this.recordingTimer);
         this.recordingTimer = null;
       }
-      if (this.mediaRecorderTimeout) {
-        clearTimeout(this.mediaRecorderTimeout);
-        this.mediaRecorderTimeout = null;
-      }
-      common_vendor.index.hideLoading();
+      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) {
@@ -972,58 +1067,39 @@ const _sfc_main = {
       } else {
         this.stopBrowserRecording();
       }
+      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 方法
+    // 修改 stopMiniProgramRecording 方法,确保正确传递追问问题ID
     stopMiniProgramRecording() {
+      console.log("停止小程序录制");
       if (!this.cameraContext) {
         console.error("相机上下文不存在");
         this.proceedToNextQuestion();
         return;
       }
-      const systemInfo = common_vendor.index.getSystemInfoSync();
-      const isIOS = systemInfo.platform === "ios";
-      const stopOptions = {
+      this.cameraContext.stopRecord({
         success: (res) => {
-          console.log("小程序录像停止成功:", res);
-          const tempFilePath = res.tempVideoPath;
-          if (!tempFilePath) {
-            console.error("未获取到视频文件路径");
-            common_vendor.index.showToast({
-              title: "录制失败,未获取到视频文件",
-              icon: "none"
-            });
-            this.proceedToNextQuestion();
-            return;
-          }
-          if (isIOS) {
-            common_vendor.index.getFileInfo({
-              filePath: tempFilePath,
-              success: () => {
-                this.uploadRecordedVideo(tempFilePath);
-              },
-              fail: (err) => {
-                console.error("视频文件不存在:", err);
-                common_vendor.index.showToast({
-                  title: "录制失败,视频文件不存在",
-                  icon: "none"
-                });
-                this.proceedToNextQuestion();
-              }
-            });
+          console.log("小程序录制停止成功:", res);
+          const videoPath = res.tempVideoPath;
+          if (videoPath) {
+            this.uploadRecordedVideo(videoPath);
           } else {
-            this.uploadRecordedVideo(tempFilePath);
+            console.error("未获取到录制视频路径");
+            this.proceedToNextQuestion();
           }
         },
         fail: (err) => {
-          console.error("小程序录像停止失败:", err);
-          common_vendor.index.showToast({
-            title: "录制失败",
-            icon: "none"
-          });
+          console.error("小程序录制停止失败:", err);
           this.proceedToNextQuestion();
         }
-      };
-      this.cameraContext.stopRecord(stopOptions);
+      });
     },
     // 添加新方法:停止浏览器录制
     stopBrowserRecording() {
@@ -1035,29 +1111,57 @@ const _sfc_main = {
         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;
-      const currentQuestion = this.getCurrentQuestionByIndex(this.currentVideoIndex);
-      if (currentQuestion && currentQuestion.id) {
-        questionId = currentQuestion.id;
-        console.log(`使用API返回的问题ID: ${questionId}, 问题: ${currentQuestion.question}`);
+      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 {
-        questionId = this.getDefaultQuestionId(this.currentVideoIndex);
-        console.log(`未找到当前问题,使用默认ID: ${questionId}`);
+        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);
+        }
       }
-      console.log("上传视频对应的问题ID:", questionId);
       const uploadTask = {
         id: Date.now().toString(),
-        // 生成唯一ID
         file: fileOrPath,
         questionId,
+        isFollowUp: isFollowUpQuestionUpload,
+        questionText,
+        questionForm,
         attempts: 0,
-        // 上传尝试次数
-        maxAttempts: 3
-        // 最大尝试次数
+        maxAttempts: 3,
+        parentQuestionId: this.currentParentQuestionId
+        // 添加父问题ID
       };
+      if (!isFollowUpQuestionUpload) {
+        this.currentParentQuestionId = questionId;
+      }
       this.uploadQueue.push(uploadTask);
       this.uploadProgress[uploadTask.id] = 0;
       this.uploadStatus[uploadTask.id] = "pending";
@@ -1070,9 +1174,28 @@ const _sfc_main = {
       if (!this.isUploading) {
         this.processUploadQueue();
       }
-      this.proceedToNextQuestion();
+      this.handlePostUploadActions(uploadTask);
     },
-    // 添加新方法:处理上传队列
+    // 添加新方法:处理上传后的逻辑
+    handlePostUploadActions(task) {
+      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.proceedToNextQuestion();
+        } else {
+          this.currentParentQuestionId = task.questionId;
+          console.log("检查常规问题的追问,父问题ID:", this.currentParentQuestionId);
+          this.checkAndPlayFollowUpQuestion(this.currentParentQuestionId);
+        }
+      }
+    },
+    // 修改 processUploadQueue 方法
     processUploadQueue() {
       if (this.uploadQueue.length === 0) {
         this.isUploading = false;
@@ -1085,10 +1208,10 @@ const _sfc_main = {
       this.uploadStatus[task.id] = "uploading";
       this.updateUploadStatusText();
       task.attempts++;
-      if (typeof task.file !== "string") {
-        this.uploadFileWithXHR(task);
-      } else {
+      if (typeof task.file === "string") {
         this.uploadFileWithUni(task);
+      } else {
+        this.uploadFileWithXHR(task);
       }
     },
     // 添加新方法:使用XMLHttpRequest上传文件
@@ -1219,33 +1342,16 @@ const _sfc_main = {
       }
     },
     // 修改 submitVideoToInterview 方法
-    submitVideoToInterview(videoUrl, task = null) {
-      console.log("提交视频URL到面试接口:", videoUrl);
-      let questionId;
-      if (task) {
-        questionId = task.questionId;
-      } else {
-        if (this.currentVideoIndex >= 1 && this.questions.length > 0) {
-          const currentQuestion = this.getCurrentQuestionByIndex(this.currentVideoIndex);
-          if (currentQuestion && currentQuestion.id) {
-            questionId = currentQuestion.id;
-            console.log(`使用API返回的问题ID: ${questionId}, 问题: ${currentQuestion.question}`);
-          } else {
-            questionId = this.getDefaultQuestionId(this.currentVideoIndex);
-            console.log(`未找到当前问题,使用默认ID: ${questionId}`);
-          }
-        } else {
-          questionId = this.getDefaultQuestionId(this.currentVideoIndex);
-          console.log(`使用备用问题ID: ${questionId} (问题索引: ${this.currentVideoIndex})`);
-        }
-      }
+    submitVideoToInterview(videoUrl, task) {
       const requestData = {
         application_id: common_vendor.index.getStorageSync("appId"),
-        question_id: questionId,
+        question_id: task.questionId,
         video_url: videoUrl,
-        tenant_id: JSON.parse(common_vendor.index.getStorageSync("userInfo")).tenant_id || "1"
+        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);
       common_vendor.index.request({
         url: `${common_config.apiBaseUrl}/api/job/upload_video`,
         method: "POST",
@@ -1254,46 +1360,15 @@ const _sfc_main = {
           "content-type": "application/x-www-form-urlencoded"
         },
         success: (res) => {
-          console.log("面试接口提交成功:", res);
-          if (res.data.code === 0 || res.data.code === 2e3) {
-            if (task) {
-              this.uploadQueue.shift();
-              this.processUploadQueue();
-            } else {
-              common_vendor.index.showToast({
-                title: "回答已提交",
-                icon: "success"
-              });
-              this.lastUploadedVideoUrl = videoUrl;
-              this.showRetryButton = false;
-              this.lastVideoToRetry = null;
-            }
+          if (res.data.code === 200 || res.data.code === 2e3) {
+            this.uploadQueue.shift();
+            this.processUploadQueue();
           } else {
-            if (task) {
-              this.handleSubmitFailure(task, res.data.msg || "提交失败");
-            } else {
-              common_vendor.index.showToast({
-                title: res.data.msg || "提交失败,请重试",
-                icon: "none"
-              });
-              this.lastVideoToRetry = videoUrl;
-              this.showRetryButton = true;
-            }
+            this.handleUploadError(task, "提交失败: " + (res.data.msg || "未知错误"));
           }
         },
         fail: (err) => {
-          console.error("面试接口提交失败:", err);
-          if (task) {
-            this.handleSubmitFailure(task, err.errMsg || "网络错误");
-          } else {
-            common_vendor.index.hideLoading();
-            common_vendor.index.showToast({
-              title: "网络错误,请重试",
-              icon: "none"
-            });
-            this.lastVideoToRetry = videoUrl;
-            this.showRetryButton = true;
-          }
+          this.handleUploadError(task, "网络错误: " + err.errMsg);
         }
       });
     },
@@ -1342,24 +1417,21 @@ const _sfc_main = {
           statusText = `上传失败,${currentTask.attempts < currentTask.maxAttempts ? "即将重试" : "已放弃"}`;
           break;
       }
-      this.uploadStatusText = `问题${currentTask.questionId - 9}:${statusText}`;
+      const questionTypeText = currentTask.isFollowUp ? "追问" : "问题";
+      const questionShortText = currentTask.questionText ? currentTask.questionText.length > 10 ? currentTask.questionText.substring(0, 10) + "..." : currentTask.questionText : `${questionTypeText}${currentTask.questionId}`;
+      this.uploadStatusText = `${questionTypeText}「${questionShortText}」:${statusText}`;
       if (this.uploadQueue.length > 1) {
         this.uploadStatusText += ` (${this.uploadQueue.length}个视频待处理)`;
       }
     },
-    // 修改 proceedToNextQuestion 方法
+    // 修改 proceedToNextQuestion 方法,确保在切换视频时重置历史时间
     proceedToNextQuestion() {
-      if (this.currentVideoIndex === 4) {
-        common_vendor.index.navigateTo({
-          url: "/pages/camera/camera"
-        });
-        return;
-      }
+      console.log("继续下一个问题");
       this.currentVideoIndex++;
+      this.historyTime = 0;
       if (this.currentVideoIndex < this.videoList.length) {
         this.videoUrl = this.videoList[this.currentVideoIndex];
         this.videoPlaying = true;
-        this.currentSubtitle = "";
         this.$nextTick(() => {
           const videoContext = common_vendor.index.createVideoContext("myVideo", this);
           if (videoContext) {
@@ -1367,22 +1439,53 @@ const _sfc_main = {
           }
         });
       } else {
-        common_vendor.index.showToast({
-          title: "面试完成",
-          icon: "success",
-          duration: 2e3
-        });
+        console.log("所有视频已播放完毕");
+        this.stopUserCamera();
+        this.clearCountdown();
         setTimeout(() => {
           common_vendor.index.navigateTo({
-            url: "/pages/interview-result/interview-result"
+            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
+                      });
+                    }
+                  });
+                }
+              });
+            }
           });
         }, 2e3);
       }
     },
-    // 修改 handleAnswerButtonClick 方法
+    // 修改 handleAnswerButtonClick 方法,确保在切换视频时重置历史时间
     handleAnswerButtonClick() {
+      console.log("点击开始回答按钮");
       this.showAnswerButton = false;
-      this.proceedToNextQuestion();
+      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) {
@@ -1438,23 +1541,45 @@ const _sfc_main = {
       const container = this.$refs.userCameraVideo.parentNode;
       container.appendChild(img);
     },
-    // 处理视频时间更新事件
+    // 修改 handleTimeUpdate 方法
     handleTimeUpdate(e) {
-      const currentTime = e.target.currentTime;
+      const currentTime = e.detail.currentTime || e.target.currentTime;
       if (this.isRecording && this.recordingTimerCount) {
         this.recordingTimeDisplay = this.formatTime(this.recordingTimerCount);
       }
-      let currentSubtitles;
-      if (this.currentVideoIndex === 0) {
-        currentSubtitles = this.subtitles;
+      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.digital_human_video_subtitle || this.currentFollowUpQuestion.question
+        }];
       } else {
-        const subtitleArrayName = `question${this.currentVideoIndex}Subtitles`;
-        currentSubtitles = this[subtitleArrayName] || [];
+        if (this.currentVideoIndex === 0) {
+          currentSubtitles = this.subtitles;
+        } else {
+          const subtitleArrayName = `question${this.currentVideoIndex}Subtitles`;
+          currentSubtitles = this[subtitleArrayName];
+        }
       }
-      const subtitle = currentSubtitles.find(
-        (sub) => currentTime >= sub.startTime && currentTime < sub.endTime
-      );
-      this.currentSubtitle = subtitle ? subtitle.text : "";
+      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() {
@@ -1653,7 +1778,7 @@ const _sfc_main = {
             resolve(compressedBlob);
           };
           videoElement.onplay = () => {
-            mediaRecorder.start(100);
+            mediaRecorder.start(10);
             const drawFrame = () => {
               if (videoElement.paused || videoElement.ended) {
                 mediaRecorder.stop();
@@ -1798,17 +1923,18 @@ const _sfc_main = {
       ];
       const sortedQuestions = [...this.questions].sort((a, b) => a.sequence_number - b.sequence_number);
       const questionsToUse = sortedQuestions.slice(0, 5);
-      questionsToUse.forEach((question) => {
+      questionsToUse.forEach((question, index) => {
         if (question.digital_human_video_url) {
           this.videoList.push(question.digital_human_video_url);
           const subtitleArray = [{
             startTime: 0,
-            endTime: 10,
-            // 默认10秒,可以根据实际情况调整
+            endTime: 30,
+            // 延长字幕显示时间到30秒
             text: question.digital_human_video_subtitle || question.question
           }];
-          const index = this.videoList.length - 1;
-          this[`question${index}Subtitles`] = subtitleArray;
+          const videoIndex = this.videoList.length - 1;
+          this[`question${videoIndex}Subtitles`] = subtitleArray;
+          this.subtitleMap[question.digital_human_video_url] = subtitleArray;
         }
       });
       if (this.videoList.length <= 1)
@@ -1903,6 +2029,198 @@ const _sfc_main = {
       console.log("identity-verify页面onShow");
       console.log("当前本地存储中的职位信息:", common_vendor.index.getStorageSync("selectedJob"));
       this.fetchQuestions();
+      this.fetchFollowUpQuestions();
+    },
+    // 添加新方法:重置录制状态,准备重新回答
+    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.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);
+          }
+        });
+      }
+    },
+    // 修改 playLowScoreVideo 方法,优化字幕显示
+    playLowScoreVideo() {
+      console.log("播放低分提示视频");
+      this.isPlayingLowScoreVideo = true;
+      this.showStartRecordingButton = false;
+      this.showStopRecordingButton = false;
+      this.showRerecordButton = false;
+      this.videoUrl = this.lowScoreVideoUrl;
+      this.videoPlaying = true;
+      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,
+                // 假设视频长度为10秒,可根据实际情况调整
+                text: "我未听清楚您在说什么,请您再说一遍!",
+                translation: "I didn't quite catch what you said, could you please repeat it?"
+              }
+            ];
+          }, 500);
+        }
+      });
+    },
+    // 添加新方法:处理重新录制按钮点击
+    handleRerecordButtonClick() {
+      console.log("点击重新录制按钮");
+      this.retryCount++;
+      console.log(`当前重试次数: ${this.retryCount}/${this.maxRetryAttempts}`);
+      this.showRerecordButton = false;
+      this.handleStartRecordingClick();
+    },
+    // 添加 onUnload 生命周期钩子,移除 WebSocket 关闭
+    onUnload() {
+      console.log("页面卸载");
+    },
+    // 修改 onHide 生命周期钩子,移除 WebSocket 关闭
+    onHide() {
+      console.log("页面隐藏");
+    },
+    // 添加新方法:阻止视频控制
+    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 (!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);
+        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.videoUrl = followUpQuestion.digital_human_video_url;
+      this.videoPlaying = true;
+      const followUpSubtitles = [{
+        startTime: 0,
+        endTime: 60,
+        // 延长显示时间到60秒
+        text: followUpQuestion.digital_human_video_subtitle || 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;
+        }
+      });
     }
   }
 };
@@ -1912,31 +2230,33 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
     b: common_vendor.o((...args) => $options.handleVideoError && $options.handleVideoError(...args)),
     c: common_vendor.o((...args) => $options.handleVideoEnded && $options.handleVideoEnded(...args)),
     d: common_vendor.o((...args) => $options.handleTimeUpdate && $options.handleTimeUpdate(...args)),
-    e: $data.showAnswerButton
+    e: common_vendor.o((...args) => $options.preventVideoControl && $options.preventVideoControl(...args)),
+    f: common_vendor.o((...args) => $options.preventVideoControl && $options.preventVideoControl(...args)),
+    g: $data.showAnswerButton
   }, $data.showAnswerButton ? {
-    f: common_vendor.o((...args) => $options.handleAnswerButtonClick && $options.handleAnswerButtonClick(...args))
+    h: common_vendor.o((...args) => $options.handleAnswerButtonClick && $options.handleAnswerButtonClick(...args))
   } : {}, {
-    g: $data.currentSubtitle
+    i: $data.currentSubtitle
   }, $data.currentSubtitle ? {
-    h: common_vendor.t($data.currentSubtitle)
+    j: common_vendor.t($data.currentSubtitle)
   } : {}, {
-    i: $data.useMiniProgramCameraComponent
+    k: $data.useMiniProgramCameraComponent
   }, $data.useMiniProgramCameraComponent ? {
-    j: common_vendor.o((...args) => $options.handleCameraError && $options.handleCameraError(...args))
+    l: common_vendor.o((...args) => $options.handleCameraError && $options.handleCameraError(...args))
   } : {}, {
-    k: $data.loading
+    m: $data.loading
   }, $data.loading ? {} : {}, {
-    l: $data.showDebugInfo
+    n: $data.showDebugInfo
   }, $data.showDebugInfo ? common_vendor.e({
-    m: $data.assistantResponse
+    o: $data.assistantResponse
   }, $data.assistantResponse ? {
-    n: common_vendor.t($data.assistantResponse)
+    p: common_vendor.t($data.assistantResponse)
   } : {}, {
-    o: $data.audioTranscript
+    q: $data.audioTranscript
   }, $data.audioTranscript ? {
-    p: common_vendor.t($data.audioTranscript)
+    r: common_vendor.t($data.audioTranscript)
   } : {}, {
-    q: common_vendor.f($data.processedResponses, (item, index, i0) => {
+    s: common_vendor.f($data.processedResponses, (item, index, i0) => {
       return common_vendor.e({
         a: item.role
       }, item.role ? {
@@ -1950,25 +2270,29 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
       });
     })
   }) : {}, {
-    r: $data.showStopRecordingButton
+    t: $data.showStopRecordingButton
   }, $data.showStopRecordingButton ? {
-    s: common_vendor.o((...args) => $options.stopRecordingAnswer && $options.stopRecordingAnswer(...args))
+    v: common_vendor.o((...args) => $options.stopRecordingAnswer && $options.stopRecordingAnswer(...args))
   } : {}, {
-    t: $data.isRecording
+    w: $data.isRecording
   }, $data.isRecording ? {
-    v: common_vendor.t($data.recordingTimeDisplay || "00:00 / 05:00")
+    x: common_vendor.t($data.recordingTimeDisplay || "00:00 / 05:00")
   } : {}, {
-    w: $data.showStartRecordingButton
+    y: $data.showStartRecordingButton
   }, $data.showStartRecordingButton ? {
-    x: common_vendor.o((...args) => $options.handleStartRecordingClick && $options.handleStartRecordingClick(...args))
+    z: common_vendor.o((...args) => $options.handleStartRecordingClick && $options.handleStartRecordingClick(...args))
   } : {}, {
-    y: $data.showRetryButton
+    A: $data.showRetryButton
   }, $data.showRetryButton ? {
-    z: common_vendor.o((...args) => $options.retryVideoUpload && $options.retryVideoUpload(...args))
+    B: common_vendor.o((...args) => $options.retryVideoUpload && $options.retryVideoUpload(...args))
   } : {}, {
-    A: $data.showCountdown
+    C: $data.showCountdown
   }, $data.showCountdown ? {
-    B: common_vendor.t($data.countdownValue)
+    D: common_vendor.t($data.countdownValue)
+  } : {}, {
+    E: $data.showRerecordButton
+  }, $data.showRerecordButton ? {
+    F: common_vendor.o((...args) => $options.handleRerecordButtonClick && $options.handleRerecordButtonClick(...args))
   } : {});
 }
 const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-464e78c6"]]);

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
unpackage/dist/dev/mp-weixin/pages/identity-verify/identity-verify.wxml


+ 82 - 9
unpackage/dist/dev/mp-weixin/pages/identity-verify/identity-verify.wxss

@@ -86,19 +86,30 @@ video.data-v-464e78c6::-webkit-media-controls-fullscreen-button {
 /* 修改字幕覆盖层样式,使其与图片中的样式一致 */
 .subtitle-overlay.data-v-464e78c6 {
   position: absolute;
-  bottom: 180px; /* 调整位置,使其更靠近底部 */
-  left: 5%; /* 从左侧留出5%的空间 */
-  width: 80%; /* 宽度设为90%,两侧各留5%实现居中 */
-  padding: 15px 20px; /* 增加左右内边距 */
+  bottom: 180px;
+  left: 5%;
+  width: 80%;
+  padding: 15px 20px;
   border-radius: 15px;
-  background-color: rgba(255, 255, 255, 0.9); /* 白色半透明背景 */
-  color: #333; /* 文字颜色为深色 */
-  text-align: left; /* 文字左对齐 */
+  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); /* 添加轻微阴影 */
+  margin: 0 auto;
+  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+  display: flex;
+  flex-direction: column;
+  gap: 8px;
+}
+.subtitle-main.data-v-464e78c6 {
+  font-weight: 500;
+}
+.subtitle-translation.data-v-464e78c6 {
+  font-size: 14px;
+  color: #666;
+  font-style: italic;
 }
 
 /* 添加计时器样式,右侧显示橙色圆点和时间 */
@@ -361,3 +372,65 @@ video.data-v-464e78c6::-webkit-media-controls-fullscreen-button {
   left: 0;
   z-index: 5; /* 确保GIF在视频上方但在字幕和按钮下方 */
 }
+
+/* 重新录制按钮容器样式 */
+.rerecord-button-container.data-v-464e78c6 {
+  position: absolute;
+  bottom: 50px; /* 统一与其他按钮的位置 */
+  left: 50%;
+  transform: translateX(-50%);
+  z-index: 20;
+}
+
+/* 重新录制按钮样式 */
+.rerecord-button.data-v-464e78c6 {
+  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-464e78c6:hover {
+  background-color: #f0f0f0;
+}
+
+/* 添加视频蒙层样式 */
+.video-overlay.data-v-464e78c6 {
+  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-464e78c6 {
+  /* ... 现有样式 ... */
+  z-index: 10; /* 确保字幕在蒙层之上 */
+}
+.answer-button-container.data-v-464e78c6,
+.stop-recording-button-container.data-v-464e78c6,
+.start-recording-button-container.data-v-464e78c6,
+.retry-button-container.data-v-464e78c6,
+.rerecord-button-container.data-v-464e78c6 {
+  /* ... 现有样式 ... */
+  z-index: 999; /* 确保按钮在蒙层之上 */
+}
+.user-camera-container.data-v-464e78c6 {
+  /* ... 现有样式 ... */
+  z-index: 20; /* 确保摄像头窗口在蒙层之上 */
+}
+.recording-indicator.data-v-464e78c6 {
+  /* ... 现有样式 ... */
+  z-index: 20; /* 确保录制指示器在蒙层之上 */
+}

+ 619 - 146
unpackage/dist/dev/mp-weixin/pages/interview-question/interview-question.js

@@ -135,8 +135,23 @@ const _sfc_main = {
       // 转写文本
       isPlayingAiVoice: false,
       // 是否正在播放AI语音
-      aiAudioPlayer: null
+      aiAudioPlayer: null,
       // AI语音播放器
+      // 添加新的状态变量
+      showContinueQuestionButton: false,
+      // 控制"继续提问"按钮显示
+      showEndInterviewButton: false,
+      // 控制"结束面试"按钮显示
+      questionRound: 0,
+      // 当前提问轮次
+      maxQuestionRounds: 2,
+      // 最大提问轮次(可配置)
+      conversationHistory: [],
+      // 对话历史记录
+      pendingAutoNavigation: false,
+      // 标记是否有待处理的自动跳转
+      hasTriedFallbackMethod: false
+      // 标记是否尝试过备选方法播放音频
     };
   },
   onLoad(options) {
@@ -187,6 +202,23 @@ const _sfc_main = {
       clearTimeout(this.mediaRecorderTimeout);
       this.mediaRecorderTimeout = null;
     }
+    if (this.mediaRecorder && this.mediaRecorder.state === "recording") {
+      try {
+        this.mediaRecorder.stop();
+      } catch (e) {
+        console.error("停止MediaRecorder失败:", e);
+      }
+    }
+    if (this.recorder) {
+      try {
+        this.cameraContext.stopRecord();
+      } catch (e) {
+        console.error("停止小程序录制失败:", e);
+      }
+    }
+    common_vendor.index.setKeepScreenOn({
+      keepScreenOn: false
+    });
   },
   methods: {
     // 初始化相机
@@ -620,7 +652,7 @@ const _sfc_main = {
       this.clearCountdown();
       this.startRecordingAnswer();
     },
-    // 修改 stopRecordingAnswer 方法,确保清除倒计时
+    // 修复 stopRecordingAnswer 方法,确保录制正确停止并上传
     stopRecordingAnswer() {
       this.clearCountdown();
       const recordingDuration = this.getRecordingDuration();
@@ -633,7 +665,19 @@ const _sfc_main = {
         });
         return;
       }
-      this.completeRecordingStop();
+      this.showStopRecordingButton = false;
+      if (this.recordingTimer) {
+        clearInterval(this.recordingTimer);
+        this.recordingTimer = null;
+      }
+      const systemInfo = common_vendor.index.getSystemInfoSync();
+      const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith("mp-");
+      if (isMiniProgram) {
+        this.stopMiniProgramRecording();
+      } else {
+        this.stopBrowserRecording();
+      }
+      this.isRecording = false;
     },
     // 添加新方法:开始录制用户回答
     startRecordingAnswer() {
@@ -977,7 +1021,19 @@ const _sfc_main = {
         });
         return;
       }
-      this.completeRecordingStop();
+      this.showStopRecordingButton = false;
+      if (this.recordingTimer) {
+        clearInterval(this.recordingTimer);
+        this.recordingTimer = null;
+      }
+      const systemInfo = common_vendor.index.getSystemInfoSync();
+      const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith("mp-");
+      if (isMiniProgram) {
+        this.stopMiniProgramRecording();
+      } else {
+        this.stopBrowserRecording();
+      }
+      this.isRecording = false;
     },
     // 添加新方法:获取录制时长
     getRecordingDuration() {
@@ -1025,19 +1081,18 @@ const _sfc_main = {
         duration: 2e3
       });
     },
-    // 添加新方法:完成录制停止流程
+    // 修复 completeRecordingStop 方法,确保视频正确上传和处理
     completeRecordingStop() {
-      this.isRecording = false;
+      console.log("完成录制停止");
+      this.showStopRecordingButton = false;
       if (this.recordingTimer) {
         clearInterval(this.recordingTimer);
         this.recordingTimer = null;
       }
-      if (this.mediaRecorderTimeout) {
-        clearTimeout(this.mediaRecorderTimeout);
-        this.mediaRecorderTimeout = null;
-      }
-      common_vendor.index.hideLoading();
-      this.showStopRecordingButton = false;
+      this.isRecording = false;
+      this.showUploadStatus = true;
+      this.uploadStatusText = "正在处理视频...";
+      this.isUploading = true;
       const systemInfo = common_vendor.index.getSystemInfoSync();
       const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith("mp-");
       if (isMiniProgram) {
@@ -1046,57 +1101,43 @@ const _sfc_main = {
         this.stopBrowserRecording();
       }
     },
-    // 修改 stopMiniProgramRecording 方法
+    // 修复 stopMiniProgramRecording 方法,确保小程序环境下正确停止录制
     stopMiniProgramRecording() {
+      console.log("停止小程序录制");
       if (!this.cameraContext) {
         console.error("相机上下文不存在");
-        this.proceedToNextQuestion();
+        this.handleRecordingError(new Error("相机上下文不存在"));
         return;
       }
-      const systemInfo = common_vendor.index.getSystemInfoSync();
-      const isIOS = systemInfo.platform === "ios";
-      const stopOptions = {
-        success: (res) => {
-          console.log("小程序录像停止成功:", res);
-          const tempFilePath = res.tempVideoPath;
-          if (!tempFilePath) {
-            console.error("未获取到视频文件路径");
-            common_vendor.index.showToast({
-              title: "录制失败,未获取到视频文件",
-              icon: "none"
-            });
-            this.proceedToNextQuestion();
-            return;
-          }
-          if (isIOS) {
-            common_vendor.index.getFileInfo({
-              filePath: tempFilePath,
-              success: () => {
-                this.uploadRecordedVideo(tempFilePath);
-              },
-              fail: (err) => {
-                console.error("视频文件不存在:", err);
-                common_vendor.index.showToast({
-                  title: "录制失败,视频文件不存在",
-                  icon: "none"
-                });
-                this.proceedToNextQuestion();
-              }
-            });
-          } else {
-            this.uploadRecordedVideo(tempFilePath);
+      try {
+        common_vendor.index.showLoading({
+          title: "正在处理视频...",
+          mask: true
+        });
+        this.cameraContext.stopRecord({
+          success: (res) => {
+            console.log("停止录制成功:", res);
+            common_vendor.index.hideLoading();
+            const tempVideoPath = res.tempVideoPath || res.tempFilePath;
+            if (tempVideoPath) {
+              console.log("获取到视频临时路径:", tempVideoPath);
+              this.uploadRecordedVideo(tempVideoPath);
+            } else {
+              console.error("未获取到视频临时路径");
+              this.handleRecordingError(new Error("未获取到视频临时路径"));
+            }
+          },
+          fail: (err) => {
+            console.error("停止录制失败:", err);
+            common_vendor.index.hideLoading();
+            this.handleRecordingError(err);
           }
-        },
-        fail: (err) => {
-          console.error("小程序录像停止失败:", err);
-          common_vendor.index.showToast({
-            title: "录制失败",
-            icon: "none"
-          });
-          this.proceedToNextQuestion();
-        }
-      };
-      this.cameraContext.stopRecord(stopOptions);
+        });
+      } catch (e) {
+        console.error("停止录制异常:", e);
+        common_vendor.index.hideLoading();
+        this.handleRecordingError(e);
+      }
     },
     // 添加新方法:停止浏览器录制
     stopBrowserRecording() {
@@ -1108,35 +1149,76 @@ const _sfc_main = {
         this.proceedToNextQuestion();
       }
     },
-    // 修改上传录制的视频方法
-    uploadRecordedVideo(fileOrPath) {
-      console.log("准备上传视频:", typeof fileOrPath === "string" ? fileOrPath : fileOrPath.name);
-      let questionId = 10;
-      const uploadTask = {
-        id: Date.now().toString(),
-        // 生成唯一ID
-        file: fileOrPath,
-        questionId,
-        attempts: 0,
-        // 上传尝试次数
-        maxAttempts: 3,
-        // 最大尝试次数
-        hasAudio: true
-        // 明确标记包含音频
-      };
-      this.uploadQueue.push(uploadTask);
-      this.uploadProgress[uploadTask.id] = 0;
-      this.uploadStatus[uploadTask.id] = "pending";
-      common_vendor.index.showToast({
-        title: "已完成回答",
-        icon: "none",
-        duration: 1500
+    // 修复 uploadRecordedVideo 方法,确保视频正确上传到服务器
+    uploadRecordedVideo(videoPath) {
+      console.log("开始上传录制的视频:", videoPath);
+      this.lastVideoToRetry = videoPath;
+      this.showUploadStatus = true;
+      this.uploadStatusText = "正在上传视频...";
+      this.isUploading = true;
+      this.saveUploadStatus();
+      const tenant_id = common_vendor.index.getStorageSync("tenant_id") || "1";
+      const openid = common_vendor.index.getStorageSync("userInfo") ? JSON.parse(common_vendor.index.getStorageSync("userInfo")).openid : "";
+      const application_id = common_vendor.index.getStorageSync("appId") || "";
+      const uploadTask = common_vendor.index.uploadFile({
+        url: `${common_config.apiBaseUrl}/api/upload/`,
+        filePath: videoPath,
+        name: "file",
+        formData: {
+          tenant_id,
+          openid,
+          application_id,
+          biz_type: "interview_video",
+          video_duration: this.recordingTimerCount || 0,
+          has_audio: "true"
+          // 明确标记包含音频
+        },
+        success: (uploadRes) => {
+          var _a, _b;
+          console.log("视频上传成功:", uploadRes);
+          try {
+            const result = typeof uploadRes.data === "string" ? JSON.parse(uploadRes.data) : uploadRes.data;
+            if ((result.success || result.code === 2e3) && (((_a = result.data) == null ? void 0 : _a.url) || ((_b = result.data) == null ? void 0 : _b.permanent_link))) {
+              const videoUrl = result.data.url || result.data.permanent_link || "";
+              console.log("视频URL:", videoUrl);
+              this.uploadStatusText = "视频处理完成,正在分析...";
+              this.saveUploadStatus();
+              this.submitToAiVoiceInteraction(videoUrl);
+            } else {
+              console.error("上传响应格式错误:", result);
+              const errorMsg = result.msg || result.message || "上传响应格式错误";
+              this.handleUploadError(new Error(errorMsg));
+            }
+          } catch (e) {
+            console.error("解析上传响应失败:", e);
+            this.handleUploadError(e);
+          }
+        },
+        fail: (err) => {
+          console.error("视频上传失败:", err);
+          let errorMessage = "网络错误,请检查网络连接";
+          if (err.errMsg) {
+            if (err.errMsg.includes("timeout")) {
+              errorMessage = "上传超时,请检查网络连接";
+            } else if (err.errMsg.includes("fail")) {
+              errorMessage = "上传失败: " + err.errMsg;
+            }
+          }
+          this.handleUploadError(new Error(errorMessage));
+        },
+        complete: () => {
+          this.showUploadStatus = false;
+          this.isUploading = false;
+          this.saveUploadStatus();
+        }
+      });
+      uploadTask.onProgressUpdate((res) => {
+        console.log("上传进度:", res.progress);
+        this.uploadStatusText = `正在上传视频... ${res.progress}%`;
+        if (res.progress < 10 && res.totalTimeMs > 1e4) {
+          this.uploadStatusText = `上传速度较慢,请耐心等待... ${res.progress}%`;
+        }
       });
-      this.updateUploadStatusText();
-      if (!this.isUploading) {
-        this.processUploadQueue();
-      }
-      this.proceedToNextQuestion();
     },
     // 修改 processUploadQueue 方法,添加后台上传支持
     processUploadQueue() {
@@ -1812,7 +1894,7 @@ const _sfc_main = {
         console.error("保存上传状态失败:", e);
       }
     },
-    // 增强 submitToAiVoiceInteraction 方法
+    // 修改 submitToAiVoiceInteraction 方法
     submitToAiVoiceInteraction(videoUrl) {
       console.log("提交视频到AI语音交互接口:", videoUrl);
       common_vendor.index.showLoading({
@@ -1820,26 +1902,29 @@ const _sfc_main = {
         mask: true
       });
       const tenant_id = common_vendor.index.getStorageSync("tenant_id") || "1";
-      const userInfo = common_vendor.index.getStorageSync("userInfo");
-      userInfo ? JSON.parse(userInfo).openid || "" : "";
-      const systemInfo = common_vendor.index.getSystemInfoSync();
-      const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith("mp-");
+      const application_id = common_vendor.index.getStorageSync("appId") || "98";
       const requestData = {
-        url: videoUrl,
-        tenant_id
-        /*   openid: openid,
-          application_id: uni.getStorageSync('appId') || '',
-          has_audio: true, // 明确标记包含音频
-          audio_format: 'mp4', // 指定音频格式
-          duration: this.recordingTimerCount || 0 // 添加录制时长 */
+        voice_url: videoUrl,
+        tenant_id,
+        application_id,
+        scene_type: "interview",
+        // 场景类型:面试
+        voice_type: "longxiaoxia",
+        // 角色:龙小侠
+        conversation_history: this.conversationHistory
+        // 添加对话历史
       };
+      const systemInfo = common_vendor.index.getSystemInfoSync();
+      const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith("mp-");
       if (isMiniProgram) {
         common_vendor.index.request({
-          url: `${common_config.apiBaseUrl}/api/voice_ai_interaction`,
+          url: `${common_config.apiBaseUrl}/api/system/voice/mcp/interaction`,
+          // 使用新的接口地址
           method: "POST",
           data: requestData,
           header: {
-            "content-type": "application/x-www-form-urlencoded"
+            "content-type": "application/json"
+            // 修改为JSON格式
           },
           success: (res) => {
             this.handleAiInteractionResponse(res.data);
@@ -1849,13 +1934,10 @@ const _sfc_main = {
           }
         });
       } else {
-        const formData = new FormData();
-        for (const key in requestData) {
-          formData.append(key, requestData[key]);
-        }
         const xhr = new XMLHttpRequest();
-        xhr.open("POST", `${common_config.apiBaseUrl}/api/voice_ai_interaction`, true);
+        xhr.open("POST", `${common_config.apiBaseUrl}/api/system/voice/mcp/interaction`, true);
         xhr.timeout = 6e4;
+        xhr.setRequestHeader("Content-Type", "application/json");
         xhr.onload = () => {
           if (xhr.status === 200) {
             try {
@@ -1875,16 +1957,25 @@ const _sfc_main = {
         xhr.ontimeout = () => {
           this.handleAiInteractionError({ errMsg: "请求超时" });
         };
-        xhr.send(formData);
+        xhr.send(JSON.stringify(requestData));
       }
     },
     // 添加处理AI交互响应的方法
     handleAiInteractionResponse(data) {
       console.log("AI语音交互接口响应:", data);
       common_vendor.index.hideLoading();
+      this.hasTriedFallbackMethod = false;
       if (data && data.success) {
         this.aiText = data.ai_text || "";
         this.transcribedText = data.transcribed_text ? data.transcribed_text.text : "";
+        this.conversationHistory.push({
+          role: "user",
+          content: this.transcribedText
+        });
+        this.conversationHistory.push({
+          role: "assistant",
+          content: this.aiText
+        });
         const aiVoiceUrl = data.ai_voice_url || "";
         if (aiVoiceUrl) {
           this.aiVoiceUrl = aiVoiceUrl.startsWith("http") ? aiVoiceUrl : `${common_config.apiBaseUrl}${aiVoiceUrl}`;
@@ -1892,42 +1983,64 @@ const _sfc_main = {
           this.currentSubtitle = this.aiText;
           const systemInfo = common_vendor.index.getSystemInfoSync();
           const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith("mp-");
+          const isUnsupportedFormat = this.checkUnsupportedAudioFormat(this.aiVoiceUrl);
+          if (isUnsupportedFormat && isMiniProgram) {
+            console.warn("检测到小程序不支持的音频格式,直接使用文本显示");
+            this.displayTextResponse();
+            return;
+          }
           if (isMiniProgram) {
             this.playMiniProgramAudio();
           } else {
             this.playAiVoice();
           }
+          this.showContinueQuestionButton = false;
+          this.showEndInterviewButton = false;
         } else {
-          console.warn("未获取到AI语音URL");
-          this.navigateToNextPage();
+          console.warn("未获取到AI语音URL,使用文本显示");
+          this.displayTextResponse();
         }
       } else {
         console.error("AI语音交互失败:", data);
-        this.navigateToNextPage();
+        this.showContinueQuestionOptions();
+        this.checkPendingNavigation();
       }
     },
-    // 添加处理AI交互错误的方法
+    // 修改 handleAiInteractionError 方法,不要直接跳转,而是显示继续提问选项
     handleAiInteractionError(err) {
       console.error("AI语音交互请求失败:", err);
       common_vendor.index.hideLoading();
       common_vendor.index.showToast({
-        title: "AI处理失败,请稍后再试",
+        title: "AI处理失败,请试",
         icon: "none",
         duration: 2e3
       });
-      this.navigateToNextPage();
+      this.showContinueQuestionOptions();
     },
     // 添加新方法:播放AI语音
     playAiVoice() {
       console.log("开始播放AI语音:", this.aiVoiceUrl);
       this.isPlayingAiVoice = true;
-      const systemInfo = common_vendor.index.getSystemInfoSync();
-      const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith("mp-");
+      this.showContinueQuestionButton = false;
+      this.showEndInterviewButton = false;
+      if (!this.aiVoiceUrl || this.aiVoiceUrl.trim() === "") {
+        console.error("无效的音频URL");
+        common_vendor.index.showToast({
+          title: "音频加载失败",
+          icon: "none",
+          duration: 2e3
+        });
+        this.isPlayingAiVoice = false;
+        this.showContinueQuestionOptions();
+        return;
+      }
       try {
         if (this.aiAudioPlayer) {
           this.aiAudioPlayer.destroy();
         }
         this.aiAudioPlayer = common_vendor.index.createInnerAudioContext();
+        this.aiAudioPlayer.autoplay = false;
+        this.aiAudioPlayer.obeyMuteSwitch = false;
         this.aiAudioPlayer.onPlay(() => {
           console.log("AI语音开始播放");
           common_vendor.index.showToast({
@@ -1944,30 +2057,47 @@ const _sfc_main = {
             this.aiAudioPlayer.destroy();
             this.aiAudioPlayer = null;
           }
-          this.navigateToNextPage();
+          this.showContinueQuestionOptions();
+          this.checkPendingNavigation();
         });
         this.aiAudioPlayer.onError((err) => {
           console.error("AI语音播放错误:", err);
+          if (!this.hasTriedFallbackMethod) {
+            this.hasTriedFallbackMethod = true;
+            console.log("尝试使用备选方法播放音频");
+            this.tryFallbackAudioPlay();
+            return;
+          }
           this.isPlayingAiVoice = false;
           this.currentSubtitle = "";
           if (this.aiAudioPlayer) {
             this.aiAudioPlayer.destroy();
             this.aiAudioPlayer = null;
           }
-          this.navigateToNextPage();
+          common_vendor.index.showToast({
+            title: "音频播放失败,请查看文字回复",
+            icon: "none",
+            duration: 2e3
+          });
+          this.showContinueQuestionOptions();
+          this.checkPendingNavigation();
+        });
+        this.aiAudioPlayer.onCanplay(() => {
+          console.log("音频已准备好播放");
         });
-        if (isMiniProgram) {
-          if (!this.aiVoiceUrl) {
-            throw new Error("无效的音频URL");
+        this.aiAudioPlayer.src = this.aiVoiceUrl;
+        const playTimeout = setTimeout(() => {
+          if (this.isPlayingAiVoice && this.aiAudioPlayer) {
+            console.warn("音频播放超时,尝试备选方法");
+            this.tryFallbackAudioPlay();
           }
-          this.aiAudioPlayer.src = this.aiVoiceUrl;
-          setTimeout(() => {
+        }, 5e3);
+        setTimeout(() => {
+          if (this.aiAudioPlayer) {
             this.aiAudioPlayer.play();
-          }, 100);
-        } else {
-          this.aiAudioPlayer.src = this.aiVoiceUrl;
-          this.aiAudioPlayer.play();
-        }
+            clearTimeout(playTimeout);
+          }
+        }, 300);
       } catch (e) {
         console.error("播放AI语音时发生错误:", e);
         this.isPlayingAiVoice = false;
@@ -1980,9 +2110,87 @@ const _sfc_main = {
           }
           this.aiAudioPlayer = null;
         }
-        this.navigateToNextPage();
+        common_vendor.index.showToast({
+          title: "音频播放失败,请查看文字回复",
+          icon: "none",
+          duration: 2e3
+        });
+        this.showContinueQuestionOptions();
+        this.checkPendingNavigation();
       }
     },
+    // 添加新方法:尝试备选音频播放方法
+    tryFallbackAudioPlay() {
+      console.log("使用备选方法播放音频:", this.aiVoiceUrl);
+      if (this.aiAudioPlayer) {
+        try {
+          this.aiAudioPlayer.destroy();
+        } catch (e) {
+          console.error("销毁音频播放器失败:", e);
+        }
+        this.aiAudioPlayer = null;
+      }
+      common_vendor.index.downloadFile({
+        url: this.aiVoiceUrl,
+        success: (res) => {
+          if (res.statusCode === 200) {
+            console.log("音频文件下载成功:", res.tempFilePath);
+            const newAudioPlayer = common_vendor.index.createInnerAudioContext();
+            this.aiAudioPlayer = newAudioPlayer;
+            newAudioPlayer.autoplay = true;
+            newAudioPlayer.src = res.tempFilePath;
+            newAudioPlayer.onPlay(() => {
+              console.log("备选方法:音频开始播放");
+            });
+            newAudioPlayer.onEnded(() => {
+              console.log("备选方法:音频播放结束");
+              this.isPlayingAiVoice = false;
+              this.currentSubtitle = "";
+              newAudioPlayer.destroy();
+              this.aiAudioPlayer = null;
+              this.showContinueQuestionOptions();
+              this.checkPendingNavigation();
+            });
+            newAudioPlayer.onError((err) => {
+              console.error("备选方法:音频播放错误:", err);
+              this.isPlayingAiVoice = false;
+              this.currentSubtitle = "";
+              newAudioPlayer.destroy();
+              this.aiAudioPlayer = null;
+              common_vendor.index.showToast({
+                title: "无法播放音频,请查看文字回复",
+                icon: "none",
+                duration: 2e3
+              });
+              this.showContinueQuestionOptions();
+              this.checkPendingNavigation();
+            });
+          } else {
+            console.error("音频文件下载失败:", res);
+            this.handleAudioPlaybackFailure();
+          }
+        },
+        fail: (err) => {
+          console.error("音频文件下载请求失败:", err);
+          this.handleAudioPlaybackFailure();
+        }
+      });
+    },
+    // 添加新方法:处理音频播放失败的情况
+    handleAudioPlaybackFailure() {
+      this.isPlayingAiVoice = false;
+      common_vendor.index.showToast({
+        title: "无法播放音频,将直接显示文字回复",
+        icon: "none",
+        duration: 2e3
+      });
+      this.currentSubtitle = this.aiText;
+      setTimeout(() => {
+        this.currentSubtitle = "";
+        this.showContinueQuestionOptions();
+        this.checkPendingNavigation();
+      }, 1e4);
+    },
     // 添加新方法:从视频中提取音频
     async extractAudioFromVideo(videoBlob) {
       console.log("开始从视频中提取音频");
@@ -2071,33 +2279,294 @@ const _sfc_main = {
     playMiniProgramAudio() {
       console.log("使用小程序原生音频API播放:", this.aiVoiceUrl);
       this.isPlayingAiVoice = true;
-      const audioContext = common_vendor.wx$1.createInnerAudioContext();
-      audioContext.src = this.aiVoiceUrl;
-      audioContext.onPlay(() => {
-        console.log("AI语音开始播放");
+      this.showContinueQuestionButton = false;
+      this.showEndInterviewButton = false;
+      if (!this.aiVoiceUrl || this.aiVoiceUrl.trim() === "") {
+        console.error("无效的音频URL");
         common_vendor.index.showToast({
-          title: "正在播放AI回复",
+          title: "音频加载失败",
           icon: "none",
           duration: 2e3
         });
-      });
-      audioContext.onEnded(() => {
-        console.log("AI语音播放结束");
         this.isPlayingAiVoice = false;
-        this.currentSubtitle = "";
-        audioContext.destroy();
-        this.navigateToNextPage();
-      });
-      audioContext.onError((err) => {
-        console.error("AI语音播放错误:", err);
+        this.showContinueQuestionOptions();
+        return;
+      }
+      try {
+        const audioContext = common_vendor.wx$1.createInnerAudioContext();
+        audioContext.autoplay = false;
+        audioContext.obeyMuteSwitch = false;
+        audioContext.onPlay(() => {
+          console.log("AI语音开始播放");
+          common_vendor.index.showToast({
+            title: "正在播放AI回复",
+            icon: "none",
+            duration: 2e3
+          });
+        });
+        audioContext.onEnded(() => {
+          console.log("AI语音播放结束");
+          this.isPlayingAiVoice = false;
+          this.currentSubtitle = "";
+          audioContext.destroy();
+          this.showContinueQuestionOptions();
+        });
+        audioContext.onError((err) => {
+          console.error("AI语音播放错误:", err);
+          this.isPlayingAiVoice = false;
+          this.currentSubtitle = "";
+          audioContext.destroy();
+          this.showContinueQuestionOptions();
+        });
+        audioContext.src = this.aiVoiceUrl;
+        const playTimeout = setTimeout(() => {
+          if (this.isPlayingAiVoice) {
+            console.warn("小程序音频播放超时,尝试备选方法");
+            this.tryMiniProgramFallbackAudioPlay();
+          }
+        }, 5e3);
+        setTimeout(() => {
+          audioContext.play();
+          clearTimeout(playTimeout);
+        }, 300);
+      } catch (e) {
+        console.error("小程序播放AI语音时发生错误:", e);
         this.isPlayingAiVoice = false;
-        this.currentSubtitle = "";
-        audioContext.destroy();
-        this.navigateToNextPage();
+        common_vendor.index.showToast({
+          title: "音频播放失败,请查看文字回复",
+          icon: "none",
+          duration: 2e3
+        });
+        this.handleAudioPlaybackFailure();
+      }
+    },
+    // 添加新方法:小程序环境的备选音频播放方法
+    tryMiniProgramFallbackAudioPlay() {
+      console.log("使用小程序备选方法播放音频:", this.aiVoiceUrl);
+      common_vendor.index.downloadFile({
+        url: this.aiVoiceUrl,
+        success: (res) => {
+          if (res.statusCode === 200) {
+            console.log("小程序音频文件下载成功:", res.tempFilePath);
+            const newAudioContext = common_vendor.wx$1.createInnerAudioContext();
+            newAudioContext.autoplay = true;
+            newAudioContext.src = res.tempFilePath;
+            newAudioContext.onPlay(() => {
+              console.log("小程序备选方法:音频开始播放");
+            });
+            newAudioContext.onEnded(() => {
+              console.log("小程序备选方法:音频播放结束");
+              this.isPlayingAiVoice = false;
+              this.currentSubtitle = "";
+              newAudioContext.destroy();
+              this.showContinueQuestionOptions();
+              this.checkPendingNavigation();
+            });
+            newAudioContext.onError((err) => {
+              console.error("小程序备选方法:音频播放错误:", err);
+              this.isPlayingAiVoice = false;
+              this.currentSubtitle = "";
+              newAudioContext.destroy();
+              this.trySystemAudioPlayer();
+            });
+          } else {
+            console.error("小程序音频文件下载失败:", res);
+            this.handleAudioPlaybackFailure();
+          }
+        },
+        fail: (err) => {
+          console.error("小程序音频文件下载请求失败:", err);
+          this.handleAudioPlaybackFailure();
+        }
+      });
+    },
+    // 添加新方法:尝试使用系统播放器
+    trySystemAudioPlayer() {
+      console.log("尝试使用系统播放器播放音频");
+      const systemInfo = common_vendor.index.getSystemInfoSync();
+      if (systemInfo.platform === "android" || systemInfo.platform === "ios") {
+        common_vendor.index.showToast({
+          title: "正在使用系统播放器",
+          icon: "none",
+          duration: 2e3
+        });
+        if (typeof common_vendor.index.playVoice === "function") {
+          common_vendor.index.playVoice({
+            filePath: this.aiVoiceUrl,
+            success: () => {
+              console.log("系统播放器播放成功");
+              setTimeout(() => {
+                this.isPlayingAiVoice = false;
+                this.currentSubtitle = "";
+                this.showContinueQuestionOptions();
+              }, 5e3);
+            },
+            fail: (err) => {
+              console.error("系统播放器播放失败:", err);
+              this.handleAudioPlaybackFailure();
+            }
+          });
+        } else {
+          common_vendor.index.openDocument({
+            filePath: this.aiVoiceUrl,
+            fileType: "audio",
+            success: () => {
+              console.log("使用系统应用打开音频文件");
+              setTimeout(() => {
+                this.isPlayingAiVoice = false;
+                this.currentSubtitle = "";
+                this.showContinueQuestionOptions();
+              }, 8e3);
+            },
+            fail: (err) => {
+              console.error("无法使用系统应用打开音频:", err);
+              this.handleAudioPlaybackFailure();
+            }
+          });
+        }
+      } else {
+        this.handleAudioPlaybackFailure();
+      }
+    },
+    // 修改 showContinueQuestionOptions 方法,确保状态正确设置
+    showContinueQuestionOptions() {
+      if (this.isPlayingAiVoice) {
+        console.log("AI语音正在播放,暂不显示继续提问选项");
+        return;
+      }
+      this.questionRound++;
+      this.currentSubtitle = "";
+      if (this.questionRound < this.maxQuestionRounds) {
+        this.showContinueQuestionButton = true;
+        this.showEndInterviewButton = true;
+        common_vendor.index.showToast({
+          title: `第${this.questionRound}轮提问完成`,
+          icon: "none",
+          duration: 2e3
+        });
+      } else {
+        this.showContinueQuestionButton = false;
+        this.showEndInterviewButton = false;
+        if (this.isPlayingAiVoice || this.isUploading) {
+          console.log("等待AI回复或上传完成后再跳转");
+          this.pendingAutoNavigation = true;
+        } else {
+          setTimeout(() => {
+            this.navigateToNextPage();
+          }, 3e3);
+        }
+      }
+      this.isRecording = false;
+      if (this.recordingTimer) {
+        clearInterval(this.recordingTimer);
+        this.recordingTimer = null;
+      }
+      this.recordedChunks = [];
+      this.recordingTimerCount = 0;
+      this.remainingTime = this.maxRecordingTime;
+    },
+    // 修复 handleContinueQuestionClick 方法,确保状态正确重置
+    handleContinueQuestionClick() {
+      if (this.isPlayingAiVoice) {
+        common_vendor.index.showToast({
+          title: "请等待面试官回复完成",
+          icon: "none",
+          duration: 2e3
+        });
+        return;
+      }
+      this.showContinueQuestionButton = false;
+      this.showEndInterviewButton = false;
+      this.isRecording = false;
+      this.recordingTimerCount = 0;
+      this.remainingTime = this.maxRecordingTime;
+      this.recordingTimeDisplay = "00:00 / " + this.formatTime(this.maxRecordingTime);
+      this.recordedChunks = [];
+      if (this.mediaRecorder && this.mediaRecorder.state === "recording") {
+        this.mediaRecorder.stop();
+      }
+      if (this.recorder) {
+        try {
+          this.cameraContext.stopRecord();
+        } catch (e) {
+          console.error("停止录制失败:", e);
+        }
+        this.recorder = null;
+      }
+      setTimeout(() => {
+        this.startRecordingAnswer();
+      }, 500);
+    },
+    // 添加新方法:处理结束面试按钮点击
+    handleEndInterviewClick() {
+      this.showContinueQuestionButton = false;
+      this.showEndInterviewButton = false;
+      this.navigateToNextPage();
+    },
+    // 添加新方法:处理录制错误
+    handleRecordingError(error) {
+      console.error("录制错误:", error);
+      common_vendor.index.showToast({
+        title: "录制失败,请重试",
+        icon: "none",
+        duration: 2e3
+      });
+      this.isRecording = false;
+      this.showStopRecordingButton = false;
+      this.showStartRecordingButton = true;
+    },
+    // 添加新方法:处理上传错误
+    handleUploadError(error) {
+      console.error("上传错误:", error);
+      common_vendor.index.showToast({
+        title: "上传失败,请重试",
+        icon: "none",
+        duration: 2e3
+      });
+      this.showRetryButton = true;
+      this.showUploadStatus = false;
+      this.isUploading = false;
+    },
+    // 添加新方法:检查是否有待处理的自动跳转
+    checkPendingNavigation() {
+      if (this.pendingAutoNavigation && !this.isPlayingAiVoice && !this.isUploading) {
+        console.log("所有处理已完成,执行自动跳转");
+        this.pendingAutoNavigation = false;
+        setTimeout(() => {
+          this.navigateToNextPage();
+        }, 2e3);
+      }
+    },
+    // 添加新方法:显示文本回复
+    displayTextResponse() {
+      this.isPlayingAiVoice = true;
+      this.currentSubtitle = this.aiText;
+      common_vendor.index.showToast({
+        title: "显示面试官文字回复",
+        icon: "none",
+        duration: 2e3
       });
+      const textLength = this.aiText.length;
+      const displayTime = Math.min(Math.max(textLength * 100, 5e3), 15e3);
       setTimeout(() => {
-        audioContext.play();
-      }, 100);
+        this.isPlayingAiVoice = false;
+        this.currentSubtitle = "";
+        this.showContinueQuestionOptions();
+        this.checkPendingNavigation();
+      }, displayTime);
+    },
+    // 添加新方法:检查不支持的音频格式
+    checkUnsupportedAudioFormat(url) {
+      if (!url)
+        return false;
+      const extension = url.split(".").pop().toLowerCase();
+      const systemInfo = common_vendor.index.getSystemInfoSync();
+      const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith("mp-");
+      if (isMiniProgram) {
+        const unsupportedFormats = ["ogg", "flac", "aac", "m4a", "opus"];
+        return unsupportedFormats.includes(extension);
+      }
+      return false;
     }
   }
 };
@@ -2166,7 +2635,11 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
     B: common_vendor.t($data.countdownValue)
   } : {}, {
     C: $data.isPlayingAiVoice
-  }, $data.isPlayingAiVoice ? {} : {});
+  }, $data.isPlayingAiVoice ? {} : {}, {
+    D: $data.showContinueQuestionButton
+  }, $data.showContinueQuestionButton ? {
+    E: common_vendor.o((...args) => $options.handleContinueQuestionClick && $options.handleContinueQuestionClick(...args))
+  } : {});
 }
 const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-2a02c54e"]]);
 wx.createPage(MiniProgramPage);

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
unpackage/dist/dev/mp-weixin/pages/interview-question/interview-question.wxml


+ 62 - 0
unpackage/dist/dev/mp-weixin/pages/interview-question/interview-question.wxss

@@ -420,3 +420,65 @@ video.data-v-2a02c54e::-webkit-media-controls-fullscreen-button {
     opacity: 1;
 }
 }
+
+/* 继续提问按钮样式 */
+.continue-question-container.data-v-2a02c54e {
+  position: absolute;
+  bottom: 100px; /* 位置高于结束面试按钮 */
+  left: 50%;
+  transform: translateX(-50%);
+  z-index: 20;
+}
+.continue-question-button.data-v-2a02c54e {
+  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;
+}
+
+/* 结束面试按钮样式 */
+.end-interview-container.data-v-2a02c54e {
+  position: absolute;
+  bottom: 50px;
+  left: 50%;
+  transform: translateX(-50%);
+  z-index: 20;
+}
+.end-interview-button.data-v-2a02c54e {
+  width: 120px;
+  height: 40px;
+  border-radius: 20px;
+  background-color: #e74c3c; /* 红色背景 */
+  color: #ffffff; /* 白色文字 */
+  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;
+}
+
+/* 提问轮次指示器样式 */
+.question-round-indicator.data-v-2a02c54e {
+  position: absolute;
+  top: 20px;
+  right: 120px; /* 位置在用户摄像头左侧 */
+  background-color: rgba(255, 255, 255, 0.9);
+  padding: 5px 10px;
+  border-radius: 15px;
+  z-index: 20;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+}
+.round-text.data-v-2a02c54e {
+  color: #333;
+  font-size: 14px;
+}

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

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

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels