From a656cfbcd0fea1048a633434f1e530fe40d4e3a0 Mon Sep 17 00:00:00 2001 From: wujingjing <gersonwu@qq.com> Date: 星期三, 25 九月 2024 11:07:10 +0800 Subject: [PATCH] Merge branch 'test' of http://47.103.154.90:83/r/WI/Web.V1.0 into test --- src/components/chat/components/playBar/PlayBar.vue | 152 +++++++++++++++++++++++++++++++++++++++++++++----- 1 files changed, 136 insertions(+), 16 deletions(-) diff --git a/src/components/chat/components/playBar/PlayBar.vue b/src/components/chat/components/playBar/PlayBar.vue index 8275d47..620da7d 100644 --- a/src/components/chat/components/playBar/PlayBar.vue +++ b/src/components/chat/components/playBar/PlayBar.vue @@ -6,26 +6,51 @@ </el-button> </div> <div class="set-input"> + <!-- @input="inputText" --> + <el-input + ref="inputRef" class="relative align-bottom set-inputAnswer" type="textarea" resize="none" :autosize="{ minRows: 1, maxRows: 8 }" v-elInputFocus - @keydown="enterInput" + @keydown="keydownInput" + @input="inputText" v-model="inputValue" placeholder="鍦ㄨ繖閲岃緭鍏ユ偍鐨勯棶棰樺紑濮嬪拰AI瀵硅瘽" - /> + > + </el-input> + <div + v-show="tipIsShow" + ref="tipEleRef" + class="absolute rounded-md bg-white border border-solid border-gray-400 py-2 z-10" + :style="{ left: popUpPosition.left + 'px', bottom: popUpPosition.bottom + 'px' }" + > + <div class="font-bold text-sm text-nowrap overflow-hidden text-ellipsis max-w-80 mb-1 px-2">Ctrl+鏁板瓧蹇嵎杈撳叆</div> + <div class="text-gray-400 text-sm text-nowrap overflow-hidden text-ellipsis max-w-80 mb-1 px-2">{{ inputValue }}</div> + <div class="max-w-96 flex flex-col"> + <div + class="hover:bg-gray-300 py-2 cursor-pointer px-5 text-nowrap overflow-hidden text-ellipsis" + v-for="(item, index) in similarList" + :key="index" + @click="similarClick(item)" + > + <span class="text-sm text-gray-500 pr-1.5">{{ index + 1 }}</span> + <span> {{ item?.question }} </span> + </div> + </div> + </div> </div> <div class="h100 flex items-center"> <div class="upload_img space-y"> <div class="imgbox cursor-pointer flex items-center"> - <el-button title="AI鐪嬪浘" class="cursor-pointer" link style="margin-left: unset"> + <!-- <el-button title="AI鐪嬪浘" class="cursor-pointer" link style="margin-left: unset"> <img src="/static/images/wave/LookImg.png" class="set-img-icon box-border" /> - </el-button> - <el-button title="AI璇煶瀵硅瘽" class="cursor-pointer" link style="margin-left: unset"> + </el-button> --> + <!-- <el-button title="AI璇煶瀵硅瘽" class="cursor-pointer" link style="margin-left: unset" @click="audioChangeWord"> <img src="/static/images/wave/HeadImg.png" class="set-img-icon box-border" /> - </el-button> + </el-button> --> <el-button title="鍙戦��" :disabled="isTalking" class="cursor-pointer" link @click="emits('sendClick')"> <div class="send"> @@ -35,29 +60,125 @@ </div> </div> </div> + <VoicePage + v-model:isShow="voicePageIsShow" + v-show="voicePageIsShow" + @submit="(cb) => emits('sendClick', cb)" + @updateInputValue="updateInputValue" + :isHome="isHome" + /> </div> </template> <script setup lang="ts"> -import { reactive } from 'vue'; +import type { InputInstance } from 'element-plus'; +import { ElMessage } from 'element-plus'; +import getCaretCoordinates from 'textarea-caret'; +import { computed, nextTick, ref } from 'vue'; +import VoicePage from './voicePage/VoicePage.vue'; +import { querySimilarityHistory } from '/@/api/ai/chat'; +import { useClickOther } from '/@/hooks/useClickOther'; +import { onClickOutside } from '@vueuse/core' const emits = defineEmits(['sendClick']); - -const props = defineProps(['isTalking']); - +const props = defineProps(['isTalking', 'isHome']); +const voicePageIsShow = defineModel('voicePageIsShow', { + type: Boolean, + default: false, +}); const inputValue = defineModel({ type: String, }); -const enterInput = (e) => { +const tipIsShow = computed(() => !!inputValue.value.trim() && similarList.value?.length > 0 && triggerShow.value); +const triggerShow = ref(false); +const inputRef = ref<InputInstance>(null); + +const updateInputValue = (val) => { + inputValue.value = val; +}; +const keydownInput = (e) => { if (props.isTalking) return; - if (!e.shiftKey && e.keyCode == 13) { + const isEnterInput = !e.shiftKey && e.key == 'Enter'; + const isDigitalInput = e.ctrlKey && e.code.startsWith('Digit') && tipIsShow.value; + if (isEnterInput || isDigitalInput) { e.cancelBubble = true; //ie闃绘鍐掓场琛屼负 e.stopPropagation(); //Firefox闃绘鍐掓场琛屼负 e.preventDefault(); //鍙栨秷浜嬩欢鐨勯粯璁ゅ姩浣�*鎹㈣ - //浠ヤ笅澶勭悊鍙戦�佹秷鎭唬鐮� - emits('sendClick'); + if (isEnterInput) { + //浠ヤ笅澶勭悊鍙戦�佹秷鎭唬鐮� + emits('sendClick'); + } else if (isDigitalInput) { + const num = Number(e.code.replace('Digit', '')); + const mapValue = similarList.value[num - 1]?.question; + if (mapValue) { + inputValue.value = mapValue; + triggerShow.value = false; + } + } } +}; + +const similarClick = (item) => { + if (item.question) { + inputValue.value = item.question; + triggerShow.value = false; + } +}; + +const tipEleRef = ref<HTMLDivElement>(null); + +const popUpPosition = ref({ + left: null, + bottom: null, +}); + +onClickOutside(tipEleRef,()=>{ + triggerShow.value = true +}) +const inputText = (text) => { + nextTick(() => { + setTimeout(() => { + const container = inputRef.value.$el; + + const textAreaEl = inputRef.value.$el.firstElementChild; + const caret = getCaretCoordinates(textAreaEl, textAreaEl.selectionEnd); + + const bottomOffset = 10; + const leftOffset = 9; + popUpPosition.value.left = caret.left + leftOffset; + popUpPosition.value.bottom = container.offsetHeight + bottomOffset; + triggerShow.value = true; + if (lastIsFinish) { + querySimilarityApi(text); + } + }, 0); + }); +}; + +const similarList = ref([]); +let lastIsFinish = true; +const querySimilarityApi = async (text: string) => { + if (!text) return; + lastIsFinish = false; + const res = await querySimilarityHistory({ + question: text, + }); + lastIsFinish = true; + const handleValues = res?.values ?? []; + + similarList.value = props.isHome ? handleValues.slice(0, 3) : handleValues; +}; +const audioChangeWord = () => { + navigator.getUserMedia( + { audio: true }, + function onSuccess(stream) { + voicePageIsShow.value = true; + }, + function onError(error) { + ElMessage.warning('璇锋墦寮�楹﹀厠椋庢潈闄�'); + } + ); }; </script> <style scoped lang="scss"> @@ -147,14 +268,13 @@ display: inline-block; width: 100%; .set-inputAnswer { - padding: 3px 0; line-height: 20px; border: none; background-color: transparent; color: #333; font-size: 15px; - :deep(.el-textarea__inner){ + :deep(.el-textarea__inner) { // 鍘婚櫎绾� box-shadow: none; } -- Gitblit v1.9.3