ソースを参照

处理ios无法预览

yangg 2 ヶ月 前
コミット
9578e484dc

+ 314 - 38
pages/identity-verify/identity-verify.vue

@@ -41,8 +41,12 @@
                 class="user-camera-video"
                 @error="handleCameraError"
                 :record-audio="true"
-                frame-size="medium"
-                resolution="medium">
+                frame-size="small"
+                resolution="low"
+                :disable-zoom="true"
+                :enable-camera="true"
+                :enable-record="true"
+                mode="normal">
         </camera>
         <!-- 在H5/App环境中使用video元素 -->
         <video v-else
@@ -215,6 +219,10 @@ export default {
     this.playDigitalHumanVideo();
     this.checkAudioPermission();
     this.initCamera();
+    this.checkIOSCameraRecordPermission();
+    
+    // 添加防御性检查,避免渲染错误
+    this.checkAndFixRenderingIssues();
     
     // 添加音频测试
     setTimeout(() => {
@@ -245,9 +253,10 @@ export default {
         // 创建相机上下文
         this.cameraContext = uni.createCameraContext();
         
-        // 确保已获取录音权限
+        // 确保已获取录音和相机权限
         uni.getSetting({
           success: (res) => {
+            // 检查录音权限
             if (!res.authSetting['scope.record']) {
               uni.authorize({
                 scope: 'scope.record',
@@ -261,6 +270,7 @@ export default {
               });
             }
             
+            // 检查相机权限
             if (!res.authSetting['scope.camera']) {
               uni.authorize({
                 scope: 'scope.camera',
@@ -273,6 +283,32 @@ export default {
                 }
               });
             }
+            
+            // 在iOS上,可能需要额外的权限检查
+            const systemInfo = uni.getSystemInfoSync();
+            if (systemInfo.platform === 'ios') {
+              // 在iOS上,不要使用无效的权限范围
+              // 移除以下代码块
+              /*
+              if (!res.authSetting['scope.camera.record']) {
+                uni.authorize({
+                  scope: 'scope.camera.record',
+                  success: () => {
+                    console.log('相机录制权限已获取');
+                  },
+                  fail: (err) => {
+                    console.error('相机录制权限获取失败:', err);
+                    this.showPermissionDialog('相机录制');
+                  }
+                });
+              }
+              */
+              
+              // 确保同时获取了相机和录音权限
+              if (!res.authSetting['scope.camera'] || !res.authSetting['scope.record']) {
+                console.log('iOS需要同时获取相机和录音权限');
+              }
+            }
           }
         });
       } else {
@@ -775,10 +811,58 @@ export default {
       this.showStopRecordingButton = true;
     },
 
-    // 修改小程序环境下的录制方法
+    // 添加一个新方法:重置相机组件
+    resetCamera() {
+      console.log('重置相机组件');
+      
+      // 先完全移除相机组件
+      this.useMiniProgramCameraComponent = false;
+      
+      // 释放相机上下文
+      if (this.cameraContext) {
+        this.cameraContext = null;
+      }
+      
+      // 延迟后重新创建相机组件
+      setTimeout(() => {
+        this.useMiniProgramCameraComponent = true;
+        
+        // 再次延迟创建相机上下文,确保组件已完全渲染
+        setTimeout(() => {
+          this.cameraContext = uni.createCameraContext();
+          console.log('相机组件已重置');
+        }, 500);
+      }, 500);
+    },
+
+    // 修改 startMiniProgramRecording 方法
     startMiniProgramRecording() {
+      console.log('开始小程序录制方法');
+      
+      // 获取平台信息
+      const systemInfo = uni.getSystemInfoSync();
+      const isIOS = systemInfo.platform === 'ios';
+      
+      // 在iOS上,先重置相机
+      if (isIOS) {
+        // 先重置相机组件
+        this.resetCamera();
+        
+        // 延迟执行录制,给相机组件足够的初始化时间
+        setTimeout(() => {
+          this.actualStartRecording(isIOS);
+        }, 1000);
+      } else {
+        // Android直接开始
+        this.actualStartRecording(isIOS);
+      }
+    },
+
+    // 添加新方法:实际开始录制
+    actualStartRecording(isIOS) {
       if (!this.cameraContext) {
         this.cameraContext = uni.createCameraContext();
+        console.log('创建新的相机上下文');
       }
       
       // 确保有录音权限
@@ -793,29 +877,95 @@ export default {
             return;
           }
           
-          // 开始录像,添加质量控制参数
-          const options = {
-            timeout: 60000, // 最长录制60秒
-            quality: 'medium', // 可选值:'low', 'medium', 'high'
-            compressed: true, // 是否压缩视频
-            success: () => {
-              console.log('小程序录像开始成功');
-            },
-            fail: (err) => {
-              console.error('小程序录像开始失败:', err);
-              uni.showToast({
-                title: '录制失败,请检查相机权限',
-                icon: 'none'
-              });
-              this.proceedToNextQuestion();
-            },
-            timeoutCallback: () => {
-              console.log('录制超时自动停止');
-              this.stopRecordingAnswer();
+          // 在iOS上,先检查相机状态
+          if (isIOS) {
+            console.log('iOS: 检查相机状态');
+            
+            // 使用最简单的选项
+            const options = {
+              timeout: 30000, // 减少超时时间
+              quality: 'low', // 降低质量
+              compressed: true,
+              success: () => {
+                console.log('iOS录制开始成功');
+              },
+              fail: (err) => {
+                console.error('iOS录制失败:', err);
+                
+                // 如果失败,尝试使用不同的方法
+                this.useAlternativeRecordingMethod();
+              }
+            };
+            
+            try {
+              console.log('尝试开始录制');
+              this.recorder = this.cameraContext.startRecord(options);
+            } catch (e) {
+              console.error('开始录制异常:', e);
+              this.useAlternativeRecordingMethod();
             }
-          };
-          
-          this.recorder = this.cameraContext.startRecord(options);
+          } else {
+            // Android使用标准选项
+            const options = {
+              timeout: 60000,
+              quality: 'medium',
+              compressed: true,
+              success: () => {
+                console.log('Android录制开始成功');
+              },
+              fail: (err) => {
+                console.error('Android录制失败:', err);
+                uni.showToast({
+                  title: '录制失败,请检查相机权限',
+                  icon: 'none'
+                });
+                this.proceedToNextQuestion();
+              }
+            };
+            
+            this.recorder = this.cameraContext.startRecord(options);
+          }
+        }
+      });
+    },
+
+    // 添加新方法:使用替代录制方法
+    useAlternativeRecordingMethod() {
+      console.log('使用替代录制方法');
+      
+      // 在iOS上,可以尝试使用chooseVideo API作为备选
+      uni.showActionSheet({
+        itemList: ['使用相册中的视频', '跳过此问题'],
+        success: (res) => {
+          if (res.tapIndex === 0) {
+            // 选择相册中的视频
+            uni.chooseVideo({
+              sourceType: ['album'],
+              maxDuration: 60,
+              camera: 'front',
+              success: (res) => {
+                console.log('选择视频成功:', res.tempFilePath);
+                // 停止录制状态
+                this.isRecording = false;
+                this.showStopRecordingButton = false;
+                
+                // 上传选择的视频
+                this.uploadRecordedVideo(res.tempFilePath);
+              },
+              fail: () => {
+                console.log('用户取消选择视频');
+                this.proceedToNextQuestion();
+              }
+            });
+          } else {
+            // 跳过此问题
+            console.log('用户选择跳过问题');
+            this.proceedToNextQuestion();
+          }
+        },
+        fail: () => {
+          console.log('操作取消');
+          this.proceedToNextQuestion();
         }
       });
     },
@@ -1074,7 +1224,7 @@ export default {
       }
     },
 
-    // 添加新方法:停止小程序录制
+    // 修改 stopMiniProgramRecording 方法
     stopMiniProgramRecording() {
       if (!this.cameraContext) {
         console.error('相机上下文不存在');
@@ -1082,13 +1232,46 @@ export default {
         return;
       }
       
-      this.cameraContext.stopRecord({
+      const systemInfo = uni.getSystemInfoSync();
+      const isIOS = systemInfo.platform === 'ios';
+      
+      // 在iOS上添加额外的错误处理
+      const stopOptions = {
         success: (res) => {
           console.log('小程序录像停止成功:', res);
           // 获取临时文件路径
           const tempFilePath = res.tempVideoPath;
-          // 上传视频
-          this.uploadRecordedVideo(tempFilePath);
+          if (!tempFilePath) {
+            console.error('未获取到视频文件路径');
+            uni.showToast({
+              title: '录制失败,未获取到视频文件',
+              icon: 'none'
+            });
+            this.proceedToNextQuestion();
+            return;
+          }
+          
+          // 在iOS上,检查文件是否存在
+          if (isIOS) {
+            uni.getFileInfo({
+              filePath: tempFilePath,
+              success: () => {
+                // 文件存在,上传视频
+                this.uploadRecordedVideo(tempFilePath);
+              },
+              fail: (err) => {
+                console.error('视频文件不存在:', err);
+                uni.showToast({
+                  title: '录制失败,视频文件不存在',
+                  icon: 'none'
+                });
+                this.proceedToNextQuestion();
+              }
+            });
+          } else {
+            // Android直接上传
+            this.uploadRecordedVideo(tempFilePath);
+          }
         },
         fail: (err) => {
           console.error('小程序录像停止失败:', err);
@@ -1098,7 +1281,10 @@ export default {
           });
           this.proceedToNextQuestion();
         }
-      });
+      };
+      
+      // 停止录制
+      this.cameraContext.stopRecord(stopOptions);
     },
 
     // 添加新方法:停止浏览器录制
@@ -1442,14 +1628,43 @@ export default {
     handleCameraError(e) {
       console.error('相机错误:', e);
       
-      // 显示错误提示
-      uni.showToast({
-        title: '相机初始化失败,请检查权限设置',
-        icon: 'none'
-      });
+      // 获取平台信息
+      const systemInfo = uni.getSystemInfoSync();
+      const isIOS = systemInfo.platform === 'ios';
       
-      // 尝试备用选项
-      this.tryFallbackOptions();
+      if (isIOS) {
+        console.log('iOS相机错误,尝试重新初始化');
+        
+        // 显示提示
+        uni.showToast({
+          title: '相机初始化中...',
+          icon: 'loading',
+          duration: 2000
+        });
+        
+        // 重置相机
+        this.resetCamera();
+        
+        // 如果正在录制,停止录制
+        if (this.isRecording) {
+          this.isRecording = false;
+          this.showStopRecordingButton = false;
+          
+          // 提供替代选项
+          setTimeout(() => {
+            this.useAlternativeRecordingMethod();
+          }, 1000);
+        }
+      } else {
+        // 显示错误提示
+        uni.showToast({
+          title: '相机初始化失败,请检查权限设置',
+          icon: 'none'
+        });
+        
+        // 尝试备用选项
+        this.tryFallbackOptions();
+      }
     },
 
     // 添加新方法:尝试备用选项
@@ -1804,6 +2019,67 @@ export default {
           videoElement.play();
         };
       });
+    },
+
+    // 修改 checkIOSCameraRecordPermission 方法
+    checkIOSCameraRecordPermission() {
+      const systemInfo = uni.getSystemInfoSync();
+      if (systemInfo.platform !== 'ios') return;
+      
+      // 在iOS上,需要同时请求相机和录音权限
+      uni.getSetting({
+        success: (res) => {
+          // 检查相机权限
+          if (!res.authSetting['scope.camera']) {
+            uni.authorize({
+              scope: 'scope.camera',
+              success: () => {
+                console.log('iOS相机权限已获取');
+              },
+              fail: (err) => {
+                console.error('iOS相机权限获取失败:', err);
+                this.showPermissionDialog('相机');
+              }
+            });
+          }
+          
+          // 检查录音权限
+          if (!res.authSetting['scope.record']) {
+            uni.authorize({
+              scope: 'scope.record',
+              success: () => {
+                console.log('iOS录音权限已获取');
+              },
+              fail: (err) => {
+                console.error('iOS录音权限获取失败:', err);
+                this.showPermissionDialog('录音');
+              }
+            });
+          }
+        }
+      });
+    },
+
+    // 添加新方法:检查并修复渲染问题
+    checkAndFixRenderingIssues() {
+      // 检查全局对象,防止渲染错误
+      try {
+        // 检查是否有全局变量u
+        if (typeof u !== 'undefined' && u) {
+          // 检查currentQuestion属性
+          if (!u.currentQuestion) {
+            console.log('修复: 创建缺失的currentQuestion对象');
+            u.currentQuestion = {};
+          }
+          // 确保isImportant属性存在
+          if (u.currentQuestion && typeof u.currentQuestion.isImportant === 'undefined') {
+            console.log('修复: 设置缺失的isImportant属性');
+            u.currentQuestion.isImportant = false;
+          }
+        }
+      } catch (e) {
+        console.log('防御性检查异常:', e);
+      }
     }
   }
 }

