|
@@ -5,6 +5,26 @@ const _sfc_main = {
|
|
|
name: "IdentityVerify",
|
|
|
data() {
|
|
|
return {
|
|
|
+ followUpQuestion: "",
|
|
|
+ // 追问问题
|
|
|
+ followUpAudioUrl: "",
|
|
|
+ // 追问音频URL
|
|
|
+ audioContext: null,
|
|
|
+ // 音频上下文
|
|
|
+ followUpQuestions: [],
|
|
|
+ // 追问问题列表
|
|
|
+ isWaitingForAnswer: false,
|
|
|
+ // 添加新的状态来控制是否在等待用户回答
|
|
|
+ currentFollowUpIndex: -1,
|
|
|
+ // 当前追问问题索引
|
|
|
+ showSubtitleText: false,
|
|
|
+ // 是否显示字幕
|
|
|
+ subtitleText: "",
|
|
|
+ // 字幕文本
|
|
|
+ parentQuestion: "",
|
|
|
+ // 父问题文本
|
|
|
+ isFollowUpQuestion: false,
|
|
|
+ // 是否是追问问题
|
|
|
loading: false,
|
|
|
responses: [],
|
|
|
processedResponses: [],
|
|
@@ -160,8 +180,25 @@ const _sfc_main = {
|
|
|
// 定时器对象
|
|
|
showCameraWarning: false,
|
|
|
// 添加新的数据属性
|
|
|
- showPageWarning: false
|
|
|
+ showPageWarning: false,
|
|
|
// 添加新的数据属性
|
|
|
+ followUpQuestion: "",
|
|
|
+ // 追问问题
|
|
|
+ followUpAudioUrl: "",
|
|
|
+ // 追问音频URL
|
|
|
+ audioContext: null,
|
|
|
+ // 音频上下文
|
|
|
+ followUpQuestions: [],
|
|
|
+ // 追问问题列表
|
|
|
+ currentFollowUpIndex: -1,
|
|
|
+ // 当前追问问题索引
|
|
|
+ showSubtitleText: false,
|
|
|
+ // 是否显示字幕
|
|
|
+ subtitleText: "",
|
|
|
+ // 字幕文本
|
|
|
+ isAudioPlaying: false,
|
|
|
+ isWaitingForAnswer: false
|
|
|
+ // 添加新的状态来控制是否在等待用户回答
|
|
|
};
|
|
|
},
|
|
|
mounted() {
|
|
@@ -213,6 +250,258 @@ const _sfc_main = {
|
|
|
this.cleanupPersonDetectionWebSocket();
|
|
|
},
|
|
|
methods: {
|
|
|
+ // 处理音频播放完成
|
|
|
+ handleAudioEnd() {
|
|
|
+ console.log("音频播放完成");
|
|
|
+ this.isWaitingForAnswer = true;
|
|
|
+ this.showStartRecordingButton = true;
|
|
|
+ setTimeout(() => {
|
|
|
+ this.startCountdown();
|
|
|
+ }, 100);
|
|
|
+ },
|
|
|
+ // 开始倒计时
|
|
|
+ startCountdown() {
|
|
|
+ this.showCountdown = true;
|
|
|
+ this.countdownValue = 5;
|
|
|
+ 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;
|
|
|
+ },
|
|
|
+ // 处理追问问题
|
|
|
+ async handleFollowUpQuestion(questionData) {
|
|
|
+ console.log("处理追问问题数据:", questionData);
|
|
|
+ if (!questionData || !questionData.follow_up_voice_url || !questionData.follow_up_question) {
|
|
|
+ console.error("追问数据不完整:", questionData);
|
|
|
+ common_vendor.index.showToast({
|
|
|
+ title: "获取追问数据失败",
|
|
|
+ icon: "none"
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.parentQuestion = questionData.original_question || "";
|
|
|
+ let audioUrl = "";
|
|
|
+ if (questionData.follow_up_voice_url.direct_url) {
|
|
|
+ audioUrl = questionData.follow_up_voice_url.direct_url;
|
|
|
+ } else if (questionData.follow_up_voice_url.file_url) {
|
|
|
+ audioUrl = questionData.follow_up_voice_url.file_url;
|
|
|
+ }
|
|
|
+ if (!audioUrl.startsWith("http")) {
|
|
|
+ audioUrl = common_config.apiBaseUrl + audioUrl;
|
|
|
+ }
|
|
|
+ console.log("处理后的音频URL:", audioUrl);
|
|
|
+ const followUpQuestionObj = {
|
|
|
+ id: Date.now(),
|
|
|
+ question: questionData.follow_up_question.trim(),
|
|
|
+ // 去除可能的空白字符
|
|
|
+ audioUrl,
|
|
|
+ originalQuestion: questionData.original_question,
|
|
|
+ sessionId: questionData.session_id
|
|
|
+ };
|
|
|
+ console.log("创建的追问问题对象:", followUpQuestionObj);
|
|
|
+ this.followUpQuestions.push(followUpQuestionObj);
|
|
|
+ this.currentFollowUpIndex = this.followUpQuestions.length - 1;
|
|
|
+ this.followUpQuestion = followUpQuestionObj.question;
|
|
|
+ this.followUpAudioUrl = followUpQuestionObj.audioUrl;
|
|
|
+ this.isFollowUpQuestion = true;
|
|
|
+ this.currentFollowUpQuestion = followUpQuestionObj;
|
|
|
+ this.showSubtitle(followUpQuestionObj.question, true);
|
|
|
+ try {
|
|
|
+ await this.playFollowUpAudio();
|
|
|
+ console.log("音频播放完成,准备录制回答");
|
|
|
+ this.prepareToAnswer(true, followUpQuestionObj);
|
|
|
+ } catch (error) {
|
|
|
+ console.error("音频播放失败:", error);
|
|
|
+ this.prepareToAnswer(true, followUpQuestionObj);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 准备回答问题
|
|
|
+ prepareToAnswer(isFollowUp = false, questionData = null) {
|
|
|
+ console.log("准备回答问题:", { isFollowUp, questionData });
|
|
|
+ this.isRecording = false;
|
|
|
+ this.recordedTime = 0;
|
|
|
+ this.showStopRecordingButton = false;
|
|
|
+ if (isFollowUp && questionData) {
|
|
|
+ this.currentFollowUpQuestion = questionData;
|
|
|
+ this.isFollowUpQuestion = true;
|
|
|
+ }
|
|
|
+ this.isWaitingForAnswer = true;
|
|
|
+ this.handleAudioEnd();
|
|
|
+ },
|
|
|
+ // 调用面试互动接口
|
|
|
+ async callInterviewInteraction(questionId) {
|
|
|
+ const userInfo = JSON.parse(common_vendor.index.getStorageSync("userInfo"));
|
|
|
+ const appId = common_vendor.index.getStorageSync("appId");
|
|
|
+ try {
|
|
|
+ console.log("开始调用面试互动接口", { questionId, appId });
|
|
|
+ const res = await common_vendor.index.request({
|
|
|
+ url: `${common_config.apiBaseUrl}/api/voice_interview_interaction/`,
|
|
|
+ method: "POST",
|
|
|
+ data: {
|
|
|
+ tenant_id: userInfo.tenant_id || 1,
|
|
|
+ question_id: questionId,
|
|
|
+ position_config_id: 6,
|
|
|
+ application_id: appId
|
|
|
+ },
|
|
|
+ header: {
|
|
|
+ "content-type": "application/json"
|
|
|
+ }
|
|
|
+ });
|
|
|
+ console.log("面试互动接口返回数据:", res);
|
|
|
+ if (res.data.success) {
|
|
|
+ await this.handleFollowUpQuestion(res.data);
|
|
|
+ } else {
|
|
|
+ console.error("面试互动接口返回错误:", res.data);
|
|
|
+ common_vendor.index.showToast({
|
|
|
+ title: "获取追问失败",
|
|
|
+ icon: "none"
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error("调用面试互动接口失败:", error);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 播放追问音频
|
|
|
+ async playFollowUpAudio() {
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ console.log("开始播放追问音频, URL:", this.followUpAudioUrl);
|
|
|
+ if (!this.followUpAudioUrl) {
|
|
|
+ console.error("没有音频URL");
|
|
|
+ common_vendor.index.showToast({
|
|
|
+ title: "音频URL无效",
|
|
|
+ icon: "none"
|
|
|
+ });
|
|
|
+ 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;
|
|
|
+ common_vendor.index.showToast({
|
|
|
+ title: "正在播放追问",
|
|
|
+ icon: "none",
|
|
|
+ duration: 2e3
|
|
|
+ });
|
|
|
+ });
|
|
|
+ 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) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const ctx = this.audioContext;
|
|
|
+ this.audioContext = null;
|
|
|
+ try {
|
|
|
+ if (this.isAudioPlaying) {
|
|
|
+ ctx.stop();
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error("停止音频播放失败:", error);
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ ctx.destroy();
|
|
|
+ } catch (error) {
|
|
|
+ console.error("销毁音频实例失败:", error);
|
|
|
+ }
|
|
|
+ this.isAudioPlaying = false;
|
|
|
+ },
|
|
|
+ // 绑定音频事件
|
|
|
+ bindAudioEvents(audioContext, resolve, reject) {
|
|
|
+ audioContext.onCanplay(() => {
|
|
|
+ console.log("音频可以播放");
|
|
|
+ common_vendor.index.showToast({
|
|
|
+ title: "正在播放追问",
|
|
|
+ icon: "none",
|
|
|
+ duration: 2e3
|
|
|
+ });
|
|
|
+ });
|
|
|
+ audioContext.onTimeUpdate(() => {
|
|
|
+ console.log("音频播放进度:", audioContext.currentTime);
|
|
|
+ });
|
|
|
+ audioContext.onEnded(() => {
|
|
|
+ console.log("追问音频播放完成");
|
|
|
+ this.cleanupAudioContext();
|
|
|
+ resolve();
|
|
|
+ });
|
|
|
+ audioContext.onError((res) => {
|
|
|
+ console.error("音频播放错误:", res);
|
|
|
+ common_vendor.index.showToast({
|
|
|
+ title: "音频播放失败",
|
|
|
+ icon: "none"
|
|
|
+ });
|
|
|
+ this.cleanupAudioContext();
|
|
|
+ reject(res);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 修改准备回答方法
|
|
|
+ prepareToAnswer(isFollowUp = false, questionData = null) {
|
|
|
+ this.isRecording = false;
|
|
|
+ this.recordedTime = 0;
|
|
|
+ this.showStopRecordingButton = false;
|
|
|
+ if (isFollowUp && questionData) {
|
|
|
+ this.currentFollowUpQuestion = questionData;
|
|
|
+ this.isFollowUpQuestion = true;
|
|
|
+ }
|
|
|
+ this.isWaitingForAnswer = true;
|
|
|
+ this.handleAudioEnd();
|
|
|
+ },
|
|
|
// 初始化相机
|
|
|
async initCamera() {
|
|
|
const systemInfo = common_vendor.index.getSystemInfoSync();
|
|
@@ -671,9 +960,14 @@ const _sfc_main = {
|
|
|
},
|
|
|
// 添加新方法:开始倒计时
|
|
|
startCountdown() {
|
|
|
+ this.clearCountdown();
|
|
|
this.showCountdown = true;
|
|
|
this.countdownValue = 10;
|
|
|
this.countdownTimer = setInterval(() => {
|
|
|
+ if (!this.showStartRecordingButton) {
|
|
|
+ this.clearCountdown();
|
|
|
+ return;
|
|
|
+ }
|
|
|
this.countdownValue--;
|
|
|
if (this.countdownValue <= 0) {
|
|
|
this.clearCountdown();
|
|
@@ -694,11 +988,14 @@ const _sfc_main = {
|
|
|
handleStartRecordingClick() {
|
|
|
this.showStartRecordingButton = false;
|
|
|
this.clearCountdown();
|
|
|
+ this.isWaitingForAnswer = false;
|
|
|
this.startRecordingAnswer();
|
|
|
},
|
|
|
// 修改 stopRecordingAnswer 方法,添加录制时长检查
|
|
|
stopRecordingAnswer() {
|
|
|
this.clearCountdown();
|
|
|
+ this.isWaitingForAnswer = false;
|
|
|
+ this.isWaitingForAnswer = false;
|
|
|
const recordingDuration = this.getRecordingDuration();
|
|
|
const minimumDuration = 3;
|
|
|
const lowScoreDuration = 7;
|
|
@@ -1051,6 +1348,7 @@ const _sfc_main = {
|
|
|
this.countdownTimer = null;
|
|
|
this.showCountdown = false;
|
|
|
}
|
|
|
+ this.isWaitingForAnswer = false;
|
|
|
const recordingDuration = this.getRecordingDuration();
|
|
|
const minimumDuration = 3;
|
|
|
const lowScoreDuration = 7;
|
|
@@ -1147,11 +1445,11 @@ const _sfc_main = {
|
|
|
return;
|
|
|
}
|
|
|
this.cameraContext.stopRecord({
|
|
|
- success: (res) => {
|
|
|
+ success: async (res) => {
|
|
|
console.log("小程序录制停止成功:", res);
|
|
|
const videoPath = res.tempVideoPath;
|
|
|
if (videoPath) {
|
|
|
- this.uploadRecordedVideo(videoPath);
|
|
|
+ await this.uploadRecordedVideo(videoPath);
|
|
|
} else {
|
|
|
console.error("未获取到录制视频路径");
|
|
|
this.proceedToNextQuestion();
|
|
@@ -1219,7 +1517,6 @@ const _sfc_main = {
|
|
|
attempts: 0,
|
|
|
maxAttempts: 3,
|
|
|
parentQuestionId: this.currentParentQuestionId
|
|
|
- // 添加父问题ID
|
|
|
};
|
|
|
if (!isFollowUpQuestionUpload) {
|
|
|
this.currentParentQuestionId = questionId;
|
|
@@ -1228,15 +1525,25 @@ const _sfc_main = {
|
|
|
this.uploadProgress[uploadTask.id] = 0;
|
|
|
this.uploadStatus[uploadTask.id] = "pending";
|
|
|
common_vendor.index.showToast({
|
|
|
- title: "已完成回答",
|
|
|
- icon: "none",
|
|
|
+ title: "正在上传回答...",
|
|
|
+ icon: "loading",
|
|
|
duration: 1500
|
|
|
});
|
|
|
this.updateUploadStatusText();
|
|
|
- if (!this.isUploading) {
|
|
|
- this.processUploadQueue();
|
|
|
- }
|
|
|
- this.handlePostUploadActions(uploadTask);
|
|
|
+ return new Promise((resolve) => {
|
|
|
+ const checkUploadStatus = () => {
|
|
|
+ if (!this.isUploading && this.uploadQueue.length === 0) {
|
|
|
+ this.handlePostUploadActions(uploadTask);
|
|
|
+ resolve();
|
|
|
+ } else {
|
|
|
+ setTimeout(checkUploadStatus, 500);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ if (!this.isUploading) {
|
|
|
+ this.processUploadQueue();
|
|
|
+ }
|
|
|
+ checkUploadStatus();
|
|
|
+ });
|
|
|
},
|
|
|
// 添加新方法:处理上传后的逻辑
|
|
|
handlePostUploadActions(task) {
|
|
@@ -1414,6 +1721,7 @@ const _sfc_main = {
|
|
|
question_form: task.questionForm,
|
|
|
question_text: task.questionText
|
|
|
};
|
|
|
+ console.log("提交视频到面试接口", requestData);
|
|
|
common_vendor.index.request({
|
|
|
url: `${common_config.apiBaseUrl}/api/job/upload_video`,
|
|
|
method: "POST",
|
|
@@ -1421,8 +1729,26 @@ const _sfc_main = {
|
|
|
header: {
|
|
|
"content-type": "application/x-www-form-urlencoded"
|
|
|
},
|
|
|
- success: (res) => {
|
|
|
+ success: async (res) => {
|
|
|
if (res.data.code === 200 || res.data.code === 2e3) {
|
|
|
+ console.log("视频提交成功,准备调用面试互动接口");
|
|
|
+ if (!task.isFollowUp) {
|
|
|
+ try {
|
|
|
+ await this.callInterviewInteraction(res.data.data.job_position_question_id);
|
|
|
+ console.log("面试互动接口调用成功");
|
|
|
+ } catch (error) {
|
|
|
+ console.error("面试互动接口调用失败:", error);
|
|
|
+ this.proceedToNextQuestion();
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ console.log("追问回答上传完成,继续下一个问题");
|
|
|
+ this.proceedToNextQuestion();
|
|
|
+ }
|
|
|
+ common_vendor.index.showToast({
|
|
|
+ title: "回答已提交",
|
|
|
+ icon: "success",
|
|
|
+ duration: 1500
|
|
|
+ });
|
|
|
this.uploadQueue.shift();
|
|
|
this.processUploadQueue();
|
|
|
} else {
|
|
@@ -1430,7 +1756,8 @@ const _sfc_main = {
|
|
|
}
|
|
|
},
|
|
|
fail: (err) => {
|
|
|
- this.handleUploadError(task, "网络错误: " + err.errMsg);
|
|
|
+ console.error("提交视频失败:", err);
|
|
|
+ this.handleUploadError(task, "提交失败: " + err.errMsg);
|
|
|
}
|
|
|
});
|
|
|
},
|
|
@@ -1672,6 +1999,7 @@ const _sfc_main = {
|
|
|
handleStartRecordingClick() {
|
|
|
this.showStartRecordingButton = false;
|
|
|
this.clearCountdown();
|
|
|
+ this.isWaitingForAnswer = false;
|
|
|
this.startRecordingAnswer();
|
|
|
},
|
|
|
// 修改 checkAudioPermission 方法,确保在录制前获取音频权限
|
|
@@ -2302,6 +2630,10 @@ const _sfc_main = {
|
|
|
// 修改检查并播放追问问题的方法
|
|
|
checkAndPlayFollowUpQuestion(parentQuestionId) {
|
|
|
console.log("检查是否有追问问题,父问题ID:", parentQuestionId);
|
|
|
+ if (this.isWaitingForAnswer) {
|
|
|
+ console.log("正在等待用户回答,暂不处理追问");
|
|
|
+ return;
|
|
|
+ }
|
|
|
if (!parentQuestionId) {
|
|
|
console.warn("没有父问题ID,无法检查追问问题");
|
|
|
this.proceedToNextQuestion();
|
|
@@ -2409,7 +2741,6 @@ const _sfc_main = {
|
|
|
this.personDetectionSocket.onMessage((res) => {
|
|
|
try {
|
|
|
const data = JSON.parse(res.data);
|
|
|
- console.log(data);
|
|
|
if (data.type === "person_detection_result") {
|
|
|
this.handlePersonDetectionResult(data);
|
|
|
}
|
|
@@ -2471,26 +2802,167 @@ const _sfc_main = {
|
|
|
}
|
|
|
},
|
|
|
handlePersonDetectionResult(data) {
|
|
|
- console.log(data.data.detection.has_person);
|
|
|
- console.log(data.data.identity.status);
|
|
|
if (data.data.identity.status !== "identity_verified") {
|
|
|
- this.showPageWarning = true;
|
|
|
+ setTimeout(() => {
|
|
|
+ this.showPageWarning = false;
|
|
|
+ }, 3e3);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 添加新方法:处理追问问题
|
|
|
+ async handleFollowUpQuestion(questionData) {
|
|
|
+ console.log("处理追问问题数据:", questionData);
|
|
|
+ if (!questionData || !questionData.follow_up_voice_url || !questionData.follow_up_question) {
|
|
|
+ console.error("追问数据不完整:", questionData);
|
|
|
common_vendor.index.showToast({
|
|
|
- title: data.data.identity.message,
|
|
|
- icon: "none",
|
|
|
- duration: 3e3
|
|
|
+ title: "获取追问数据失败",
|
|
|
+ icon: "none"
|
|
|
});
|
|
|
- common_vendor.index.vibrateLong({
|
|
|
- success: function() {
|
|
|
- console.log("Vibration successful");
|
|
|
- },
|
|
|
- fail: function(err) {
|
|
|
- console.error("Vibration failed:", err);
|
|
|
- }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.parentQuestion = questionData.original_question || "";
|
|
|
+ let audioUrl = "";
|
|
|
+ if (questionData.follow_up_voice_url.direct_url) {
|
|
|
+ audioUrl = questionData.follow_up_voice_url.direct_url;
|
|
|
+ } else if (questionData.follow_up_voice_url.file_url) {
|
|
|
+ audioUrl = questionData.follow_up_voice_url.file_url;
|
|
|
+ }
|
|
|
+ if (!audioUrl.startsWith("http")) {
|
|
|
+ audioUrl = common_config.apiBaseUrl + audioUrl;
|
|
|
+ }
|
|
|
+ console.log("处理后的音频URL:", audioUrl);
|
|
|
+ const followUpQuestionObj = {
|
|
|
+ id: Date.now(),
|
|
|
+ question: questionData.follow_up_question.trim(),
|
|
|
+ // 去除可能的空白字符
|
|
|
+ audioUrl,
|
|
|
+ originalQuestion: questionData.original_question,
|
|
|
+ sessionId: questionData.session_id
|
|
|
+ };
|
|
|
+ console.log("创建的追问问题对象:", followUpQuestionObj);
|
|
|
+ this.followUpQuestions.push(followUpQuestionObj);
|
|
|
+ this.currentFollowUpIndex = this.followUpQuestions.length - 1;
|
|
|
+ this.followUpQuestion = followUpQuestionObj.question;
|
|
|
+ this.followUpAudioUrl = followUpQuestionObj.audioUrl;
|
|
|
+ this.isFollowUpQuestion = true;
|
|
|
+ this.currentFollowUpQuestion = followUpQuestionObj;
|
|
|
+ this.showSubtitle(followUpQuestionObj.question, true);
|
|
|
+ try {
|
|
|
+ await this.playFollowUpAudio();
|
|
|
+ console.log("音频播放完成,准备录制回答");
|
|
|
+ this.prepareToAnswer(true, followUpQuestionObj);
|
|
|
+ } catch (error) {
|
|
|
+ console.error("音频播放失败:", error);
|
|
|
+ this.prepareToAnswer(true, followUpQuestionObj);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 播放追问音频
|
|
|
+ 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;
|
|
|
+ common_vendor.index.showToast({
|
|
|
+ title: "正在播放追问",
|
|
|
+ icon: "none",
|
|
|
+ duration: 2e3
|
|
|
+ });
|
|
|
+ });
|
|
|
+ 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) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const ctx = this.audioContext;
|
|
|
+ this.audioContext = null;
|
|
|
+ try {
|
|
|
+ if (this.isAudioPlaying) {
|
|
|
+ ctx.stop();
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error("停止音频播放失败:", error);
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ ctx.destroy();
|
|
|
+ } catch (error) {
|
|
|
+ console.error("销毁音频实例失败:", error);
|
|
|
+ }
|
|
|
+ this.isAudioPlaying = false;
|
|
|
+ },
|
|
|
+ // 显示字幕
|
|
|
+ showSubtitle(text, isFollowUp = true) {
|
|
|
+ console.log("显示字幕:", text);
|
|
|
+ this.subtitleText = text;
|
|
|
+ this.showSubtitleText = true;
|
|
|
+ this.isFollowUpQuestion = isFollowUp;
|
|
|
+ this.$nextTick(() => {
|
|
|
setTimeout(() => {
|
|
|
- this.showPageWarning = false;
|
|
|
- }, 3e3);
|
|
|
+ this.showSubtitleText = false;
|
|
|
+ }, 8e3);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 显示问题对话框
|
|
|
+ showQuestionDialog() {
|
|
|
+ if (this.followUpQuestion) {
|
|
|
+ common_vendor.index.showModal({
|
|
|
+ title: "追问问题",
|
|
|
+ content: this.followUpQuestion,
|
|
|
+ showCancel: false,
|
|
|
+ success: () => {
|
|
|
+ this.prepareToAnswer(true, this.followUpQuestions[this.currentFollowUpIndex]);
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
}
|
|
|
},
|
|
@@ -2537,8 +3009,8 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
}, $data.showAnswerButton ? {
|
|
|
h: common_vendor.o((...args) => $options.handleAnswerButtonClick && $options.handleAnswerButtonClick(...args))
|
|
|
} : {}, {
|
|
|
- i: $data.currentSubtitle
|
|
|
- }, $data.currentSubtitle ? common_vendor.e({
|
|
|
+ i: $data.currentSubtitle || $data.showSubtitleText && $data.subtitleText
|
|
|
+ }, $data.currentSubtitle || $data.showSubtitleText && $data.subtitleText ? common_vendor.e({
|
|
|
j: $data.currentVideoIndex > 0
|
|
|
}, $data.currentVideoIndex > 0 ? {
|
|
|
k: common_vendor.t($data.currentVideoIndex),
|
|
@@ -2549,7 +3021,7 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
n: common_vendor.t($data.currentSubtitle)
|
|
|
} : {
|
|
|
o: common_vendor.t($data.parentQuestion),
|
|
|
- p: common_vendor.t($data.currentSubtitle)
|
|
|
+ p: common_vendor.t($data.subtitleText || $data.currentSubtitle)
|
|
|
}) : {}, {
|
|
|
q: $data.useMiniProgramCameraComponent
|
|
|
}, $data.useMiniProgramCameraComponent ? {
|