|
@@ -1,7 +1,7 @@
|
|
<template>
|
|
<template>
|
|
<div
|
|
<div
|
|
tabindex="0"
|
|
tabindex="0"
|
|
- class="chat-online relative flex size-full flex-col items-center justify-center overflow-hidden rounded-lg bg-[url('@/assets/images/knowledge/knowledge-back-test.png')] bg-[length:100%_100%] bg-no-repeat"
|
|
|
|
|
|
+ class="chat-online relative flex size-full flex-col items-center justify-center overflow-hidden rounded-lg bg-[url('@/assets/images/chat/bg-2.png')] bg-[length:100%_100%] bg-no-repeat"
|
|
@focus="state.isFocus = true"
|
|
@focus="state.isFocus = true"
|
|
@blur="state.isFocus = false"
|
|
@blur="state.isFocus = false"
|
|
@mousedown.left="onSpeakStart"
|
|
@mousedown.left="onSpeakStart"
|
|
@@ -18,10 +18,11 @@
|
|
<template v-if="!state.isWaiting">
|
|
<template v-if="!state.isWaiting">
|
|
<div class="flex flex-col items-center">
|
|
<div class="flex flex-col items-center">
|
|
<div>
|
|
<div>
|
|
- <soundWave :volume="state.isAsk ? volume : 0" :num="30" />
|
|
|
|
|
|
+ <soundWave :volume="volumeCpt" :num="30" />
|
|
</div>
|
|
</div>
|
|
<div class="mt-4 h-7 text-lg font-bold text-[var(--czr-main-color)]">
|
|
<div class="mt-4 h-7 text-lg font-bold text-[var(--czr-main-color)]">
|
|
<template v-if="state.isAsk">正在聆听 {{ durationCpt }}</template>
|
|
<template v-if="state.isAsk">正在聆听 {{ durationCpt }}</template>
|
|
|
|
+ <template v-else-if="state.isThink">正在思考……</template>
|
|
<template v-else-if="state.isAnswer">正在回答</template>
|
|
<template v-else-if="state.isAnswer">正在回答</template>
|
|
</div>
|
|
</div>
|
|
<div class="mt-3 flex items-center text-sm text-[#909399]">
|
|
<div class="mt-3 flex items-center text-sm text-[#909399]">
|
|
@@ -32,6 +33,7 @@
|
|
class="mr-1"
|
|
class="mr-1"
|
|
/>
|
|
/>
|
|
<template v-if="state.isAsk"> 松开鼠标左键/Space以提问 </template>
|
|
<template v-if="state.isAsk"> 松开鼠标左键/Space以提问 </template>
|
|
|
|
+ <template v-else-if="state.isThink"> 正在思考中,请稍后…… </template>
|
|
<template v-else-if="state.isAnswer"> 鼠标左键/Space以打断 </template>
|
|
<template v-else-if="state.isAnswer"> 鼠标左键/Space以打断 </template>
|
|
<template v-else> 按住鼠标左键/Space开始提问 </template>
|
|
<template v-else> 按住鼠标左键/Space开始提问 </template>
|
|
</div>
|
|
</div>
|
|
@@ -71,18 +73,22 @@
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
import { computed, reactive } from 'vue'
|
|
import { computed, reactive } from 'vue'
|
|
import soundWave from './audio/sound-wave.vue'
|
|
import soundWave from './audio/sound-wave.vue'
|
|
-import useSpeechToAudio from '@/utils/useSpeechToAudio'
|
|
|
|
|
|
+import useSpeechToAudio from '@/views/chat/audio/useSpeechToAudio'
|
|
import { ElMessage } from 'element-plus'
|
|
import { ElMessage } from 'element-plus'
|
|
|
|
+import useAudio from '@/views/chat/audio/useAudio'
|
|
|
|
|
|
const emit = defineEmits(['hangUp'])
|
|
const emit = defineEmits(['hangUp'])
|
|
const state: any = reactive({
|
|
const state: any = reactive({
|
|
isWaiting: true, // 等待接听
|
|
isWaiting: true, // 等待接听
|
|
isAsk: false, // 提问录音中
|
|
isAsk: false, // 提问录音中
|
|
isAnswer: false, // 聆听回答中
|
|
isAnswer: false, // 聆听回答中
|
|
|
|
+ isThink: false, // 思考回答中
|
|
isFocus: false, // 语音聊天是否聚焦
|
|
isFocus: false, // 语音聊天是否聚焦
|
|
duration: 0, // 提问录音时长
|
|
duration: 0, // 提问录音时长
|
|
timer: null, // 开始提问防抖
|
|
timer: null, // 开始提问防抖
|
|
clickSpace: false, // 按下空格会一直触发,添加个判断
|
|
clickSpace: false, // 按下空格会一直触发,添加个判断
|
|
|
|
+ answerVolume: 0, //回答音频的音量
|
|
|
|
+ answerAudioControl: null,
|
|
})
|
|
})
|
|
const durationCpt = computed(() => {
|
|
const durationCpt = computed(() => {
|
|
const minutes = Math.floor(state.duration / 60)
|
|
const minutes = Math.floor(state.duration / 60)
|
|
@@ -95,29 +101,58 @@ const onSpeak = ({ duration }) => {
|
|
}
|
|
}
|
|
const onEnd = (audio) => {
|
|
const onEnd = (audio) => {
|
|
state.isAsk = false
|
|
state.isAsk = false
|
|
- state.isAnswer = true
|
|
|
|
if (state.duration < 2) {
|
|
if (state.duration < 2) {
|
|
ElMessage.warning('提问时长过短,请持续提问!')
|
|
ElMessage.warning('提问时长过短,请持续提问!')
|
|
- return
|
|
|
|
|
|
+ state.return
|
|
}
|
|
}
|
|
console.log(audio)
|
|
console.log(audio)
|
|
|
|
+ state.isThink = true
|
|
|
|
+ setTimeout(() => {
|
|
|
|
+ state.isThink = false
|
|
|
|
+ useAudio(
|
|
|
|
+ 'https://lf-bot-studio-plugin-resource.coze.cn/obj/bot-studio-platform-plugin-tos/sami_podcast/tts/134d9d71475043199ef7372567fa9689.mp3',
|
|
|
|
+ // 'https://lf-bot-studio-plugin-resource.coze.cn/obj/bot-studio-platform-plugin-tos/artist/image/32afe00820aa466192ce0f7b6495e946.mp3',
|
|
|
|
+ () => {
|
|
|
|
+ state.isAnswer = false
|
|
|
|
+ },
|
|
|
|
+ ).then(({ volume, play, stop, pause }: any) => {
|
|
|
|
+ state.isAnswer = true
|
|
|
|
+ state.answerAudioControl = {
|
|
|
|
+ play,
|
|
|
|
+ stop,
|
|
|
|
+ pause,
|
|
|
|
+ }
|
|
|
|
+ state.answerVolume = volume
|
|
|
|
+ play()
|
|
|
|
+ })
|
|
|
|
+ }, 1000)
|
|
}
|
|
}
|
|
const { speak, stop, volume } = useSpeechToAudio({
|
|
const { speak, stop, volume } = useSpeechToAudio({
|
|
onEnd,
|
|
onEnd,
|
|
onSpeak,
|
|
onSpeak,
|
|
timeout: 0,
|
|
timeout: 0,
|
|
})
|
|
})
|
|
|
|
+const volumeCpt = computed(() => {
|
|
|
|
+ if (state.isAsk) {
|
|
|
|
+ return volume.value
|
|
|
|
+ }
|
|
|
|
+ if (state.isAnswer) {
|
|
|
|
+ return state.answerVolume
|
|
|
|
+ }
|
|
|
|
+ return 0
|
|
|
|
+})
|
|
const onCall = () => {
|
|
const onCall = () => {
|
|
state.isWaiting = false
|
|
state.isWaiting = false
|
|
state.isAsk = false
|
|
state.isAsk = false
|
|
|
|
+ state.isThink = false
|
|
state.isAnswer = false
|
|
state.isAnswer = false
|
|
}
|
|
}
|
|
const onSpeakStart = () => {
|
|
const onSpeakStart = () => {
|
|
- if (state.isAnswer) {
|
|
|
|
- onStopAnswer()
|
|
|
|
- }
|
|
|
|
if (!state.isWaiting && !state.isAsk && !state.clickSpace) {
|
|
if (!state.isWaiting && !state.isAsk && !state.clickSpace) {
|
|
state.timer = setTimeout(() => {
|
|
state.timer = setTimeout(() => {
|
|
|
|
+ if (state.isAnswer) {
|
|
|
|
+ onStopAnswer()
|
|
|
|
+ }
|
|
speak()
|
|
speak()
|
|
}, 300)
|
|
}, 300)
|
|
}
|
|
}
|
|
@@ -129,8 +164,10 @@ const onSpeakStop = () => {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
const onSpaceSpeakStart = () => {
|
|
const onSpaceSpeakStart = () => {
|
|
- onSpeakStart()
|
|
|
|
- state.clickSpace = true
|
|
|
|
|
|
+ if (!state.isThink) {
|
|
|
|
+ onSpeakStart()
|
|
|
|
+ state.clickSpace = true
|
|
|
|
+ }
|
|
}
|
|
}
|
|
const onSpaceSpeakStop = () => {
|
|
const onSpaceSpeakStop = () => {
|
|
onSpeakStop()
|
|
onSpeakStop()
|