You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
virtual-patient-web/src/views/consultation/components/VoiceInspect/VoiceInquiry.vue

166 lines
4.2 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<script setup lang="ts">
import { ref, reactive, onBeforeUnmount } from "vue";
import AudioRecorder from "js-audio-recorder";
import { receiveVoiceFile } from "@/api/inquiry";
import tokeGifImg from "@/assets/inquiry/toke.gif";
import tokeImg from "@/assets/inquiry/toke.png";
import { onClickOutside } from "@vueuse/core";
import { onMounted } from "vue";
import { message } from "@/utils/message";
defineOptions({
name: "VoiceInquiry"
});
const defultText = "正在问诊......";
const text = ref(defultText);
const container = ref(null);
let audioRecorder: any = reactive({ undefined });
let intervalId: any = reactive({ undefined });
const recordType = ref("0"); // 0未开始 1 开始录制 2 暂停 3完成
onMounted(() => {
recordType.value = "0";
// 使用js-audio-recorder录制音频
audioRecorder = new AudioRecorder({
sampleBits: 16, // 采样位数,支持 8 或 16默认是16
sampleRate: 16000, // 采样率,支持 11025、16000、22050、24000、44100、48000根据浏览器默认值我的chrome是48000
numChannels: 1 // 声道,支持 1 或 2 默认是1
});
startRecording();
checkSpeaking();
});
function checkSpeaking() {
intervalId = setInterval(() => {
const dataArray = audioRecorder.getRecordAnalyseData();
const isSpeaking = Array.from(dataArray).some(value => value > 128);
if (isSpeaking) {
if (recordType.value === "0") {
recordType.value = "1";
// startRecording();
} else if (recordType.value === "2") {
audioRecorder.resume();
}
} else {
if (recordType.value === "1") {
audioRecorder.pause();
recordType.value = "2";
} else if (recordType.value === "2") {
stopRecording();
}
}
console.log("Is speaking:", isSpeaking);
}, 500); // 每 500 毫秒获取一次音量
}
const startRecording = () => {
audioRecorder.start();
};
async function stopRecording() {
recordType.value = "0";
clearInterval(intervalId);
audioRecorder.stop();
const blob = audioRecorder.getWAVBlob();
const params = new FormData();
params.append("file", blob);
const { data } = await receiveVoiceFile(params);
text.value = data;
recordType.value = "3";
sendVoiceOption();
}
const emit = defineEmits(["changeType", "save"]);
// const reset = () => {
// text.value = defultText;
// recordType.value = "0";
// startRecording();
// checkSpeaking();
// };
onClickOutside(container, () => emit("changeType", 0));
const sendVoiceOption = () => {
if (!text.value || text.value === defultText) {
message("问诊内容不能为空!", { type: "error" });
}
emit("changeType", 0);
emit("save", text.value);
};
onBeforeUnmount(() => {
audioRecorder.destroy();
});
</script>
<template>
<div ref="container" class="voiceInquiry">
<div class="voice_footer_cotent">
<img v-show="recordType === '3'" :src="tokeImg" alt="" />
<img v-show="recordType !== '3'" :src="tokeGifImg" alt="" />
<span>{{ text }}</span>
</div>
<!-- <div v-show="recordType === '3'" class="btn_list">
<span @click="reset"></span>
<el-button
class="btn"
size="large"
@click="sendVoiceOption"
type="primary"
>发送</el-button
>
</div> -->
</div>
</template>
<style lang="scss" scoped>
.voiceInquiry {
position: fixed;
bottom: 66px;
display: flex;
justify-content: center;
width: 500px;
height: 104px;
background-image: url("@/assets/inquiry/voice_bg.png");
background-size: 100% 100%;
box-shadow: 0 0 8px 0 rgb(0 0 0 / 15%);
.voice_footer_cotent {
display: flex;
flex-direction: column;
align-items: center;
img {
width: 300px;
height: 40px;
margin-top: 16px;
cursor: pointer;
}
span {
margin-top: 6px;
font-size: 14px;
font-weight: 400;
color: #364c63;
}
}
.btn_list {
position: absolute;
top: 15px;
right: 16px;
display: flex;
align-items: center;
height: 104px;
span {
margin-right: 16px;
font-size: 16px;
font-weight: 400;
color: #4287ff;
cursor: pointer;
}
img {
width: 24px;
height: 24px;
margin-right: 16px;
cursor: pointer;
}
}
}
</style>