"use strict"; const common_vendor = require("../../common/vendor.js"); const common_config = require("../../common/config.js"); const _sfc_main = { name: "IdentityVerify", data() { return { loading: false, responses: [], processedResponses: [], assistantResponse: "", audioTranscript: "", videoPlaying: false, showDebugInfo: false, // 设置为true可以显示调试信息 videoUrl: "http://121.36.251.245:9000/minlong/tenant_1/general_uploads/abdaa6fda8494e3a8613304743ed0433.mp4", // 用于存储AI数字人视频URL showReplayButton: false, cameraStream: null, // 存储摄像头流 cameraError: null, // 存储摄像头错误信息 useMiniProgramCameraComponent: false, // 添加小程序相机组件标志 cameraContext: null, // 添加相机上下文 currentSubtitle: "", subtitles: [ { startTime: 0, // 开始时间(秒) endTime: 6, // 结束时间(秒) text: "您已完成本次面试全部题目,请问您对于这个岗位还有什么想要了解的吗?" } ], // secondVideoSubtitles: [ // { // startTime: 0, // endTime: 10, // text: '请结合您的基本信息与过往履历进行简单的自我介绍,并讲一讲您有哪些优势胜任本岗位:' // } // ], // thirdVideoSubtitles: [ // { // startTime: 0, // endTime: 4, // text: '在工作中,你如何确保个人防护装备的正确使用?' // } // ], // fourthVideoSubtitles: [ // { // startTime: 0, // endTime: 4, // text: '描述一次你与团队合作改善生产流程的经历。' // } // ], // fifthVideoSubtitles: [ // { // startTime: 0, // endTime: 6, // text: '你在团队合作中曾遇到过哪些挑战?如何解决团队内部的分歧?' // } // ], // sixthVideoSubtitles: [ // { // startTime: 0, // endTime: 5, // text: '您已完成本次面试全部题目,请问您对于这个岗位还有什么想要了解的吗?' // } // ], showAnswerButton: false, // 控制答题按钮显示 currentVideoIndex: 0, // 当前播放的视频索引 videoList: [ "http://121.36.251.245:9000/minlong/tenant_1/general_uploads/abdaa6fda8494e3a8613304743ed0433.mp4" //结束 ], isRecording: false, recordingTimer: null, showStopRecordingButton: false, mediaRecorder: null, recordedChunks: [], recorder: null, lastUploadedVideoUrl: "", showStartRecordingButton: false, showRetryButton: false, // 控制重试按钮显示 lastVideoToRetry: null, // 存储上次失败的视频URL,用于重试 recordingStartTime: null, // 录制开始时间 recordingTimerCount: 0, // 录制计时器计数 recordingTimeDisplay: "00:00", // 格式化的录制时间显示 // 添加上传队列相关数据 uploadQueue: [], // 存储待上传的视频 isUploading: false, // 标记是否正在上传 uploadProgress: {}, // 存储每个视频的上传进度 uploadStatus: {}, // 存储每个视频的上传状态 showUploadStatus: false, // 是否显示上传状态指示器 uploadStatusText: "", // 上传状态文本 mediaRecorderTimeout: null, // 用于存储MediaRecorder的超时机制 maxRecordingTime: 300, // 最大录制时间(秒)- 从60秒改为300秒(5分钟) remainingTime: 300, // 剩余录制时间(秒)- 从60秒改为300秒 // 修改初始视频索引,添加参数控制 startFromLastVideo: false, // 是否从最后一个视频开始播放 countdownValue: 10, // 倒计时数值 showCountdown: false, // 是否显示倒计时蒙层 countdownTimer: null, showGif: false, // 控制是否显示GIF gifUrl: "" // GIF图片的URL }; }, onLoad(options) { if (options && options.startFromLast === "true") { this.startFromLastVideo = true; this.currentVideoIndex = this.videoList.length - 1; } }, mounted() { if (this.startFromLastVideo) { console.log("从最后一个视频开始播放"); this.currentVideoIndex = this.videoList.length - 1; this.videoUrl = this.videoList[this.currentVideoIndex]; } this.playDigitalHumanVideo(); this.checkAudioPermission(); this.initCamera(); this.checkIOSCameraRecordPermission(); this.checkAndFixRenderingIssues(); setTimeout(() => { if (this.cameraStream && !this.useMiniProgramCameraComponent) { this.testAudioInput(); } }, 3e3); common_vendor.index.setKeepScreenOn({ keepScreenOn: true }); }, beforeDestroy() { this.stopUserCamera(); }, methods: { // 初始化相机 async initCamera() { const systemInfo = common_vendor.index.getSystemInfoSync(); const isMiniProgram = systemInfo.uniPlatform === "mp-weixin" || systemInfo.uniPlatform === "mp-alipay" || systemInfo.uniPlatform === "mp-baidu"; if (isMiniProgram) { this.useMiniProgramCameraComponent = true; this.cameraContext = common_vendor.index.createCameraContext(); common_vendor.index.getSetting({ success: (res) => { if (!res.authSetting["scope.record"]) { common_vendor.index.authorize({ scope: "scope.record", success: () => { console.log("录音权限已获取"); }, fail: (err) => { console.error("录音权限获取失败:", err); this.showPermissionDialog("录音"); } }); } if (!res.authSetting["scope.camera"]) { common_vendor.index.authorize({ scope: "scope.camera", success: () => { console.log("相机权限已获取"); }, fail: (err) => { console.error("相机权限获取失败:", err); this.showPermissionDialog("相机"); } }); } const systemInfo2 = common_vendor.index.getSystemInfoSync(); if (systemInfo2.platform === "ios") { if (!res.authSetting["scope.camera"] || !res.authSetting["scope.record"]) { console.log("iOS需要同时获取相机和录音权限"); } } } }); } else { try { const constraints = { audio: { echoCancellation: true, noiseSuppression: true, autoGainControl: true }, video: { width: { ideal: 640, max: 1280 }, // 控制视频宽度 height: { ideal: 480, max: 720 }, // 控制视频高度 frameRate: { ideal: 15, max: 24 }, // 控制帧率 facingMode: "user" } }; const stream = await navigator.mediaDevices.getUserMedia(constraints); this.cameraStream = stream; const audioTracks = stream.getAudioTracks(); console.log("音频轨道数量:", audioTracks.length); if (audioTracks.length > 0) { console.log("音频轨道已获取:", audioTracks[0].label); audioTracks[0].enabled = true; } else { console.warn("未检测到音频轨道,尝试单独获取音频"); this.tryGetAudioOnly(); } const videoElement = this.$refs.userCameraVideo; if (videoElement) { videoElement.srcObject = stream; videoElement.muted = true; } } catch (error) { console.error("获取摄像头失败:", error); this.cameraError = error.message || "无法访问摄像头"; common_vendor.index.showToast({ title: "无法访问摄像头,请检查权限设置", icon: "none" }); } } }, // 停止用户摄像头 stopUserCamera() { if (this.cameraStream) { this.cameraStream.getTracks().forEach((track) => { track.stop(); }); this.cameraStream = null; } }, async fetchData() { this.loading = true; this.assistantResponse = ""; this.audioTranscript = ""; this.processedResponses = []; try { const requestTask = common_vendor.index.request({ url: "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions", method: "POST", header: { "Content-Type": "application/json", "Authorization": "Bearer sk-9e1ec73a7d97493b8613c63f06b6110c" }, data: { "model": "qwen-omni-turbo", "messages": [ { "role": "user", "content": [ { "type": "input_audio", "input_audio": { "data": "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20250211/tixcef/cherry.wav", "format": "wav" } }, { "type": "text", "text": "这段音频在说什么" } ] } ], "stream": true, "stream_options": { "include_usage": true }, "modalities": ["text", "audio"], "audio": { "voice": "Cherry", "format": "wav" } }, success: (res) => { console.log("请求成功,响应数据:", res.data); if (typeof res.data === "string" && res.data.includes("data: {")) { const chunks = res.data.split("data: ").filter((chunk) => chunk.trim() !== ""); chunks.forEach((chunk) => { this.handleStreamResponse(chunk); }); } else { this.handleStreamResponse(res.data); } this.playDigitalHumanVideo(); }, fail: (err) => { console.error("请求失败:", err); }, complete: () => { this.loading = false; } }); } catch (error) { console.error("获取数据失败:", error); this.loading = false; } }, handleStreamResponse(data) { if (typeof data === "string") { if (data === "[DONE]") return; try { const cleanData = data.trim(); if (cleanData.startsWith("{") && cleanData.endsWith("}")) { const jsonData = JSON.parse(cleanData); this.processStreamChunk(jsonData); } } catch (e) { console.error("解析JSON失败:", e, "原始数据:", data); } } else { this.processStreamChunk(data); } }, processStreamChunk(chunk) { if (chunk.choices && chunk.choices.length > 0) { const choice = chunk.choices[0]; if (choice.delta && choice.delta.content) { this.assistantResponse += choice.delta.content; } if (choice.delta && choice.delta.audio && choice.delta.audio.transcript) { this.audioTranscript += choice.delta.audio.transcript; } if (choice.delta) { const result = {}; if (choice.delta.role) { result.role = choice.delta.role; } if (choice.delta.audio && choice.delta.audio.transcript) { result.transcript = choice.delta.audio.transcript; } if (Object.keys(result).length > 0) { this.processedResponses.push(result); } } } }, processResponseData() { this.processedResponses = this.responses.map((item) => { const result = {}; if (item.delta && item.delta.role) { result.role = item.delta.role; } if (item.delta && item.delta.audio && item.delta.audio.transcript) { result.transcript = item.delta.audio.transcript; } return result; }).filter((item) => Object.keys(item).length > 0); }, // 播放数字人视频 playDigitalHumanVideo() { this.videoUrl = this.videoList[this.currentVideoIndex]; this.videoPlaying = true; console.log(`播放视频 ${this.currentVideoIndex + 1}/${this.videoList.length}: ${this.videoUrl}`); this.$nextTick(() => { const videoContext = common_vendor.index.createVideoContext("myVideo", this); if (videoContext) { videoContext.play(); setTimeout(() => { if (this.videoPlaying && this.$refs.videoPlayer) { console.log("视频应该正在播放"); } else { console.log("视频可能未成功播放,尝试替代方案"); this.tryAlternativeVideoPath(); } }, 1e3); } else { console.error("无法创建视频上下文"); this.tryAlternativeVideoPath(); } }); }, // 修改 tryAlternativeVideoPath 方法 tryAlternativeVideoPath() { console.log("尝试使用替代路径"); const alternativePaths = [ "./static/demo.mp4", "../static/demo.mp4", "static/demo.mp4", "/static/demo.mp4", // 添加绝对路径 `${window.location.origin}/static/demo.mp4` ]; const currentPathIndex = alternativePaths.indexOf(this.videoUrl); const nextPathIndex = (currentPathIndex + 1) % alternativePaths.length; this.videoUrl = alternativePaths[nextPathIndex]; console.log("尝试新路径:", this.videoUrl); this.$nextTick(() => { const videoContext = common_vendor.index.createVideoContext("myVideo", this); if (videoContext) { videoContext.stop(); videoContext.play(); setTimeout(() => { if (nextPathIndex === alternativePaths.length - 1 && !this.videoPlaying) { console.log("所有路径均失败,尝试使用uni.getVideoInfo检查视频"); this.checkVideoWithAPI(); } }, 1e3); } }); }, // 添加新方法:使用uni API检查视频 checkVideoWithAPI() { common_vendor.index.getVideoInfo({ src: "/static/demo.mp4", success: (res) => { console.log("视频信息获取成功:", res); this.videoUrl = "/static/demo.mp4"; this.$nextTick(() => { const videoContext = common_vendor.index.createVideoContext("myVideo", this); if (videoContext) { videoContext.play(); } }); }, fail: (err) => { console.error("视频信息获取失败:", err); this.fallbackToLocalVideo(); } }); }, // 添加新方法:回退到本地视频 fallbackToLocalVideo() { console.log("尝试使用本地视频资源"); const platform = common_vendor.index.getSystemInfoSync().platform; if (platform === "android" || platform === "ios") { this.videoUrl = platform === "android" ? "android.resource://package_name/raw/demo" : "file:///assets/demo.mp4"; this.$nextTick(() => { const videoContext = common_vendor.index.createVideoContext("myVideo", this); if (videoContext) { videoContext.play(); } }); } else { this.videoPlaying = false; common_vendor.index.showToast({ title: "视频加载失败,显示静态图片", icon: "none" }); } }, // 修改 handleVideoError 方法 handleVideoError(e) { console.error("视频加载错误:", e); if (e && e.detail) { console.error("详细错误信息:", e.detail); } common_vendor.index.getFileInfo({ filePath: this.videoUrl.startsWith("/") ? this.videoUrl.substring(1) : this.videoUrl, success: (res) => { console.log("文件存在,大小:", res.size); this.tryDifferentFormat(); }, fail: (err) => { console.error("文件不存在或无法访问:", err); this.tryAlternativeVideoPath(); } }); common_vendor.index.showToast({ title: "视频加载失败,请检查文件是否存在", icon: "none", duration: 2e3 }); }, // 添加新方法:尝试不同格式 tryDifferentFormat() { console.log("尝试不同的视频格式"); const formats = [ { ext: "mp4", mime: "video/mp4" }, { ext: "webm", mime: "video/webm" }, { ext: "ogg", mime: "video/ogg" }, { ext: "mov", mime: "video/quicktime" } ]; const currentPath = this.videoUrl; const basePath = currentPath.substring(0, currentPath.lastIndexOf(".")) || "/static/demo"; let nextFormat = formats.find((f) => !currentPath.endsWith(f.ext)); if (nextFormat) { this.videoUrl = `${basePath}.${nextFormat.ext}`; console.log("尝试新格式:", this.videoUrl); this.$nextTick(() => { const videoContext = common_vendor.index.createVideoContext("myVideo", this); if (videoContext) { videoContext.stop(); videoContext.play(); } }); } else { this.useBuiltInResource(); } }, // 添加新方法:使用内置资源 useBuiltInResource() { console.log("尝试使用内置资源"); const platform = common_vendor.index.getSystemInfoSync().platform; if (platform === "windows") { process.env.UNI_INPUT_DIR || ""; this.videoUrl = `./static/demo.mp4`; console.log("Windows平台尝试路径:", this.videoUrl); } else if (platform === "android" || platform === "ios") { this.useNativeVideo(); } else { const baseUrl = window.location.origin; this.videoUrl = `${baseUrl}/static/demo.mp4`; console.log("Web平台尝试URL:", this.videoUrl); } this.$nextTick(() => { const videoContext = common_vendor.index.createVideoContext("myVideo", this); if (videoContext) { videoContext.play(); } }); }, // 添加新方法:使用原生视频能力 useNativeVideo() { console.log("尝试使用原生视频能力"); common_vendor.index.chooseVideo({ sourceType: ["album"], success: (res) => { this.videoUrl = res.tempFilePath; this.$nextTick(() => { const videoContext = common_vendor.index.createVideoContext("myVideo", this); if (videoContext) { videoContext.play(); } }); }, fail: () => { this.videoPlaying = false; common_vendor.index.showToast({ title: "无法加载视频,显示静态图片", icon: "none" }); } }); }, // 处理视频结束事件 handleVideoEnded() { console.log("视频播放结束,当前视频索引:", this.currentVideoIndex); this.videoPlaying = false; this.gifUrl = "http://121.36.251.245:9000/minlong/tenant_1/general_uploads/5273282d971441249aeadf35a7574f01.gif"; this.showGif = true; this.showStartRecordingButton = true; this.startCountdown(); this.showAnswerButton = false; }, // 添加新方法:开始倒计时 startCountdown() { this.showCountdown = true; this.countdownValue = 10; this.countdownTimer = setInterval(() => { this.countdownValue--; if (this.countdownValue <= 0) { this.clearCountdown(); this.showStartRecordingButton = false; this.startRecordingAnswer(); } }, 1e3); }, // 添加新方法:清除倒计时 clearCountdown() { if (this.countdownTimer) { clearInterval(this.countdownTimer); this.countdownTimer = null; } this.showCountdown = false; }, // 修改 handleStartRecordingClick 方法,使其可以终止倒计时 handleStartRecordingClick() { this.showStartRecordingButton = false; this.clearCountdown(); this.startRecordingAnswer(); }, // 修改 stopRecordingAnswer 方法,确保清除倒计时 stopRecordingAnswer() { this.clearCountdown(); const recordingDuration = this.getRecordingDuration(); const minimumDuration = 5; if (recordingDuration < minimumDuration) { common_vendor.index.showToast({ title: "录制时间过短,请至少录制5秒", icon: "none", duration: 2e3 }); return; } this.completeRecordingStop(); }, // 添加新方法:开始录制用户回答 startRecordingAnswer() { console.log("开始录制用户回答"); this.isRecording = true; this.recordingStartTime = Date.now(); this.recordingTimerCount = 0; this.remainingTime = this.maxRecordingTime; this.recordingTimer = setInterval(() => { this.recordingTimerCount++; this.remainingTime = Math.max(0, this.maxRecordingTime - this.recordingTimerCount); this.recordingTimeDisplay = this.formatTime(this.recordingTimerCount) + " / " + this.formatTime(this.maxRecordingTime); if (this.recordingTimerCount >= this.maxRecordingTime) { console.log("已达到最大录制时间(60秒),自动停止录制"); this.stopRecordingAnswer(); } }, 1e3); const systemInfo = common_vendor.index.getSystemInfoSync(); const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith("mp-"); if (isMiniProgram) { this.startMiniProgramRecording(); } else { this.startBrowserRecording(); } this.showStopRecordingButton = true; }, // 添加一个新方法:重置相机组件 resetCamera() { console.log("重置相机组件"); this.useMiniProgramCameraComponent = false; if (this.cameraContext) { this.cameraContext = null; } setTimeout(() => { this.useMiniProgramCameraComponent = true; setTimeout(() => { this.cameraContext = common_vendor.index.createCameraContext(); console.log("相机组件已重置"); }, 500); }, 500); }, // 修改 startMiniProgramRecording 方法 startMiniProgramRecording() { console.log("开始小程序录制方法"); const systemInfo = common_vendor.index.getSystemInfoSync(); const isIOS = systemInfo.platform === "ios"; if (isIOS) { this.resetCamera(); setTimeout(() => { this.actualStartRecording(isIOS); }, 1e3); } else { this.actualStartRecording(isIOS); } }, // 添加新方法:实际开始录制 actualStartRecording(isIOS) { if (!this.cameraContext) { this.cameraContext = common_vendor.index.createCameraContext(); console.log("创建新的相机上下文"); } common_vendor.index.getSetting({ success: (res) => { const hasRecordAuth = res.authSetting["scope.record"]; const hasCameraAuth = res.authSetting["scope.camera"]; if (!hasRecordAuth || !hasCameraAuth) { console.warn("缺少必要权限,请求权限"); this.requestMiniProgramPermissions(); return; } if (isIOS) { console.log("iOS: 检查相机状态"); const options = { timeout: 3e5, // 300秒超时 (5分钟) quality: "low", // 降低质量 compressed: true, success: () => { console.log("iOS录制开始成功"); }, fail: (err) => { console.error("iOS录制失败:", err); this.useAlternativeRecordingMethod(); } }; try { console.log("尝试开始录制"); this.recorder = this.cameraContext.startRecord(options); } catch (e) { console.error("开始录制异常:", e); this.useAlternativeRecordingMethod(); } } else { const options = { timeout: 3e5, // 300秒超时 (5分钟) quality: "medium", compressed: true, success: () => { console.log("Android录制开始成功"); }, fail: (err) => { console.error("Android录制失败:", err); common_vendor.index.showToast({ title: "录制失败,请检查相机权限", icon: "none" }); this.proceedToNextQuestion(); } }; this.recorder = this.cameraContext.startRecord(options); } } }); }, // 添加新方法:使用替代录制方法 useAlternativeRecordingMethod() { console.log("使用替代录制方法"); common_vendor.index.showActionSheet({ itemList: ["使用相册中的视频", "跳过此问题"], success: (res) => { if (res.tapIndex === 0) { common_vendor.index.chooseVideo({ sourceType: ["album"], maxDuration: 300, // 从60秒改为300秒 camera: "front", success: (res2) => { console.log("选择视频成功:", res2.tempFilePath); this.isRecording = false; this.showStopRecordingButton = false; this.uploadRecordedVideo(res2.tempFilePath); }, fail: () => { console.log("用户取消选择视频"); this.proceedToNextQuestion(); } }); } else { console.log("用户选择跳过问题"); this.proceedToNextQuestion(); } }, fail: () => { console.log("操作取消"); this.proceedToNextQuestion(); } }); }, // 添加新方法:请求小程序权限 requestMiniProgramPermissions() { common_vendor.index.authorize({ scope: "scope.record", success: () => { console.log("录音权限已获取"); common_vendor.index.authorize({ scope: "scope.camera", success: () => { console.log("相机权限已获取"); this.startMiniProgramRecording(); }, fail: (err) => { console.error("相机权限获取失败:", err); this.showPermissionDialog("相机"); } }); }, fail: (err) => { console.error("录音权限获取失败:", err); this.showPermissionDialog("录音"); } }); }, // 修改浏览器环境下的录制方法 startBrowserRecording() { if (!this.cameraStream) { console.error("没有可用的摄像头流"); common_vendor.index.showToast({ title: "录制失败,摄像头未就绪", icon: "none" }); this.proceedToNextQuestion(); return; } try { const hasAudio = this.cameraStream.getAudioTracks().length > 0; if (!hasAudio) { console.warn("警告:媒体流中没有音频轨道,尝试重新获取带音频的媒体流"); navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: true, noiseSuppression: true, autoGainControl: true }, video: true }).then((newStream) => { const audioTracks = newStream.getAudioTracks(); if (audioTracks.length > 0) { console.log("成功获取音频轨道:", audioTracks[0].label); const videoTrack = this.cameraStream.getVideoTracks()[0]; const audioTrack = newStream.getAudioTracks()[0]; const combinedStream = new MediaStream(); if (videoTrack) combinedStream.addTrack(videoTrack); if (audioTrack) combinedStream.addTrack(audioTrack); this.cameraStream = combinedStream; const videoElement = this.$refs.userCameraVideo; if (videoElement) { videoElement.srcObject = combinedStream; videoElement.muted = true; } this.setupMediaRecorder(combinedStream); } else { console.warn("仍然无法获取音频轨道"); this.setupMediaRecorder(this.cameraStream); } }).catch((err) => { console.error("获取音频失败:", err); this.setupMediaRecorder(this.cameraStream); }); } else { console.log("检测到音频轨道,直接使用"); this.setupMediaRecorder(this.cameraStream); } } catch (error) { console.error("浏览器录制失败:", error); common_vendor.index.showToast({ title: "录制失败,浏览器可能不支持此功能", icon: "none" }); this.proceedToNextQuestion(); } }, // 修改 setupMediaRecorder 方法 setupMediaRecorder(stream) { const videoTracks = stream.getVideoTracks(); const audioTracks = stream.getAudioTracks(); console.log("设置MediaRecorder - 视频轨道:", videoTracks.length, "音频轨道:", audioTracks.length); let mimeType = ""; const supportedTypes = [ "video/webm;codecs=vp9,opus", "video/webm;codecs=vp8,opus", "video/webm;codecs=h264,opus", "video/mp4;codecs=h264,aac", "video/webm", "video/mp4" ]; for (const type of supportedTypes) { if (MediaRecorder.isTypeSupported(type)) { mimeType = type; console.log("使用支持的MIME类型:", mimeType); break; } } const options = { mimeType: mimeType || "", audioBitsPerSecond: 64e3, // 降低音频比特率 videoBitsPerSecond: 1e6 // 降低视频比特率到1Mbps }; try { this.mediaRecorder = new MediaRecorder(stream, options); console.log("MediaRecorder创建成功,使用选项:", options); } catch (e) { console.warn("使用指定选项创建MediaRecorder失败,尝试使用默认选项"); this.mediaRecorder = new MediaRecorder(stream); } this.recordedChunks = []; this.mediaRecorder.ondataavailable = (event) => { if (event.data && event.data.size > 0) { this.recordedChunks.push(event.data); console.log(`收到数据块: ${event.data.size} 字节`); } }; this.mediaRecorder.onstop = async () => { console.log("MediaRecorder停止,数据块数量:", this.recordedChunks.length); if (this.recordedChunks.length === 0) { console.error("没有录制到数据"); common_vendor.index.showToast({ title: "录制失败,未捕获到数据", icon: "none" }); this.proceedToNextQuestion(); return; } const mimeType2 = this.mediaRecorder.mimeType || "video/webm"; const blob = new Blob(this.recordedChunks, { type: mimeType2 }); console.log("创建Blob,原始大小:", blob.size, "类型:", mimeType2); common_vendor.index.showLoading({ title: "正在处理视频...", mask: true }); try { const compressedBlob = await this.compressVideo(blob); const fileName = `answer_${this.currentVideoIndex}_${Date.now()}.webm`; const file = new File([compressedBlob], fileName, { type: mimeType2 }); common_vendor.index.hideLoading(); this.uploadRecordedVideo(file); } catch (error) { console.error("视频处理失败:", error); common_vendor.index.hideLoading(); const fileName = `answer_${this.currentVideoIndex}_${Date.now()}.webm`; const file = new File([blob], fileName, { type: mimeType2 }); this.uploadRecordedVideo(file); } }; this.mediaRecorder.onerror = (event) => { console.error("MediaRecorder错误:", event.error); }; try { this.mediaRecorder.start(1e3); console.log("MediaRecorder开始录制"); this.mediaRecorderTimeout = setTimeout(() => { if (this.mediaRecorder && this.mediaRecorder.state === "recording") { console.log("MediaRecorder备份超时机制触发,停止录制"); this.mediaRecorder.stop(); } }, 3e5); } catch (e) { console.error("开始录制失败:", e); } }, // 添加新方法:停止录制用户回答 stopRecordingAnswer() { console.log("停止录制用户回答"); if (this.countdownTimer) { clearInterval(this.countdownTimer); this.countdownTimer = null; this.showCountdown = false; } const recordingDuration = this.getRecordingDuration(); const minimumDuration = 5; if (recordingDuration < minimumDuration) { common_vendor.index.showToast({ title: "录制时间过短,请至少录制5秒", icon: "none", duration: 2e3 }); return; } this.completeRecordingStop(); }, // 添加新方法:获取录制时长 getRecordingDuration() { if (this.recordingStartTime) { return (Date.now() - this.recordingStartTime) / 1e3; } if (this.mediaRecorder && this.$refs.userCameraVideo) { return this.$refs.userCameraVideo.currentTime || 0; } if (this.recordingTimerCount) { return this.recordingTimerCount; } return 0; }, // 添加新方法:重置录制 resetRecording() { if (this.recordingTimer) { clearTimeout(this.recordingTimer); } this.recordingStartTime = Date.now(); this.recordingTimerCount = 0; if (this.mediaRecorder && this.mediaRecorder.state !== "inactive") { this.mediaRecorder.stop(); this.recordedChunks = []; setTimeout(() => { this.startBrowserRecording(); }, 500); } else if (this.cameraContext) { this.cameraContext.stopRecord({ success: () => { console.log("重置录制:停止当前录制成功"); setTimeout(() => { this.startMiniProgramRecording(); }, 500); }, fail: (err) => { console.error("重置录制:停止当前录制失败", err); this.startMiniProgramRecording(); } }); } common_vendor.index.showToast({ title: "请重新开始回答", icon: "none", duration: 2e3 }); }, // 添加新方法:完成录制停止流程 completeRecordingStop() { this.isRecording = false; if (this.recordingTimer) { clearInterval(this.recordingTimer); this.recordingTimer = null; } if (this.mediaRecorderTimeout) { clearTimeout(this.mediaRecorderTimeout); this.mediaRecorderTimeout = null; } common_vendor.index.hideLoading(); this.showStopRecordingButton = false; const systemInfo = common_vendor.index.getSystemInfoSync(); const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith("mp-"); if (isMiniProgram) { this.stopMiniProgramRecording(); } else { this.stopBrowserRecording(); } }, // 修改 stopMiniProgramRecording 方法 stopMiniProgramRecording() { if (!this.cameraContext) { console.error("相机上下文不存在"); this.proceedToNextQuestion(); return; } const systemInfo = common_vendor.index.getSystemInfoSync(); const isIOS = systemInfo.platform === "ios"; const stopOptions = { success: (res) => { console.log("小程序录像停止成功:", res); const tempFilePath = res.tempVideoPath; if (!tempFilePath) { console.error("未获取到视频文件路径"); common_vendor.index.showToast({ title: "录制失败,未获取到视频文件", icon: "none" }); this.proceedToNextQuestion(); return; } if (isIOS) { common_vendor.index.getFileInfo({ filePath: tempFilePath, success: () => { this.uploadRecordedVideo(tempFilePath); }, fail: (err) => { console.error("视频文件不存在:", err); common_vendor.index.showToast({ title: "录制失败,视频文件不存在", icon: "none" }); this.proceedToNextQuestion(); } }); } else { this.uploadRecordedVideo(tempFilePath); } }, fail: (err) => { console.error("小程序录像停止失败:", err); common_vendor.index.showToast({ title: "录制失败", icon: "none" }); this.proceedToNextQuestion(); } }; this.cameraContext.stopRecord(stopOptions); }, // 添加新方法:停止浏览器录制 stopBrowserRecording() { if (this.mediaRecorder && this.mediaRecorder.state !== "inactive") { this.mediaRecorder.stop(); console.log("浏览器录制停止成功"); } else { console.error("MediaRecorder不存在或已经停止"); this.proceedToNextQuestion(); } }, // 修改上传录制的视频方法 uploadRecordedVideo(fileOrPath) { console.log("准备上传视频:", typeof fileOrPath === "string" ? fileOrPath : fileOrPath.name); let questionId = 10; const uploadTask = { id: Date.now().toString(), // 生成唯一ID file: fileOrPath, questionId, attempts: 0, // 上传尝试次数 maxAttempts: 3 // 最大尝试次数 }; this.uploadQueue.push(uploadTask); this.uploadProgress[uploadTask.id] = 0; this.uploadStatus[uploadTask.id] = "pending"; common_vendor.index.showToast({ title: "已完成回答", icon: "none", duration: 1500 }); this.updateUploadStatusText(); if (!this.isUploading) { this.processUploadQueue(); } this.proceedToNextQuestion(); }, // 修改 processUploadQueue 方法,添加后台上传支持 processUploadQueue() { if (this.uploadQueue.length === 0) { this.isUploading = false; this.showUploadStatus = false; try { common_vendor.index.removeStorageSync("videoUploadStatus"); } catch (e) { console.error("清除上传状态失败:", e); } this.notifyUploadComplete(); return; } this.isUploading = true; this.showUploadStatus = true; const task = this.uploadQueue[0]; this.uploadStatus[task.id] = "uploading"; this.updateUploadStatusText(); task.attempts++; if (typeof task.file !== "string") { this.uploadFileWithXHR(task); } else { this.uploadFileWithUni(task); } this.saveUploadStatus(); }, // 添加新方法:发送上传完成通知 notifyUploadComplete() { try { common_vendor.index.$emit("videoUploadComplete", { timestamp: Date.now() }); console.log("发送上传完成通知"); } catch (e) { console.error("发送上传完成通知失败:", e); } const systemInfo = common_vendor.index.getSystemInfoSync(); if (systemInfo.platform === "android" || systemInfo.platform === "ios") { if (plus && plus.push) { plus.push.createMessage("视频上传完成", "您的面试视频已成功上传", {}); } } }, // 添加新方法:使用XMLHttpRequest上传文件 uploadFileWithXHR(task) { const userInfo = common_vendor.index.getStorageSync("userInfo"); const openid = userInfo ? JSON.parse(userInfo).openid || "" : ""; const tenant_id = common_vendor.index.getStorageSync("tenant_id") || "1"; const formData = new FormData(); formData.append("file", task.file); formData.append("openid", openid); formData.append("tenant_id", tenant_id); formData.append("application_id", common_vendor.index.getStorageSync("appId")); formData.append("question_id", task.questionId); formData.append("video_duration", 0); formData.append("has_audio", "true"); const xhr = new XMLHttpRequest(); xhr.open("POST", `${common_config.apiBaseUrl}/api/upload/`, true); xhr.timeout = 12e4; xhr.upload.onprogress = (event) => { if (event.lengthComputable) { const percentComplete = Math.round(event.loaded / event.total * 100); this.uploadProgress[task.id] = percentComplete; this.updateUploadStatusText(); } }; xhr.onload = () => { if (xhr.status === 200) { try { const res = JSON.parse(xhr.responseText); console.log("上传响应:", res); if (res.code === 2e3) { const videoUrl = res.data.url || res.data.photoUrl || ""; if (videoUrl) { this.uploadStatus[task.id] = "success"; this.updateUploadStatusText(); this.submitVideoToInterview(videoUrl, task); } else { this.handleUploadFailure(task, "视频URL获取失败"); } } else { this.handleUploadFailure(task, res.msg || "上传失败"); } } catch (e) { this.handleUploadFailure(task, "解析响应失败"); } } else { this.handleUploadFailure(task, "HTTP状态: " + xhr.status); } }; xhr.onerror = () => { this.handleUploadFailure(task, "网络错误"); }; xhr.ontimeout = () => { this.handleUploadFailure(task, "上传超时"); }; xhr.send(formData); }, // 添加新方法:使用uni.uploadFile上传文件 uploadFileWithUni(task) { const userInfo = common_vendor.index.getStorageSync("userInfo"); const openid = userInfo ? JSON.parse(userInfo).openid || "" : ""; const tenant_id = common_vendor.index.getStorageSync("tenant_id") || "1"; const uploadTask = common_vendor.index.uploadFile({ url: `${common_config.apiBaseUrl}/api/upload/`, filePath: task.file, name: "file", formData: { openid, tenant_id, application_id: common_vendor.index.getStorageSync("appId"), question_id: task.questionId, video_duration: 0, has_audio: "true" }, success: (uploadRes) => { try { const res = JSON.parse(uploadRes.data); console.log("上传响应:", res); if (res.code === 2e3) { const videoUrl = res.data.permanent_link || res.data.url || ""; if (videoUrl) { this.uploadStatus[task.id] = "success"; this.updateUploadStatusText(); this.submitVideoToInterview(videoUrl, task); } else { this.handleUploadFailure(task, "视频URL获取失败"); } } else { this.handleUploadFailure(task, res.msg || "上传失败"); } } catch (e) { this.handleUploadFailure(task, "解析响应失败"); } }, fail: (err) => { this.handleUploadFailure(task, err.errMsg || "上传失败"); } }); uploadTask.onProgressUpdate((res) => { this.uploadProgress[task.id] = res.progress; this.updateUploadStatusText(); }); }, // 添加新方法:处理上传失败 handleUploadFailure(task, errorMsg) { console.error("上传失败:", errorMsg); this.uploadStatus[task.id] = "failed"; this.updateUploadStatusText(); if (task.attempts < task.maxAttempts) { console.log(`将在5秒后重试上传,当前尝试次数: ${task.attempts}/${task.maxAttempts}`); setTimeout(() => { this.uploadProgress[task.id] = 0; if (typeof task.file !== "string") { this.uploadFileWithXHR(task); } else { this.uploadFileWithUni(task); } }, 5e3); } else { console.log("超过最大重试次数,放弃上传"); common_vendor.index.showToast({ title: "视频上传失败,请稍后重试", icon: "none", duration: 2e3 }); this.uploadQueue.shift(); this.processUploadQueue(); } }, // 修改 submitVideoToInterview 方法 submitVideoToInterview(videoUrl, task = null) { console.log("提交视频URL到面试接口:", videoUrl); let questionId; if (task) { questionId = task.questionId; } else { switch (this.currentVideoIndex) { case 1: questionId = 36; break; case 2: questionId = 11; break; case 3: questionId = 12; break; case 4: questionId = 13; break; default: questionId = 10; } } const requestData = { application_id: common_vendor.index.getStorageSync("appId"), question_id: questionId, video_url: videoUrl, tenant_id: common_vendor.index.getStorageSync("tenant_id") || "1" }; common_vendor.index.request({ url: `${common_config.apiBaseUrl}/api/job/upload_video`, method: "POST", data: requestData, header: { "content-type": "application/x-www-form-urlencoded" }, success: (res) => { console.log("面试接口提交成功:", res); if (res.data.code === 0 || res.data.code === 2e3) { if (task) { this.uploadQueue.shift(); this.processUploadQueue(); } else { common_vendor.index.showToast({ title: "回答已提交", icon: "success" }); this.lastUploadedVideoUrl = videoUrl; this.showRetryButton = false; this.lastVideoToRetry = null; } } else { if (task) { this.handleSubmitFailure(task, res.data.msg || "提交失败"); } else { common_vendor.index.showToast({ title: res.data.msg || "提交失败,请重试", icon: "none" }); this.lastVideoToRetry = videoUrl; this.showRetryButton = true; } } }, fail: (err) => { console.error("面试接口提交失败:", err); if (task) { this.handleSubmitFailure(task, err.errMsg || "网络错误"); } else { common_vendor.index.hideLoading(); common_vendor.index.showToast({ title: "网络错误,请重试", icon: "none" }); this.lastVideoToRetry = videoUrl; this.showRetryButton = true; } } }); }, // 添加新方法:处理提交失败 handleSubmitFailure(task, errorMsg) { console.error("提交失败:", errorMsg); this.uploadStatus[task.id] = "failed"; this.updateUploadStatusText(); if (task.attempts < task.maxAttempts) { console.log(`将在5秒后重试提交,当前尝试次数: ${task.attempts}/${task.maxAttempts}`); setTimeout(() => { this.submitVideoToInterview(task.videoUrl, task); }, 5e3); } else { console.log("超过最大重试次数,放弃提交"); common_vendor.index.showToast({ title: "视频提交失败,请稍后重试", icon: "none", duration: 2e3 }); this.uploadQueue.shift(); this.processUploadQueue(); } }, // 添加新方法:更新上传状态文本 updateUploadStatusText() { if (this.uploadQueue.length === 0) { this.uploadStatusText = ""; return; } const currentTask = this.uploadQueue[0]; const progress = this.uploadProgress[currentTask.id] || 0; const status = this.uploadStatus[currentTask.id] || "pending"; let statusText = ""; switch (status) { case "pending": statusText = "等待上传"; break; case "uploading": statusText = `上传中 ${progress}%`; break; case "success": statusText = "上传成功,提交中..."; break; case "failed": statusText = `上传失败,${currentTask.attempts < currentTask.maxAttempts ? "即将重试" : "已放弃"}`; break; } this.uploadStatusText = `问题${currentTask.questionId - 9}:${statusText}`; if (this.uploadQueue.length > 1) { this.uploadStatusText += ` (${this.uploadQueue.length}个视频待处理)`; } }, // 修改 proceedToNextQuestion 方法 proceedToNextQuestion() { console.log("准备跳转到下一页面"); this.navigateToNextPage(); if (this.uploadQueue.length > 0) { console.log("上传队列将在后台继续处理..."); this.saveUploadStatus(); } }, // 修改 navigateToNextPage 方法 navigateToNextPage() { console.log("导航到下一个页面"); common_vendor.index.navigateTo({ url: "/pages/interview-result/interview-result?uploading=" + (this.uploadQueue.length > 0 ? "true" : "false"), success: () => { console.log("成功跳转到结果页面"); }, fail: (err) => { console.error("跳转失败:", err); common_vendor.index.navigateTo({ url: "/pages/interview/interview", fail: (err2) => { console.error("备用跳转也失败:", err2); common_vendor.index.navigateBack({ delta: 1 }); } }); } }); }, // 修改 handleAnswerButtonClick 方法 handleAnswerButtonClick() { this.showAnswerButton = false; this.showGif = false; this.gifUrl = ""; common_vendor.index.showToast({ title: "面试完成", icon: "success", duration: 500 // 只显示0.5秒 }); setTimeout(() => { this.navigateToNextPage(); }, 500); }, // 处理相机错误 handleCameraError(e) { console.error("相机错误:", e); const systemInfo = common_vendor.index.getSystemInfoSync(); const isIOS = systemInfo.platform === "ios"; if (isIOS) { console.log("iOS相机错误,尝试重新初始化"); common_vendor.index.showToast({ title: "相机初始化中...", icon: "loading", duration: 2e3 }); this.resetCamera(); if (this.isRecording) { this.isRecording = false; this.showStopRecordingButton = false; setTimeout(() => { this.useAlternativeRecordingMethod(); }, 1e3); } } else { common_vendor.index.showToast({ title: "相机初始化失败,请检查权限设置", icon: "none" }); this.tryFallbackOptions(); } }, // 添加新方法:尝试备用选项 tryFallbackOptions() { const systemInfo = common_vendor.index.getSystemInfoSync(); if (systemInfo.uniPlatform === "mp-weixin" || systemInfo.uniPlatform === "mp-alipay") { this.useMiniProgramCamera(); } else { this.showStaticCameraPlaceholder(); } }, // 添加新方法:使用小程序相机API useMiniProgramCamera() { console.log("尝试使用小程序相机组件"); this.useMiniProgramCameraComponent = true; }, // 添加新方法:显示静态图像 showStaticCameraPlaceholder() { console.log("显示静态摄像头占位图"); const img = document.createElement("img"); img.src = "/static/images/camera-placeholder.png"; img.className = "static-camera-image"; img.style.width = "100%"; img.style.height = "100%"; img.style.objectFit = "cover"; const container = this.$refs.userCameraVideo.parentNode; container.appendChild(img); }, // 处理视频时间更新事件 handleTimeUpdate(e) { const currentTime = e.target.currentTime; if (this.isRecording && this.recordingTimerCount) { this.recordingTimeDisplay = this.formatTime(this.recordingTimerCount); } let currentSubtitles; if (this.currentVideoIndex === 0) { currentSubtitles = this.subtitles; } else if (this.currentVideoIndex === 1) { currentSubtitles = this.secondVideoSubtitles; } else if (this.currentVideoIndex === 2) { currentSubtitles = this.thirdVideoSubtitles; } else if (this.currentVideoIndex === 3) { currentSubtitles = this.fourthVideoSubtitles; } else if (this.currentVideoIndex === 4) { currentSubtitles = this.fifthVideoSubtitles; } else if (this.currentVideoIndex === 5) { currentSubtitles = this.sixthVideoSubtitles; } else { currentSubtitles = []; } const subtitle = currentSubtitles.find( (sub) => currentTime >= sub.startTime && currentTime < sub.endTime ); this.currentSubtitle = subtitle ? subtitle.text : ""; }, // Add a new method to handle the "Start Recording" button click handleStartRecordingClick() { this.showStartRecordingButton = false; this.clearCountdown(); this.startRecordingAnswer(); }, // 修改 checkAudioPermission 方法,确保在录制前获取音频权限 checkAudioPermission() { const systemInfo = common_vendor.index.getSystemInfoSync(); const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith("mp-"); if (isMiniProgram) { common_vendor.index.getSetting({ success: (res) => { if (!res.authSetting["scope.record"]) { common_vendor.index.authorize({ scope: "scope.record", success: () => { console.log("录音权限已获取"); }, fail: (err) => { console.error("录音权限获取失败:", err); this.showPermissionDialog("录音"); } }); } if (!res.authSetting["scope.camera"]) { common_vendor.index.authorize({ scope: "scope.camera", success: () => { console.log("相机权限已获取"); }, fail: (err) => { console.error("相机权限获取失败:", err); this.showPermissionDialog("相机"); } }); } } }); } }, // 添加新方法:测试音频输入 testAudioInput() { if (!this.cameraStream) { console.warn("没有可用的媒体流,无法测试音频"); return; } const audioTracks = this.cameraStream.getAudioTracks(); if (audioTracks.length === 0) { console.warn("没有检测到音频轨道,尝试重新获取"); this.tryGetAudioOnly(); return; } console.log("音频轨道信息:", audioTracks[0].getSettings()); try { const AudioContext = window.AudioContext || window.webkitAudioContext; if (!AudioContext) { console.warn("浏览器不支持AudioContext"); return; } const audioContext = new AudioContext(); const analyser = audioContext.createAnalyser(); const microphone = audioContext.createMediaStreamSource(this.cameraStream); microphone.connect(analyser); analyser.fftSize = 256; const bufferLength = analyser.frequencyBinCount; const dataArray = new Uint8Array(bufferLength); let silenceCounter = 0; const checkAudio = () => { if (this.isRecording) return; analyser.getByteFrequencyData(dataArray); let sum = 0; for (let i = 0; i < bufferLength; i++) { sum += dataArray[i]; } const average = sum / bufferLength; if (average > 10) { console.log("检测到音频输入,音量:", average); silenceCounter = 0; } else { silenceCounter++; if (silenceCounter > 10) { console.warn("持续检测不到音频输入,可能麦克风未正常工作"); silenceCounter = 0; } } requestAnimationFrame(checkAudio); }; checkAudio(); } catch (e) { console.error("音频测试失败:", e); } }, // 添加新方法:尝试单独获取音频 tryGetAudioOnly() { navigator.mediaDevices.getUserMedia({ audio: true }).then((audioStream) => { if (this.cameraStream) { const videoTrack = this.cameraStream.getVideoTracks()[0]; const audioTrack = audioStream.getAudioTracks()[0]; const combinedStream = new MediaStream(); if (videoTrack) combinedStream.addTrack(videoTrack); if (audioTrack) combinedStream.addTrack(audioTrack); this.cameraStream = combinedStream; const videoElement = this.$refs.userCameraVideo; if (videoElement) { videoElement.srcObject = combinedStream; videoElement.muted = true; } console.log("成功合并音频和视频轨道"); } else { console.warn("没有视频流可合并"); } }).catch((err) => { console.error("单独获取音频失败:", err); }); }, // 添加新方法:显示权限对话框 showPermissionDialog(permissionType) { common_vendor.index.showModal({ title: "需要权限", content: `请允许使用${permissionType}权限,否则可能影响面试功能`, confirmText: "去设置", success: (res) => { if (res.confirm) { common_vendor.index.openSetting({ success: (settingRes) => { console.log("设置页面打开成功", settingRes); } }); } } }); }, // 添加重试上传方法 retryVideoUpload() { if (this.lastVideoToRetry) { this.showRetryButton = false; common_vendor.index.showLoading({ title: "正在重新提交...", mask: true }); this.submitVideoToInterview(this.lastVideoToRetry); } else { common_vendor.index.showToast({ title: "没有可重试的视频", icon: "none" }); } }, // 添加一个新方法用于压缩视频 async compressVideo(videoBlob) { if (videoBlob.size < 5 * 1024 * 1024) { return videoBlob; } console.log("开始压缩视频,原始大小:", videoBlob.size); const videoElement = document.createElement("video"); videoElement.muted = true; videoElement.autoplay = false; const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); videoElement.src = URL.createObjectURL(videoBlob); return new Promise((resolve) => { videoElement.onloadedmetadata = () => { const width = Math.floor(videoElement.videoWidth / 2); const height = Math.floor(videoElement.videoHeight / 2); canvas.width = width; canvas.height = height; const stream = canvas.captureStream(15); if (videoElement.captureStream) { const originalStream = videoElement.captureStream(); const audioTracks = originalStream.getAudioTracks(); if (audioTracks.length > 0) { stream.addTrack(audioTracks[0]); } } const options = { mimeType: "video/webm;codecs=vp8,opus", audioBitsPerSecond: 64e3, videoBitsPerSecond: 8e5 // 800kbps }; const mediaRecorder = new MediaRecorder(stream, options); const chunks = []; mediaRecorder.ondataavailable = (e) => { if (e.data.size > 0) { chunks.push(e.data); } }; mediaRecorder.onstop = () => { const compressedBlob = new Blob(chunks, { type: "video/webm" }); console.log("视频压缩完成,压缩后大小:", compressedBlob.size); resolve(compressedBlob); }; videoElement.onplay = () => { mediaRecorder.start(100); const drawFrame = () => { if (videoElement.paused || videoElement.ended) { mediaRecorder.stop(); return; } ctx.drawImage(videoElement, 0, 0, width, height); requestAnimationFrame(drawFrame); }; drawFrame(); }; videoElement.play(); }; }); }, // 修改 checkIOSCameraRecordPermission 方法 checkIOSCameraRecordPermission() { const systemInfo = common_vendor.index.getSystemInfoSync(); if (systemInfo.platform !== "ios") return; common_vendor.index.getSetting({ success: (res) => { if (!res.authSetting["scope.camera"]) { common_vendor.index.authorize({ scope: "scope.camera", success: () => { console.log("iOS相机权限已获取"); }, fail: (err) => { console.error("iOS相机权限获取失败:", err); this.showPermissionDialog("相机"); } }); } if (!res.authSetting["scope.record"]) { common_vendor.index.authorize({ scope: "scope.record", success: () => { console.log("iOS录音权限已获取"); }, fail: (err) => { console.error("iOS录音权限获取失败:", err); this.showPermissionDialog("录音"); } }); } } }); }, // 添加新方法:检查并修复渲染问题 checkAndFixRenderingIssues() { try { if (typeof u !== "undefined" && u) { if (!u.currentQuestion) { console.log("修复: 创建缺失的currentQuestion对象"); u.currentQuestion = {}; } if (u.currentQuestion && typeof u.currentQuestion.isImportant === "undefined") { console.log("修复: 设置缺失的isImportant属性"); u.currentQuestion.isImportant = false; } } } catch (e) { console.log("防御性检查异常:", e); } }, // 添加格式化时间的辅助方法 formatTime(seconds) { if (!seconds && seconds !== 0) return "03:30"; const minutes = Math.floor(seconds / 60); const remainingSeconds = seconds % 60; return `${minutes.toString().padStart(2, "0")}:${remainingSeconds.toString().padStart(2, "0")}`; }, // 添加新方法:保存上传状态到本地存储 saveUploadStatus() { const uploadStatus = { isUploading: this.isUploading, uploadQueue: this.uploadQueue.length, timestamp: Date.now() }; try { common_vendor.index.setStorageSync("videoUploadStatus", JSON.stringify(uploadStatus)); } catch (e) { console.error("保存上传状态失败:", e); } } } }; function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { return common_vendor.e({ a: $data.showGif && $data.gifUrl }, $data.showGif && $data.gifUrl ? { b: $data.gifUrl } : {}, { c: !$data.showGif }, !$data.showGif ? { d: $data.videoUrl, e: common_vendor.o((...args) => $options.handleVideoError && $options.handleVideoError(...args)), f: common_vendor.o((...args) => $options.handleVideoEnded && $options.handleVideoEnded(...args)), g: common_vendor.o((...args) => $options.handleTimeUpdate && $options.handleTimeUpdate(...args)) } : {}, { h: $data.showAnswerButton }, $data.showAnswerButton ? { i: common_vendor.o((...args) => $options.handleAnswerButtonClick && $options.handleAnswerButtonClick(...args)) } : {}, { j: $data.currentSubtitle }, $data.currentSubtitle ? { k: common_vendor.t($data.currentSubtitle) } : {}, { l: $data.useMiniProgramCameraComponent }, $data.useMiniProgramCameraComponent ? { m: common_vendor.o((...args) => $options.handleCameraError && $options.handleCameraError(...args)) } : {}, { n: $data.loading }, $data.loading ? {} : {}, { o: $data.showDebugInfo }, $data.showDebugInfo ? common_vendor.e({ p: $data.assistantResponse }, $data.assistantResponse ? { q: common_vendor.t($data.assistantResponse) } : {}, { r: $data.audioTranscript }, $data.audioTranscript ? { s: common_vendor.t($data.audioTranscript) } : {}, { t: common_vendor.f($data.processedResponses, (item, index, i0) => { return common_vendor.e({ a: item.role }, item.role ? { b: common_vendor.t(item.role) } : {}, { c: item.transcript }, item.transcript ? { d: common_vendor.t(item.transcript) } : {}, { e: index }); }) }) : {}, { v: $data.showStopRecordingButton }, $data.showStopRecordingButton ? { w: common_vendor.o((...args) => $options.stopRecordingAnswer && $options.stopRecordingAnswer(...args)) } : {}, { x: $data.isRecording }, $data.isRecording ? { y: common_vendor.t($data.recordingTimeDisplay || "00:00 / 05:00") } : {}, { z: $data.showStartRecordingButton }, $data.showStartRecordingButton ? { A: common_vendor.o((...args) => $options.handleStartRecordingClick && $options.handleStartRecordingClick(...args)) } : {}, { B: $data.showRetryButton }, $data.showRetryButton ? { C: common_vendor.o((...args) => $options.retryVideoUpload && $options.retryVideoUpload(...args)) } : {}, { D: $data.showCountdown }, $data.showCountdown ? { E: common_vendor.t($data.countdownValue) } : {}); } const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-2a02c54e"]]); wx.createPage(MiniProgramPage);