Quellcode durchsuchen

修改卡顿及跳转延时

yangg vor 2 Wochen
Ursprung
Commit
a95b172162

+ 21 - 3
pages/Personal/Personal.vue

@@ -258,7 +258,8 @@
 					
 					<view class="form-row">
 						<view class="form-item" v-if="showFamilyPhoneField">
-							<text class="label required">联系电话</text>
+							<!-- required -->
+							<text class="label">联系电话</text>
 							<input 
 								type="number" 
 								v-model="familyMemberForm.phone" 
@@ -1889,11 +1890,9 @@ import { apiBaseUrl } from '@/common/config.js';
 									icon: 'success',
 									duration: 2000
 								});
-								setTimeout(() => {
 									uni.navigateTo({ 
 										url: '/pages/interview-notice/interview-notice'
 									});
-								}, 2000);
 							} else {
 								uni.showToast({
 									title: res.data.msg || '提交失败',
@@ -2835,6 +2834,25 @@ import { apiBaseUrl } from '@/common/config.js';
 					this.workErrors.employeeCount = '请输入单位人数';
 					isValid = false;
 				}
+				if (this.shouldValidateField('department', 'work') && !this.workForm.department) {
+					this.workErrors.department = '请输入任职部门';
+					isValid = false;
+				}
+
+				if (this.shouldValidateField('position', 'work') && !this.workForm.position) {
+					this.workErrors.position = '请输入担任职务';
+					isValid = false;
+				}
+
+				if (this.shouldValidateField('employeeCount', 'work') && !this.workForm.employeeCount) {
+					this.workErrors.employeeCount = '请输入单位人数';
+					isValid = false;
+				}
+
+				if (this.shouldValidateField('monthlySalary', 'work') && !this.workForm.monthlySalary) {
+					this.workErrors.monthlySalary = '请输入月总收入';
+					isValid = false;
+				}
 
 				if (!isValid) {
 					uni.showToast({

+ 8 - 10
pages/camera/camera.vue

@@ -644,16 +644,14 @@
 						if (!this.showResult) {
 							this.checkAnswer();
 							// 短暂延迟后自动进入下一题
-							setTimeout(() => {
-								if (this.currentQuestionIndex < this.questions.length - 1) {
-									this.goToNextQuestion();
-								} else {
-									// 如果是最后一题,显示结束模态框或跳转
-									uni.navigateTo({
-										url: '/pages/posture-guide/posture-guide'
-									});
-								}
-							}, 1500);
+							if (this.currentQuestionIndex < this.questions.length - 1) {
+								this.goToNextQuestion();
+							} else {
+								// 如果是最后一题,显示结束模态框或跳转
+								uni.navigateTo({
+									url: '/pages/posture-guide/posture-guide'
+								});
+							}
 						}
 					}
 					

+ 0 - 2
pages/face-photo/face-photo.vue

@@ -332,7 +332,6 @@ export default {
               ? '/pages/identity-verify/identity-verify'
               : '/pages/camera/camera';
 
-            setTimeout(() => {
               uni.navigateTo({
                 url: targetUrl,
                 fail: (err) => {
@@ -343,7 +342,6 @@ export default {
                   });
                 }
               });
-            }, 1500);
           } catch (e) {
             console.error('解析上传结果失败:', e);
             uni.showToast({

+ 471 - 181
pages/identity-verify/identity-verify.vue

@@ -365,6 +365,8 @@ export default {
       showCameraWarning: false, // 添加新的数据属性
       showPageWarning: false, // 添加新的数据属性
 	  showPageDRWarning:false,//多人提示
+      lastIOSDetectionTime: 0, // iOS检测时间记录
+      isIOSPhotoCapturing: false, // iOS拍照状态标记
       followUpQuestion: '', // 追问问题
       followUpAudioUrl: '', // 追问音频URL
       audioContext: null, // 音频上下文
@@ -864,7 +866,7 @@ export default {
         this.handleAudioEnd();
       },
       // 调用面试互动接口
-      async callInterviewInteraction(jobPositionQuestionId, retryCount = 0, maxRetries = 3) {
+      async callInterviewInteraction(jobPositionQuestionId, retryCount = 0, maxRetries = 5) {
         // 防重入:同一父问题并发保护
         /* if (jobPositionQuestionId && this.followUpRequestInFlight[jobPositionQuestionId]) {
           console.log('追问请求已在进行中,跳过本次调用');
@@ -941,95 +943,6 @@ export default {
         } */
       },
       
-      // 播放追问音频
-      async playFollowUpAudio() {
-        return new Promise((resolve, reject) => {
-          console.log('开始播放追问音频, URL:', this.followUpAudioUrl);
-          
-          // 检查音频URL
-          if (!this.followUpAudioUrl) {
-            console.error('没有音频URL');
-           /* uni.showToast({
-              title: '音频URL无效',
-              icon: 'none'
-            }); */
-            reject(new Error('没有音频URL'));
-            return;
-          }
-          
-          // 显示加载提示
-          uni.showLoading({
-            title: '思考中...'
-          });
-          
-          // 停止并销毁之前的音频实例
-          this.stopAndDestroyAudio();
-          
-          try {
-            // 创建新的音频上下文
-            const innerAudioContext = uni.createInnerAudioContext();
-            this.audioContext = innerAudioContext;
-            
-            // 设置音频属性
-            innerAudioContext.autoplay = true;
-            innerAudioContext.obeyMuteSwitch = false;
-            innerAudioContext.volume = 1.0;
-            
-            // 监听音频加载状态
-            innerAudioContext.onCanplay(() => {
-              console.log('音频可以播放');
-              uni.hideLoading();
-              this.isAudioPlaying = true;
-              /* uni.showToast({
-                title: '正在播放追问',
-                icon: 'none',
-                duration: 2000
-              }); */
-            });
-            
-            // 监听音频播放完成
-            innerAudioContext.onEnded(() => {
-              console.log('追问音频播放完成');
-              this.isAudioPlaying = false;
-              resolve();
-              // 延迟清理资源,确保不会影响播放完成的回调
-              setTimeout(() => {
-                this.stopAndDestroyAudio();
-                // 音频播放完成后,自动准备录制回答
-                this.prepareToAnswer(true, this.currentFollowUpQuestion);
-              }, 100);
-            });
-            
-            // 监听音频播放错误
-            innerAudioContext.onError((res) => {
-              console.error('音频播放错误:', res);
-              this.isAudioPlaying = false;
-              uni.hideLoading();
-              /* uni.showToast({
-                title: '音频播放失败',
-                icon: 'none'
-              }); */
-              reject(res);
-              this.stopAndDestroyAudio();
-            });
-            
-            // 设置音频源
-            console.log('设置音频源:', this.followUpAudioUrl);
-            innerAudioContext.src = this.followUpAudioUrl;
-            
-          } catch (error) {
-            console.error('创建或播放音频失败:', error);
-            this.isAudioPlaying = false;
-            uni.hideLoading();
-            /* uni.showToast({
-              title: '音频播放失败',
-              icon: 'none'
-            }); */
-            this.stopAndDestroyAudio();
-            reject(error);
-          }
-        });
-      },
       
       // 停止并销毁音频
       stopAndDestroyAudio() {
@@ -1057,41 +970,6 @@ export default {
         this.isAudioPlaying = false;
       },
       
-      // 绑定音频事件
-      bindAudioEvents(audioContext, resolve, reject) {
-        // 监听音频加载状态
-        audioContext.onCanplay(() => {
-          console.log('音频可以播放');
-          /* uni.showToast({
-            title: '正在播放追问',
-            icon: 'none',
-            duration: 2000
-          }); */
-        });
-        
-        // 监听播放进度
-        audioContext.onTimeUpdate(() => {
-          console.log('音频播放进度:', audioContext.currentTime);
-        });
-        
-        // 监听音频播放完成
-        audioContext.onEnded(() => {
-          console.log('追问音频播放完成');
-          this.cleanupAudioContext();
-          resolve();
-        });
-        
-        // 监听音频播放错误
-        audioContext.onError((res) => {
-          console.error('音频播放错误:', res);
-          /* uni.showToast({
-            title: '音频播放失败',
-            icon: 'none'
-          }); */
-          this.cleanupAudioContext();
-          reject(res);
-        });
-      },
 
       // 修改准备回答方法
       prepareToAnswer(isFollowUp = false, questionData = null) {
@@ -1872,13 +1750,26 @@ export default {
       this.isRecording = true;
       // 录制开始:重置帧抓取节流时间
       this.lastFrameCaptureAt = 0;
+      // 录制开始:重置iOS检测时间
+      this.lastIOSDetectionTime = 0;
       // 录制开始:若人脸检测socket已就绪,立即启动帧抓取监听
       try {
         if (this.personDetectionSocket && this.personDetectionSocket.readyState === 1) {
-          if (!this.hiddenCanvasReady) { this.initHiddenCanvasNode(false, 3); }
-          this.startFrameStreamCapture();
+          // 检查是否为iOS平台
+          const systemInfo = uni.getSystemInfoSync();
+          const isIOS = systemInfo.platform === 'ios';
+          
+          if (isIOS) {
+            console.log('iOS录制开始,使用特殊检测逻辑');
+            // iOS端不立即启动帧抓取,等待定时器触发
+          } else {
+            if (!this.hiddenCanvasReady) { this.initHiddenCanvasNode(false, 3); }
+            this.startFrameStreamCapture();
+          }
         }
-      } catch (e) {}
+      } catch (e) {
+        console.warn('录制开始时的检测初始化失败:', e);
+      }
       
       // 记录录制开始时间
       this.recordingStartTime = Date.now();
@@ -2411,6 +2302,10 @@ export default {
       // 停止帧监听(如有)
       this.stopFrameStreamCapture();
       
+      // 重置iOS相关状态
+      this.isIOSPhotoCapturing = false;
+      this.lastIOSDetectionTime = 0;
+      
       // 根据平台选择不同的停止录制方法
       const systemInfo = uni.getSystemInfoSync();
       const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith('mp-');
@@ -2467,24 +2362,59 @@ export default {
         return;
       }
       
+      // 设置超时保护机制
+      let isCompleted = false;
+      const timeoutDuration = 10000; // 10秒超时
+      
+      const timeoutId = setTimeout(() => {
+        if (!isCompleted) {
+          console.warn('停止录制超时,强制继续流程');
+          isCompleted = true;
+          this.proceedToNextQuestion();
+        }
+      }, timeoutDuration);
+      
       // 停止录制
       this.cameraContext.stopRecord({
         success: async (res) => {
+          if (isCompleted) {
+            console.log('录制停止回调已超时,忽略结果');
+            return;
+          }
+          
+          isCompleted = true;
+          clearTimeout(timeoutId);
+          
           console.log('小程序录制停止成功:', res);
           
           // 获取录制的视频文件路径
           const videoPath = res.tempVideoPath;
+          console.log('小程序录制停止成功:', videoPath);
           
           // 上传视频文件
           if (videoPath) {
-            // 等待上传完成后再继续
-            await this.uploadRecordedVideo(videoPath);
+            try {
+              // 等待上传完成后再继续
+              await this.uploadRecordedVideo(videoPath);
+            } catch (uploadError) {
+              console.error('上传视频失败:', uploadError);
+              // 上传失败时继续流程,避免卡住
+              this.proceedToNextQuestion();
+            }
           } else {
             console.error('未获取到录制视频路径');
             this.proceedToNextQuestion();
           }
         },
         fail: (err) => {
+          if (isCompleted) {
+            console.log('录制停止失败回调已超时,忽略错误');
+            return;
+          }
+          
+          isCompleted = true;
+          clearTimeout(timeoutId);
+          
           console.error('小程序录制停止失败:', err);
           this.proceedToNextQuestion();
         }
@@ -2599,11 +2529,30 @@ export default {
         // 返回立即解决的Promise
         return Promise.resolve();
       } else {
-        // 常规问题保持原有逻辑,等待上传完成
-        return new Promise((resolve) => {
+        // 常规问题保持原有逻辑,等待上传完成,但添加超时保护
+        return new Promise((resolve, reject) => {
+          let isCompleted = false;
+          const uploadTimeoutDuration = 30000; // 30秒上传超时
+          
+          // 设置上传超时保护
+          const uploadTimeoutId = setTimeout(() => {
+            if (!isCompleted) {
+              console.warn('上传超时,强制继续流程');
+              isCompleted = true;
+              this.hideThinkingLoading(); // 隐藏思考中loading
+              resolve(); // 即使超时也继续流程
+            }
+          }, uploadTimeoutDuration);
+          
           const checkUploadStatus = () => {
+            if (isCompleted) {
+              return; // 已超时,停止检查
+            }
+            
             if (!this.isUploading && this.uploadQueue.length === 0) {
               // 上传完成后执行后续操作
+              isCompleted = true;
+              clearTimeout(uploadTimeoutId);
               this.handlePostUploadActions(uploadTask);
               resolve();
             } else {
@@ -5014,8 +4963,18 @@ export default {
             return;
           }
 
+          // 获取系统信息,检查是否为iOS平台
+          const systemInfo = uni.getSystemInfoSync();
+          const isIOS = systemInfo.platform === 'ios';
+
           if (this.isRecording && this.useMiniProgramCameraComponent) {
-            this.startFrameStreamCapture();
+            // iOS端录制时的特殊处理
+            if (isIOS) {
+              // 在iOS录制期间,降低检测频率并增加错误处理
+              this.handleIOSRecordingDetection();
+            } else {
+              this.startFrameStreamCapture();
+            }
           } else {
             this.stopFrameStreamCapture();
             this.safeTakePhotoAndSend();
@@ -5026,6 +4985,111 @@ export default {
       }, this.frameCaptureIntervalMs || 5000);
     },
 
+    // 新增方法:处理iOS端录制时的检测逻辑
+    handleIOSRecordingDetection() {
+      // 检查是否正在录制
+      if (!this.isRecording) {
+        return;
+      }
+
+      // 检查WebSocket连接状态
+      if (!this.personDetectionSocket || this.personDetectionSocket.readyState !== 1) {
+        console.warn('iOS录制检测:WebSocket连接未就绪');
+        return;
+      }
+
+      // 检查相机上下文
+      if (!this.cameraContext) {
+        console.warn('iOS录制检测:相机上下文不存在');
+        return;
+      }
+
+      // 在iOS录制期间,使用更安全的检测方式
+      // 降低检测频率,避免与录制功能冲突
+      const now = Date.now();
+      if (this.lastIOSDetectionTime && (now - this.lastIOSDetectionTime) < 5000) {
+        // 5秒内只检测一次,避免频繁调用
+        return;
+      }
+
+      this.lastIOSDetectionTime = now;
+
+      // 使用try-catch包装,确保错误不会影响录制
+      try {
+        // 尝试使用帧抓取方式
+        if (this.hiddenCanvasReady) {
+          this.startFrameStreamCapture();
+        } else {
+          // 如果帧抓取不可用,使用安全的拍照方式
+          this.safeTakePhotoForIOSRecording();
+        }
+      } catch (error) {
+        console.warn('iOS录制检测出错,但不影响录制:', error);
+        // 不抛出错误,确保录制继续进行
+      }
+    },
+
+    // 新增方法:iOS录制期间的安全拍照
+    safeTakePhotoForIOSRecording() {
+      // 防止重复调用
+      if (this.isIOSPhotoCapturing) {
+        return;
+      }
+
+      this.isIOSPhotoCapturing = true;
+
+      try {
+        this.cameraContext.takePhoto({
+          quality: 'low',
+          success: (res) => {
+            const tempFilePath = res && res.tempImagePath;
+            if (!tempFilePath) {
+              this.isIOSPhotoCapturing = false;
+              return;
+            }
+
+            // 异步处理文件读取,不阻塞主流程
+            setTimeout(() => {
+              uni.getFileSystemManager().readFile({
+                filePath: tempFilePath,
+                encoding: 'base64',
+                success: (r) => {
+                  try {
+                    const base64Image = r.data;
+                    if (this.personDetectionSocket && this.personDetectionSocket.readyState === 1) {
+                      this.personDetectionSocket.send({
+                        data: JSON.stringify({
+                          type: 'person_detection',
+                          image_data: base64Image,
+                          platform: 'ios_recording' // 标记为iOS录制期间的检测
+                        })
+                      });
+                      console.log('iOS录制期间检测图片已发送');
+                    }
+                  } catch (sendError) {
+                    console.warn('iOS录制期间发送检测图片失败:', sendError);
+                  } finally {
+                    this.isIOSPhotoCapturing = false;
+                  }
+                },
+                fail: (readError) => {
+                  console.warn('iOS录制期间读取图片文件失败:', readError);
+                  this.isIOSPhotoCapturing = false;
+                }
+              });
+            }, 100); // 延迟100ms处理,避免阻塞录制
+          },
+          fail: (photoError) => {
+            console.warn('iOS录制期间拍照失败:', photoError);
+            this.isIOSPhotoCapturing = false;
+          }
+        });
+      } catch (error) {
+        console.warn('iOS录制期间拍照异常:', error);
+        this.isIOSPhotoCapturing = false;
+      }
+    },
+
     cleanupPersonDetectionWebSocket() {
       if (this.personDetectionInterval) {
         clearInterval(this.personDetectionInterval);
@@ -5209,56 +5273,24 @@ export default {
         this.stopAndDestroyAudio();
         
         try {
-          // 创建新的音频上下文
-          const innerAudioContext = uni.createInnerAudioContext();
-          this.audioContext = innerAudioContext;
+          // 获取系统信息,判断平台
+          const systemInfo = uni.getSystemInfoSync();
+          const isIOS = systemInfo.platform === 'ios';
+          const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith('mp-');
           
-          // 设置音频属性
-          innerAudioContext.autoplay = true;
-          innerAudioContext.obeyMuteSwitch = false;
-          innerAudioContext.volume = 1.0;
+          console.log('平台信息:', { isIOS, isMiniProgram, platform: systemInfo.platform });
           
-          // 监听音频加载状态
-          innerAudioContext.onCanplay(() => {
-            console.log('音频可以播放');
-            uni.hideLoading();
-            this.isAudioPlaying = true;
-            /* uni.showToast({
-              title: '正在播放追问',
-              icon: 'none',
-              duration: 2000
-            }); */
-          });
-          
-          // 监听音频播放完成
-          innerAudioContext.onEnded(() => {
-            console.log('追问音频播放完成');
-            this.isAudioPlaying = false;
-            resolve();
-            // 延迟清理资源,确保不会影响播放完成的回调
-            setTimeout(() => {
-              this.stopAndDestroyAudio();
-              // 音频播放完成后,自动准备录制回答
-              this.prepareToAnswer(true, this.currentFollowUpQuestion);
-            }, 100);
-          });
-          
-          // 监听音频播放错误
-          innerAudioContext.onError((res) => {
-            console.error('音频播放错误:', res);
-            this.isAudioPlaying = false;
-            uni.hideLoading();
-            uni.showToast({
-              title: '音频播放失败',
-              icon: 'none'
-            });
-            reject(res);
-            this.stopAndDestroyAudio();
-          });
-          
-          // 设置音频源
-          console.log('设置音频源:', this.followUpAudioUrl);
-          innerAudioContext.src = this.followUpAudioUrl;
+          // 根据平台选择播放方式
+          if (isMiniProgram && isIOS) {
+            // iOS小程序环境使用BackgroundAudioManager
+            this.playIOSMiniProgramFollowUpAudio(resolve, reject);
+          } else if (isIOS) {
+            // iOS App/H5环境使用专门的iOS播放方法
+            this.playIOSFollowUpAudio(resolve, reject);
+          } else {
+            // 其他平台使用通用方法
+            this.playGeneralFollowUpAudio(resolve, reject);
+          }
           
         } catch (error) {
           console.error('创建或播放音频失败:', error);
@@ -5273,6 +5305,264 @@ export default {
         }
       });
     },
+
+    // iOS小程序专用音频播放方法
+    playIOSMiniProgramFollowUpAudio(resolve, reject) {
+      try {
+        const bgAudio = uni.getBackgroundAudioManager();
+        // iOS 小程序需要设置 title 等元信息,否则可能不触发播放
+        bgAudio.title = '追问语音';
+        bgAudio.epname = 'Follow Up Question';
+        bgAudio.singer = 'Interviewer';
+        
+        // 先绑定事件再设置 src,防止错过 canplay 回调
+        bgAudio.onCanplay(() => {
+          try {
+            bgAudio.play();
+          } catch (e) {
+            console.warn('iOS小程序调用 play 失败,稍后重试', e);
+            setTimeout(() => {
+              try { bgAudio.play(); } catch (_) {}
+            }, 50);
+          }
+        });
+
+        bgAudio.onPlay(() => {
+          console.log('iOS小程序追问音频开始播放');
+          uni.hideLoading();
+          this.isAudioPlaying = true;
+        });
+
+        bgAudio.onEnded(() => {
+          console.log('iOS小程序追问音频播放完成');
+          this.isAudioPlaying = false;
+          try { bgAudio.stop(); } catch (_) {}
+          resolve();
+          // 延迟清理资源,确保不会影响播放完成的回调
+          setTimeout(() => {
+            this.stopAndDestroyAudio();
+            // 音频播放完成后,自动准备录制回答
+            this.prepareToAnswer(true, this.currentFollowUpQuestion);
+          }, 100);
+        });
+
+        bgAudio.onError((err) => {
+          console.error('iOS小程序追问音频播放错误:', err);
+          this.isAudioPlaying = false;
+          uni.hideLoading();
+          try { bgAudio.stop(); } catch (_) {}
+          // 尝试备选方案
+          this.fallbackIOSFollowUpAudio(resolve, reject);
+        });
+
+        bgAudio.autoplay = true;
+        bgAudio.src = this.followUpAudioUrl;
+      } catch (error) {
+        console.error('iOS小程序音频播放失败:', error);
+        this.fallbackIOSFollowUpAudio(resolve, reject);
+      }
+    },
+
+    // iOS App/H5专用音频播放方法
+    playIOSFollowUpAudio(resolve, reject) {
+      try {
+        // 创建新的音频播放器
+        this.audioContext = uni.createInnerAudioContext();
+        
+        // 配置播放器 - iOS特殊配置
+        this.audioContext.autoplay = true;
+        this.audioContext.obeyMuteSwitch = false; // 不遵循静音开关,确保播放
+        this.audioContext.volume = 1.0;
+        
+        // 设置音频源
+        this.audioContext.src = this.followUpAudioUrl;
+        
+        // 监听事件
+        this.audioContext.onPlay(() => {
+          console.log('iOS追问音频开始播放');
+          uni.hideLoading();
+          this.isAudioPlaying = true;
+        });
+        
+        this.audioContext.onEnded(() => {
+          console.log('iOS追问音频播放完成');
+          this.isAudioPlaying = false;
+          resolve();
+          // 延迟清理资源,确保不会影响播放完成的回调
+          setTimeout(() => {
+            this.stopAndDestroyAudio();
+            // 音频播放完成后,自动准备录制回答
+            this.prepareToAnswer(true, this.currentFollowUpQuestion);
+          }, 100);
+        });
+        
+        this.audioContext.onError((err) => {
+          console.error('iOS追问音频播放错误:', err);
+          this.isAudioPlaying = false;
+          uni.hideLoading();
+          // 尝试备选方案
+          this.fallbackIOSFollowUpAudio(resolve, reject);
+        });
+        
+        this.audioContext.onWaiting(() => {
+          console.log('iOS追问音频加载中...');
+        });
+        
+        this.audioContext.onCanplay(() => {
+          console.log('iOS追问音频准备就绪');
+        });
+        
+        // 设置超时保护
+        setTimeout(() => {
+          if (this.isAudioPlaying && this.audioContext) {
+            console.log('iOS追问音频播放超时,尝试备选方案');
+            this.fallbackIOSFollowUpAudio(resolve, reject);
+          }
+        }, 10000); // 10秒超时
+        
+      } catch (error) {
+        console.error('创建iOS追问音频播放器失败:', error);
+        this.fallbackIOSFollowUpAudio(resolve, reject);
+      }
+    },
+
+    // iOS备选音频播放方案
+    fallbackIOSFollowUpAudio(resolve, reject) {
+      console.log('iOS追问音频备选播放方案');
+      
+      try {
+        // 停止当前播放器
+        this.stopAndDestroyAudio();
+        
+        // 创建新的音频播放器
+        this.audioContext = uni.createInnerAudioContext();
+        
+        // 使用更保守的设置
+        this.audioContext.autoplay = true;
+        this.audioContext.obeyMuteSwitch = true; // 遵循静音开关
+        this.audioContext.volume = 0.8;
+        
+        // 直接使用原URL
+        this.audioContext.src = this.followUpAudioUrl;
+        
+        // 设置简化的事件监听
+        this.audioContext.onPlay(() => {
+          console.log('iOS备选方案:追问音频开始播放');
+          uni.hideLoading();
+          this.isAudioPlaying = true;
+        });
+        
+        this.audioContext.onEnded(() => {
+          console.log('iOS备选方案:追问音频播放结束');
+          this.isAudioPlaying = false;
+          resolve();
+          setTimeout(() => {
+            this.stopAndDestroyAudio();
+            this.prepareToAnswer(true, this.currentFollowUpQuestion);
+          }, 100);
+        });
+        
+        this.audioContext.onError((err) => {
+          console.error('iOS备选方案:追问音频播放错误:', err);
+          this.useIOSFollowUpTextFallback(resolve, reject);
+        });
+        
+        // 设置超时,如果5秒内没有开始播放,使用文本回退
+        setTimeout(() => {
+          if (this.isAudioPlaying && this.audioContext) {
+            console.log('iOS追问音频播放超时,使用文本回退');
+            this.useIOSFollowUpTextFallback(resolve, reject);
+          }
+        }, 5000);
+        
+      } catch (e) {
+        console.error('iOS备选追问音频播放失败:', e);
+        this.useIOSFollowUpTextFallback(resolve, reject);
+      }
+    },
+
+    // iOS文本回退方案
+    useIOSFollowUpTextFallback(resolve, reject) {
+      console.log('iOS追问音频使用文本回退方案');
+      this.isAudioPlaying = false;
+      uni.hideLoading();
+      
+      // 显示文本提示
+      uni.showToast({
+        title: '音频播放失败,请查看文字问题',
+        icon: 'none',
+        duration: 3000
+      });
+      
+      // 直接解析,继续流程
+      resolve();
+      setTimeout(() => {
+        this.stopAndDestroyAudio();
+        this.prepareToAnswer(true, this.currentFollowUpQuestion);
+      }, 100);
+    },
+
+    // 通用音频播放方法(非iOS平台)
+    playGeneralFollowUpAudio(resolve, reject) {
+      try {
+        // 创建新的音频上下文
+        const innerAudioContext = uni.createInnerAudioContext();
+        this.audioContext = innerAudioContext;
+        
+        // 设置音频属性
+        innerAudioContext.autoplay = true;
+        innerAudioContext.obeyMuteSwitch = false;
+        innerAudioContext.volume = 1.0;
+        
+        // 监听音频加载状态
+        innerAudioContext.onCanplay(() => {
+          console.log('音频可以播放');
+          uni.hideLoading();
+          this.isAudioPlaying = true;
+        });
+        
+        // 监听音频播放完成
+        innerAudioContext.onEnded(() => {
+          console.log('追问音频播放完成');
+          this.isAudioPlaying = false;
+          resolve();
+          // 延迟清理资源,确保不会影响播放完成的回调
+          setTimeout(() => {
+            this.stopAndDestroyAudio();
+            // 音频播放完成后,自动准备录制回答
+            this.prepareToAnswer(true, this.currentFollowUpQuestion);
+          }, 100);
+        });
+        
+        // 监听音频播放错误
+        innerAudioContext.onError((res) => {
+          console.error('音频播放错误:', res);
+          this.isAudioPlaying = false;
+          uni.hideLoading();
+          uni.showToast({
+            title: '音频播放失败',
+            icon: 'none'
+          });
+          reject(res);
+          this.stopAndDestroyAudio();
+        });
+        
+        // 设置音频源
+        console.log('设置音频源:', this.followUpAudioUrl);
+        innerAudioContext.src = this.followUpAudioUrl;
+        
+      } catch (error) {
+        console.error('创建或播放音频失败:', error);
+        this.isAudioPlaying = false;
+        uni.hideLoading();
+        uni.showToast({
+          title: '音频播放失败',
+          icon: 'none'
+        });
+        this.stopAndDestroyAudio();
+        reject(error);
+      }
+    },
     
     // 停止并销毁音频
     stopAndDestroyAudio() {

+ 14 - 5
pages/index/index.vue

@@ -137,7 +137,11 @@ import { apiBaseUrl } from '@/common/config.js';
 				}
 				if (parsedTenantId) {
 					const storedTenantId = uni.getStorageSync('tenant_id');
-					if (storedTenantId && storedTenantId !== parsedTenantId) {
+					const userInfo = uni.getStorageSync('userInfo');
+					const userInfoTenantId = userInfo.tenant_id;
+					/* console.log('userInfoTenantId:', userInfoTenantId);
+					console.log('storedTenantId:', storedTenantId , 'parsedTenantId:', parsedTenantId, storedTenantId !== parsedTenantId); */
+					if (storedTenantId && storedTenantId !== userInfoTenantId) {
 						// 租户发生变化时,静默清除登录态以避免越租户数据串联
 						this.silentLogout();
 					}
@@ -364,7 +368,7 @@ import { apiBaseUrl } from '@/common/config.js';
 			},
 			
 			// 处理用户信息获取和页面跳转逻辑
-			handleUserInfoAndNavigation() {
+			handleUserInfoAndNavigation(require_resume_upload) {
 				// 调用获取用户完整信息的接口
 				const openid = JSON.parse(uni.getStorageSync('userInfo')).openid;
 				uni.request({
@@ -373,7 +377,7 @@ import { apiBaseUrl } from '@/common/config.js';
 					success: (infoRes) => {
 						if (infoRes.statusCode === 200 && infoRes.data && infoRes.data.data && infoRes.data.data.profile) {
 							const resumeUrl = infoRes.data.data.profile.resume_url || '';
-							if (!resumeUrl) {
+							if (!resumeUrl && require_resume_upload) {
 								// resume_url 为空,跳转到其他页面
 								uni.navigateTo({
 									url: '/pages/uploadResume/uploadResume', // 假设跳转到上传简历页面
@@ -449,6 +453,7 @@ import { apiBaseUrl } from '@/common/config.js';
 								// 检查是否启用了视频宣讲功能
 								const configData = res.data.data;
 								const enableVideoPresentation = configData?.enable_video_presentation || false;
+								const requireResumeUpload = configData?.require_resume_upload || false;
 								
 								if (enableVideoPresentation) {
 									// 如果启用了视频宣讲,跳转到video-briefing页面
@@ -460,12 +465,12 @@ import { apiBaseUrl } from '@/common/config.js';
 										fail: (err) => {
 											console.error('跳转到视频宣讲页面失败:', err);
 											// 如果跳转失败,执行原有的逻辑
-											this.handleUserInfoAndNavigation();
+											this.handleUserInfoAndNavigation(requireResumeUpload);
 										}
 									});
 								} else {
 									// 如果未启用视频宣讲,执行原有的逻辑
-									this.handleUserInfoAndNavigation();
+									this.handleUserInfoAndNavigation(requireResumeUpload);
 								}
 							} else {
 								// 其他逻辑
@@ -730,6 +735,10 @@ import { apiBaseUrl } from '@/common/config.js';
 				this.formData.gender = displayGender;
 			},
 			viewJobDetail(job) {
+				// 未登录则先进行登录校验
+				// if (!this.checkLogin()) {
+				// 	return;
+				// }
 				// 保存所选职位信息到本地存储
 				uni.setStorageSync('currentJobDetail', JSON.stringify(job));
 				console.log(job);

+ 0 - 4
pages/interview-question/interview-question.vue

@@ -2281,7 +2281,6 @@ export default {
       this.currentSubtitle = '';
       
       // 添加延迟确保状态已更新
-      setTimeout(() => {
         uni.reLaunch({
           url: '/pages/success/success',
           success: () => {
@@ -2296,7 +2295,6 @@ export default {
             });
           }
         });
-      }, 100);
     },
 
     // 添加处理导航失败的方法
@@ -3280,7 +3278,6 @@ export default {
       this.currentSubtitle = '';
       
       // 添加延迟确保状态已更新
-      setTimeout(() => {
         uni.reLaunch({
           url: '/pages/success/success',
           success: () => {
@@ -3295,7 +3292,6 @@ export default {
             });
           }
         });
-      }, 100);
     },
 
     // 新增方法:专门处理iOS小程序音频播放

+ 2 - 2
pages/interview/interview.vue

@@ -530,12 +530,12 @@ import { apiBaseUrl } from '@/common/config.js'; // Import the base URL from a c
 								duration: 2000,
 								success: () => {
 									// 延迟跳转,让用户看到成功提示
-									setTimeout(() => {
+			
 										// 使用redirectTo替代navigateTo,避免页面栈溢出
 										uni.redirectTo({
 											url: '/pages/interview_success/interview_success'
 										});
-									}, 100);
+									
 								}
 							});
 						},

+ 2 - 2
pages/interview_retake/interview_retake.vue

@@ -211,12 +211,12 @@ export default {
 				duration: 1500,
 				success: () => {
 					// 延迟跳转到成功页面
-					setTimeout(() => {
+					
 						/* uni.redirectTo({
 							url: '/pages/interview-question/interview-question'//'/pages/success/success?type=retake&message=手部照片补拍完成,请等待系统审核'
 						}); */
 						this.navigateToNextPage();
-					}, 1500);
+					
 				}
 			});
 		},

+ 3 - 3
pages/job-detail/job-detail.vue

@@ -140,7 +140,7 @@ export default {
     async getJobDetail(jobId) {
       try {
         const { data } = await uni.request({
-          url: `${apiBaseUrl}/api/mini/job/detail?id=${jobId}&tenant_id=${this.tenant_id||JSON.parse(uni.getStorageSync('userInfo')).tenant_id ||1}`,
+          url: `${apiBaseUrl}/api/mini/job/detail?id=${jobId}&tenant_id=${this.tenant_id||(() => { try { const s = uni.getStorageSync('userInfo'); return s ? (JSON.parse(s).tenant_id || 1) : 1; } catch { return 1; } })()}`,
           method: 'GET',
         });
         
@@ -515,8 +515,8 @@ export default {
         uni.openLocation({
           latitude: this.mapInfo.latitude,
           longitude: this.mapInfo.longitude,
-          name: this.jobDetail.title,
-          address: this.formatLocation(this.jobDetail.location),
+          name: this.formatLocation(this.jobDetail.location),
+          // address: this.formatLocation(this.jobDetail.location),
           success: function () {
             console.log('导航打开成功');
           },

+ 1 - 1
pages/posture-guide/posture-guide.vue

@@ -2,7 +2,7 @@
   <view class="posture-guide">
     <view class="guide-content">
       <view class="guide-title">体态评估环节</view>
-      <view class="guide-subtitle">请仔细阅读下方说明,完整展示手臂</view>
+      <view class="guide-subtitle">请仔细阅读下方说明,完整展示手臂,向右滑动查看更多</view>
       
       <!-- 添加轮播图组件 -->
       <swiper 

+ 19 - 5
unpackage/dist/dev/mp-weixin/pages/Personal/Personal.js

@@ -1143,11 +1143,9 @@ const _sfc_main = {
                 icon: "success",
                 duration: 2e3
               });
-              setTimeout(() => {
-                common_vendor.index.navigateTo({
-                  url: "/pages/interview-notice/interview-notice"
-                });
-              }, 2e3);
+              common_vendor.index.navigateTo({
+                url: "/pages/interview-notice/interview-notice"
+              });
             } else {
               common_vendor.index.showToast({
                 title: res.data.msg || "提交失败",
@@ -1885,6 +1883,22 @@ const _sfc_main = {
         this.workErrors.employeeCount = "请输入单位人数";
         isValid = false;
       }
+      if (this.shouldValidateField("department", "work") && !this.workForm.department) {
+        this.workErrors.department = "请输入任职部门";
+        isValid = false;
+      }
+      if (this.shouldValidateField("position", "work") && !this.workForm.position) {
+        this.workErrors.position = "请输入担任职务";
+        isValid = false;
+      }
+      if (this.shouldValidateField("employeeCount", "work") && !this.workForm.employeeCount) {
+        this.workErrors.employeeCount = "请输入单位人数";
+        isValid = false;
+      }
+      if (this.shouldValidateField("monthlySalary", "work") && !this.workForm.monthlySalary) {
+        this.workErrors.monthlySalary = "请输入月总收入";
+        isValid = false;
+      }
       if (!isValid) {
         common_vendor.index.showToast({
           title: "请完善工作经历必填信息",

Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
unpackage/dist/dev/mp-weixin/pages/Personal/Personal.wxml


+ 7 - 9
unpackage/dist/dev/mp-weixin/pages/camera/camera.js

@@ -414,15 +414,13 @@ const _sfc_main = {
           clearInterval(this.timerInterval);
           if (!this.showResult) {
             this.checkAnswer();
-            setTimeout(() => {
-              if (this.currentQuestionIndex < this.questions.length - 1) {
-                this.goToNextQuestion();
-              } else {
-                common_vendor.index.navigateTo({
-                  url: "/pages/posture-guide/posture-guide"
-                });
-              }
-            }, 1500);
+            if (this.currentQuestionIndex < this.questions.length - 1) {
+              this.goToNextQuestion();
+            } else {
+              common_vendor.index.navigateTo({
+                url: "/pages/posture-guide/posture-guide"
+              });
+            }
           }
         }
         const min = Math.floor(seconds / 60).toString().padStart(2, "0");

+ 10 - 12
unpackage/dist/dev/mp-weixin/pages/face-photo/face-photo.js

@@ -251,18 +251,16 @@ const _sfc_main = {
               configData = {};
             }
             const targetUrl = ((_a = configData == null ? void 0 : configData.question_form_switches) == null ? void 0 : _a.enable_open_questions) ? "/pages/identity-verify/identity-verify" : "/pages/camera/camera";
-            setTimeout(() => {
-              common_vendor.index.navigateTo({
-                url: targetUrl,
-                fail: (err) => {
-                  console.error("页面跳转失败:", err);
-                  common_vendor.index.showToast({
-                    title: "页面跳转失败",
-                    icon: "none"
-                  });
-                }
-              });
-            }, 1500);
+            common_vendor.index.navigateTo({
+              url: targetUrl,
+              fail: (err) => {
+                console.error("页面跳转失败:", err);
+                common_vendor.index.showToast({
+                  title: "页面跳转失败",
+                  icon: "none"
+                });
+              }
+            });
           } catch (e) {
             console.error("解析上传结果失败:", e);
             common_vendor.index.showToast({

+ 366 - 109
unpackage/dist/dev/mp-weixin/pages/identity-verify/identity-verify.js

@@ -223,6 +223,10 @@ const _sfc_main = {
       // 添加新的数据属性
       showPageDRWarning: false,
       //多人提示
+      lastIOSDetectionTime: 0,
+      // iOS检测时间记录
+      isIOSPhotoCapturing: false,
+      // iOS拍照状态标记
       followUpQuestion: "",
       // 追问问题
       followUpAudioUrl: "",
@@ -696,7 +700,7 @@ const _sfc_main = {
       this.handleAudioEnd();
     },
     // 调用面试互动接口
-    async callInterviewInteraction(jobPositionQuestionId, retryCount = 0, maxRetries = 3) {
+    async callInterviewInteraction(jobPositionQuestionId, retryCount = 0, maxRetries = 5) {
       const userInfo = JSON.parse(common_vendor.index.getStorageSync("userInfo"));
       const appId = common_vendor.index.getStorageSync("appId");
       const positionConfigId = JSON.parse(common_vendor.index.getStorageSync("configData")).id;
@@ -750,57 +754,6 @@ const _sfc_main = {
         return false;
       }
     },
-    // 播放追问音频
-    async playFollowUpAudio() {
-      return new Promise((resolve, reject) => {
-        console.log("开始播放追问音频, URL:", this.followUpAudioUrl);
-        if (!this.followUpAudioUrl) {
-          console.error("没有音频URL");
-          reject(new Error("没有音频URL"));
-          return;
-        }
-        common_vendor.index.showLoading({
-          title: "思考中..."
-        });
-        this.stopAndDestroyAudio();
-        try {
-          const innerAudioContext = common_vendor.index.createInnerAudioContext();
-          this.audioContext = innerAudioContext;
-          innerAudioContext.autoplay = true;
-          innerAudioContext.obeyMuteSwitch = false;
-          innerAudioContext.volume = 1;
-          innerAudioContext.onCanplay(() => {
-            console.log("音频可以播放");
-            common_vendor.index.hideLoading();
-            this.isAudioPlaying = true;
-          });
-          innerAudioContext.onEnded(() => {
-            console.log("追问音频播放完成");
-            this.isAudioPlaying = false;
-            resolve();
-            setTimeout(() => {
-              this.stopAndDestroyAudio();
-              this.prepareToAnswer(true, this.currentFollowUpQuestion);
-            }, 100);
-          });
-          innerAudioContext.onError((res) => {
-            console.error("音频播放错误:", res);
-            this.isAudioPlaying = false;
-            common_vendor.index.hideLoading();
-            reject(res);
-            this.stopAndDestroyAudio();
-          });
-          console.log("设置音频源:", this.followUpAudioUrl);
-          innerAudioContext.src = this.followUpAudioUrl;
-        } catch (error) {
-          console.error("创建或播放音频失败:", error);
-          this.isAudioPlaying = false;
-          common_vendor.index.hideLoading();
-          this.stopAndDestroyAudio();
-          reject(error);
-        }
-      });
-    },
     // 停止并销毁音频
     stopAndDestroyAudio() {
       if (!this.audioContext) {
@@ -822,25 +775,6 @@ const _sfc_main = {
       }
       this.isAudioPlaying = false;
     },
-    // 绑定音频事件
-    bindAudioEvents(audioContext, resolve, reject) {
-      audioContext.onCanplay(() => {
-        console.log("音频可以播放");
-      });
-      audioContext.onTimeUpdate(() => {
-        console.log("音频播放进度:", audioContext.currentTime);
-      });
-      audioContext.onEnded(() => {
-        console.log("追问音频播放完成");
-        this.cleanupAudioContext();
-        resolve();
-      });
-      audioContext.onError((res) => {
-        console.error("音频播放错误:", res);
-        this.cleanupAudioContext();
-        reject(res);
-      });
-    },
     // 修改准备回答方法
     prepareToAnswer(isFollowUp = false, questionData = null) {
       this.isRecording = false;
@@ -1387,14 +1321,22 @@ const _sfc_main = {
       console.log("开始录制用户回答");
       this.isRecording = true;
       this.lastFrameCaptureAt = 0;
+      this.lastIOSDetectionTime = 0;
       try {
         if (this.personDetectionSocket && this.personDetectionSocket.readyState === 1) {
-          if (!this.hiddenCanvasReady) {
-            this.initHiddenCanvasNode(false, 3);
+          const systemInfo2 = common_vendor.index.getSystemInfoSync();
+          const isIOS = systemInfo2.platform === "ios";
+          if (isIOS) {
+            console.log("iOS录制开始,使用特殊检测逻辑");
+          } else {
+            if (!this.hiddenCanvasReady) {
+              this.initHiddenCanvasNode(false, 3);
+            }
+            this.startFrameStreamCapture();
           }
-          this.startFrameStreamCapture();
         }
       } catch (e) {
+        console.warn("录制开始时的检测初始化失败:", e);
       }
       this.recordingStartTime = Date.now();
       this.recordingTimerCount = 0;
@@ -1760,6 +1702,8 @@ const _sfc_main = {
       this.showStopRecordingButton = false;
       this.isRecording = false;
       this.stopFrameStreamCapture();
+      this.isIOSPhotoCapturing = false;
+      this.lastIOSDetectionTime = 0;
       const systemInfo = common_vendor.index.getSystemInfoSync();
       const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith("mp-");
       if (isMiniProgram) {
@@ -1804,18 +1748,45 @@ const _sfc_main = {
         this.proceedToNextQuestion();
         return;
       }
+      let isCompleted = false;
+      const timeoutDuration = 1e4;
+      const timeoutId = setTimeout(() => {
+        if (!isCompleted) {
+          console.warn("停止录制超时,强制继续流程");
+          isCompleted = true;
+          this.proceedToNextQuestion();
+        }
+      }, timeoutDuration);
       this.cameraContext.stopRecord({
         success: async (res) => {
+          if (isCompleted) {
+            console.log("录制停止回调已超时,忽略结果");
+            return;
+          }
+          isCompleted = true;
+          clearTimeout(timeoutId);
           console.log("小程序录制停止成功:", res);
           const videoPath = res.tempVideoPath;
+          console.log("小程序录制停止成功:", videoPath);
           if (videoPath) {
-            await this.uploadRecordedVideo(videoPath);
+            try {
+              await this.uploadRecordedVideo(videoPath);
+            } catch (uploadError) {
+              console.error("上传视频失败:", uploadError);
+              this.proceedToNextQuestion();
+            }
           } else {
             console.error("未获取到录制视频路径");
             this.proceedToNextQuestion();
           }
         },
         fail: (err) => {
+          if (isCompleted) {
+            console.log("录制停止失败回调已超时,忽略错误");
+            return;
+          }
+          isCompleted = true;
+          clearTimeout(timeoutId);
           console.error("小程序录制停止失败:", err);
           this.proceedToNextQuestion();
         }
@@ -1894,9 +1865,24 @@ const _sfc_main = {
         this.startBackgroundUpload(uploadTask);
         return Promise.resolve();
       } else {
-        return new Promise((resolve) => {
+        return new Promise((resolve, reject) => {
+          let isCompleted = false;
+          const uploadTimeoutDuration = 3e4;
+          const uploadTimeoutId = setTimeout(() => {
+            if (!isCompleted) {
+              console.warn("上传超时,强制继续流程");
+              isCompleted = true;
+              this.hideThinkingLoading();
+              resolve();
+            }
+          }, uploadTimeoutDuration);
           const checkUploadStatus = () => {
+            if (isCompleted) {
+              return;
+            }
             if (!this.isUploading && this.uploadQueue.length === 0) {
+              isCompleted = true;
+              clearTimeout(uploadTimeoutId);
               this.handlePostUploadActions(uploadTask);
               resolve();
             } else {
@@ -3628,8 +3614,14 @@ const _sfc_main = {
             console.warn("人脸检测:相机上下文或WebSocket连接未就绪");
             return;
           }
+          const systemInfo = common_vendor.index.getSystemInfoSync();
+          const isIOS = systemInfo.platform === "ios";
           if (this.isRecording && this.useMiniProgramCameraComponent) {
-            this.startFrameStreamCapture();
+            if (isIOS) {
+              this.handleIOSRecordingDetection();
+            } else {
+              this.startFrameStreamCapture();
+            }
           } else {
             this.stopFrameStreamCapture();
             this.safeTakePhotoAndSend();
@@ -3639,6 +3631,90 @@ const _sfc_main = {
         }
       }, this.frameCaptureIntervalMs || 5e3);
     },
+    // 新增方法:处理iOS端录制时的检测逻辑
+    handleIOSRecordingDetection() {
+      if (!this.isRecording) {
+        return;
+      }
+      if (!this.personDetectionSocket || this.personDetectionSocket.readyState !== 1) {
+        console.warn("iOS录制检测:WebSocket连接未就绪");
+        return;
+      }
+      if (!this.cameraContext) {
+        console.warn("iOS录制检测:相机上下文不存在");
+        return;
+      }
+      const now = Date.now();
+      if (this.lastIOSDetectionTime && now - this.lastIOSDetectionTime < 5e3) {
+        return;
+      }
+      this.lastIOSDetectionTime = now;
+      try {
+        if (this.hiddenCanvasReady) {
+          this.startFrameStreamCapture();
+        } else {
+          this.safeTakePhotoForIOSRecording();
+        }
+      } catch (error) {
+        console.warn("iOS录制检测出错,但不影响录制:", error);
+      }
+    },
+    // 新增方法:iOS录制期间的安全拍照
+    safeTakePhotoForIOSRecording() {
+      if (this.isIOSPhotoCapturing) {
+        return;
+      }
+      this.isIOSPhotoCapturing = true;
+      try {
+        this.cameraContext.takePhoto({
+          quality: "low",
+          success: (res) => {
+            const tempFilePath = res && res.tempImagePath;
+            if (!tempFilePath) {
+              this.isIOSPhotoCapturing = false;
+              return;
+            }
+            setTimeout(() => {
+              common_vendor.index.getFileSystemManager().readFile({
+                filePath: tempFilePath,
+                encoding: "base64",
+                success: (r) => {
+                  try {
+                    const base64Image = r.data;
+                    if (this.personDetectionSocket && this.personDetectionSocket.readyState === 1) {
+                      this.personDetectionSocket.send({
+                        data: JSON.stringify({
+                          type: "person_detection",
+                          image_data: base64Image,
+                          platform: "ios_recording"
+                          // 标记为iOS录制期间的检测
+                        })
+                      });
+                      console.log("iOS录制期间检测图片已发送");
+                    }
+                  } catch (sendError) {
+                    console.warn("iOS录制期间发送检测图片失败:", sendError);
+                  } finally {
+                    this.isIOSPhotoCapturing = false;
+                  }
+                },
+                fail: (readError) => {
+                  console.warn("iOS录制期间读取图片文件失败:", readError);
+                  this.isIOSPhotoCapturing = false;
+                }
+              });
+            }, 100);
+          },
+          fail: (photoError) => {
+            console.warn("iOS录制期间拍照失败:", photoError);
+            this.isIOSPhotoCapturing = false;
+          }
+        });
+      } catch (error) {
+        console.warn("iOS录制期间拍照异常:", error);
+        this.isIOSPhotoCapturing = false;
+      }
+    },
     cleanupPersonDetectionWebSocket() {
       if (this.personDetectionInterval) {
         clearInterval(this.personDetectionInterval);
@@ -3763,38 +3839,17 @@ const _sfc_main = {
         });
         this.stopAndDestroyAudio();
         try {
-          const innerAudioContext = common_vendor.index.createInnerAudioContext();
-          this.audioContext = innerAudioContext;
-          innerAudioContext.autoplay = true;
-          innerAudioContext.obeyMuteSwitch = false;
-          innerAudioContext.volume = 1;
-          innerAudioContext.onCanplay(() => {
-            console.log("音频可以播放");
-            common_vendor.index.hideLoading();
-            this.isAudioPlaying = true;
-          });
-          innerAudioContext.onEnded(() => {
-            console.log("追问音频播放完成");
-            this.isAudioPlaying = false;
-            resolve();
-            setTimeout(() => {
-              this.stopAndDestroyAudio();
-              this.prepareToAnswer(true, this.currentFollowUpQuestion);
-            }, 100);
-          });
-          innerAudioContext.onError((res) => {
-            console.error("音频播放错误:", res);
-            this.isAudioPlaying = false;
-            common_vendor.index.hideLoading();
-            common_vendor.index.showToast({
-              title: "音频播放失败",
-              icon: "none"
-            });
-            reject(res);
-            this.stopAndDestroyAudio();
-          });
-          console.log("设置音频源:", this.followUpAudioUrl);
-          innerAudioContext.src = this.followUpAudioUrl;
+          const systemInfo = common_vendor.index.getSystemInfoSync();
+          const isIOS = systemInfo.platform === "ios";
+          const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith("mp-");
+          console.log("平台信息:", { isIOS, isMiniProgram, platform: systemInfo.platform });
+          if (isMiniProgram && isIOS) {
+            this.playIOSMiniProgramFollowUpAudio(resolve, reject);
+          } else if (isIOS) {
+            this.playIOSFollowUpAudio(resolve, reject);
+          } else {
+            this.playGeneralFollowUpAudio(resolve, reject);
+          }
         } catch (error) {
           console.error("创建或播放音频失败:", error);
           this.isAudioPlaying = false;
@@ -3808,6 +3863,208 @@ const _sfc_main = {
         }
       });
     },
+    // iOS小程序专用音频播放方法
+    playIOSMiniProgramFollowUpAudio(resolve, reject) {
+      try {
+        const bgAudio = common_vendor.index.getBackgroundAudioManager();
+        bgAudio.title = "追问语音";
+        bgAudio.epname = "Follow Up Question";
+        bgAudio.singer = "Interviewer";
+        bgAudio.onCanplay(() => {
+          try {
+            bgAudio.play();
+          } catch (e) {
+            console.warn("iOS小程序调用 play 失败,稍后重试", e);
+            setTimeout(() => {
+              try {
+                bgAudio.play();
+              } catch (_) {
+              }
+            }, 50);
+          }
+        });
+        bgAudio.onPlay(() => {
+          console.log("iOS小程序追问音频开始播放");
+          common_vendor.index.hideLoading();
+          this.isAudioPlaying = true;
+        });
+        bgAudio.onEnded(() => {
+          console.log("iOS小程序追问音频播放完成");
+          this.isAudioPlaying = false;
+          try {
+            bgAudio.stop();
+          } catch (_) {
+          }
+          resolve();
+          setTimeout(() => {
+            this.stopAndDestroyAudio();
+            this.prepareToAnswer(true, this.currentFollowUpQuestion);
+          }, 100);
+        });
+        bgAudio.onError((err) => {
+          console.error("iOS小程序追问音频播放错误:", err);
+          this.isAudioPlaying = false;
+          common_vendor.index.hideLoading();
+          try {
+            bgAudio.stop();
+          } catch (_) {
+          }
+          this.fallbackIOSFollowUpAudio(resolve, reject);
+        });
+        bgAudio.autoplay = true;
+        bgAudio.src = this.followUpAudioUrl;
+      } catch (error) {
+        console.error("iOS小程序音频播放失败:", error);
+        this.fallbackIOSFollowUpAudio(resolve, reject);
+      }
+    },
+    // iOS App/H5专用音频播放方法
+    playIOSFollowUpAudio(resolve, reject) {
+      try {
+        this.audioContext = common_vendor.index.createInnerAudioContext();
+        this.audioContext.autoplay = true;
+        this.audioContext.obeyMuteSwitch = false;
+        this.audioContext.volume = 1;
+        this.audioContext.src = this.followUpAudioUrl;
+        this.audioContext.onPlay(() => {
+          console.log("iOS追问音频开始播放");
+          common_vendor.index.hideLoading();
+          this.isAudioPlaying = true;
+        });
+        this.audioContext.onEnded(() => {
+          console.log("iOS追问音频播放完成");
+          this.isAudioPlaying = false;
+          resolve();
+          setTimeout(() => {
+            this.stopAndDestroyAudio();
+            this.prepareToAnswer(true, this.currentFollowUpQuestion);
+          }, 100);
+        });
+        this.audioContext.onError((err) => {
+          console.error("iOS追问音频播放错误:", err);
+          this.isAudioPlaying = false;
+          common_vendor.index.hideLoading();
+          this.fallbackIOSFollowUpAudio(resolve, reject);
+        });
+        this.audioContext.onWaiting(() => {
+          console.log("iOS追问音频加载中...");
+        });
+        this.audioContext.onCanplay(() => {
+          console.log("iOS追问音频准备就绪");
+        });
+        setTimeout(() => {
+          if (this.isAudioPlaying && this.audioContext) {
+            console.log("iOS追问音频播放超时,尝试备选方案");
+            this.fallbackIOSFollowUpAudio(resolve, reject);
+          }
+        }, 1e4);
+      } catch (error) {
+        console.error("创建iOS追问音频播放器失败:", error);
+        this.fallbackIOSFollowUpAudio(resolve, reject);
+      }
+    },
+    // iOS备选音频播放方案
+    fallbackIOSFollowUpAudio(resolve, reject) {
+      console.log("iOS追问音频备选播放方案");
+      try {
+        this.stopAndDestroyAudio();
+        this.audioContext = common_vendor.index.createInnerAudioContext();
+        this.audioContext.autoplay = true;
+        this.audioContext.obeyMuteSwitch = true;
+        this.audioContext.volume = 0.8;
+        this.audioContext.src = this.followUpAudioUrl;
+        this.audioContext.onPlay(() => {
+          console.log("iOS备选方案:追问音频开始播放");
+          common_vendor.index.hideLoading();
+          this.isAudioPlaying = true;
+        });
+        this.audioContext.onEnded(() => {
+          console.log("iOS备选方案:追问音频播放结束");
+          this.isAudioPlaying = false;
+          resolve();
+          setTimeout(() => {
+            this.stopAndDestroyAudio();
+            this.prepareToAnswer(true, this.currentFollowUpQuestion);
+          }, 100);
+        });
+        this.audioContext.onError((err) => {
+          console.error("iOS备选方案:追问音频播放错误:", err);
+          this.useIOSFollowUpTextFallback(resolve, reject);
+        });
+        setTimeout(() => {
+          if (this.isAudioPlaying && this.audioContext) {
+            console.log("iOS追问音频播放超时,使用文本回退");
+            this.useIOSFollowUpTextFallback(resolve, reject);
+          }
+        }, 5e3);
+      } catch (e) {
+        console.error("iOS备选追问音频播放失败:", e);
+        this.useIOSFollowUpTextFallback(resolve, reject);
+      }
+    },
+    // iOS文本回退方案
+    useIOSFollowUpTextFallback(resolve, reject) {
+      console.log("iOS追问音频使用文本回退方案");
+      this.isAudioPlaying = false;
+      common_vendor.index.hideLoading();
+      common_vendor.index.showToast({
+        title: "音频播放失败,请查看文字问题",
+        icon: "none",
+        duration: 3e3
+      });
+      resolve();
+      setTimeout(() => {
+        this.stopAndDestroyAudio();
+        this.prepareToAnswer(true, this.currentFollowUpQuestion);
+      }, 100);
+    },
+    // 通用音频播放方法(非iOS平台)
+    playGeneralFollowUpAudio(resolve, reject) {
+      try {
+        const innerAudioContext = common_vendor.index.createInnerAudioContext();
+        this.audioContext = innerAudioContext;
+        innerAudioContext.autoplay = true;
+        innerAudioContext.obeyMuteSwitch = false;
+        innerAudioContext.volume = 1;
+        innerAudioContext.onCanplay(() => {
+          console.log("音频可以播放");
+          common_vendor.index.hideLoading();
+          this.isAudioPlaying = true;
+        });
+        innerAudioContext.onEnded(() => {
+          console.log("追问音频播放完成");
+          this.isAudioPlaying = false;
+          resolve();
+          setTimeout(() => {
+            this.stopAndDestroyAudio();
+            this.prepareToAnswer(true, this.currentFollowUpQuestion);
+          }, 100);
+        });
+        innerAudioContext.onError((res) => {
+          console.error("音频播放错误:", res);
+          this.isAudioPlaying = false;
+          common_vendor.index.hideLoading();
+          common_vendor.index.showToast({
+            title: "音频播放失败",
+            icon: "none"
+          });
+          reject(res);
+          this.stopAndDestroyAudio();
+        });
+        console.log("设置音频源:", this.followUpAudioUrl);
+        innerAudioContext.src = this.followUpAudioUrl;
+      } catch (error) {
+        console.error("创建或播放音频失败:", error);
+        this.isAudioPlaying = false;
+        common_vendor.index.hideLoading();
+        common_vendor.index.showToast({
+          title: "音频播放失败",
+          icon: "none"
+        });
+        this.stopAndDestroyAudio();
+        reject(error);
+      }
+    },
     // 停止并销毁音频
     stopAndDestroyAudio() {
       if (!this.audioContext) {

+ 8 - 5
unpackage/dist/dev/mp-weixin/pages/index/index.js

@@ -56,7 +56,9 @@ const _sfc_main = {
       }
       if (parsedTenantId) {
         const storedTenantId = common_vendor.index.getStorageSync("tenant_id");
-        if (storedTenantId && storedTenantId !== parsedTenantId) {
+        const userInfo = common_vendor.index.getStorageSync("userInfo");
+        const userInfoTenantId = userInfo.tenant_id;
+        if (storedTenantId && storedTenantId !== userInfoTenantId) {
           this.silentLogout();
         }
         this.setTenantId(parsedTenantId);
@@ -235,7 +237,7 @@ const _sfc_main = {
       console.log("已选择职位:", job.id, job.title);
     },
     // 处理用户信息获取和页面跳转逻辑
-    handleUserInfoAndNavigation() {
+    handleUserInfoAndNavigation(require_resume_upload) {
       const openid = JSON.parse(common_vendor.index.getStorageSync("userInfo")).openid;
       common_vendor.index.request({
         url: `${common_config.apiBaseUrl}/api/wechat/user/get_full_info?tenant_id=${this.tenant_id || JSON.parse(common_vendor.index.getStorageSync("userInfo")).tenant_id || 1}&openid=${openid}`,
@@ -243,7 +245,7 @@ const _sfc_main = {
         success: (infoRes) => {
           if (infoRes.statusCode === 200 && infoRes.data && infoRes.data.data && infoRes.data.data.profile) {
             const resumeUrl = infoRes.data.data.profile.resume_url || "";
-            if (!resumeUrl) {
+            if (!resumeUrl && require_resume_upload) {
               common_vendor.index.navigateTo({
                 url: "/pages/uploadResume/uploadResume",
                 // 假设跳转到上传简历页面
@@ -313,6 +315,7 @@ const _sfc_main = {
               common_vendor.index.setStorageSync("configData", JSON.stringify(res.data.data));
               const configData = res.data.data;
               const enableVideoPresentation = (configData == null ? void 0 : configData.enable_video_presentation) || false;
+              const requireResumeUpload = (configData == null ? void 0 : configData.require_resume_upload) || false;
               if (enableVideoPresentation) {
                 const videoUrl = (configData == null ? void 0 : configData.video_presentation_url) || "https://data.qicai321.com/minlong/latentsync/9791ad45-dd30-4f84-a1c6-0c07c4d08707_result.mp4";
                 const nextPage = "/pages/Personal/Personal";
@@ -320,11 +323,11 @@ const _sfc_main = {
                   url: `/pages/video-briefing/video-briefing?src=${encodeURIComponent(videoUrl)}&next=${encodeURIComponent(nextPage)}`,
                   fail: (err) => {
                     console.error("跳转到视频宣讲页面失败:", err);
-                    this.handleUserInfoAndNavigation();
+                    this.handleUserInfoAndNavigation(requireResumeUpload);
                   }
                 });
               } else {
-                this.handleUserInfoAndNavigation();
+                this.handleUserInfoAndNavigation(requireResumeUpload);
               }
             }
           } else {

+ 28 - 32
unpackage/dist/dev/mp-weixin/pages/interview-question/interview-question.js

@@ -1505,22 +1505,20 @@ const _sfc_main = {
       console.log("执行页面跳转");
       this.isPlayingAiVoice = false;
       this.currentSubtitle = "";
-      setTimeout(() => {
-        common_vendor.index.reLaunch({
-          url: "/pages/success/success",
-          success: () => {
-            console.log("页面跳转成功");
-          },
-          fail: (err) => {
-            console.error("页面跳转失败:", err);
-            common_vendor.index.showToast({
-              title: "页面跳转失败",
-              icon: "none",
-              duration: 2e3
-            });
-          }
-        });
-      }, 100);
+      common_vendor.index.reLaunch({
+        url: "/pages/success/success",
+        success: () => {
+          console.log("页面跳转成功");
+        },
+        fail: (err) => {
+          console.error("页面跳转失败:", err);
+          common_vendor.index.showToast({
+            title: "页面跳转失败",
+            icon: "none",
+            duration: 2e3
+          });
+        }
+      });
     },
     // 添加处理导航失败的方法
     handleNavigationFailure() {
@@ -2235,22 +2233,20 @@ const _sfc_main = {
       console.log("执行页面跳转");
       this.isPlayingAiVoice = false;
       this.currentSubtitle = "";
-      setTimeout(() => {
-        common_vendor.index.reLaunch({
-          url: "/pages/success/success",
-          success: () => {
-            console.log("页面跳转成功");
-          },
-          fail: (err) => {
-            console.error("页面跳转失败:", err);
-            common_vendor.index.showToast({
-              title: "页面跳转失败",
-              icon: "none",
-              duration: 2e3
-            });
-          }
-        });
-      }, 100);
+      common_vendor.index.reLaunch({
+        url: "/pages/success/success",
+        success: () => {
+          console.log("页面跳转成功");
+        },
+        fail: (err) => {
+          console.error("页面跳转失败:", err);
+          common_vendor.index.showToast({
+            title: "页面跳转失败",
+            icon: "none",
+            duration: 2e3
+          });
+        }
+      });
     },
     // 新增方法:专门处理iOS小程序音频播放
     playIOSMiniProgramAudio() {

+ 3 - 5
unpackage/dist/dev/mp-weixin/pages/interview/interview.js

@@ -332,11 +332,9 @@ const _sfc_main = {
               icon: "success",
               duration: 2e3,
               success: () => {
-                setTimeout(() => {
-                  common_vendor.index.redirectTo({
-                    url: "/pages/interview_success/interview_success"
-                  });
-                }, 100);
+                common_vendor.index.redirectTo({
+                  url: "/pages/interview_success/interview_success"
+                });
               }
             });
           },

+ 1 - 3
unpackage/dist/dev/mp-weixin/pages/interview_retake/interview_retake.js

@@ -146,9 +146,7 @@ const _sfc_main = {
         icon: "success",
         duration: 1500,
         success: () => {
-          setTimeout(() => {
-            this.navigateToNextPage();
-          }, 1500);
+          this.navigateToNextPage();
         }
       });
     },

+ 10 - 3
unpackage/dist/dev/mp-weixin/pages/job-detail/job-detail.js

@@ -68,7 +68,14 @@ const _sfc_main = {
     async getJobDetail(jobId) {
       try {
         const { data } = await common_vendor.index.request({
-          url: `${common_config.apiBaseUrl}/api/mini/job/detail?id=${jobId}&tenant_id=${this.tenant_id || JSON.parse(common_vendor.index.getStorageSync("userInfo")).tenant_id || 1}`,
+          url: `${common_config.apiBaseUrl}/api/mini/job/detail?id=${jobId}&tenant_id=${this.tenant_id || (() => {
+            try {
+              const s = common_vendor.index.getStorageSync("userInfo");
+              return s ? JSON.parse(s).tenant_id || 1 : 1;
+            } catch {
+              return 1;
+            }
+          })()}`,
           method: "GET"
         });
         if (data.code === 2e3) {
@@ -388,8 +395,8 @@ const _sfc_main = {
         common_vendor.index.openLocation({
           latitude: this.mapInfo.latitude,
           longitude: this.mapInfo.longitude,
-          name: this.jobDetail.title,
-          address: this.formatLocation(this.jobDetail.location),
+          name: this.formatLocation(this.jobDetail.location),
+          // address: this.formatLocation(this.jobDetail.location),
           success: function() {
             console.log("导航打开成功");
           },

+ 1 - 1
unpackage/dist/dev/mp-weixin/pages/posture-guide/posture-guide.wxml

@@ -1 +1 @@
-<view class="posture-guide"><view class="guide-content"><view class="guide-title">体态评估环节</view><view class="guide-subtitle">请仔细阅读下方说明,完整展示手臂</view><swiper class="guide-swiper" indicator-dots="{{true}}" indicator-color="rgba(0, 0, 0, .3)" indicator-active-color="#000000" autoplay="{{false}}" bindchange="{{b}}"><swiper-item wx:for="{{a}}" wx:for-item="item" wx:key="c"><view class="swiper-item"><image src="{{item.a}}" mode="aspectFit" class="guide-image"></image><view class="image-description">{{item.b}}</view></view></swiper-item></swiper><button class="{{['confirm-button', d && 'button-disabled']}}" disabled="{{e}}" bindtap="{{f}}">{{c}}</button></view></view>
+<view class="posture-guide"><view class="guide-content"><view class="guide-title">体态评估环节</view><view class="guide-subtitle">请仔细阅读下方说明,完整展示手臂,向右滑动查看更多</view><swiper class="guide-swiper" indicator-dots="{{true}}" indicator-color="rgba(0, 0, 0, .3)" indicator-active-color="#000000" autoplay="{{false}}" bindchange="{{b}}"><swiper-item wx:for="{{a}}" wx:for-item="item" wx:key="c"><view class="swiper-item"><image src="{{item.a}}" mode="aspectFit" class="guide-image"></image><view class="image-description">{{item.b}}</view></view></swiper-item></swiper><button class="{{['confirm-button', d && 'button-disabled']}}" disabled="{{e}}" bindtap="{{f}}">{{c}}</button></view></view>

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

@@ -8,7 +8,7 @@
     "urlCheck": false,
     "es6": true,
     "postcss": false,
-    "minified": false,
+    "minified": true,
     "newFeature": true,
     "bigPackageSizeSupport": true,
     "babelSetting": {
@@ -18,7 +18,7 @@
     }
   },
   "compileType": "miniprogram",
-  "libVersion": "3.10.2",
+  "libVersion": "3.10.3",
   "appid": "wxc9655eeaa3223b75",
   "projectname": "interview_uni",
   "condition": {

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

@@ -10,7 +10,7 @@
         {
           "name": "pages/index/index",
           "pathName": "pages/index/index",
-          "query": "scene=15",
+          "query": "scene=1",
           "launchMode": "default",
           "scene": 1047
         },

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.