From 5809dbeb20d83b30a9d4e5354016e5d56d9a7e6e Mon Sep 17 00:00:00 2001 From: wujingjing <gersonwu@qq.com> Date: 星期二, 31 十二月 2024 13:48:25 +0800 Subject: [PATCH] 整理 常用语组件 --- src/components/chat/Chat.vue | 13 src/components/chat/components/playBar/PlayBar.vue | 241 +-------------------- src/components/chat/components/playBar/SceneSwitch.vue | 33 +++ src/components/chat/components/playBar/index.scss | 143 +++++++++++++ src/components/chat/components/playBar/phrase/index.scss | 92 ++++++++ src/components/chat/components/playBar/phrase/CommonPhrases.vue | 133 +++--------- 6 files changed, 327 insertions(+), 328 deletions(-) diff --git a/src/components/chat/Chat.vue b/src/components/chat/Chat.vue index 737079c..2b10d65 100644 --- a/src/components/chat/Chat.vue +++ b/src/components/chat/Chat.vue @@ -13,7 +13,7 @@ :msgList="computedMessageList" :isTalking="isTalking" @shareClick="shareClick" - @setCommonQuestionClick="setCommonQuestionClick" + @setCommonQuestionClick="setCommonPhraseClick" @sendChatMessage="sendChatMessage" @askMoreClick="askMoreClick" /> @@ -27,6 +27,7 @@ <!-- 杈撳叆鍖哄煙 --> <template #input-area> <PlayBar + ref="playBarRef" v-model:voicePageIsShow="voicePageIsShow" :isTalking="isTalking" :isHome="false" @@ -36,7 +37,6 @@ @stopGenClick="stopGenClick" @showDownChatClick="showDownChatClick" :style="{ width: chatWidth }" - :setCommonQuestionInfo="setCommonQuestionInfo" /> </template> @@ -660,14 +660,11 @@ messageContent.value.values = content; }; //#endregion -//#region ====================== 鐢ㄦ埛璇㈤棶鐨勯棶棰樿缃负甯哥敤璇� ====================== -const setCommonQuestionInfo = ref({}); - +const playBarRef = useCompRef(PlayBar); //鐢ㄦ埛闂璁剧疆涓哄父鐢ㄨ -const setCommonQuestionClick = (item) => { - setCommonQuestionInfo.value = item; +const setCommonPhraseClick = (item) => { + playBarRef.value.addPhrase(item); }; -//#endregion //#region ====================== 鍒嗕韩 ====================== diff --git a/src/components/chat/components/playBar/PlayBar.vue b/src/components/chat/components/playBar/PlayBar.vue index 673813b..3464b73 100644 --- a/src/components/chat/components/playBar/PlayBar.vue +++ b/src/components/chat/components/playBar/PlayBar.vue @@ -1,35 +1,8 @@ <template> <div class="playInput hl_input rounded-[22px] input-border input-shadow"> - <!-- 搴旂敤鍦烘櫙 --> - <div class="application-scenarios absolute bottom-[114%] left-4"> - <div class="flex-items-center space-x-2" :class="isHome ? 'set-next-group-type' : ''"> - <div - class="border border-gray-400 border-solid h-8 flex-items-center px-3 py-2 rounded-2xl cursor-pointer space-x-1 hover:bg-[#cae3ff]" - :class="{ 'bg-[#c5e0ff]': activeGroupType === item, '!text-[#1c86ff]': activeGroupType === item }" - v-for="item in groupTypeList" - @click="groupTypeClick(item)" - > - <span :class="['ywifont', groupTypeMapIcon[item]]"></span> - <div class="">{{ item }}</div> - </div> - </div> - </div> - <!-- 褰撳墠搴旂敤鍦烘櫙 --> - <!-- <div - class="bg-[#f9fafb] rounded-t-[22px] absolute bottom-[100%] left-0 w-full input-border h-11 flex-items-center justify-between text-[14px]" - style="padding: 4px 4px 4px 18px; border-bottom: none" - > - <div class="flex-items-center"> - <span :class="[groupTypeMapIcon[activeGroupType]]" class="ywifont mr-2 !text-[14px]"></span> - <div>{{ activeGroupType }}</div> - </div> - <el-tooltip content="閫�鍑哄簲鐢ㄥ満鏅�" placement="top"> - <span - @click="closeCurrentGroupType" - class="ywifont ywicon-guanbi mr-3 rounded-sm p-1 hover:bg-[#eaebec] cursor-pointer" - ></span> - </el-tooltip> - </div> --> + <!-- 涓诲満鏅� --> + <SceneSwitch :isHome="isHome" @change="groupTypeChange" /> + <div class="assembly flex"> <el-button title="杈撳叆甯哥敤璇爣棰橈紝鍙揩鎹疯皟鐢ㄥ父鐢ㄨ" @@ -88,12 +61,6 @@ <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"> - <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" @click="audioChangeWord"> - <img src="/static/images/wave/HeadImg.png" class="set-img-icon box-border" /> - </el-button> --> <el-button title="娓呴櫎" class="cursor-pointer" @@ -134,8 +101,8 @@ v-model:isShow="isShowPhrase" v-show="isShowPhrase" :isHome="isHome" - ref="commonPhrasesRef" - @updateCommonChatInput="updateCommonChatInput" + ref="commonPhraseRef" + @updateInput="updateInput" /> </div> </template> @@ -150,8 +117,10 @@ import InfoDetail from './InfoDetail.vue'; import CommonPhrases from './phrase/CommonPhrases.vue'; import VoicePage from './voicePage/VoicePage.vue'; +import SceneSwitch from './SceneSwitch.vue'; import { getMetricsNames, querySimilarityHistory } from '/@/api/ai/chat'; import { activeGroupType, groupTypeList, groupTypeMapIcon } from '/@/stores/chatRoom'; +import { useCompRef } from '/@/utils/types'; const emits = defineEmits(['sendClick', 'showUpChatClick', 'showDownChatClick', 'stopGenClick']); const props = defineProps({ isTalking: Boolean, @@ -162,15 +131,13 @@ }, }); -const { setCommonQuestionInfo } = toRefs(props); const voicePageIsShow = defineModel('voicePageIsShow', { type: Boolean, default: false, }); -const isShowPhrase = defineModel('isShowPhrase', { - type: Boolean, - default: false, -}); + + +const isShowPhrase = ref(false); const inputValue = defineModel({ type: String, }); @@ -459,195 +426,27 @@ }; //#endregion -//#region ====================== 褰撳墠搴旂敤鍦烘櫙 ====================== -const currentGroupTypeIsShow = computed(() => !!activeGroupType.value); -const groupTypeClick = (item) => { - activeGroupType.value = item; +const groupTypeChange = () => { inputRef.value.focus(); - commonPhrasesRef.value.getCommonPhrases(); + commonPhraseRef.value.updatePhrase(); }; - -// 鍏抽棴褰撳墠 groupType 闈㈡澘 -const closeCurrentGroupType = () => { - activeGroupType.value = null; +const updateInput = (val) => { + inputValue.value = val; }; -//#endregion - //#region ====================== 甯哥敤璇姛鑳� ====================== -const commonPhrasesRef = ref(null); +const commonPhraseRef = useCompRef(CommonPhrases); // 甯哥敤璇姛鑳界偣鍑� const commonPhrasesClick = () => { isShowPhrase.value = true; }; -// 鍖哄煙鍏抽棴甯哥敤璇姛鑳介潰鏉� -onClickOutside( - commonPhrasesRef, - () => { - isShowPhrase.value = false; - }, - { - ignore: ['.el-message-box'], - } -); -// 甯哥敤璇姛鑳借緭鍏ユ鏇存柊 -const updateCommonChatInput = (val) => { - inputValue.value = val; - isShowPhrase.value = false; + +const addPhrase = (val) => { + commonPhraseRef.value.addPhrase(val); }; -watch(setCommonQuestionInfo, (val) => { - if (!props.isHome) { - let obj = { - id: val?.historyId, - question: val?.content.values, - }; - commonPhrasesRef.value.commonChatByUser(obj); - isShowPhrase.value = true; - } -}); +defineExpose({ addPhrase }); //#endregion </script> <style scoped lang="scss"> -.set-waterTitle { - line-height: 24px; - font-weight: 500; - font-size: 18px; - color: #3b4066; - vertical-align: middle; -} -strong { - font-size: 26px; - font-weight: 700; - margin-right: 12px; -} -.layout-logo-medium-img { - width: 28px; - margin-right: 7px; -} -.pc-roleList { - margin: 40px 0 26px; - position: relative; -} -.modelItem { - height: 34px; - padding: 0 16px; - border-radius: 17px; - border: 1px solid #00000020; - background-color: #f2f4f8; - transition: background-color 0.1s, border-color 0.1s, color 0.1s; - color: #333; - .set-icon { - width: 20px; - height: 20px; - position: relative; - } - .set-icon-more { - width: 16px; - height: 16px; - position: relative; - } - span { - margin-left: 8px; - font-weight: 500; - font-size: 15px; - } -} -.modelItemActive { - background-color: #1c86ff; - border-color: #1c86ff; - color: #fff; -} - -.input-shadow { - -webkit-box-shadow: 0 0 0 1px transparent, 0 3px 16px 0 #dee0f3; - box-shadow: 0 0 0 1px transparent, 0 3px 16px 0 #dee0f3; -} - -.input-border { - border: 1px solid #00000030; - - -webkit-transition: border-color 0.1s ease-in-out, -webkit-box-shadow 0.1s ease-in-out; - transition: border-color 0.1s ease-in-out, -webkit-box-shadow 0.1s ease-in-out; - -o-transition: border-color 0.1s ease-in-out, box-shadow 0.1s ease-in-out; - transition: border-color 0.1s ease-in-out, box-shadow 0.1s ease-in-out; - transition: border-color 0.1s ease-in-out, box-shadow 0.1s ease-in-out, -webkit-box-shadow 0.1s ease-in-out; -} -.playInput { - align-items: flex-start; - width: 760px; - position: relative; - padding: 4px 4px 4px 12px; - - display: flex; - -webkit-box-align: end; - -ms-flex-align: end; - align-items: flex-end; - -webkit-box-sizing: border-box; - box-sizing: border-box; - - background-color: #fff; - .assembly { - position: relative; - align-self: flex-end; - margin-right: 12px; - .label { - height: 38px; - } - } - .set-input { - position: relative; - vertical-align: bottom; - font-size: 14px; - 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) { - // 鍘婚櫎绾� - box-shadow: none; - } - } - :deep(.el-input__wrapper) { - box-shadow: unset; - } - } - .upload_img { - .imgbox { - height: 38px; - .set-img-icon { - width: 38px; - height: 38px; - border-radius: 5px; - transition: background-color 0.1s ease-in-out; - } - .send { - width: 36px; - height: 36px; - border-radius: 50%; - background-color: #2c1e1d; - img { - margin: 4px 0 0 -2px; - } - } - } - } -} - -.stop-breathe { - @keyframes breathe { - 0%, - 100% { - transform: scale(1); - } - 50% { - transform: scale(1.35); - } - } - animation: breathe 3s infinite ease-in-out; -} +@use './index.scss'; </style> diff --git a/src/components/chat/components/playBar/SceneSwitch.vue b/src/components/chat/components/playBar/SceneSwitch.vue new file mode 100644 index 0000000..715562b --- /dev/null +++ b/src/components/chat/components/playBar/SceneSwitch.vue @@ -0,0 +1,33 @@ +<template> + <div class="scene-switch absolute bottom-[114%] left-4"> + <div class="flex-items-center space-x-2" :class="isHome ? 'set-next-group-type' : ''"> + <div + class="border border-gray-400 border-solid h-8 flex-items-center px-3 py-2 rounded-2xl cursor-pointer space-x-1 hover:bg-[#cae3ff]" + :class="{ 'bg-[#c5e0ff]': activeGroupType === item, '!text-[#1c86ff]': activeGroupType === item }" + v-for="item in groupTypeList" + :key="item" + @click="groupTypeClick(item)" + > + <span :class="['ywifont', groupTypeMapIcon[item]]"></span> + <div class="">{{ item }}</div> + </div> + </div> + </div> +</template> + +<script setup lang="ts" name="SceneSwitch"> +import { activeGroupType, groupTypeList, groupTypeMapIcon } from '/@/stores/chatRoom'; +const props = defineProps({ + isHome: Boolean, +}); +const emit = defineEmits(['change']); + +let preGroupType = activeGroupType.value; +const groupTypeClick = (item) => { + if (preGroupType === item) return; + activeGroupType.value = item; + preGroupType = item; + emit('change', item); +}; +</script> +<style scoped lang="scss"></style> diff --git a/src/components/chat/components/playBar/index.scss b/src/components/chat/components/playBar/index.scss new file mode 100644 index 0000000..e116b2b --- /dev/null +++ b/src/components/chat/components/playBar/index.scss @@ -0,0 +1,143 @@ + +.set-waterTitle { + line-height: 24px; + font-weight: 500; + font-size: 18px; + color: #3b4066; + vertical-align: middle; +} +strong { + font-size: 26px; + font-weight: 700; + margin-right: 12px; +} +.layout-logo-medium-img { + width: 28px; + margin-right: 7px; +} +.pc-roleList { + margin: 40px 0 26px; + position: relative; +} +.modelItem { + height: 34px; + padding: 0 16px; + border-radius: 17px; + border: 1px solid #00000020; + background-color: #f2f4f8; + transition: background-color 0.1s, border-color 0.1s, color 0.1s; + color: #333; + .set-icon { + width: 20px; + height: 20px; + position: relative; + } + .set-icon-more { + width: 16px; + height: 16px; + position: relative; + } + span { + margin-left: 8px; + font-weight: 500; + font-size: 15px; + } +} +.modelItemActive { + background-color: #1c86ff; + border-color: #1c86ff; + color: #fff; +} + +.input-shadow { + -webkit-box-shadow: 0 0 0 1px transparent, 0 3px 16px 0 #dee0f3; + box-shadow: 0 0 0 1px transparent, 0 3px 16px 0 #dee0f3; +} + +.input-border { + border: 1px solid #00000030; + + -webkit-transition: border-color 0.1s ease-in-out, -webkit-box-shadow 0.1s ease-in-out; + transition: border-color 0.1s ease-in-out, -webkit-box-shadow 0.1s ease-in-out; + -o-transition: border-color 0.1s ease-in-out, box-shadow 0.1s ease-in-out; + transition: border-color 0.1s ease-in-out, box-shadow 0.1s ease-in-out; + transition: border-color 0.1s ease-in-out, box-shadow 0.1s ease-in-out, -webkit-box-shadow 0.1s ease-in-out; +} +.playInput { + align-items: flex-start; + width: 760px; + position: relative; + padding: 4px 4px 4px 12px; + + display: flex; + -webkit-box-align: end; + -ms-flex-align: end; + align-items: flex-end; + -webkit-box-sizing: border-box; + box-sizing: border-box; + + background-color: #fff; + .assembly { + position: relative; + align-self: flex-end; + margin-right: 12px; + .label { + height: 38px; + } + } + .set-input { + position: relative; + vertical-align: bottom; + font-size: 14px; + 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) { + // 鍘婚櫎绾� + box-shadow: none; + } + } + :deep(.el-input__wrapper) { + box-shadow: unset; + } + } + .upload_img { + .imgbox { + height: 38px; + .set-img-icon { + width: 38px; + height: 38px; + border-radius: 5px; + transition: background-color 0.1s ease-in-out; + } + .send { + width: 36px; + height: 36px; + border-radius: 50%; + background-color: #2c1e1d; + img { + margin: 4px 0 0 -2px; + } + } + } + } +} + +.stop-breathe { + @keyframes breathe { + 0%, + 100% { + transform: scale(1); + } + 50% { + transform: scale(1.35); + } + } + animation: breathe 3s infinite ease-in-out; +} \ No newline at end of file diff --git a/src/components/chat/components/playBar/phrase/CommonPhrases.vue b/src/components/chat/components/playBar/phrase/CommonPhrases.vue index f650df3..61bde4d 100644 --- a/src/components/chat/components/playBar/phrase/CommonPhrases.vue +++ b/src/components/chat/components/playBar/phrase/CommonPhrases.vue @@ -1,5 +1,5 @@ <template> - <div class="container" :class="isHome ? 'top-[100%] mt-[8px]' : 'bottom-[100%] mb-[8px]'"> + <div ref="commonPhrasesRef" class="container" :class="isHome ? 'top-[100%] mt-[8px]' : 'bottom-[100%] mb-[8px]'"> <div class="container_header"> <div class="question">甯哥敤璇�</div> <span class="ywifont ywicon-guanbi text-[15px] cursor-pointer text-[#767a97]" @click="closeCommonPhrases"></span> @@ -63,6 +63,7 @@ import { computed, onMounted, reactive, ref } from 'vue'; import { addUserSample, deleteUserSample, listUserSample, updateUserSample } from '/@/api/ai/chat'; import { activeGroupType, activeRoomId, activeSampleId, setRoomConfig } from '/@/stores/chatRoom'; +import { onClickOutside } from '@vueuse/core'; const state = reactive({ useCommonPhrasesDialog: false, show_sample_title: false, @@ -71,7 +72,9 @@ sample_id: null, }); const commonPhrases = ref([]); -const props = defineProps(['isHome']); +const props = defineProps({ + isHome: Boolean, +}); const isShow = defineModel('isShow', { type: Boolean, }); @@ -87,7 +90,7 @@ }; //#endregion //#region ====================== 鑾峰彇甯哥敤璇� ====================== -const getCommonPhrases = async () => { +const updatePhrase = async () => { const res = await listUserSample({ group_type: activeGroupType.value, }); @@ -161,10 +164,11 @@ //#endregion //#region ====================== 甯哥敤璇埌瀵硅瘽妗� ====================== const emits = defineEmits<{ - (event: 'updateCommonChatInput', val): void; + (event: 'updateInput', val): void; }>(); const titleClick = (item) => { - emits('updateCommonChatInput', item.question); + emits('updateInput', item.question); + isShow.value = false; setRoomConfig(activeRoomId.value, 'isAnswerByLLM', false); activeSampleId.value = item.id; }; @@ -179,102 +183,33 @@ } }; //#endregion -onMounted(() => { - getCommonPhrases(); -}); -defineExpose({ commonChatByUser, getCommonPhrases }); -</script> -<style scoped lang="scss"> -.container { - position: absolute; - width: 100%; - max-height: 40vh; - padding: 0 8px 8px; - left: 0px; - border-radius: 12px; - background-color: #ffffff; - border: 1px solid #e5e5e5; - box-shadow: 0px 8px 25px 0px #0000000d; - display: flex; - flex-direction: column; - z-index: 990; - &_header { - width: 100%; - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; - padding: 10px 6px; - color: #060607; - .question { - font-size: 14px; - color: #060607; - font-weight: 600; - line-height: 20px; - letter-spacing: 0.25px; - flex-grow: 1; - display: flex; - } - } - &_content { - width: 100%; - max-height: 35vh; - height: fit-content; - overflow-y: auto; - .set_phrases { - outline: none; - overflow-y: auto; - position: relative; - transition: height 0.1s linear; - .phase_item { - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; - cursor: pointer; - padding: 6px 8px; - flex-shrink: 0; - background: #fff; - border-radius: 8px; - width: 100%; - &:hover { - background: #e5e7ed; - } - .question { - font-size: 14px; - color: #8d8e99; - font-weight: 400; - font-style: normal; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - &:hover { - color: #060607; - } - } - .content { - font-size: 12px; - color: #5e6772; - font-family: PingFang SC; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - } - } - } +const commonPhrasesRef = ref<HTMLDivElement>(null); +onClickOutside( + commonPhrasesRef, + () => { + isShow.value = false; + }, + { + ignore: ['.el-message-box'], } - &_add { - display: flex; - flex-direction: row; - align-items: center; - cursor: pointer; - padding: 6px 8px; - background: #fff; - border-radius: 8px; - &:hover { - background: #e5e7ed; - } +); + +const addPhrase = (val) =>{ + if (!props.isHome) { + let obj = { + id: val?.historyId, + question: val?.content.values, + }; + commonChatByUser(obj); + isShow.value = true; } } +onMounted(() => { + updatePhrase(); +}); +defineExpose({ addPhrase, updatePhrase }); +</script> +<style scoped lang="scss"> +@use './index.scss'; </style> diff --git a/src/components/chat/components/playBar/phrase/index.scss b/src/components/chat/components/playBar/phrase/index.scss new file mode 100644 index 0000000..1e27f73 --- /dev/null +++ b/src/components/chat/components/playBar/phrase/index.scss @@ -0,0 +1,92 @@ +.container { + position: absolute; + width: 100%; + max-height: 40vh; + padding: 0 8px 8px; + left: 0px; + border-radius: 12px; + background-color: #ffffff; + border: 1px solid #e5e5e5; + box-shadow: 0px 8px 25px 0px #0000000d; + display: flex; + flex-direction: column; + z-index: 990; + &_header { + width: 100%; + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + padding: 10px 6px; + color: #060607; + .question { + font-size: 14px; + color: #060607; + font-weight: 600; + line-height: 20px; + letter-spacing: 0.25px; + flex-grow: 1; + display: flex; + } + } + &_content { + width: 100%; + max-height: 35vh; + height: fit-content; + overflow-y: auto; + .set_phrases { + outline: none; + overflow-y: auto; + position: relative; + transition: height 0.1s linear; + .phase_item { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + cursor: pointer; + padding: 6px 8px; + flex-shrink: 0; + background: #fff; + border-radius: 8px; + width: 100%; + &:hover { + background: #e5e7ed; + } + .question { + font-size: 14px; + color: #8d8e99; + font-weight: 400; + font-style: normal; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + &:hover { + color: #060607; + } + } + + .content { + font-size: 12px; + color: #5e6772; + font-family: PingFang SC; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + } + } + } + } + &_add { + display: flex; + flex-direction: row; + align-items: center; + cursor: pointer; + padding: 6px 8px; + background: #fff; + border-radius: 8px; + &:hover { + background: #e5e7ed; + } + } +} \ No newline at end of file -- Gitblit v1.9.3