yangg 1 сар өмнө
parent
commit
ccbcc91c2e

+ 8 - 5
pages/Personal/Personal.vue

@@ -1221,7 +1221,7 @@ import { apiBaseUrl } from '@/common/config.js';
 					},
 					
 					// 教育经历映射
-					education: this.educationList.map((edu, index) => ({
+					educations: this.educationList.map((edu, index) => ({
 						education_type: index === 0 ? 1 : 2, // 第一个为第一学历,第二个为最高学历
 						degree: this.mapDegreeToNumber(edu.degree),
 						start_date: edu.startTime,
@@ -1561,6 +1561,9 @@ import { apiBaseUrl } from '@/common/config.js';
 					url: `${apiBaseUrl}/api/wechat/user/get_full_info?tenant_id=1&openid=${openid}`,
 					method: 'GET',
 					success: (res) => {
+						// 无论结果如何,都保持承诺书显示状态
+						this.showPromiseModal = true;
+						
 						/* if (res.data.code === 2000) { */
 							// Successfully fetched data
 							this.populateFormData(res.data.data);
@@ -1721,10 +1724,10 @@ import { apiBaseUrl } from '@/common/config.js';
 					});
 				}
 				
-				// If user profile is complete, we can skip the promise modal
-				if (user_info && user_info.is_profile_complete) {
-					this.showPromiseModal = false;
-				}
+				// 移除这段代码,确保承诺书始终显示
+				// if (user_info && user_info.is_profile_complete) {
+				//     this.showPromiseModal = false;
+				// }
 			},
 		},
 		// 添加监听器来清除错误信息

+ 17 - 0
pages/camera/camera.vue

@@ -155,6 +155,8 @@
 				showContinueButton: false, // 是否显示继续按钮
 				scrollToBottom: false, // 新增:是否需要滚动到底部
 				scrollTop: 0, // 控制 scroll-view 的滚动位置
+				_clickTimer: null,
+				_isClicking: false,
 			}
 		},
 		computed: {
@@ -756,8 +758,23 @@
 					return;
 				}
 				
+				// 使用更简单的防重复点击逻辑
+				// 检查是否在提交中
+				if (this.isSubmitting) {
+					console.log('正在提交答案,请稍候...');
+					return;
+				}
+				
+				// 设置临时标记防止重复点击
+				this.isSubmitting = true;
+				
 				// 如果是当前题目,调用原有的选择逻辑
 				this.selectOption(index);
+				
+				// 短暂延迟后重置状态,允许下一次点击
+				setTimeout(() => {
+					this.isSubmitting = false;
+				}, 500);
 			},
 
 			// 处理题目分组

+ 311 - 40
pages/interview-question/interview-question.vue

