JLBA202505130001_关于吉林银行新建AI智能培训系统的需求_替换新录音组件,练习考试错题本,Pk

This commit is contained in:
田岩
2026-03-05 19:52:34 +08:00
parent 344b07bbf5
commit 6b6bd90642
5 changed files with 231 additions and 36 deletions
-1
View File
@@ -98,7 +98,6 @@ export const vibrateLight = () : void => {
if (IsAndEnv) {
uni.vibrateShort({
success: function () {
console.log('success');
}
});
} else {
+78 -24
View File
@@ -159,6 +159,16 @@
type: Number,
default: 500
},
// 最小录音时长
minRecordDuration: {
type: Number,
default: 1000
},
// 最大录音时长
maxRecordDuration: {
type: Number,
default: 60000
},
adjustPosition: {
default: false,
type: Boolean
@@ -213,6 +223,8 @@
const isInputVisible = ref(true); // true=显示录音按钮,false=显示输入框
const recordStartTime = ref(0); // 录音开始时间戳
let pressTimer = null;
// 时长自动关闭定时器
let durationTimer = null;
// 计算属性:判断是否仅语音/仅文字模式(简化模板逻辑)
const isVoiceOnlyMode = computed(() => workMode.value === 'voice-only');
const isTextOnlyMode = computed(() => workMode.value === 'text-only');
@@ -241,6 +253,7 @@
// 开启语音
const startRecord = async (obj: { touches: any[] }) => {
if (props.isDisabled) return;
if (props.isLoading) return common.msg(props.loadingText);
if (pressTimer || isRecording.value) return;
if (props.canAnswer) return common.msg(props.canAnswerText);
try {
@@ -271,7 +284,7 @@
}
ws.value = socketTask;
wsStatus.value = true;
console.log('WS连接成功');
console.log('WS连接成功', isRecording.value, );
ws.value.onMessage((res: { data: Uint8Array | ArrayBuffer }) => {
try {
const { msgType, body } = ProtocolCodec.unpack(res.data);
@@ -289,6 +302,10 @@
// 如果不等于init说明已经超时,被超时函数处理完了,这里即使返回也不做处理
if (status.value === 'voice_to_text' && voice_to_text_status.value !== 'init') return;
if (status.value === 'send_over') return;
// 时间太短,关掉的时候就处理了,这里不处理
const recordDurationMs = Date.now() - recordStartTime.value;
if (recordDurationMs <= props.minRecordDuration) return;
status.value = 'send_over'; // 设置成发送完成
if (voiceTimer) clearTimeout(voiceTimer);
// 设置识别结果
@@ -320,11 +337,13 @@
console.log('网络出现问题');
});
pressTimer = setTimeout(() => {
if(!isRecording.value) {
if (!isRecording.value) {
console.log('定时器被取消还是进入了');
return
return;
}
pressTimer = null;
status.value = 'voice_recording';
console.log('触感震动');
vibrateLight(); // 触感震动
// 重设按下位置
const changedTouche = obj.touches[0];
@@ -333,7 +352,7 @@
// 记录开始时间戳(毫秒)
recordStartTime.value = Date.now();
// 弹出录音界面
popupRef.value.open();
startRecordingTimer(true) // 启动超长定时器
startAudioRecord({
onFrame: (pcmData: any) => {
if (wsStatus.value && ws.value) {
@@ -343,6 +362,7 @@
onStart: (res: any) => {
console.log('启动', res);
recordId.value = res.recordId ?? '';
popupRef.value.open();
},
onStop: () => {
console.log('关闭');
@@ -354,11 +374,12 @@
}
}
});
}, 100);
}, 140);
};
// 结束录音
const closePopup = () => {
startRecordingTimer(false)
isRecording.value = false;
popupRef.value.close();
};
@@ -382,6 +403,11 @@
clearTimeout(pressTimer);
console.log('取消一个存在的定时器');
pressTimer = null;
isRecording.value = false;
setTimeout(() => {
status.value = 'default'
}, 50);
return;
}
if (!isRecording.value) return; // 未处于录音状态
if (status.value !== 'voice_recording') {
@@ -389,35 +415,38 @@
closePopup();
return;
}
// 核心:计算录音总时长(毫秒转秒,保留1位小数)
const recordDurationMs = Date.now() - recordStartTime.value;
console.log('recordDurationMs', recordDurationMs);
// 拖动到转文字按钮上抬手或者仅文字模式的发送也强行算他转文字
const _isOutStatus = workMode.value === 'text-only' && isOutStatus.value === '01' ? '03' : isOutStatus.value;
if (_isOutStatus === '03') {
// 时间太短03也直接关了
if (_isOutStatus === '03' && !(recordDurationMs <= props.minRecordDuration)) {
console.log('时间不短进来了');
status.value = 'voice_to_text'; //主状态设置为转文字
voice_to_text_status.value = 'init';
if (voiceTimer) clearTimeout(voiceTimer);
voiceTimer = setTimeout(() => {
voiceTimer = null;
console.log('3号定时器', voice_to_text_status.value, status.value);
if (voice_to_text_status.value !== 'init') return;
if (status.value === 'send_over') return;
voice_to_text_status.value = 'networkError';
status.value = 'send_over'; // 设置成发送完成
emit('submitVoice', { ossKey: '', text: '', recordId: recordId.value });
}, 5000);
}, 4000);
} else if (_isOutStatus === '01') {
status.value = 'voice_send_ing'; //主状态设置为语音发送中
}
const recordDurationMs = Date.now() - recordStartTime.value;
// 核心:计算录音总时长(毫秒转秒,保留1位小数)
if (recordDurationMs < 540) {
if ((_isOutStatus !== '03' || recordDurationMs <= props.minRecordDuration) && recordDurationMs < 640) {
await new Promise<void>((resolve) => {
setTimeout(() => {
resolve();
}, 540 - recordDurationMs);
}, 640 - recordDurationMs);
});
}
// 取消的时候自己主动关闭websocket,其他的时候需要等待后端的消息关闭
if (_isOutStatus === '02' || errrStatus === 'networkError') {
closeWS();
@@ -431,19 +460,26 @@
}
stopAudioRecord(); // 关掉录音
isRecording.value = false;
if (_isOutStatus !== '03' || errrStatus === 'networkError') {
console.log('_isOutStatus', _isOutStatus);
if (_isOutStatus !== '03' || errrStatus === 'networkError' || recordDurationMs <= props.minRecordDuration) {
// 转文字时候不关遮罩层,网络错误必须关遮罩层
console.log('转文字时候不关遮罩层,网络错误必须关遮罩层');
closePopup();
// 关掉弹窗后的提示
if (errrStatus === 'networkError') {
if (errrStatus === 'networkError' && _isOutStatus === '01') {
status.value = 'send_over'; // 设置成发送完成
if (_isOutStatus !== '03') {
emit('submitVoice', { ossKey: '', text: '', recordId: recordId.value });
emit('submitVoice', { ossKey: '', text: '', recordId: recordId.value });
return;
} else if (recordDurationMs <= props.minRecordDuration) {
console.log('进入这里了', status.value);
if (_isOutStatus !== '02') {
showErrorTip(ErrorCode.ShortRecord);
}
// return showErrorTip(ErrorCode.NetworkError);
} else if (_isOutStatus === '01' && recordDurationMs <= 1000) {
status.value = 'send_over'; // 设置成发送完成
return showErrorTip(ErrorCode.ShortRecord);
setTimeout(() => {
status.value = 'send_over'; // 设置成发送完成
}, 200);
return;
}
}
if (_isOutStatus === '01' && status.value == 'voice_send_ing') {
@@ -451,13 +487,14 @@
// 如果socket长时间没有返回,这里兜底一下
if (voiceTimer) clearTimeout(voiceTimer);
voiceTimer = setTimeout(() => {
console.log('1号定时器', voice_to_text_status.value, status.value);
voiceTimer = null;
if (workMode.value === 'voice-only') {
if (status.value === 'send_over') return;
status.value = 'send_over'; // 恢复成默认状态
emit('submitVoice', { ossKey: '', text: '', recordId: recordId.value });
}
}, 5000);
}, 4000);
}
};
@@ -523,7 +560,24 @@
const _height = Math.max(height - 100, 0);
pageBoxMarginBottom.value = `${_height}px`;
});
const startRecordingTimer = (status: boolean) => {
const clearRecordingTimer = () => {
if (durationTimer) {
clearTimeout(durationTimer);
durationTimer = null; // 重置定时器变量,避免内存泄漏
console.log('录音时长定时器已清除');
}
};
clearRecordingTimer();
if (!status) return;
const maxDuration = props.maxRecordDuration;
durationTimer = setTimeout(() => {
console.log(`录音达到最大时长 ${maxDuration} 秒,自动关闭`);
// 执行关闭录音的逻辑
stopRecord();
clearRecordingTimer();
}, maxDuration);
};
// 外面调用放弃这次
const give_up = () => {
console.log('调用结束语音回答');