CzRger 2 hónapja%!(EXTRA string=óta)
szülő
commit
aa55108b3c
1 módosított fájl, 73 hozzáadás és 53 törlés
  1. 73 53
      src/views/chat/online.vue

+ 73 - 53
src/views/chat/online.vue

@@ -2,14 +2,13 @@
   <div
     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"
-    @focus="onFocus"
-    @blur="onBlur"
-    @mousedown.left="onMousedown"
-    @mouseup.left="onMouseup"
-    @keydown.space="onKeydown"
-    @keyup.space="onKeyup"
+    @focus="state.isFocus = true"
+    @blur="state.isFocus = false"
+    @mousedown.left="onSpeakStart"
+    @mouseup.left="onSpeakStop"
+    @keydown.space="onSpaceSpeakStart"
+    @keyup.space="onSpaceSpeakStop"
   >
-    <div class="absolute top-0 left-0">焦点:{{ state.isFocus }}</div>
     <div
       class="absolute top-1/10 flex flex-col items-center gap-3 text-2xl font-bold text-[#303133]"
     >
@@ -19,11 +18,11 @@
     <template v-if="!state.isWaiting">
       <div class="flex flex-col items-center">
         <div>
-          <soundWave :volume="volume" :num="30" />
+          <soundWave :volume="state.isAsk ? volume : 0" :num="30" />
         </div>
-        <div class="mt-4 text-lg font-bold text-[var(--czr-main-color)]">
-          <template v-if="state.isAsk">正在聆听</template>
-          <template v-else>正在回答</template>
+        <div class="mt-4 h-7 text-lg font-bold text-[var(--czr-main-color)]">
+          <template v-if="state.isAsk">正在聆听 {{ durationCpt }}</template>
+          <template v-else-if="state.isAnswer">正在回答</template>
         </div>
         <div class="mt-3 flex items-center text-sm text-[#909399]">
           <SvgIcon
@@ -32,30 +31,23 @@
             size="20"
             class="mr-1"
           />
-          <template v-if="state.isAsk">松开鼠标左键/Space以提问</template>
-          <template v-else>按住鼠标左键/Space以打断</template>
+          <template v-if="state.isAsk"> 松开鼠标左键/Space以提问 </template>
+          <template v-else-if="state.isAnswer"> 鼠标左键/Space以打断 </template>
+          <template v-else> 按住鼠标左键/Space开始提问 </template>
         </div>
-        <!--        <div>-->
-        <!--          <template v-if="state.isSpeak">-->
-        <!--            <el-button @click="stop">停止录音</el-button>-->
-        <!--          </template>-->
-        <!--          <template v-else>-->
-        <!--            <el-button @click="speak">开始录音</el-button>-->
-        <!--          </template>-->
-        <!--        </div>-->
       </div>
     </template>
     <div class="absolute bottom-1/15 flex w-full justify-center gap-[20%]">
       <template v-if="state.isWaiting">
         <div
           class="__hover flex flex-col items-center gap-2 text-[#0064F9]"
-          @click="onListen"
+          @click.stop="onCall"
         >
           <div class="relative flex size-38 items-center justify-center">
             <img src="@/assets/images/chat/chat-call.png" class="size-full" />
             <div
-              class="absolute z-0 size-full scale-70 animate-ping rounded-full bg-[#0064F9]/10"
-              style="animation-duration: 3s"
+              class="absolute z-0 size-full scale-70 animate-ping rounded-full bg-[#0064F9]/20"
+              style="animation-duration: 1.5s"
             ></div>
           </div>
           <div class="text-sm font-bold">接听</div>
@@ -64,7 +56,7 @@
       </template>
       <div
         class="__hover flex flex-col items-center gap-2 text-[#FF5454]"
-        @click="$emit('hangUp')"
+        @click.stop="$emit('hangUp')"
       >
         <div class="relative flex size-38 items-center justify-center">
           <img src="@/assets/images/chat/chat-hang.png" class="size-full" />
@@ -77,54 +69,82 @@
 </template>
 
 <script setup lang="ts">
-import { reactive } from 'vue'
+import { computed, reactive } from 'vue'
 import soundWave from './audio/sound-wave.vue'
 import useSpeechToAudio from '@/utils/useSpeechToAudio'
+import { ElMessage } from 'element-plus'
 
 const emit = defineEmits(['hangUp'])
 const state: any = reactive({
-  isWaiting: true,
-  isAsk: false,
-  isSpeak: false,
-  isFocus: false,
+  isWaiting: true, // 等待接听
+  isAsk: false, // 提问录音中
+  isAnswer: false, // 聆听回答中
+  isFocus: false, // 语音聊天是否聚焦
+  duration: 0, // 提问录音时长
+  timer: null, // 开始提问防抖
+  clickSpace: false, // 按下空格会一直触发,添加个判断
 })
-const onListen = () => {
-  state.isWaiting = false
-  state.isAsk = false
+const durationCpt = computed(() => {
+  const minutes = Math.floor(state.duration / 60)
+  const seconds = Math.floor(state.duration % 60)
+  return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`
+})
+const onSpeak = ({ duration }) => {
+  state.isAsk = true
+  state.duration = duration
 }
 const onEnd = (audio) => {
-  state.isSpeak = false
+  state.isAsk = false
+  state.isAnswer = true
+  if (state.duration < 2) {
+    ElMessage.warning('提问时长过短,请持续提问!')
+    return
+  }
   console.log(audio)
 }
-const onSpeak = ({ duration }) => {
-  state.isSpeak = true
-  // console.log('duration', duration)
-}
 const { speak, stop, volume } = useSpeechToAudio({
   onEnd,
   onSpeak,
   timeout: 0,
 })
-const onFocus = () => {
-  console.log('focus')
-  state.isFocus = true
+const onCall = () => {
+  state.isWaiting = false
+  state.isAsk = false
+  state.isAnswer = false
 }
-const onBlur = () => {
-  console.log('blur')
-  state.isFocus = false
+const onSpeakStart = () => {
+  if (state.isAnswer) {
+    onStopAnswer()
+  }
+  if (!state.isWaiting && !state.isAsk && !state.clickSpace) {
+    state.timer = setTimeout(() => {
+      speak()
+    }, 300)
+  }
 }
-const onMousedown = () => {
-  console.log('mousedown')
+const onSpeakStop = () => {
+  clearTimeout(state.timer)
+  if (!state.isWaiting && state.isAsk) {
+    stop()
+  }
 }
-const onMouseup = () => {
-  console.log('mouseup')
+const onSpaceSpeakStart = () => {
+  onSpeakStart()
+  state.clickSpace = true
 }
-const onKeydown = () => {
-  console.log('keydown')
+const onSpaceSpeakStop = () => {
+  onSpeakStop()
+  state.clickSpace = false
 }
-const onKeyup = () => {
-  console.log('keyup')
+const onStopAnswer = () => {
+  state.isAnswer = false
 }
 </script>
 
-<style lang="scss" scoped></style>
+<style lang="scss" scoped>
+.chat-online {
+  * {
+    outline: none;
+  }
+}
+</style>