@@ -315,9 +315,29 @@ export default {
     
     // 销毁AI音频播放器
     if (this.aiAudioPlayer) {
-      this.aiAudioPlayer.destroy();
+      try {
+        this.aiAudioPlayer.destroy();
+      } catch (e) {
+        console.error('销毁音频播放器失败:', e);
+      }
       this.aiAudioPlayer = null;
     }
+    
+    // 清除所有计时器
+    if (this.recordingTimer) {
+      clearInterval(this.recordingTimer);
+      this.recordingTimer = null;
+    }
+    
+    if (this.countdownTimer) {
+      clearInterval(this.countdownTimer);
+      this.countdownTimer = null;
+    }
+    
+    if (this.mediaRecorderTimeout) {
+      clearTimeout(this.mediaRecorderTimeout);
+      this.mediaRecorderTimeout = null;
+    }
   },
   methods: {
     // 初始化相机
@@ -1615,6 +1635,7 @@ export default {
         questionId: questionId,
         attempts: 0, // 上传尝试次数
         maxAttempts: 3, // 最大尝试次数
+        hasAudio: true, // 明确标记包含音频
       };
       
       // 添加到上传队列
@@ -1726,8 +1747,8 @@ export default {
       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');
+      formData.append('video_duration', this.recordingTimerCount || 0);
+      formData.append('has_audio', 'true'); // 明确标记包含音频
       
       // 创建XMLHttpRequest
       const xhr = new XMLHttpRequest();
@@ -1804,8 +1825,8 @@ export default {
           tenant_id: tenant_id,
           application_id: uni.getStorageSync('appId'),
           question_id: task.questionId,
-          video_duration: 0,
-          has_audio: 'true'
+          video_duration: this.recordingTimerCount || 0,
+          has_audio: 'true' // 明确标记包含音频
         },
         success: (uploadRes) => {
           try {
@@ -1919,11 +1940,12 @@ export default {
         application_id: uni.getStorageSync('appId'),
         question_id: questionId,
         video_url: videoUrl,
-        tenant_id: uni.getStorageSync('tenant_id') || '1'
+        tenant_id: uni.getStorageSync('tenant_id') || '1',
+        has_audio: true // 明确标记包含音频
       };
       
       // 首先提交到面试接口
-      uni.request({
+     /*  uni.request({
         url: `${apiBaseUrl}/api/job/upload_video`,
         method: 'POST',
         data: requestData,
@@ -1957,7 +1979,7 @@ export default {
             }
             
             // 提交到AI语音交互接口
-            this.submitToAiVoiceInteraction(videoUrl);
+            
           } else {
             // 提交失败
             if (task) {
@@ -1997,7 +2019,8 @@ export default {
             this.showRetryButton = true;
           }
         }
-      });
+      }); */
+      this.submitToAiVoiceInteraction(videoUrl);
     },
     
     // 添加新方法:处理提交失败
@@ -2082,7 +2105,7 @@ export default {
       }
       
       // 不再等待上传队列完成,直接跳转
-      this.navigateToNextPage();
+      // this.navigateToNextPage();
       
       // 如果有未完成的上传任务,在后台继续处理
       if (this.uploadQueue.length > 0) {
@@ -2639,13 +2662,13 @@ export default {
       }
     },
 
-    // 修改 submitToAiVoiceInteraction 方法,使用 FormData 提交
+    // 增强 submitToAiVoiceInteraction 方法
     submitToAiVoiceInteraction(videoUrl) {
       console.log('提交视频到AI语音交互接口:', videoUrl);
       
       // 显示加载提示
       uni.showLoading({
-        title: 'AI正在思考...',
+        title: '面试官正在思考...',
         mask: true
       });
       
@@ -2658,19 +2681,25 @@ export default {
       const systemInfo = uni.getSystemInfoSync();
       const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith('mp-');
       
+      // 准备请求数据
+      const requestData = {
+        url: videoUrl,
+        tenant_id: tenant_id,
+      /*   openid: openid,
+        application_id: uni.getStorageSync('appId') || '',
+        has_audio: true, // 明确标记包含音频
+        audio_format: 'mp4', // 指定音频格式
+        duration: this.recordingTimerCount || 0 // 添加录制时长 */
+      };
+      
       if (isMiniProgram) {
         // 小程序环境使用 uni.request
         uni.request({
           url: `${apiBaseUrl}/api/voice_ai_interaction`,
           method: 'POST',
-          data: {
-            url: videoUrl,
-            tenant_id: tenant_id,
-            openid: openid,
-            application_id: uni.getStorageSync('appId') || ''
-          },
+          data: requestData,
           header: {
-            'content-type': 'application/json'
+            'content-type': 'application/x-www-form-urlencoded'
           },
           success: (res) => {
             this.handleAiInteractionResponse(res.data);
@@ -2682,10 +2711,9 @@ export default {
       } else {
         // H5/App环境使用 FormData 和 XMLHttpRequest
         const formData = new FormData();
-        formData.append('url', videoUrl);
-        formData.append('tenant_id', tenant_id);
-        formData.append('openid', openid);
-        formData.append('application_id', uni.getStorageSync('appId') || '');
+        for (const key in requestData) {
+          formData.append(key, requestData[key]);
+        }
         
         const xhr = new XMLHttpRequest();
         xhr.open('POST', `${apiBaseUrl}/api/voice_ai_interaction`, true);
@@ -2742,8 +2770,18 @@ export default {
           // 显示AI回复文本作为字幕
           this.currentSubtitle = this.aiText;
           
-          // 播放AI语音
-          this.playAiVoice();
+          // 检查平台
+          const systemInfo = uni.getSystemInfoSync();
+          const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith('mp-');
+          
+          // 根据平台选择不同的播放方法
+          if (isMiniProgram) {
+            // 小程序环境使用原生API
+            this.playMiniProgramAudio();
+          } else {
+            // H5/App环境使用通用方法
+            this.playAiVoice();
+          }
         } else {
           console.warn('未获取到AI语音URL');
           // 如果没有语音URL,直接跳转
@@ -2779,13 +2817,247 @@ export default {
       // 标记正在播放AI语音
       this.isPlayingAiVoice = true;
       
-      // 创建音频播放器
-      this.aiAudioPlayer = uni.createInnerAudioContext();
-      this.aiAudioPlayer.src = this.aiVoiceUrl;
-      this.aiAudioPlayer.autoplay = true;
+      // 检查平台
+      const systemInfo = uni.getSystemInfoSync();
+      const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith('mp-');
+      
+      try {
+        // 创建音频播放器 - 使用 uni.createInnerAudioContext 而不是直接赋值
+        if (this.aiAudioPlayer) {
+          // 如果已存在,先销毁
+          this.aiAudioPlayer.destroy();
+        }
+        
+        // 重新创建音频上下文
+        this.aiAudioPlayer = uni.createInnerAudioContext();
+        
+        // 监听播放开始事件
+        this.aiAudioPlayer.onPlay(() => {
+          console.log('AI语音开始播放');
+          
+          // 显示正在播放提示
+          uni.showToast({
+            title: '正在播放面试官的回复',
+            icon: 'none',
+            duration: 2000
+          });
+        });
+        
+        // 监听播放结束事件
+        this.aiAudioPlayer.onEnded(() => {
+          console.log('AI语音播放结束');
+          
+          // 标记播放结束
+          this.isPlayingAiVoice = false;
+          
+          // 清空字幕
+          this.currentSubtitle = '';
+          
+          // 销毁音频播放器
+          if (this.aiAudioPlayer) {
+            this.aiAudioPlayer.destroy();
+            this.aiAudioPlayer = null;
+          }
+          
+          // 播放结束后跳转到下一页
+          this.navigateToNextPage();
+        });
+        
+        // 监听播放错误事件
+        this.aiAudioPlayer.onError((err) => {
+          console.error('AI语音播放错误:', err);
+          
+          // 标记播放结束
+          this.isPlayingAiVoice = false;
+          
+          // 清空字幕
+          this.currentSubtitle = '';
+          
+          // 销毁音频播放器
+          if (this.aiAudioPlayer) {
+            this.aiAudioPlayer.destroy();
+            this.aiAudioPlayer = null;
+          }
+          
+          // 播放错误时也跳转到下一页
+          this.navigateToNextPage();
+        });
+        
+        // 在小程序环境中,先设置src,然后再调用play()
+        if (isMiniProgram) {
+          // 确保URL是有效的
+          if (!this.aiVoiceUrl) {
+            throw new Error('无效的音频URL');
+          }
+          
+          // 设置音频源 - 在小程序中直接设置字符串,不要使用Promise
+          this.aiAudioPlayer.src = this.aiVoiceUrl;
+          
+          // 延迟一小段时间再播放,确保src已经设置完成
+          setTimeout(() => {
+            this.aiAudioPlayer.play();
+          }, 100);
+        } else {
+          // 在H5/App环境中可以直接设置src并播放
+          this.aiAudioPlayer.src = this.aiVoiceUrl;
+          this.aiAudioPlayer.play();
+        }
+      } catch (e) {
+        console.error('播放AI语音时发生错误:', e);
+        
+        // 标记播放结束
+        this.isPlayingAiVoice = false;
+        
+        // 清空字幕
+        this.currentSubtitle = '';
+        
+        // 尝试销毁音频播放器
+        if (this.aiAudioPlayer) {
+          try {
+            this.aiAudioPlayer.destroy();
+          } catch (destroyError) {
+            console.error('销毁音频播放器失败:', destroyError);
+          }
+          this.aiAudioPlayer = null;
+        }
+        
+        // 发生错误时跳转到下一页
+        this.navigateToNextPage();
+      }
+    },
+
+    // 添加新方法:从视频中提取音频
+    async extractAudioFromVideo(videoBlob) {
+      console.log('开始从视频中提取音频');
+      
+      return new Promise((resolve, reject) => {
+        try {
+          // 创建一个视频元素来加载视频
+          const videoElement = document.createElement('video');
+          videoElement.muted = false;
+          videoElement.autoplay = false;
+          
+          // 创建音频上下文
+          const audioContext = new (window.AudioContext || window.webkitAudioContext)();
+          let audioDestination = null;
+          let mediaRecorder = null;
+          const audioChunks = [];
+          
+          // 设置视频源
+          videoElement.src = URL.createObjectURL(videoBlob);
+          
+          videoElement.onloadedmetadata = () => {
+            console.log('视频元数据已加载,视频时长:', videoElement.duration);
+            
+            // 创建媒体源和目标节点
+            const source = audioContext.createMediaElementSource(videoElement);
+            audioDestination = audioContext.createMediaStreamDestination();
+            source.connect(audioDestination);
+            
+            // 创建MediaRecorder来录制音频
+            mediaRecorder = new MediaRecorder(audioDestination.stream);
+            
+            mediaRecorder.ondataavailable = (event) => {
+              if (event.data.size > 0) {
+                audioChunks.push(event.data);
+              }
+            };
+            
+            mediaRecorder.onstop = () => {
+              const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
+              console.log('音频提取完成,大小:', audioBlob.size);
+              resolve(audioBlob);
+            };
+            
+            // 开始播放视频并录制音频
+            videoElement.onplay = () => {
+              mediaRecorder.start(100);
+            };
+            
+            videoElement.onended = () => {
+              mediaRecorder.stop();
+              audioContext.close();
+            };
+            
+            // 开始播放
+            videoElement.play();
+          };
+          
+          videoElement.onerror = (err) => {
+            console.error('视频加载失败:', err);
+            reject(new Error('视频加载失败'));
+          };
+        } catch (err) {
+          console.error('提取音频失败:', err);
+          reject(err);
+        }
+      });
+    },
+
+    // 添加新方法:上传音频文件
+    async uploadAudioFile(audioBlob, videoUrl) {
+      console.log('准备上传音频文件');
+      
+      // 创建FormData
+      const formData = new FormData();
+      
+      // 将Blob转换为File对象
+      const fileName = `audio_${Date.now()}.wav`;
+      const audioFile = new File([audioBlob], fileName, { type: 'audio/wav' });
+      
+      // 添加文件和其他参数
+      formData.append('audio_file', audioFile);
+      formData.append('video_url', videoUrl);
+      formData.append('tenant_id', uni.getStorageSync('tenant_id') || '1');
+      formData.append('openid', uni.getStorageSync('userInfo') ? JSON.parse(uni.getStorageSync('userInfo')).openid : '');
+      formData.append('application_id', uni.getStorageSync('appId') || '');
+      
+      return new Promise((resolve, reject) => {
+        // 创建XMLHttpRequest
+        const xhr = new XMLHttpRequest();
+        xhr.open('POST', `${apiBaseUrl}/api/voice_ai_interaction`, true);
+        xhr.timeout = 60000; // 60秒超时
+        
+        xhr.onload = () => {
+          if (xhr.status === 200) {
+            try {
+              const response = JSON.parse(xhr.responseText);
+              resolve(response);
+            } catch (e) {
+              reject(new Error('解析响应失败'));
+            }
+          } else {
+            reject(new Error('HTTP状态: ' + xhr.status));
+          }
+        };
+        
+        xhr.onerror = () => {
+          reject(new Error('网络错误'));
+        };
+        
+        xhr.ontimeout = () => {
+          reject(new Error('请求超时'));
+        };
+        
+        xhr.send(formData);
+      });
+    },
+
+    // 添加一个新方法:使用小程序原生音频API
+    playMiniProgramAudio() {
+      console.log('使用小程序原生音频API播放:', this.aiVoiceUrl);
+      
+      // 标记正在播放AI语音
+      this.isPlayingAiVoice = true;
+      
+      // 使用wx.createAudioContext API (微信小程序)
+      const audioContext = wx.createInnerAudioContext();
+      
+      // 设置音频源
+      audioContext.src = this.aiVoiceUrl;
       
       // 监听播放开始事件
-      this.aiAudioPlayer.onPlay(() => {
+      audioContext.onPlay(() => {
         console.log('AI语音开始播放');
         
         // 显示正在播放提示
@@ -2797,7 +3069,7 @@ export default {
       });
       
       // 监听播放结束事件
-      this.aiAudioPlayer.onEnded(() => {
+      audioContext.onEnded(() => {
         console.log('AI语音播放结束');
         
         // 标记播放结束
@@ -2807,17 +3079,14 @@ export default {
         this.currentSubtitle = '';
         
         // 销毁音频播放器
-        if (this.aiAudioPlayer) {
-          this.aiAudioPlayer.destroy();
-          this.aiAudioPlayer = null;
-        }
+        audioContext.destroy();
         
         // 播放结束后跳转到下一页
         this.navigateToNextPage();
       });
       
       // 监听播放错误事件
-      this.aiAudioPlayer.onError((err) => {
+      audioContext.onError((err) => {
         console.error('AI语音播放错误:', err);
         
         // 标记播放结束
@@ -2827,14 +3096,16 @@ export default {
         this.currentSubtitle = '';
         
         // 销毁音频播放器
-        if (this.aiAudioPlayer) {
-          this.aiAudioPlayer.destroy();
-          this.aiAudioPlayer = null;
-        }
+        audioContext.destroy();
         
         // 播放错误时也跳转到下一页
         this.navigateToNextPage();
       });
+      
+      // 开始播放
+      setTimeout(() => {
+        audioContext.play();
+      }, 100);
     },
   }
 }

+ 2 - 4
unpackage/dist/dev/mp-weixin/pages/Personal/Personal.js

@@ -568,7 +568,7 @@ const _sfc_main = {
           recruitment_source_detail: this.formData.sourceType === "social" ? this.formData.socialSource === "other" ? this.formData.otherSocialSource : this.formData.socialSource === "BOSS" ? "BOSS直聘" : this.formData.socialSource === "zhilian" ? "智联招聘" : this.formData.socialSource === "liepin" ? "猎聘" : "" : this.formData.otherSchoolSource
         },
         // 教育经历映射
-        education: this.educationList.map((edu, index) => ({
+        educations: this.educationList.map((edu, index) => ({
           education_type: index === 0 ? 1 : 2,
           // 第一个为第一学历,第二个为最高学历
           degree: this.mapDegreeToNumber(edu.degree),
@@ -849,6 +849,7 @@ const _sfc_main = {
         url: `${common_config.apiBaseUrl}/api/wechat/user/get_full_info?tenant_id=1&openid=${openid}`,
         method: "GET",
         success: (res) => {
+          this.showPromiseModal = true;
           this.populateFormData(res.data.data);
         },
         fail: (err) => {
@@ -958,9 +959,6 @@ const _sfc_main = {
           };
         });
       }
-      if (user_info && user_info.is_profile_complete) {
-        this.showPromiseModal = false;
-      }
     }
   },
   // 添加监听器来清除错误信息

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

@@ -60,8 +60,10 @@ const _sfc_main = {
       // 是否显示继续按钮
       scrollToBottom: false,
       // 新增:是否需要滚动到底部
-      scrollTop: 0
+      scrollTop: 0,
       // 控制 scroll-view 的滚动位置
+      _clickTimer: null,
+      _isClicking: false
     };
   },
   computed: {
@@ -492,7 +494,15 @@ const _sfc_main = {
         this.currentScrollId = "question-" + firstUnansweredIndex;
         return;
       }
+      if (this.isSubmitting) {
+        console.log("正在提交答案,请稍候...");
+        return;
+      }
+      this.isSubmitting = true;
       this.selectOption(index);
+      setTimeout(() => {
+        this.isSubmitting = false;
+      }, 500);
     },
     // 处理题目分组
     processQuestionGroups(questions) {

+ 212 - 87
unpackage/dist/dev/mp-weixin/pages/interview-question/interview-question.js

@@ -168,9 +168,25 @@ const _sfc_main = {
   beforeDestroy() {
     this.stopUserCamera();
     if (this.aiAudioPlayer) {
-      this.aiAudioPlayer.destroy();
+      try {
+        this.aiAudioPlayer.destroy();
+      } catch (e) {
+        console.error("销毁音频播放器失败:", e);
+      }
       this.aiAudioPlayer = null;
     }
+    if (this.recordingTimer) {
+      clearInterval(this.recordingTimer);
+      this.recordingTimer = null;
+    }
+    if (this.countdownTimer) {
+      clearInterval(this.countdownTimer);
+      this.countdownTimer = null;
+    }
+    if (this.mediaRecorderTimeout) {
+      clearTimeout(this.mediaRecorderTimeout);
+      this.mediaRecorderTimeout = null;
+    }
   },
   methods: {
     // 初始化相机
@@ -1103,8 +1119,10 @@ const _sfc_main = {
         questionId,
         attempts: 0,
         // 上传尝试次数
-        maxAttempts: 3
+        maxAttempts: 3,
         // 最大尝试次数
+        hasAudio: true
+        // 明确标记包含音频
       };
       this.uploadQueue.push(uploadTask);
       this.uploadProgress[uploadTask.id] = 0;
@@ -1174,7 +1192,7 @@ const _sfc_main = {
       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("video_duration", this.recordingTimerCount || 0);
       formData.append("has_audio", "true");
       const xhr = new XMLHttpRequest();
       xhr.open("POST", `${common_config.apiBaseUrl}/api/upload/`, true);
@@ -1232,8 +1250,9 @@ const _sfc_main = {
           tenant_id,
           application_id: common_vendor.index.getStorageSync("appId"),
           question_id: task.questionId,
-          video_duration: 0,
+          video_duration: this.recordingTimerCount || 0,
           has_audio: "true"
+          // 明确标记包含音频
         },
         success: (uploadRes) => {
           try {
@@ -1314,63 +1333,15 @@ const _sfc_main = {
             questionId = 10;
         }
       }
-      const requestData = {
+      ({
         application_id: common_vendor.index.getStorageSync("appId"),
         question_id: questionId,
         video_url: videoUrl,
-        tenant_id: common_vendor.index.getStorageSync("tenant_id") || "1"
-      };
-      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;
-            }
-            this.submitToAiVoiceInteraction(videoUrl);
-          } 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;
-          }
-        }
+        tenant_id: common_vendor.index.getStorageSync("tenant_id") || "1",
+        has_audio: true
+        // 明确标记包含音频
       });
+      this.submitToAiVoiceInteraction(videoUrl);
     },
     // 添加新方法:处理提交失败
     handleSubmitFailure(task, errorMsg) {
@@ -1429,7 +1400,6 @@ const _sfc_main = {
         console.log("AI语音正在播放,等待播放完成后再跳转");
         return;
       }
-      this.navigateToNextPage();
       if (this.uploadQueue.length > 0) {
         console.log("上传队列将在后台继续处理...");
         this.saveUploadStatus();
@@ -1842,30 +1812,34 @@ const _sfc_main = {
         console.error("保存上传状态失败:", e);
       }
     },
-    // 修改 submitToAiVoiceInteraction 方法,使用 FormData 提交
+    // 增强 submitToAiVoiceInteraction 方法
     submitToAiVoiceInteraction(videoUrl) {
       console.log("提交视频到AI语音交互接口:", videoUrl);
       common_vendor.index.showLoading({
-        title: "AI正在思考...",
+        title: "面试官正在思考...",
         mask: true
       });
       const tenant_id = common_vendor.index.getStorageSync("tenant_id") || "1";
       const userInfo = common_vendor.index.getStorageSync("userInfo");
-      const openid = userInfo ? JSON.parse(userInfo).openid || "" : "";
+      userInfo ? JSON.parse(userInfo).openid || "" : "";
       const systemInfo = common_vendor.index.getSystemInfoSync();
       const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith("mp-");
+      const requestData = {
+        url: videoUrl,
+        tenant_id
+        /*   openid: openid,
+          application_id: uni.getStorageSync('appId') || '',
+          has_audio: true, // 明确标记包含音频
+          audio_format: 'mp4', // 指定音频格式
+          duration: this.recordingTimerCount || 0 // 添加录制时长 */
+      };
       if (isMiniProgram) {
         common_vendor.index.request({
           url: `${common_config.apiBaseUrl}/api/voice_ai_interaction`,
           method: "POST",
-          data: {
-            url: videoUrl,
-            tenant_id,
-            openid,
-            application_id: common_vendor.index.getStorageSync("appId") || ""
-          },
+          data: requestData,
           header: {
-            "content-type": "application/json"
+            "content-type": "application/x-www-form-urlencoded"
           },
           success: (res) => {
             this.handleAiInteractionResponse(res.data);
@@ -1876,10 +1850,9 @@ const _sfc_main = {
         });
       } else {
         const formData = new FormData();
-        formData.append("url", videoUrl);
-        formData.append("tenant_id", tenant_id);
-        formData.append("openid", openid);
-        formData.append("application_id", common_vendor.index.getStorageSync("appId") || "");
+        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.timeout = 6e4;
@@ -1917,7 +1890,13 @@ const _sfc_main = {
           this.aiVoiceUrl = aiVoiceUrl.startsWith("http") ? aiVoiceUrl : `${common_config.apiBaseUrl}${aiVoiceUrl}`;
           console.log("AI语音URL:", this.aiVoiceUrl);
           this.currentSubtitle = this.aiText;
-          this.playAiVoice();
+          const systemInfo = common_vendor.index.getSystemInfoSync();
+          const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith("mp-");
+          if (isMiniProgram) {
+            this.playMiniProgramAudio();
+          } else {
+            this.playAiVoice();
+          }
         } else {
           console.warn("未获取到AI语音URL");
           this.navigateToNextPage();
@@ -1942,10 +1921,159 @@ const _sfc_main = {
     playAiVoice() {
       console.log("开始播放AI语音:", this.aiVoiceUrl);
       this.isPlayingAiVoice = true;
-      this.aiAudioPlayer = common_vendor.index.createInnerAudioContext();
-      this.aiAudioPlayer.src = this.aiVoiceUrl;
-      this.aiAudioPlayer.autoplay = true;
-      this.aiAudioPlayer.onPlay(() => {
+      const systemInfo = common_vendor.index.getSystemInfoSync();
+      const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith("mp-");
+      try {
+        if (this.aiAudioPlayer) {
+          this.aiAudioPlayer.destroy();
+        }
+        this.aiAudioPlayer = common_vendor.index.createInnerAudioContext();
+        this.aiAudioPlayer.onPlay(() => {
+          console.log("AI语音开始播放");
+          common_vendor.index.showToast({
+            title: "正在播放面试官的回复",
+            icon: "none",
+            duration: 2e3
+          });
+        });
+        this.aiAudioPlayer.onEnded(() => {
+          console.log("AI语音播放结束");
+          this.isPlayingAiVoice = false;
+          this.currentSubtitle = "";
+          if (this.aiAudioPlayer) {
+            this.aiAudioPlayer.destroy();
+            this.aiAudioPlayer = null;
+          }
+          this.navigateToNextPage();
+        });
+        this.aiAudioPlayer.onError((err) => {
+          console.error("AI语音播放错误:", err);
+          this.isPlayingAiVoice = false;
+          this.currentSubtitle = "";
+          if (this.aiAudioPlayer) {
+            this.aiAudioPlayer.destroy();
+            this.aiAudioPlayer = null;
+          }
+          this.navigateToNextPage();
+        });
+        if (isMiniProgram) {
+          if (!this.aiVoiceUrl) {
+            throw new Error("无效的音频URL");
+          }
+          this.aiAudioPlayer.src = this.aiVoiceUrl;
+          setTimeout(() => {
+            this.aiAudioPlayer.play();
+          }, 100);
+        } else {
+          this.aiAudioPlayer.src = this.aiVoiceUrl;
+          this.aiAudioPlayer.play();
+        }
+      } catch (e) {
+        console.error("播放AI语音时发生错误:", e);
+        this.isPlayingAiVoice = false;
+        this.currentSubtitle = "";
+        if (this.aiAudioPlayer) {
+          try {
+            this.aiAudioPlayer.destroy();
+          } catch (destroyError) {
+            console.error("销毁音频播放器失败:", destroyError);
+          }
+          this.aiAudioPlayer = null;
+        }
+        this.navigateToNextPage();
+      }
+    },
+    // 添加新方法:从视频中提取音频
+    async extractAudioFromVideo(videoBlob) {
+      console.log("开始从视频中提取音频");
+      return new Promise((resolve, reject) => {
+        try {
+          const videoElement = document.createElement("video");
+          videoElement.muted = false;
+          videoElement.autoplay = false;
+          const audioContext = new (window.AudioContext || window.webkitAudioContext)();
+          let audioDestination = null;
+          let mediaRecorder = null;
+          const audioChunks = [];
+          videoElement.src = URL.createObjectURL(videoBlob);
+          videoElement.onloadedmetadata = () => {
+            console.log("视频元数据已加载,视频时长:", videoElement.duration);
+            const source = audioContext.createMediaElementSource(videoElement);
+            audioDestination = audioContext.createMediaStreamDestination();
+            source.connect(audioDestination);
+            mediaRecorder = new MediaRecorder(audioDestination.stream);
+            mediaRecorder.ondataavailable = (event) => {
+              if (event.data.size > 0) {
+                audioChunks.push(event.data);
+              }
+            };
+            mediaRecorder.onstop = () => {
+              const audioBlob = new Blob(audioChunks, { type: "audio/wav" });
+              console.log("音频提取完成,大小:", audioBlob.size);
+              resolve(audioBlob);
+            };
+            videoElement.onplay = () => {
+              mediaRecorder.start(100);
+            };
+            videoElement.onended = () => {
+              mediaRecorder.stop();
+              audioContext.close();
+            };
+            videoElement.play();
+          };
+          videoElement.onerror = (err) => {
+            console.error("视频加载失败:", err);
+            reject(new Error("视频加载失败"));
+          };
+        } catch (err) {
+          console.error("提取音频失败:", err);
+          reject(err);
+        }
+      });
+    },
+    // 添加新方法:上传音频文件
+    async uploadAudioFile(audioBlob, videoUrl) {
+      console.log("准备上传音频文件");
+      const formData = new FormData();
+      const fileName = `audio_${Date.now()}.wav`;
+      const audioFile = new File([audioBlob], fileName, { type: "audio/wav" });
+      formData.append("audio_file", audioFile);
+      formData.append("video_url", videoUrl);
+      formData.append("tenant_id", common_vendor.index.getStorageSync("tenant_id") || "1");
+      formData.append("openid", common_vendor.index.getStorageSync("userInfo") ? JSON.parse(common_vendor.index.getStorageSync("userInfo")).openid : "");
+      formData.append("application_id", common_vendor.index.getStorageSync("appId") || "");
+      return new Promise((resolve, reject) => {
+        const xhr = new XMLHttpRequest();
+        xhr.open("POST", `${common_config.apiBaseUrl}/api/voice_ai_interaction`, true);
+        xhr.timeout = 6e4;
+        xhr.onload = () => {
+          if (xhr.status === 200) {
+            try {
+              const response = JSON.parse(xhr.responseText);
+              resolve(response);
+            } catch (e) {
+              reject(new Error("解析响应失败"));
+            }
+          } else {
+            reject(new Error("HTTP状态: " + xhr.status));
+          }
+        };
+        xhr.onerror = () => {
+          reject(new Error("网络错误"));
+        };
+        xhr.ontimeout = () => {
+          reject(new Error("请求超时"));
+        };
+        xhr.send(formData);
+      });
+    },
+    // 添加一个新方法:使用小程序原生音频API
+    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语音开始播放");
         common_vendor.index.showToast({
           title: "正在播放AI回复",
@@ -1953,26 +2081,23 @@ const _sfc_main = {
           duration: 2e3
         });
       });
-      this.aiAudioPlayer.onEnded(() => {
+      audioContext.onEnded(() => {
         console.log("AI语音播放结束");
         this.isPlayingAiVoice = false;
         this.currentSubtitle = "";
-        if (this.aiAudioPlayer) {
-          this.aiAudioPlayer.destroy();
-          this.aiAudioPlayer = null;
-        }
+        audioContext.destroy();
         this.navigateToNextPage();
       });
-      this.aiAudioPlayer.onError((err) => {
+      audioContext.onError((err) => {
         console.error("AI语音播放错误:", err);
         this.isPlayingAiVoice = false;
         this.currentSubtitle = "";
-        if (this.aiAudioPlayer) {
-          this.aiAudioPlayer.destroy();
-          this.aiAudioPlayer = null;
-        }
+        audioContext.destroy();
         this.navigateToNextPage();
       });
+      setTimeout(() => {
+        audioContext.play();
+      }, 100);
     }
   }
 };