|
@@ -320,18 +320,17 @@ export default {
|
|
|
needPlayLowScoreVideo: false, // 是否需要播放低分视频
|
|
|
finalRecordingDuration: 0, // 最终录制时长
|
|
|
historyTime: 0, // 添加历史时间记录
|
|
|
- followUpQuestions: [], // 存储追问问题数据
|
|
|
- currentParentQuestionId: null, // 当前父问题ID
|
|
|
+ followUpQuestions: [], // 存储追问问题数据(预加载的静态追问)
|
|
|
hasPlayedFollowUp: {}, // 记录已播放的追问,格式: {questionId: true}
|
|
|
isFollowUpQuestion: false, // 标记当前是否正在播放追问问题
|
|
|
currentFollowUpQuestion: null, // 添加当前追问问题的完整信息
|
|
|
lastQuestionWasFollowUp: false,
|
|
|
lastFollowUpQuestionId: null,
|
|
|
- // 追问次数控制
|
|
|
- defaultFollowUpLimit: 1, // 默认每个主题目最多2次追问
|
|
|
- followUpLimitMap: {}, // { parentJobPositionQuestionId: limit }
|
|
|
- followUpAskedCountMap: {}, // { parentJobPositionQuestionId: askedCount }
|
|
|
- followUpRequestInFlight: {}, // { parentJobPositionQuestionId: boolean }
|
|
|
+ // 追问次数控制 - 统一使用job_position_question_id作为key
|
|
|
+ defaultFollowUpLimit: 1, // 默认每个主题目最多1次追问
|
|
|
+ followUpLimitMap: {}, // { job_position_question_id: limit }
|
|
|
+ followUpAskedCountMap: {}, // { job_position_question_id: askedCount }
|
|
|
+ followUpRequestInFlight: {}, // { job_position_question_id: boolean }
|
|
|
lastUpdateTime: Date.now(), // 添加最后更新时间戳
|
|
|
subtitleMap: {}, // 用于存储字幕和翻译的映射
|
|
|
progressPercent: 0, // 录制进度百分比
|
|
@@ -425,43 +424,52 @@ export default {
|
|
|
},
|
|
|
methods: {
|
|
|
// ===== 追问次数控制:工具方法 =====
|
|
|
- getFollowUpLimit(parentId) {
|
|
|
- if (!parentId) return this.defaultFollowUpLimit;
|
|
|
- return this.followUpLimitMap[parentId] || this.defaultFollowUpLimit;
|
|
|
+ getFollowUpLimit(jobPositionQuestionId) {
|
|
|
+ if (!jobPositionQuestionId) return this.defaultFollowUpLimit;
|
|
|
+ return this.followUpLimitMap[jobPositionQuestionId] || this.defaultFollowUpLimit;
|
|
|
},
|
|
|
- setFollowUpLimit(parentId, limit) {
|
|
|
- if (!parentId) return;
|
|
|
+ setFollowUpLimit(jobPositionQuestionId, limit) {
|
|
|
+ if (!jobPositionQuestionId) return;
|
|
|
const parsed = parseInt(limit);
|
|
|
- this.followUpLimitMap[parentId] = Number.isFinite(parsed) && parsed > 0 ? parsed : this.defaultFollowUpLimit;
|
|
|
+ this.followUpLimitMap[jobPositionQuestionId] = Number.isFinite(parsed) && parsed > 0 ? parsed : this.defaultFollowUpLimit;
|
|
|
+ console.log(`设置问题 ${jobPositionQuestionId} 的追问上限为: ${this.followUpLimitMap[jobPositionQuestionId]}`);
|
|
|
},
|
|
|
- resetFollowUpAskedCount(parentId) {
|
|
|
- if (!parentId) return;
|
|
|
- this.followUpAskedCountMap[parentId] = 0;
|
|
|
+ resetFollowUpAskedCount(jobPositionQuestionId) {
|
|
|
+ if (!jobPositionQuestionId) return;
|
|
|
+ this.followUpAskedCountMap[jobPositionQuestionId] = 0;
|
|
|
+ console.log(`重置问题 ${jobPositionQuestionId} 的追问次数为: 0`);
|
|
|
},
|
|
|
- incrementFollowUpCount(parentId) {
|
|
|
- if (!parentId) return;
|
|
|
- const current = this.followUpAskedCountMap[parentId] || 0;
|
|
|
- this.followUpAskedCountMap[parentId] = current + 1;
|
|
|
+ incrementFollowUpCount(jobPositionQuestionId) {
|
|
|
+ if (!jobPositionQuestionId) return;
|
|
|
+ const current = this.followUpAskedCountMap[jobPositionQuestionId] || 0;
|
|
|
+ this.followUpAskedCountMap[jobPositionQuestionId] = current + 1;
|
|
|
+ console.log(`问题 ${jobPositionQuestionId} 的追问次数增加到: ${this.followUpAskedCountMap[jobPositionQuestionId]}`);
|
|
|
},
|
|
|
- canAskMoreFollowUps(parentId) {
|
|
|
- if (!parentId) return false;
|
|
|
- const asked = this.followUpAskedCountMap[parentId] || 0;
|
|
|
- const limit = this.getFollowUpLimit(parentId);
|
|
|
- return asked < limit;
|
|
|
+ canAskMoreFollowUps(jobPositionQuestionId) {
|
|
|
+ if (!jobPositionQuestionId) return false;
|
|
|
+ const asked = this.followUpAskedCountMap[jobPositionQuestionId] || 0;
|
|
|
+ const limit = this.getFollowUpLimit(jobPositionQuestionId);
|
|
|
+ const canAsk = asked < limit;
|
|
|
+ console.log(`检查问题 ${jobPositionQuestionId} 是否可以继续追问: ${canAsk} (已问${asked}次/上限${limit}次)`);
|
|
|
+ return canAsk;
|
|
|
},
|
|
|
- async maybeRequestNextFollowUp(parentId) {
|
|
|
- if (!parentId) {
|
|
|
+ async maybeRequestNextFollowUp(jobPositionQuestionId) {
|
|
|
+ if (!jobPositionQuestionId) {
|
|
|
+ console.log('缺少job_position_question_id,直接进入下一题');
|
|
|
this.proceedToNextQuestion();
|
|
|
return;
|
|
|
}
|
|
|
- if (this.canAskMoreFollowUps(parentId)) {
|
|
|
+
|
|
|
+ console.log(`检查是否需要继续追问,问题ID: ${jobPositionQuestionId}`);
|
|
|
+
|
|
|
+ if (this.canAskMoreFollowUps(jobPositionQuestionId)) {
|
|
|
// 避免重复触发并发请求
|
|
|
- if (this.followUpRequestInFlight[parentId]) {
|
|
|
+ if (this.followUpRequestInFlight[jobPositionQuestionId]) {
|
|
|
console.log('已有追问请求进行中,跳过重复触发');
|
|
|
return;
|
|
|
}
|
|
|
// 交由 callInterviewInteraction 统一处理并发标记
|
|
|
- const ok = await this.callInterviewInteraction(parentId);
|
|
|
+ const ok = await this.callInterviewInteraction(jobPositionQuestionId);
|
|
|
if (!ok) {
|
|
|
console.log('未获取到下一条追问或调用失败,进入下一题');
|
|
|
this.isFollowUpMode = false;
|
|
@@ -471,6 +479,7 @@ export default {
|
|
|
}
|
|
|
} else {
|
|
|
// 已达上限,进入下一题
|
|
|
+ console.log(`问题 ${jobPositionQuestionId} 追问次数已达上限,进入下一题`);
|
|
|
this.isFollowUpMode = false;
|
|
|
this.isFollowUpQuestion = false;
|
|
|
this.currentFollowUpQuestion = null;
|
|
@@ -616,14 +625,14 @@ export default {
|
|
|
this.handleAudioEnd();
|
|
|
},
|
|
|
// 调用面试互动接口
|
|
|
- async callInterviewInteraction(questionId, retryCount = 0, maxRetries = 3) {
|
|
|
+ async callInterviewInteraction(jobPositionQuestionId, retryCount = 0, maxRetries = 3) {
|
|
|
// 防重入:同一父问题并发保护
|
|
|
- if (questionId && this.followUpRequestInFlight[questionId]) {
|
|
|
+ if (jobPositionQuestionId && this.followUpRequestInFlight[jobPositionQuestionId]) {
|
|
|
console.log('追问请求已在进行中,跳过本次调用');
|
|
|
return false;
|
|
|
}
|
|
|
- if (questionId) {
|
|
|
- this.followUpRequestInFlight[questionId] = true;
|
|
|
+ if (jobPositionQuestionId) {
|
|
|
+ this.followUpRequestInFlight[jobPositionQuestionId] = true;
|
|
|
}
|
|
|
const userInfo = JSON.parse(uni.getStorageSync('userInfo'));
|
|
|
const appId = uni.getStorageSync('appId');
|
|
@@ -632,13 +641,13 @@ export default {
|
|
|
try {
|
|
|
// 显示思考中loading
|
|
|
this.showThinkingLoading();
|
|
|
- console.log('开始调用面试互动接口', { questionId, appId });
|
|
|
+ console.log('开始调用面试互动接口', { jobPositionQuestionId, appId });
|
|
|
const res = await uni.request({
|
|
|
url: `${apiBaseUrl}/api/voice_interview_interaction/`,
|
|
|
method: 'POST',
|
|
|
data: {
|
|
|
tenant_id: userInfo.tenant_id || 1,
|
|
|
- question_id: questionId,
|
|
|
+ question_id: jobPositionQuestionId,
|
|
|
position_config_id: positionConfigId,
|
|
|
application_id: appId
|
|
|
},
|
|
@@ -654,7 +663,7 @@ export default {
|
|
|
console.log(`视频转写未完成,${retryCount + 1}次重试中...`);
|
|
|
// 等待3秒后重试
|
|
|
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
|
- return this.callInterviewInteraction(questionId, retryCount + 1, maxRetries);
|
|
|
+ return this.callInterviewInteraction(jobPositionQuestionId, retryCount + 1, maxRetries);
|
|
|
} else {
|
|
|
console.log('达到最大重试次数,视频转写仍未完成');
|
|
|
uni.showToast({
|
|
@@ -667,9 +676,9 @@ export default {
|
|
|
}
|
|
|
|
|
|
if (res.data.success) {
|
|
|
- // 成功获取到一条追问,计数 +1(表示“已请求”这条追问)
|
|
|
- if (questionId) {
|
|
|
- this.incrementFollowUpCount(questionId);
|
|
|
+ // 成功获取到一条追问,计数 +1(表示"已请求"这条追问)
|
|
|
+ if (jobPositionQuestionId) {
|
|
|
+ this.incrementFollowUpCount(jobPositionQuestionId);
|
|
|
}
|
|
|
// 处理本次追问(即便已达到上限,也应该播放本次追问)
|
|
|
await this.handleFollowUpQuestion(res.data);
|
|
@@ -685,8 +694,8 @@ export default {
|
|
|
this.hideThinkingLoading();
|
|
|
return false;
|
|
|
} finally {
|
|
|
- if (questionId) {
|
|
|
- this.followUpRequestInFlight[questionId] = false;
|
|
|
+ if (jobPositionQuestionId) {
|
|
|
+ this.followUpRequestInFlight[jobPositionQuestionId] = false;
|
|
|
}
|
|
|
}
|
|
|
},
|
|
@@ -2246,7 +2255,7 @@ export default {
|
|
|
|
|
|
|
|
|
console.log('准备上传视频:', typeof fileOrPath === 'string' ? fileOrPath : fileOrPath.name);
|
|
|
- console.log('当前问题ID:', this.currentParentQuestionId);
|
|
|
+ console.log('当前父问题ID:', this.parentJobPositionQuestionId);
|
|
|
console.log('当前问题类型:', this.isFollowUpQuestion);
|
|
|
console.log('当前追问问题:', this.currentFollowUpQuestion);
|
|
|
|
|
@@ -2299,14 +2308,11 @@ export default {
|
|
|
questionForm: questionForm,
|
|
|
attempts: 0,
|
|
|
maxAttempts: 3,
|
|
|
- parentQuestionId: this.currentParentQuestionId,
|
|
|
+ parentQuestionId: this.parentJobPositionQuestionId,
|
|
|
videoDuration: this.currentRecordingDuration || 0 // 添加视频时长
|
|
|
};
|
|
|
|
|
|
- // 如果不是追问问题,记录当前问题ID作为父问题ID
|
|
|
- if (!isFollowUpQuestionUpload) {
|
|
|
- this.currentParentQuestionId = questionId;
|
|
|
- }
|
|
|
+ // 如果不是追问问题,当前问题ID会在提交成功后成为父问题ID
|
|
|
|
|
|
// 添加到上传队列
|
|
|
this.uploadQueue.push(uploadTask);
|
|
@@ -2681,18 +2687,24 @@ export default {
|
|
|
// 若未达到上限则继续请求下一条追问,否则进入下一题
|
|
|
this.maybeRequestNextFollowUp(this.parentJobPositionQuestionId);
|
|
|
} else {
|
|
|
- // 如果是常规问题,记录父问题ID并检查追问问题
|
|
|
- this.currentParentQuestionId = task.questionId;
|
|
|
- console.log('检查常规问题的追问,父问题ID:', this.currentParentQuestionId);
|
|
|
- // 从题目读取追问上限(若后端提供),否则使用默认
|
|
|
- const currentQuestion = this.getCurrentQuestionByIndex(this.currentVideoIndex);
|
|
|
- if (currentQuestion && typeof currentQuestion.follow_up_limit !== 'undefined') {
|
|
|
- this.setFollowUpLimit(this.currentParentQuestionId, currentQuestion.follow_up_limit);
|
|
|
- } else if (typeof this.defaultFollowUpLimit !== 'undefined') {
|
|
|
- this.setFollowUpLimit(this.currentParentQuestionId, this.defaultFollowUpLimit);
|
|
|
+ // 如果是常规问题,检查追问问题
|
|
|
+ console.log('常规问题回答完成,准备检查追问,父问题ID:', this.parentJobPositionQuestionId);
|
|
|
+ // 注意:这里应该使用从后端返回的job_position_question_id,而不是前端的questionId
|
|
|
+ // parentJobPositionQuestionId应该在提交视频成功后就已经设置好了
|
|
|
+ if (this.parentJobPositionQuestionId) {
|
|
|
+ // 从题目读取追问上限(若后端提供),否则使用默认
|
|
|
+ const currentQuestion = this.getCurrentQuestionByIndex(this.currentVideoIndex);
|
|
|
+ if (currentQuestion && typeof currentQuestion.follow_up_limit !== 'undefined') {
|
|
|
+ this.setFollowUpLimit(this.parentJobPositionQuestionId, currentQuestion.follow_up_limit);
|
|
|
+ } else if (typeof this.defaultFollowUpLimit !== 'undefined') {
|
|
|
+ this.setFollowUpLimit(this.parentJobPositionQuestionId, this.defaultFollowUpLimit);
|
|
|
+ }
|
|
|
+ this.resetFollowUpAskedCount(this.parentJobPositionQuestionId);
|
|
|
+ this.checkAndPlayFollowUpQuestion(this.parentJobPositionQuestionId);
|
|
|
+ } else {
|
|
|
+ console.error('缺少parentJobPositionQuestionId,无法检查追问,直接进入下一题');
|
|
|
+ this.proceedToNextQuestion();
|
|
|
}
|
|
|
- this.resetFollowUpAskedCount(this.currentParentQuestionId);
|
|
|
- this.checkAndPlayFollowUpQuestion(this.currentParentQuestionId);
|
|
|
}
|
|
|
}
|
|
|
},
|
|
@@ -3275,8 +3287,8 @@ export default {
|
|
|
}
|
|
|
|
|
|
// 清理当前父题的追问中的并发锁
|
|
|
- if (this.currentParentQuestionId) {
|
|
|
- this.followUpRequestInFlight[this.currentParentQuestionId] = false;
|
|
|
+ if (this.parentJobPositionQuestionId) {
|
|
|
+ this.followUpRequestInFlight[this.parentJobPositionQuestionId] = false;
|
|
|
}
|
|
|
|
|
|
// 增加当前视频索引,切换到下一个视频
|
|
@@ -4549,9 +4561,9 @@ export default {
|
|
|
this.hasPlayedFollowUp = {};
|
|
|
},
|
|
|
|
|
|
- // 修改检查并播放追问问题的方法
|
|
|
- checkAndPlayFollowUpQuestion(parentQuestionId) {
|
|
|
- console.log('检查是否有追问问题,父问题ID:', parentQuestionId);
|
|
|
+ // 修改检查并播放追问问题的方法 - 使用动态追问API
|
|
|
+ async checkAndPlayFollowUpQuestion(jobPositionQuestionId) {
|
|
|
+ console.log('检查是否有追问问题,父问题ID:', jobPositionQuestionId);
|
|
|
|
|
|
// 如果正在等待用户回答,不进行任何操作
|
|
|
if (this.isWaitingForAnswer) {
|
|
@@ -4559,80 +4571,54 @@ export default {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // 超过追问上限则直接进入下一题
|
|
|
- if (!this.canAskMoreFollowUps(parentQuestionId)) {
|
|
|
- console.log('追问次数已达上限,进入下一题');
|
|
|
+ if (!jobPositionQuestionId) {
|
|
|
+ console.warn('没有父问题ID,无法检查追问问题');
|
|
|
this.proceedToNextQuestion();
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
- if (!parentQuestionId) {
|
|
|
- console.warn('没有父问题ID,无法检查追问问题');
|
|
|
- this.proceedToNextQuestion();
|
|
|
+
|
|
|
+ // 检查录制时长,如果时长太短则播放低分提示视频而非追问
|
|
|
+ const recordingDuration = this.getRecordingDuration();
|
|
|
+ const lowScoreDuration = 7; // 低分阈值时长(秒),少于7秒视为低分
|
|
|
+ const minDuration = 3; // 最小录制时长阈值(秒)
|
|
|
+
|
|
|
+ // 如果录制时间少于最小时长或者在最小时长和低分阈值之间,播放"未听清楚"提示视频
|
|
|
+ if (recordingDuration < lowScoreDuration) {
|
|
|
+ let message = recordingDuration < minDuration ?
|
|
|
+ `录制时间 ${recordingDuration} 秒,少于最小时长 ${minDuration} 秒` :
|
|
|
+ `录制时间 ${recordingDuration} 秒,少于标准时长 ${lowScoreDuration} 秒`;
|
|
|
+ console.log(message + ',将播放低分提示视频');
|
|
|
+
|
|
|
+ // 增加重试次数
|
|
|
+ this.retryCount++;
|
|
|
+
|
|
|
+ // 设置需要播放低分提示视频
|
|
|
+ this.needPlayLowScoreVideo = true;
|
|
|
+
|
|
|
+ // 播放低分提示视频
|
|
|
+ this.playLowScoreVideo();
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
- // 如果已经播放过这个问题的追问,则直接进入下一个问题
|
|
|
- if (this.hasPlayedFollowUp[parentQuestionId]) {
|
|
|
- console.log('已经播放过此问题的追问,直接进入下一个问题');
|
|
|
- this.retryCount = 0;
|
|
|
+
|
|
|
+ // 如果录制时长足够,重置重试次数
|
|
|
+ this.retryCount = 0;
|
|
|
+
|
|
|
+ // 检查是否可以继续追问
|
|
|
+ if (!this.canAskMoreFollowUps(jobPositionQuestionId)) {
|
|
|
+ console.log('追问次数已达上限,进入下一题');
|
|
|
this.proceedToNextQuestion();
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
- // 查找对应的追问问题
|
|
|
- const followUpQuestion = this.followUpQuestions.find(q =>
|
|
|
- q.parent_question_id === parentQuestionId &&
|
|
|
- q.digital_human_video_url &&
|
|
|
- q.question_form === 5
|
|
|
- );
|
|
|
-
|
|
|
- if (followUpQuestion) {
|
|
|
- console.log('找到追问问题:', followUpQuestion);
|
|
|
-
|
|
|
- // 检查录制时长
|
|
|
- const recordingDuration = this.getRecordingDuration();
|
|
|
- const lowScoreDuration = 7; // 低分阈值时长(秒),少于7秒视为低分
|
|
|
- const minDuration = 3; // 最小录制时长阈值(秒)
|
|
|
-
|
|
|
- // 如果录制时间少于最小时长或者在最小时长和低分阈值之间,播放"未听清楚"提示视频
|
|
|
- if (recordingDuration < lowScoreDuration) {
|
|
|
- let message = recordingDuration < minDuration ?
|
|
|
- `录制时间 ${recordingDuration} 秒,少于最小时长 ${minDuration} 秒` :
|
|
|
- `录制时间 ${recordingDuration} 秒,少于标准时长 ${lowScoreDuration} 秒`;
|
|
|
- console.log(message + ',将播放低分提示视频');
|
|
|
-
|
|
|
- // 增加重试次数
|
|
|
- this.retryCount++;
|
|
|
-
|
|
|
- // 设置需要播放低分提示视频
|
|
|
- this.needPlayLowScoreVideo = true;
|
|
|
-
|
|
|
- // 播放低分提示视频
|
|
|
- this.playLowScoreVideo();
|
|
|
- return;
|
|
|
+
|
|
|
+ // 调用追问API
|
|
|
+ try {
|
|
|
+ const success = await this.callInterviewInteraction(jobPositionQuestionId);
|
|
|
+ if (!success) {
|
|
|
+ console.log('获取追问失败,进入下一题');
|
|
|
+ this.proceedToNextQuestion();
|
|
|
}
|
|
|
-
|
|
|
- // 如果录制时长足够,重置重试次数
|
|
|
- this.retryCount = 0;
|
|
|
-
|
|
|
- // 标记此追问已播放
|
|
|
- this.hasPlayedFollowUp[parentQuestionId] = true;
|
|
|
-
|
|
|
- // 标记当前是追问问题
|
|
|
- this.isFollowUpQuestion = true;
|
|
|
-
|
|
|
- // 记录当前父问题ID
|
|
|
- this.currentParentQuestionId = parentQuestionId;
|
|
|
-
|
|
|
- // 保存当前追问问题的完整信息
|
|
|
- this.currentFollowUpQuestion = followUpQuestion;
|
|
|
-
|
|
|
- // 播放追问问题视频
|
|
|
- this.playFollowUpQuestionVideo(followUpQuestion);
|
|
|
- } else {
|
|
|
- console.log('没有找到对应的追问问题,继续下一个问题');
|
|
|
- this.retryCount = 0;
|
|
|
+ } catch (error) {
|
|
|
+ console.error('调用追问接口失败:', error);
|
|
|
this.proceedToNextQuestion();
|
|
|
}
|
|
|
},
|