+ 288 - 289
unpackage/dist/dev/mp-weixin/pages/identity-verify/identity-verify.js

@@ -105,18 +105,16 @@ const _sfc_main = {
       showStartRecordingButton: false,
       showRetryButton: false,
       // 控制重试按钮显示
-      lastVideoToRetry: null,
+      lastVideoToRetry: null
       // 存储上次失败的视频URL,用于重试
-      stopIOSRecording: null,
-      // 存储iOS特殊停止录制函数
-      cameraInitialized: false,
-      iosDevice: false
     };
   },
   mounted() {
     this.playDigitalHumanVideo();
     this.checkAudioPermission();
     this.initCamera();
+    this.checkIOSCameraRecordPermission();
+    this.checkAndFixRenderingIssues();
     setTimeout(() => {
       if (this.cameraStream && !this.useMiniProgramCameraComponent) {
         this.testAudioInput();
@@ -130,18 +128,44 @@ const _sfc_main = {
     // 初始化相机
     async initCamera() {
       const systemInfo = common_vendor.index.getSystemInfoSync();
-      this.iosDevice = systemInfo.platform === "ios";
-      console.log("当前设备平台:", systemInfo.platform, "是否iOS:", this.iosDevice);
       const isMiniProgram = systemInfo.uniPlatform === "mp-weixin" || systemInfo.uniPlatform === "mp-alipay" || systemInfo.uniPlatform === "mp-baidu";
       if (isMiniProgram) {
         this.useMiniProgramCameraComponent = true;
-        await this.checkMiniProgramPermissions();
-        setTimeout(() => {
-          if (!this.cameraContext) {
-            this.cameraContext = common_vendor.index.createCameraContext();
-            console.log("相机上下文创建完成");
+        this.cameraContext = common_vendor.index.createCameraContext();
+        common_vendor.index.getSetting({
+          success: (res) => {
+            if (!res.authSetting["scope.record"]) {
+              common_vendor.index.authorize({
+                scope: "scope.record",
+                success: () => {
+                  console.log("录音权限已获取");
+                },
+                fail: (err) => {
+                  console.error("录音权限获取失败:", err);
+                  this.showPermissionDialog("录音");
+                }
+              });
+            }
+            if (!res.authSetting["scope.camera"]) {
+              common_vendor.index.authorize({
+                scope: "scope.camera",
+                success: () => {
+                  console.log("相机权限已获取");
+                },
+                fail: (err) => {
+                  console.error("相机权限获取失败:", err);
+                  this.showPermissionDialog("相机");
+                }
+              });
+            }
+            const systemInfo2 = common_vendor.index.getSystemInfoSync();
+            if (systemInfo2.platform === "ios") {
+              if (!res.authSetting["scope.camera"] || !res.authSetting["scope.record"]) {
+                console.log("iOS需要同时获取相机和录音权限");
+              }
+            }
           }
-        }, 500);
+        });
       } else {
         try {
           const constraints = {
@@ -519,131 +543,150 @@ const _sfc_main = {
       }
       this.showStopRecordingButton = true;
     },
-    // 修改小程序环境下的录制方法
+    // 添加一个新方法:重置相机组件
+    resetCamera() {
+      console.log("重置相机组件");
+      this.useMiniProgramCameraComponent = false;
+      if (this.cameraContext) {
+        this.cameraContext = null;
+      }
+      setTimeout(() => {
+        this.useMiniProgramCameraComponent = true;
+        setTimeout(() => {
+          this.cameraContext = common_vendor.index.createCameraContext();
+          console.log("相机组件已重置");
+        }, 500);
+      }, 500);
+    },
+    // 修改 startMiniProgramRecording 方法
     startMiniProgramRecording() {
-      console.log("开始小程序录像,相机初始化状态:", this.cameraInitialized);
-      if (!this.cameraInitialized) {
-        common_vendor.index.showToast({
-          title: "相机正在初始化,请稍候",
-          icon: "none"
-        });
+      console.log("开始小程序录制方法");
+      const systemInfo = common_vendor.index.getSystemInfoSync();
+      const isIOS = systemInfo.platform === "ios";
+      if (isIOS) {
+        this.resetCamera();
         setTimeout(() => {
-          this.startMiniProgramRecording();
+          this.actualStartRecording(isIOS);
         }, 1e3);
-        return;
+      } else {
+        this.actualStartRecording(isIOS);
       }
+    },
+    // 添加新方法:实际开始录制
+    actualStartRecording(isIOS) {
       if (!this.cameraContext) {
         this.cameraContext = common_vendor.index.createCameraContext();
-        console.log("创建相机上下文");
+        console.log("创建新的相机上下文");
       }
-      const options = {
-        timeout: 6e4,
-        // 最长录制60秒
-        success: () => {
-          console.log("小程序录像开始成功");
-          this.isRecording = true;
-        },
-        fail: (err) => {
-          console.error("小程序录像开始失败:", err);
-          if (this.iosDevice && !this.hasRetriedIOS) {
-            this.hasRetriedIOS = true;
-            console.log("iOS设备录制失败,尝试使用备用方法");
-            setTimeout(() => {
-              this.cameraContext = common_vendor.index.createCameraContext();
-              this.cameraContext.startRecord({
-                success: () => {
-                  console.log("iOS备用方法录像开始成功");
-                  this.isRecording = true;
-                },
-                fail: (retryErr) => {
-                  console.error("iOS备用方法录像失败:", retryErr);
-                  common_vendor.index.showToast({
-                    title: "录制失败,请检查相机权限",
-                    icon: "none"
-                  });
-                  this.proceedToNextQuestion();
-                }
-              });
-            }, 500);
+      common_vendor.index.getSetting({
+        success: (res) => {
+          const hasRecordAuth = res.authSetting["scope.record"];
+          const hasCameraAuth = res.authSetting["scope.camera"];
+          if (!hasRecordAuth || !hasCameraAuth) {
+            console.warn("缺少必要权限,请求权限");
+            this.requestMiniProgramPermissions();
             return;
           }
-          common_vendor.index.showToast({
-            title: "录制失败,请检查相机权限",
-            icon: "none"
-          });
+          if (isIOS) {
+            console.log("iOS: 检查相机状态");
+            const options = {
+              timeout: 3e4,
+              // 减少超时时间
+              quality: "low",
+              // 降低质量
+              compressed: true,
+              success: () => {
+                console.log("iOS录制开始成功");
+              },
+              fail: (err) => {
+                console.error("iOS录制失败:", err);
+                this.useAlternativeRecordingMethod();
+              }
+            };
+            try {
+              console.log("尝试开始录制");
+              this.recorder = this.cameraContext.startRecord(options);
+            } catch (e) {
+              console.error("开始录制异常:", e);
+              this.useAlternativeRecordingMethod();
+            }
+          } else {
+            const options = {
+              timeout: 6e4,
+              quality: "medium",
+              compressed: true,
+              success: () => {
+                console.log("Android录制开始成功");
+              },
+              fail: (err) => {
+                console.error("Android录制失败:", err);
+                common_vendor.index.showToast({
+                  title: "录制失败,请检查相机权限",
+                  icon: "none"
+                });
+                this.proceedToNextQuestion();
+              }
+            };
+            this.recorder = this.cameraContext.startRecord(options);
+          }
+        }
+      });
+    },
+    // 添加新方法:使用替代录制方法
+    useAlternativeRecordingMethod() {
+      console.log("使用替代录制方法");
+      common_vendor.index.showActionSheet({
+        itemList: ["使用相册中的视频", "跳过此问题"],
+        success: (res) => {
+          if (res.tapIndex === 0) {
+            common_vendor.index.chooseVideo({
+              sourceType: ["album"],
+              maxDuration: 60,
+              camera: "front",
+              success: (res2) => {
+                console.log("选择视频成功:", res2.tempFilePath);
+                this.isRecording = false;
+                this.showStopRecordingButton = false;
+                this.uploadRecordedVideo(res2.tempFilePath);
+              },
+              fail: () => {
+                console.log("用户取消选择视频");
+                this.proceedToNextQuestion();
+              }
+            });
+          } else {
+            console.log("用户选择跳过问题");
+            this.proceedToNextQuestion();
+          }
+        },
+        fail: () => {
+          console.log("操作取消");
           this.proceedToNextQuestion();
         }
-      };
-      if (this.iosDevice) {
-        delete options.timeout;
-        console.log("使用iOS专用录制参数");
-      } else {
-        options.quality = "medium";
-        options.compressed = true;
-        options.timeoutCallback = () => {
-          console.log("录制超时自动停止");
-          this.stopRecordingAnswer();
-        };
-      }
-      console.log("调用startRecord,参数:", JSON.stringify(options));
-      this.recorder = this.cameraContext.startRecord(options);
+      });
     },
     // 添加新方法:请求小程序权限
-    async checkMiniProgramPermissions() {
-      return new Promise((resolve) => {
-        common_vendor.index.getSetting({
-          success: (res) => {
-            const hasRecordAuth = res.authSetting["scope.record"];
-            const hasCameraAuth = res.authSetting["scope.camera"];
-            const authPromises = [];
-            if (!hasRecordAuth) {
-              authPromises.push(
-                new Promise((resolveAuth) => {
-                  common_vendor.index.authorize({
-                    scope: "scope.record",
-                    success: () => {
-                      console.log("录音权限已获取");
-                      resolveAuth();
-                    },
-                    fail: (err) => {
-                      console.error("录音权限获取失败:", err);
-                      this.showPermissionDialog("录音");
-                      resolveAuth();
-                    }
-                  });
-                })
-              );
-            }
-            if (!hasCameraAuth) {
-              authPromises.push(
-                new Promise((resolveAuth) => {
-                  common_vendor.index.authorize({
-                    scope: "scope.camera",
-                    success: () => {
-                      console.log("相机权限已获取");
-                      resolveAuth();
-                    },
-                    fail: (err) => {
-                      console.error("相机权限获取失败:", err);
-                      this.showPermissionDialog("相机");
-                      resolveAuth();
-                    }
-                  });
-                })
-              );
-            }
-            if (authPromises.length > 0) {
-              Promise.all(authPromises).then(() => {
-                resolve();
-              });
-            } else {
-              resolve();
+    requestMiniProgramPermissions() {
+      common_vendor.index.authorize({
+        scope: "scope.record",
+        success: () => {
+          console.log("录音权限已获取");
+          common_vendor.index.authorize({
+            scope: "scope.camera",
+            success: () => {
+              console.log("相机权限已获取");
+              this.startMiniProgramRecording();
+            },
+            fail: (err) => {
+              console.error("相机权限获取失败:", err);
+              this.showPermissionDialog("相机");
             }
-          },
-          fail: () => {
-            resolve();
-          }
-        });
+          });
+        },
+        fail: (err) => {
+          console.error("录音权限获取失败:", err);
+          this.showPermissionDialog("录音");
+        }
       });
     },
     // 修改浏览器环境下的录制方法
@@ -658,8 +701,6 @@ const _sfc_main = {
         return;
       }
       try {
-        const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
-        console.log("当前设备是否为iOS:", isIOS);
         const hasAudio = this.cameraStream.getAudioTracks().length > 0;
         if (!hasAudio) {
           console.warn("警告:媒体流中没有音频轨道,尝试重新获取带音频的媒体流");
@@ -687,18 +728,18 @@ const _sfc_main = {
                 videoElement.srcObject = combinedStream;
                 videoElement.muted = true;
               }
-              this.setupMediaRecorder(combinedStream, isIOS);
+              this.setupMediaRecorder(combinedStream);
             } else {
               console.warn("仍然无法获取音频轨道");
-              this.setupMediaRecorder(this.cameraStream, isIOS);
+              this.setupMediaRecorder(this.cameraStream);
             }
           }).catch((err) => {
             console.error("获取音频失败:", err);
-            this.setupMediaRecorder(this.cameraStream, isIOS);
+            this.setupMediaRecorder(this.cameraStream);
           });
         } else {
           console.log("检测到音频轨道,直接使用");
-          this.setupMediaRecorder(this.cameraStream, isIOS);
+          this.setupMediaRecorder(this.cameraStream);
         }
       } catch (error) {
         console.error("浏览器录制失败:", error);
@@ -709,16 +750,11 @@ const _sfc_main = {
         this.proceedToNextQuestion();
       }
     },
-    // 修改 setupMediaRecorder 方法,添加 isIOS 参数
-    setupMediaRecorder(stream, isIOS) {
+    // 修改 setupMediaRecorder 方法
+    setupMediaRecorder(stream) {
       const videoTracks = stream.getVideoTracks();
       const audioTracks = stream.getAudioTracks();
       console.log("设置MediaRecorder - 视频轨道:", videoTracks.length, "音频轨道:", audioTracks.length);
-      if (isIOS) {
-        console.log("检测到iOS设备,使用替代录制方法");
-        this.setupIOSRecording(stream);
-        return;
-      }
       let mimeType = "";
       const supportedTypes = [
         "video/webm;codecs=vp9,opus",
@@ -798,109 +834,6 @@ const _sfc_main = {
         console.error("开始录制失败:", e);
       }
     },
-    // 添加新方法:为iOS设备设置特殊录制方法
-    setupIOSRecording(stream) {
-      console.log("设置iOS特殊录制方法");
-      const videoElement = this.$refs.userCameraVideo;
-      const canvas = document.createElement("canvas");
-      const ctx = canvas.getContext("2d");
-      canvas.width = 640;
-      canvas.height = 480;
-      this.recordedFrames = [];
-      this.recordingStartTime = Date.now();
-      this.frameCount = 0;
-      const audioTracks = stream.getAudioTracks();
-      let audioRecorder = null;
-      let audioChunks = [];
-      if (audioTracks.length > 0) {
-        const audioStream = new MediaStream([audioTracks[0]]);
-        try {
-          audioRecorder = new MediaRecorder(audioStream);
-          audioRecorder.ondataavailable = (e) => {
-            if (e.data.size > 0) {
-              audioChunks.push(e.data);
-            }
-          };
-          audioRecorder.start(1e3);
-        } catch (e) {
-          console.warn("iOS音频录制器创建失败:", e);
-        }
-      }
-      const captureFrame = () => {
-        if (!this.isRecording)
-          return;
-        try {
-          ctx.drawImage(videoElement, 0, 0, canvas.width, canvas.height);
-          const imageData = canvas.toDataURL("image/jpeg", 0.8);
-          this.recordedFrames.push({
-            image: imageData,
-            timestamp: Date.now() - this.recordingStartTime
-          });
-          this.frameCount++;
-          if (this.frameCount % 15 === 0) {
-            console.log(`已捕获 ${this.frameCount} 帧`);
-          }
-          this.frameCapturingId = requestAnimationFrame(captureFrame);
-        } catch (e) {
-          console.error("捕获视频帧失败:", e);
-        }
-      };
-      this.frameCapturingId = requestAnimationFrame(captureFrame);
-      this.stopIOSRecording = async () => {
-        console.log("停止iOS录制,已捕获帧数:", this.recordedFrames.length);
-        if (this.frameCapturingId) {
-          cancelAnimationFrame(this.frameCapturingId);
-          this.frameCapturingId = null;
-        }
-        if (audioRecorder && audioRecorder.state !== "inactive") {
-          audioRecorder.stop();
-        }
-        common_vendor.index.showLoading({
-          title: "正在处理视频...",
-          mask: true
-        });
-        try {
-          if (audioRecorder) {
-            await new Promise((resolve) => {
-              audioRecorder.onstop = resolve;
-              if (audioRecorder.state === "inactive")
-                resolve();
-            });
-          }
-          const videoBlob = await this.createVideoFromFrames(this.recordedFrames, audioChunks);
-          const fileName = `answer_${this.currentVideoIndex}_${Date.now()}.mp4`;
-          const file = new File([videoBlob], fileName, { type: "video/mp4" });
-          common_vendor.index.hideLoading();
-          this.uploadRecordedVideo(file);
-        } catch (error) {
-          console.error("iOS视频处理失败:", error);
-          common_vendor.index.hideLoading();
-          common_vendor.index.showToast({
-            title: "视频处理失败",
-            icon: "none"
-          });
-          this.proceedToNextQuestion();
-        }
-      };
-    },
-    // 添加新方法:从帧创建视频
-    async createVideoFromFrames(frames, audioChunks) {
-      console.log("从帧创建视频,帧数:", frames.length);
-      const videoData = {
-        frames: frames.slice(0, Math.min(frames.length, 300)),
-        // 限制帧数以减小大小
-        audioBlob: audioChunks.length > 0 ? await new Blob(audioChunks, { type: "audio/webm" }).arrayBuffer() : null,
-        metadata: {
-          duration: frames.length > 0 ? frames[frames.length - 1].timestamp : 0,
-          frameCount: frames.length,
-          hasAudio: audioChunks.length > 0,
-          deviceInfo: navigator.userAgent,
-          timestamp: Date.now()
-        }
-      };
-      const jsonString = JSON.stringify(videoData);
-      return new Blob([jsonString], { type: "application/json" });
-    },
     // 添加新方法:停止录制用户回答
     stopRecordingAnswer() {
       console.log("停止录制用户回答");
@@ -911,48 +844,56 @@ const _sfc_main = {
       }
       common_vendor.index.hideLoading();
       this.showStopRecordingButton = false;
-      const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
       const systemInfo = common_vendor.index.getSystemInfoSync();
       const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith("mp-");
       if (isMiniProgram) {
         this.stopMiniProgramRecording();
-      } else if (isIOS && this.stopIOSRecording) {
-        this.stopIOSRecording();
       } else {
         this.stopBrowserRecording();
       }
     },
-    // 添加新方法:停止小程序录制
+    // 修改 stopMiniProgramRecording 方法
     stopMiniProgramRecording() {
-      console.log("停止小程序录像");
       if (!this.cameraContext) {
         console.error("相机上下文不存在");
         this.proceedToNextQuestion();
         return;
       }
-      common_vendor.index.showLoading({
-        title: "正在处理视频...",
-        mask: true
-      });
-      this.cameraContext.stopRecord({
+      const systemInfo = common_vendor.index.getSystemInfoSync();
+      const isIOS = systemInfo.platform === "ios";
+      const stopOptions = {
         success: (res) => {
           console.log("小程序录像停止成功:", res);
-          common_vendor.index.hideLoading();
-          const tempFilePath = res.tempVideoPath || res.tempThumbPath || res.tempFilePath;
-          if (tempFilePath) {
-            console.log("获取到视频文件路径:", tempFilePath);
-            this.uploadRecordedVideo(tempFilePath);
-          } else {
+          const tempFilePath = res.tempVideoPath;
+          if (!tempFilePath) {
             console.error("未获取到视频文件路径");
             common_vendor.index.showToast({
               title: "录制失败,未获取到视频文件",
               icon: "none"
             });
             this.proceedToNextQuestion();
+            return;
+          }
+          if (isIOS) {
+            common_vendor.index.getFileInfo({
+              filePath: tempFilePath,
+              success: () => {
+                this.uploadRecordedVideo(tempFilePath);
+              },
+              fail: (err) => {
+                console.error("视频文件不存在:", err);
+                common_vendor.index.showToast({
+                  title: "录制失败,视频文件不存在",
+                  icon: "none"
+                });
+                this.proceedToNextQuestion();
+              }
+            });
+          } else {
+            this.uploadRecordedVideo(tempFilePath);
           }
         },
         fail: (err) => {
-          common_vendor.index.hideLoading();
           console.error("小程序录像停止失败:", err);
           common_vendor.index.showToast({
             title: "录制失败",
@@ -960,7 +901,8 @@ const _sfc_main = {
           });
           this.proceedToNextQuestion();
         }
-      });
+      };
+      this.cameraContext.stopRecord(stopOptions);
     },
     // 添加新方法:停止浏览器录制
     stopBrowserRecording() {
@@ -975,7 +917,6 @@ const _sfc_main = {
     // 修改上传录制的视频方法
     uploadRecordedVideo(fileOrPath) {
       console.log("准备上传视频:", typeof fileOrPath === "string" ? fileOrPath : fileOrPath.name);
-      const isIOSSpecialFormat = typeof fileOrPath !== "string" && fileOrPath.type === "application/json";
       common_vendor.index.showLoading({
         title: "正在上传...",
         mask: true
@@ -1009,9 +950,6 @@ const _sfc_main = {
         formData.append("question_id", questionId);
         formData.append("video_duration", 0);
         formData.append("has_audio", "true");
-        if (isIOSSpecialFormat) {
-          formData.append("is_ios_format", "true");
-        }
         const xhr = new XMLHttpRequest();
         xhr.open("POST", `${common_config.apiBaseUrl}/api/system/upload/`, true);
         xhr.timeout = 12e4;
@@ -1241,11 +1179,30 @@ const _sfc_main = {
     // 处理相机错误
     handleCameraError(e) {
       console.error("相机错误:", e);
-      common_vendor.index.showToast({
-        title: "相机初始化失败,请检查权限设置",
-        icon: "none"
-      });
-      this.tryFallbackOptions();
+      const systemInfo = common_vendor.index.getSystemInfoSync();
+      const isIOS = systemInfo.platform === "ios";
+      if (isIOS) {
+        console.log("iOS相机错误,尝试重新初始化");
+        common_vendor.index.showToast({
+          title: "相机初始化中...",
+          icon: "loading",
+          duration: 2e3
+        });
+        this.resetCamera();
+        if (this.isRecording) {
+          this.isRecording = false;
+          this.showStopRecordingButton = false;
+          setTimeout(() => {
+            this.useAlternativeRecordingMethod();
+          }, 1e3);
+        }
+      } else {
+        common_vendor.index.showToast({
+          title: "相机初始化失败,请检查权限设置",
+          icon: "none"
+        });
+        this.tryFallbackOptions();
+      }
     },
     // 添加新方法:尝试备用选项
     tryFallbackOptions() {
@@ -1508,12 +1465,55 @@ const _sfc_main = {
         };
       });
     },
-    // 添加相机初始化完成的处理方法
-    handleCameraInit() {
-      console.log("相机初始化完成");
-      this.cameraInitialized = true;
-      if (!this.cameraContext && this.useMiniProgramCameraComponent) {
-        this.cameraContext = common_vendor.index.createCameraContext();
+    // 修改 checkIOSCameraRecordPermission 方法
+    checkIOSCameraRecordPermission() {
+      const systemInfo = common_vendor.index.getSystemInfoSync();
+      if (systemInfo.platform !== "ios")
+        return;
+      common_vendor.index.getSetting({
+        success: (res) => {
+          if (!res.authSetting["scope.camera"]) {
+            common_vendor.index.authorize({
+              scope: "scope.camera",
+              success: () => {
+                console.log("iOS相机权限已获取");
+              },
+              fail: (err) => {
+                console.error("iOS相机权限获取失败:", err);
+                this.showPermissionDialog("相机");
+              }
+            });
+          }
+          if (!res.authSetting["scope.record"]) {
+            common_vendor.index.authorize({
+              scope: "scope.record",
+              success: () => {
+                console.log("iOS录音权限已获取");
+              },
+              fail: (err) => {
+                console.error("iOS录音权限获取失败:", err);
+                this.showPermissionDialog("录音");
+              }
+            });
+          }
+        }
+      });
+    },
+    // 添加新方法:检查并修复渲染问题
+    checkAndFixRenderingIssues() {
+      try {
+        if (typeof u !== "undefined" && u) {
+          if (!u.currentQuestion) {
+            console.log("修复: 创建缺失的currentQuestion对象");
+            u.currentQuestion = {};
+          }
+          if (u.currentQuestion && typeof u.currentQuestion.isImportant === "undefined") {
+            console.log("修复: 设置缺失的isImportant属性");
+            u.currentQuestion.isImportant = false;
+          }
+        }
+      } catch (e) {
+        console.log("防御性检查异常:", e);
       }
     }
   }
@@ -1534,22 +1534,21 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
   } : {}, {
     i: $data.useMiniProgramCameraComponent
   }, $data.useMiniProgramCameraComponent ? {
-    j: common_vendor.o((...args) => $options.handleCameraError && $options.handleCameraError(...args)),
-    k: common_vendor.o((...args) => $options.handleCameraInit && $options.handleCameraInit(...args))
+    j: common_vendor.o((...args) => $options.handleCameraError && $options.handleCameraError(...args))
   } : {}, {
-    l: $data.loading
+    k: $data.loading
   }, $data.loading ? {} : {}, {
-    m: $data.showDebugInfo
+    l: $data.showDebugInfo
   }, $data.showDebugInfo ? common_vendor.e({
-    n: $data.assistantResponse
+    m: $data.assistantResponse
   }, $data.assistantResponse ? {
-    o: common_vendor.t($data.assistantResponse)
+    n: common_vendor.t($data.assistantResponse)
   } : {}, {
-    p: $data.audioTranscript
+    o: $data.audioTranscript
   }, $data.audioTranscript ? {
-    q: common_vendor.t($data.audioTranscript)
+    p: common_vendor.t($data.audioTranscript)
   } : {}, {
-    r: common_vendor.f($data.processedResponses, (item, index, i0) => {
+    q: common_vendor.f($data.processedResponses, (item, index, i0) => {
       return common_vendor.e({
         a: item.role
       }, item.role ? {
@@ -1563,19 +1562,19 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
       });
     })
   }) : {}, {
-    s: $data.showStopRecordingButton
+    r: $data.showStopRecordingButton
   }, $data.showStopRecordingButton ? {
-    t: common_vendor.o((...args) => $options.stopRecordingAnswer && $options.stopRecordingAnswer(...args))
+    s: common_vendor.o((...args) => $options.stopRecordingAnswer && $options.stopRecordingAnswer(...args))
   } : {}, {
-    v: $data.isRecording
+    t: $data.isRecording
   }, $data.isRecording ? {} : {}, {
-    w: $data.showStartRecordingButton
+    v: $data.showStartRecordingButton
   }, $data.showStartRecordingButton ? {
-    x: common_vendor.o((...args) => $options.handleStartRecordingClick && $options.handleStartRecordingClick(...args))
+    w: common_vendor.o((...args) => $options.handleStartRecordingClick && $options.handleStartRecordingClick(...args))
   } : {}, {
-    y: $data.showRetryButton
+    x: $data.showRetryButton
   }, $data.showRetryButton ? {
-    z: common_vendor.o((...args) => $options.retryVideoUpload && $options.retryVideoUpload(...args))
+    y: common_vendor.o((...args) => $options.retryVideoUpload && $options.retryVideoUpload(...args))
   } : {});
 }
 const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-464e78c6"]]);

ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/dist/dev/mp-weixin/pages/identity-verify/identity-verify.wxml


この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません