From 3cc575268b3042b35e785ffeebf51a6ea3b5e73d Mon Sep 17 00:00:00 2001 From: gerson <1405270578@qq.com> Date: 星期五, 01 十一月 2024 11:32:13 +0800 Subject: [PATCH] Merge branch 'test' of http://47.103.154.90:83/r/WI/Web.V1.0 into test --- src/components/chat/Chat.vue | 29 ++- src/views/project/ch/home/Home.vue | 22 -- src/components/chat/chatComponents/summaryCom/components/recordSet/components/TimeRange.vue | 2 src/components/drawer/CustomDrawer.vue | 116 ++++-------- src/components/chat/chatComponents/summaryCom/components/recordSet/components/List.vue | 8 src/views/project/ch/home/component/waterRight/bottom.vue | 18 - src/layout/component/sidebar/components/MenuList.vue | 18 + customer_list/ch/static/config/globalConfig.pro.js | 2 src/components/chat/components/playBar/PlayBar.vue | 29 ++ src/components/chat/hooks/useScrollLoad.ts | 35 ++- customer_list/ch/static/config/globalConfig.test.js | 2 src/views/project/ch/home/component/waterRight/center.vue | 10 - src/components/chat/model/types.ts | 4 src/stores/chatRoom.ts | 42 ++- src/components/chat/components/playBar/phrase/CommonPhrases.vue | 169 ++++++++++++++++++ 15 files changed, 326 insertions(+), 180 deletions(-) diff --git a/customer_list/ch/static/config/globalConfig.pro.js b/customer_list/ch/static/config/globalConfig.pro.js index 78756d0..cd47234 100644 --- a/customer_list/ch/static/config/globalConfig.pro.js +++ b/customer_list/ch/static/config/globalConfig.pro.js @@ -7,7 +7,7 @@ ICPLicense: '娌狪CP澶�14049296鍙�-2', WebApiUrl: { - MainUrl: 'http://wi.cpolar.top', + MainUrl: 'https://wi.cpolar.top', AuthUrl: 'http://47.100.245.85:8190/', }, SoftWareInfo: { diff --git a/customer_list/ch/static/config/globalConfig.test.js b/customer_list/ch/static/config/globalConfig.test.js index 90e571d..586c3b4 100644 --- a/customer_list/ch/static/config/globalConfig.test.js +++ b/customer_list/ch/static/config/globalConfig.test.js @@ -7,7 +7,7 @@ ICPLicense: '娌狪CP澶�14049296鍙�-2', WebApiUrl: { - MainUrl: 'https://widev.cpolar.top', + MainUrl: 'http://widev.cpolar.top', AuthUrl: 'http://47.100.245.85:8190/', }, SoftWareInfo: { diff --git a/src/components/chat/Chat.vue b/src/components/chat/Chat.vue index c5352f3..3fb1699 100644 --- a/src/components/chat/Chat.vue +++ b/src/components/chat/Chat.vue @@ -1,18 +1,19 @@ <template> <div class="flex h-full"> <div class="flex flex-col h-full flex-auto"> - <div ref="chatListDom" class="relative h-full flex flex-col items-center overflow-y-auto "> + <div ref="chatListDom" class="relative h-full flex flex-col items-center overflow-y-auto"> <span class="more-loading absolute text-blue-400 left-[50%] translate-x-[-50%] cursor-pointer w-10" v-loading="moreIsLoading" ></span> - <div class="h-full" v-loading="chatListLoading" :style="{ width: chatWidth }"> + <div class="h-full relative" v-loading="chatListLoading" :style="{ width: chatWidth }"> <div class="group flex px-4 py-6 hover:bg-slate-100 rounded-lg relative" :class="{ 'flex-row-reverse': item.role === RoleEnum.user }" v-for="(item, index) of computedMessageList" :key="`${item.historyId}_${item.role}`" > + <div class="absolute top-0 left-[72px] text-[#8d8e99]">{{ item?.createTime }}</div> <img class="rounded-full size-12 flex-0" :class="{ 'mr-4': item.role === RoleEnum.assistant, 'ml-4': item.role === RoleEnum.user }" @@ -143,7 +144,7 @@ </div> </div> - <div class="sticky bottom-0 w-full p-6 bg-[rgb(247,248,250)] flex justify-center"> + <div class="sticky bottom-0 w-full p-6 bg-[rgb(247,248,250)] flex justify-center"> <PlayBar v-model:voicePageIsShow="voicePageIsShow" :isTalking="isTalking" @@ -161,6 +162,7 @@ <script setup lang="ts"> import _ from 'lodash'; +import moment from 'moment'; import { v4 as uuidv4 } from 'uuid'; import { computed, onMounted, ref } from 'vue'; import FeedbackPanel from './components/FeedbackPanel.vue'; @@ -171,11 +173,20 @@ import { useScrollToBottom } from './hooks/useScrollToBottom'; import type { ChatContent } from './model/types'; import { AnswerState, AnswerType, RoleEnum, answerTypeMapCom, roleImageMap, type ChatMessage } from './model/types'; -import { GetHistoryAnswer, QuestionAi, extCallQuery } from '/@/api/ai/chat'; +import { QuestionAi, extCallQuery } from '/@/api/ai/chat'; import PlayBar from '/@/components/chat/components/playBar/PlayBar.vue'; import CustomDrawer from '/@/components/drawer/CustomDrawer.vue'; import router from '/@/router'; -import { activeChatRoom, activeGroupType, activeLLMId, activeRoomId, activeSampleId, activeSectionAId, getRoomConfig, roomConfig } from '/@/stores/chatRoom'; +import { + activeChatRoom, + activeGroupType, + activeLLMId, + activeRoomId, + activeSampleId, + activeSectionAId, + getRoomConfig, + roomConfig, +} from '/@/stores/chatRoom'; import { ErrorCode } from '/@/utils/request'; const chatWidth = '75%'; @@ -193,7 +204,6 @@ const computedMessageList = computed(() => { return messageList.value.filter((v) => !!v); }); - const parseContent = (res) => { if (!res) return null; let content: ChatContent = { @@ -253,10 +263,8 @@ content.origin = res; return content; }; - const { clearQueryProcess, process, processId, queryProcess } = useQueryProcess(); const DEFAULT_SECTION_A_ID = 'knowledge_base'; - let questionRes = null; let finalCalcSectionAId = null; @@ -301,7 +309,7 @@ ...judgeParams, } as any; - if(activeGroupType.value){ + if (activeGroupType.value) { params.group_type = activeGroupType.value; } @@ -332,7 +340,6 @@ let currentSampleId = ''; let currentLLMId = null; - const sendChatMessage = async (content: ChatContent = messageContent.value, cb?: any, isCallExtParams?: any) => { if (!content?.values || isTalking.value || chatListLoading.value) return; @@ -399,8 +406,10 @@ sendChatMessage(messageContent.value, cb); }; const appendLastMessageContent = (content: ChatContent) => { + const currentTime = moment().format('MM骞碊D鏃� HH:mm:ss'); if (messageList.value.at(-1)) { messageList.value.at(-1).content = content; + messageList.value.at(-1).createTime = currentTime; } }; const { loadRangeData, onChatListScroll, moreIsLoading, nextUserMsgEndIndex } = useScrollLoad({ diff --git a/src/components/chat/chatComponents/summaryCom/components/recordSet/components/List.vue b/src/components/chat/chatComponents/summaryCom/components/recordSet/components/List.vue index 80f4e11..eccf785 100644 --- a/src/components/chat/chatComponents/summaryCom/components/recordSet/components/List.vue +++ b/src/components/chat/chatComponents/summaryCom/components/recordSet/components/List.vue @@ -35,7 +35,8 @@ } }; -const selectList = getSelectList(props.data.origin.step_value); +const selectList = getSelectList(props.data?.origin?.step_value); +// const fontSize = ref('14px'); const emit = defineEmits(['change']); const SELECT_OFFSET = 47; @@ -44,7 +45,7 @@ // 浠ユ渶澶у瓧闀夸负瀹藉害 const widthList = props.data.list.map((item) => getTextWidth(item.title, { - size: fontSize.value, + size:'14px', }) ); const maxWidth = Math.max(...widthList); @@ -55,7 +56,6 @@ } }); -const fontSize = ref('14px'); const selectValue = defineModel({ type: String, }); @@ -66,6 +66,6 @@ </script> <style scoped lang="scss"> :deep(.el-input) { - font-size: v-bind(fontSize); + font-size: 14px; } </style> diff --git a/src/components/chat/chatComponents/summaryCom/components/recordSet/components/TimeRange.vue b/src/components/chat/chatComponents/summaryCom/components/recordSet/components/TimeRange.vue index 20a8cd0..005ad19 100644 --- a/src/components/chat/chatComponents/summaryCom/components/recordSet/components/TimeRange.vue +++ b/src/components/chat/chatComponents/summaryCom/components/recordSet/components/TimeRange.vue @@ -84,7 +84,7 @@ } }; -const timeRangeMapTitle = getRangeMapTitle(props.data.origin.time_step); +const timeRangeMapTitle = getRangeMapTitle(props.data?.origin?.time_step); const dateValue = defineModel({ type: definePropType<[string, string]>(Array), }); diff --git a/src/components/chat/components/playBar/PlayBar.vue b/src/components/chat/components/playBar/PlayBar.vue index 21e61fd..2ad4d43 100644 --- a/src/components/chat/components/playBar/PlayBar.vue +++ b/src/components/chat/components/playBar/PlayBar.vue @@ -1,5 +1,5 @@ <template> - <div class="playInput hl_input rounded-[22px] input-border input-shadow" > + <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"> @@ -31,7 +31,12 @@ </el-tooltip> </div> --> <div class="assembly flex"> - <el-button title="鎻掍欢鑿滃崟" class="label flex items-center cursor-pointer" link> + <el-button + title="杈撳叆甯哥敤璇爣棰橈紝鍙揩鎹疯皟鐢ㄥ父鐢ㄨ" + class="label flex items-center cursor-pointer" + link + @click="commonPhrasesClick" + > <img src="/static/images/wave/PlugIn.png" class="set-icon box-border" /> </el-button> </div> @@ -103,24 +108,29 @@ @updateInputValue="updateInputValue" :isHome="isHome" /> + <CommonPhrases v-model:isShow="isShowPhrase" v-show="isShowPhrase" :isHome="isHome"/> </div> </template> <script setup lang="ts"> +import { onClickOutside } from '@vueuse/core'; import type { InputInstance } from 'element-plus'; import { ElMessage } from 'element-plus'; +import _ from 'lodash'; import getCaretCoordinates from 'textarea-caret'; -import { computed, nextTick, ref, triggerRef } from 'vue'; +import { computed, nextTick, ref } from 'vue'; import InfoDetail from './InfoDetail.vue'; +import CommonPhrases from './phrase/CommonPhrases.vue'; import VoicePage from './voicePage/VoicePage.vue'; import { getMetricsNames, querySimilarityHistory } from '/@/api/ai/chat'; - -import { onClickOutside } from '@vueuse/core'; -import _ from 'lodash'; import { activeGroupType, groupTypeList, groupTypeMapIcon } from '/@/stores/chatRoom'; const emits = defineEmits(['sendClick']); const props = defineProps(['isTalking', 'isHome']); const voicePageIsShow = defineModel('voicePageIsShow', { + type: Boolean, + default: false, +}); +const isShowPhrase = defineModel('isShowPhrase', { type: Boolean, default: false, }); @@ -213,6 +223,7 @@ lastIsFinish = false; const res = await querySimilarityHistory({ question: text, + group_type: activeGroupType.value, }); lastIsFinish = true; const handleValues = res?.values ?? []; @@ -416,6 +427,12 @@ activeGroupType.value = null; }; //#endregion + +//#region ====================== 甯哥敤璇姛鑳� ====================== +const commonPhrasesClick = () => { + isShowPhrase.value = true; +}; +//#endregion </script> <style scoped lang="scss"> .set-waterTitle { diff --git a/src/components/chat/components/playBar/phrase/CommonPhrases.vue b/src/components/chat/components/playBar/phrase/CommonPhrases.vue new file mode 100644 index 0000000..267c41e --- /dev/null +++ b/src/components/chat/components/playBar/phrase/CommonPhrases.vue @@ -0,0 +1,169 @@ +<template> + <div class="container" :class="isHome ? 'top-[100%] mt-[8px]' : 'bottom-[100%] mb-[8px]'"> + <div class="container_header"> + <div class="title">甯哥敤璇�</div> + <span class="ywifont ywicon-guanbi text-[15px] cursor-pointer text-[#767a97]" @click="closeCommonPhrases"></span> + </div> + <div class="container_content"> + <div class="set_phrases" :style="{ height: commonPhrases.length * 40 + 'px' }"> + <div class="w-full h-full absolute top-0"> + <div class="py-0 mt-0 box-border h-full"> + <div style="overflow-anchor: none" v-for="(item, index) in commonPhrases" :key="index"> + <div class="phase_item"> + <div class="flex flex-col"> + <div class="title"> + {{ item.title }} + </div> + <div class="content"> + {{ item.content }} + </div> + </div> + </div> + </div> + </div> + </div> + </div> + </div> + <div class="container_add" @click="addCommonPhrases"> + <span class="ywifont ywicon-jia text-[15px] cursor-pointer text-[#767a97]"></span> + <div class="grow">娣诲姞甯哥敤璇�</div> + </div> + <el-dialog v-model="state.useCommonPhrasesDialog" :title="state?.sample_title" width="500" :before-close="handleClose"> + <el-input v-model="state.inputCommonPhrases" :rows="10" type="textarea"></el-input> + <template #footer> + <div class="dialog-footer"> + <el-button @click="handleClose">鍙栨秷</el-button> + <el-button type="primary" @click="submitCommonPhrases"> 娣诲姞 </el-button> + </div> + </template> + </el-dialog> + </div> +</template> + +<script setup lang="ts"> +import { reactive, ref } from 'vue'; +const state = reactive({ + useCommonPhrasesDialog: false, + sample_title: '娣诲姞甯哥敤璇�', + inputCommonPhrases: '', +}); +const commonPhrases = ref([ + { + id: 1, + title: '浣犲ソ锛岃闂湁浠�涔堝彲浠ュ府鍔╂偍锛�', + content: '鎮ㄥソ锛屾垜鎯冲挩璇竴涓嬪叧浜庢偍鐨勮鍗曘��', + }, + { + id: 2, + title: '娴嬭瘯1?', + content: '鎴戞兂鍜ㄨ涓�涓嬪叧浜庢偍鐨勮鍗曘��', + }, + { + id: 3, + title: '娴嬭瘯2?', + content: '鎴戞兂鍜ㄨ涓�涓嬪叧浜庢偍鐨勮鍗曘��', + }, +]); +const props = defineProps(['isHome']); +const closeCommonPhrases = () => {}; +//鍏抽棴甯哥敤璇脊绐� +const handleClose = () => { + state.useCommonPhrasesDialog = false; +}; +//鎵撳紑甯哥敤璇脊绐� +const addCommonPhrases = () => { + state.useCommonPhrasesDialog = true; +}; +//鎻愪氦甯哥敤璇� +const submitCommonPhrases = () => {}; +</script> +<style scoped lang="scss"> +.container { + position: absolute; + width: 100%; + max-height: 45vh; + 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: 100; + &_header { + width: 100%; + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + padding: 10px 6px; + color: #060607; + .title { + 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: 40vh; + height: fit-content; + .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; + } + .title { + font-size: 14px; + color: #060607; + font-family: PingFang HK; + font-weight: 600; + font-style: normal; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + } + .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; + } + } +} +</style> diff --git a/src/components/chat/hooks/useScrollLoad.ts b/src/components/chat/hooks/useScrollLoad.ts index 457bfc1..2f74288 100644 --- a/src/components/chat/hooks/useScrollLoad.ts +++ b/src/components/chat/hooks/useScrollLoad.ts @@ -1,8 +1,8 @@ -import { Ref, ShallowRef, nextTick, onBeforeUnmount, ref, unref } from 'vue'; +import moment from 'moment'; +import { Ref, ShallowRef, computed, nextTick, onBeforeUnmount, ref, unref } from 'vue'; import { LOAD_CHAT_LIMIT } from '../constants'; import { AnswerType, ChatContent, ChatMessage, RoleEnum } from '../model/types'; import { GetHistoryAnswer, QueryHistoryDetail } from '/@/api/ai/chat'; - type UseScrollLoadOption = { container: ShallowRef<HTMLDivElement>; historyGroupId: string | Ref<string>; @@ -28,12 +28,17 @@ history_id: historyId, }); }; - + const formatShowTimeYear = computed(() => { + return (str) => { + return moment(str).format('MM鏈圖D鏃� HH:mm:ss'); + }; + }); /** * 鑾峰彇鐢ㄦ埛鍥炲鏁版嵁锛屽苟鎻掑叆鍒板璇濆綋涓幓 */ const loadReplyData = async (userMsg: any[]) => { - const sectionAIdMap = new Map(); + const userItemIdMap = new Map(); + // 鐢ㄦ埛娑堟伅 const tmpMessageList: ChatMessage[] = userMsg.map((item) => { return { historyId: item.history_id, @@ -46,7 +51,7 @@ }); const resList = await Promise.all( (userMsg ?? []).map((item) => { - sectionAIdMap.set(item.history_id, item.section_a_id); + userItemIdMap.set(item.history_id, item); return getAnswerById(item.history_id); }) ); @@ -55,6 +60,9 @@ const insertIndex = index + 1 + i; const currentUserMsg = tmpMessageList[insertIndex - 1]; currentUserMsg.content.values = item?.answer?.question ?? currentUserMsg.content.values; + + const mapUser = userItemIdMap.get(item.answer.history_id); + const answerTime = formatShowTimeYear.value(mapUser?.create_time); tmpMessageList.splice( insertIndex, 0, @@ -65,7 +73,8 @@ role: RoleEnum.assistant, content: parseAnswerContent(item.answer), state: item.answer_state, - sectionAId: sectionAIdMap.get(item.answer.history_id), + sectionAId: mapUser?.section_a_id, + createTime: answerTime, } ); i++; @@ -97,7 +106,6 @@ //婊氬姩鐩戝惉 async function onChatListScroll() { if (container.value.scrollTop == 0) { - // 鏇村鏁版嵁姝e湪鍔犺浇鏃� if (moreIsLoading.value) { return; @@ -113,9 +121,9 @@ moreIsLoading.value = false; }); //鏇存柊鍚庯紝绛夊緟椤甸潰娓叉煋瀹屾瘯鍐嶅幓鎷縮crollHeight,鍚﹀垯鎷垮埌鐨勬槸涔嬪墠鐨� - nextTick(()=>{ - nextTick(()=>{ - nextTick(()=>{ + nextTick(() => { + nextTick(() => { + nextTick(() => { let h2 = container.value.scrollHeight; container.value.scrollTo({ //椤堕儴鍦ㄥ師鍏堝熀纭�涓婂線涓嬫粴鍔�50px锛岄湶鍑烘柊鍔犺浇鏁版嵁鐨勪竴鐐� @@ -123,10 +131,9 @@ top: h2 - h1, behavior: 'instant', //auto-鑷姩婊氬姩 instant-鐬棿婊氬姩 smooth-骞虫粦婊氬姩 }); - }) - }) - }) - + }); + }); + }); } } diff --git a/src/components/chat/model/types.ts b/src/components/chat/model/types.ts index 262dc7a..9abc70c 100644 --- a/src/components/chat/model/types.ts +++ b/src/components/chat/model/types.ts @@ -46,6 +46,7 @@ errCode?: string; errMsg?: string; origin?: any; + createTime?: string; }; export interface ChatMessage { @@ -53,7 +54,8 @@ role: RoleEnum; content?: ChatContent; state?: null | '1' | '0'; - sectionAId?:string + sectionAId?:string, + createTime?:string } export const roleImageMap = { diff --git a/src/components/drawer/CustomDrawer.vue b/src/components/drawer/CustomDrawer.vue index de14af5..47b69f5 100644 --- a/src/components/drawer/CustomDrawer.vue +++ b/src/components/drawer/CustomDrawer.vue @@ -5,19 +5,6 @@ </div> <div class="pc-mouldboard column exampleSlide"> <div class="header flex items-center justify-center"> - <!-- <div - class="box-border flex w-[234px] h-[32px] rounded-md items-center justify-between cursor-pointer relative border border-solid border-[#2c2d33]" - > - <div - class="tabbar-item" - :class="activeGroupType.value === item.ID ? 'set-tabbar-active' : ''" - @click="handleTabClick(item)" - v-for="item in state.tabNameList" - :key="item.ID" - > - {{ item.Name }} - </div> - </div> --> <i class="ywifont ywicon-guanbi text-[#999] text-[18px] absolute right-[14px] top-5 cursor-pointer" @click="handleCloseTemplate" @@ -83,7 +70,7 @@ <div class="box-border w-[354px] flex-1 min-h-0 bg-[#e0e7fb]" v-show="activeGroupType == '鍔炲叕鍔╂墜'"> <div class="flex flex-col w100 h100 pt-0 pr-[15px] pb-0 pl-[20px]"> <div class="flex items-center w100 h-[30px] border border-solid border-[#b2b2b2] transition-[border-color 1s] rounded-2xl"> - <el-input v-model="officeParams.template_title" placeholder="鎼滅储鏇村" class="set-input" :prefix-icon="Search" clearable> + <el-input v-model="officeParams.sample_title" placeholder="鎼滅储鏇村" class="set-input" :prefix-icon="Search" clearable> </el-input> </div> <div class="mt10 w100 relative h100" v-show="state.customOfficeList.length > 0"> @@ -114,12 +101,12 @@ </div> </div> <div class="mt10 w100 overflow-auto set-height-custom"> - <div class="w100 pb-[20px] flex flex-col" v-for="item in finalOfficeList" :key="item.group_id"> + <div class="w100 pb-[20px] flex flex-col" v-for="item in finalOfficeList" :key="item.sample_id"> <div class="bg-[#f5f7fd] p-[12px] transition-[background-color .2s] flex flex-col rounded-2xl"> <div class="flex justify-between"> - <span class="set-title">{{ item.template_title }}</span> + <span class="set-title">{{ item.sample_title }}</span> </div> - <div class="example-body ellipsis">{{ item.template_value }}</div> + <div class="example-body ellipsis">{{ item.sample_question }}</div> <div class="example-bottom"> <span class="example-item">{{ item.template_type }}</span> <el-button type="primary" class="set-button" @click="templateUseClick(item)">浣跨敤</el-button> @@ -133,7 +120,7 @@ <div class="box-border w-[354px] flex-1 min-h-0 bg-[#e0e7fb]" v-show="activeGroupType == '鐭ヨ瘑搴�'"> <div class="flex flex-col w100 h100 pt-0 pr-[15px] pb-0 pl-[20px]"> <div class="flex items-center w100 h-[30px] border border-solid border-[#b2b2b2] transition-[border-color 1s] rounded-2xl"> - <el-input v-model="queryParams.sample_title" placeholder="鎼滅储鏇村" class="set-input" :prefix-icon="Search" clearable> + <el-input v-model="knowledgeParams.sample_title" placeholder="鎼滅储鏇村" class="set-input" :prefix-icon="Search" clearable> </el-input> </div> <div class="mt10 w100 relative h100" v-show="state.knowledgeBaseList.length > 0"> @@ -186,7 +173,7 @@ </div> </div> </div> - <el-dialog v-model="state.useInstructDialog" :title="state.instructInfo?.template_title" width="500" :before-close="handleClose"> + <el-dialog v-model="state.useInstructDialog" :title="state.instructInfo?.sample_title" width="500" :before-close="handleClose"> <el-input v-model="state.inputInstruct" :rows="10" type="textarea"></el-input> <template #footer> <div class="dialog-footer"> @@ -202,9 +189,17 @@ <script setup lang="ts"> import { Search } from '@element-plus/icons-vue'; import { computed, reactive, ref, watch } from 'vue'; -import { getSectionList, getSelectSample, getUserTemplateList } from '/@/api/ai/chat'; import { useSearch } from '/@/hooks/useSearch'; -import { activeGroupType, activeRoomId, activeSampleId, activeSectionAId, sectionAList, setRoomConfig } from '/@/stores/chatRoom'; +import { + activeGroupType, + activeRoomId, + activeSampleId, + activeSectionAId, + exampleSceneList, + sceneGroupList, + sectionAList, + setRoomConfig, +} from '/@/stores/chatRoom'; import { convertListToTree, debounce } from '/@/utils/util'; import { OptClassificationMap, classificationEnum } from '/@/views/types/processDrawing/index'; let state = reactive({ @@ -226,9 +221,6 @@ exampleRandomContent: [], exampleContent: [], listSampleLoading: false, - listInstructLoading: false, - listSampleExpand: false, - listInstructExpand: false, }); //#region ====================== 浼犲弬 ====================== const isShow = defineModel('isShow', { @@ -242,28 +234,9 @@ const exampleList = ref([]); //绀轰緥鍒楄〃 //鑾峰彇妯$増鍒楄〃 const getSelectListSample = async () => { - state.listSampleLoading = true; - const res = await getSelectSample({}).finally(() => { - state.listSampleLoading = false; - }); - state.exampleRandomContent = res.samples; - const array = []; - res.samples.forEach((sample, index) => { - sample.Icon = '/static/images/wave/ChatImg.png'; - sample.BgColor = randomHexColor(); - if (index < 4) { - array.push(sample); - } - }); - exampleList.value = res.samples; - state.exampleContent = array; + exampleList.value = exampleSceneList.value; }; -//闅忔満鐢熸垚棰滆壊 -const randomHexColor = () => { - return `#${Math.floor(Math.random() * 16777215) - .toString(16) - .padEnd(6, '0')}`; -}; + const changeExample = (item) => { emit('updateChatInput', item.sample_question); setRoomConfig(activeRoomId.value, 'isAnswerByLLM', false); @@ -272,11 +245,7 @@ }; //鑾峰彇鐢ㄦ埛妯℃澘 const getUserTemplate = async () => { - state.listInstructLoading = true; - const res = await getUserTemplateList().finally(() => { - state.listInstructLoading = false; - }); - instructContentList.value = res.templates; + instructContentList.value = exampleSceneList.value; }; //#endregion //#region ====================== 榛樿閫夋嫨绗竴涓殑鍦烘櫙鐨勫瓙鍦烘櫙 ====================== @@ -335,7 +304,6 @@ }; //鑾峰彇涓诲満鏅垪琛� const getMainSectionList = async () => { - const res = await getSectionList(); const iconList = [ 'biaodan', 'putong', @@ -347,10 +315,10 @@ 'jinridaiban', 'gongju', ]; - res.groups.forEach((sectionItem, index) => { + await sceneGroupList.value.forEach((sectionItem, index) => { sectionItem.Icon = iconList[index]; }); - sectionAList.value = res.groups; + sectionAList.value = sceneGroupList.value; tagListClick(sectionAList.value); }; const loadingData = ref(false); @@ -361,9 +329,7 @@ loadingData.value = false; }); if (activeGroupType.value == '涓氬姟鍦烘櫙' || activeGroupType.value == '鐭ヨ瘑搴�') { - if (state.listSampleExpand) return; await getSelectListSample(); - state.listSampleExpand = true; } } }; @@ -372,7 +338,7 @@ const templateUseClick = (row) => { state.useInstructDialog = true; state.instructInfo = row; - state.inputInstruct = row.template_value; + state.inputInstruct = row.sample_question; }; const handleClose = () => { state.useInstructDialog = false; @@ -401,24 +367,24 @@ ); //鍔炲叕 const officeParams = ref({ - template_title: '', + sample_title: '', }); const { query: queryInstruct, queryData: showInstructList } = useSearch(instructContentList, officeParams); const finalOfficeList = computed(() => { - const result = showInstructList.value.filter((item) => item.template_group == state.activeOfficeChildName); + const result = showInstructList.value.filter((item) => item.group_id == state.activeOfficeChildName); return result ?? []; }); const instructQuery = debounce(queryInstruct); watch( - () => officeParams.value.template_title, + () => officeParams.value.sample_title, (val) => { instructQuery(); } ); //鐭ヨ瘑搴� const knowledgeParams = ref({ - template_title: '', + sample_title: '', }); const { query: queryKnowledge, queryData: showKnowledgeList } = useSearch(exampleList, knowledgeParams); const finalKnowledgeList = computed(() => { @@ -428,7 +394,7 @@ const knowledgeQuery = debounce(queryKnowledge); watch( - () => officeParams.value.template_title, + () => knowledgeParams.value.sample_title, (val) => { knowledgeQuery(); } @@ -461,10 +427,10 @@ Children: 'Children', ParentID: 'p_group_id', }); - state.customBusinessList = treeBusinessList; //涓氬姟鍦烘櫙鏁版嵁婧� - state.activeBusinessName = treeBusinessList[0].group_id; //榛樿閫変腑绗竴涓笟鍔″満鏅� - state.customBusinessChildList = treeBusinessList[0].Children; //榛樿閫変腑绗竴涓笟鍔″満鏅殑绗竴涓瓙鍦烘櫙鐨勬暟鎹簮 - state.activeBusinessChildName = treeBusinessList[0].Children[0].group_id; + state.customBusinessList = treeBusinessList ?? []; //涓氬姟鍦烘櫙鏁版嵁婧� + state.activeBusinessName = treeBusinessList[0]?.group_id; //榛樿閫変腑绗竴涓笟鍔″満鏅� + state.customBusinessChildList = treeBusinessList[0]?.Children; //榛樿閫変腑绗竴涓笟鍔″満鏅殑绗竴涓瓙鍦烘櫙鐨勬暟鎹簮 + state.activeBusinessChildName = treeBusinessList[0]?.Children[0]?.group_id; break; case '鍔炲叕鍔╂墜': const treeOfficeList = convertListToTree(officeList, { @@ -472,10 +438,10 @@ Children: 'Children', ParentID: 'p_group_id', }); - state.customOfficeList = treeOfficeList; //鍔炲叕鍔╂墜鏁版嵁婧� - state.activeOfficeName = treeOfficeList[0].group_id; //榛樿閫変腑绗竴涓姙鍏姪鎵� - state.customOfficeChildList = treeOfficeList[0].Children; //榛樿閫変腑绗竴涓姙鍏姪鎵嬬殑绗竴涓瓙鍦烘櫙鐨勬暟鎹簮 - state.activeOfficeChildName = treeOfficeList[0].Children[0].group_id; //榛樿閫変腑绗竴涓姙鍏姪鎵嬬殑绗竴涓瓙鍦烘櫙 + state.customOfficeList = treeOfficeList ?? []; //鍔炲叕鍔╂墜鏁版嵁婧� + state.activeOfficeName = treeOfficeList[0]?.group_id; //榛樿閫変腑绗竴涓姙鍏姪鎵� + state.customOfficeChildList = treeOfficeList[0]?.Children; //榛樿閫変腑绗竴涓姙鍏姪鎵嬬殑绗竴涓瓙鍦烘櫙鐨勬暟鎹簮 + state.activeOfficeChildName = treeOfficeList[0]?.Children[0]?.group_id; //榛樿閫変腑绗竴涓姙鍏姪鎵嬬殑绗竴涓瓙鍦烘櫙 break; case '鐭ヨ瘑搴�': const treeTagList = convertListToTree(selectTagList, { @@ -483,10 +449,10 @@ Children: 'Children', ParentID: 'p_group_id', }); - state.knowledgeBaseList = treeTagList; //鐭ヨ瘑搴撴暟鎹簮 - state.activeKnowledgeName = treeTagList[0].group_id; //榛樿閫変腑绗竴涓煡璇嗗簱 - state.customKnowledgeChildList = treeTagList[0].Children; //榛樿閫変腑绗竴涓煡璇嗗簱鐨勭涓�涓瓙鍦烘櫙鐨勬暟鎹簮 - state.activeKnowledgeChildName = treeTagList[0].Children[0].group_id; //榛樿閫変腑绗竴涓煡璇嗗簱鐨勭涓�涓瓙鍦烘櫙 + state.knowledgeBaseList = treeTagList ?? []; //鐭ヨ瘑搴撴暟鎹簮 + state.activeKnowledgeName = treeTagList[0]?.group_id; //榛樿閫変腑绗竴涓煡璇嗗簱 + state.customKnowledgeChildList = treeTagList[0]?.Children; //榛樿閫変腑绗竴涓煡璇嗗簱鐨勭涓�涓瓙鍦烘櫙鐨勬暟鎹簮 + state.activeKnowledgeChildName = treeTagList[0]?.Children[0]?.group_id; //榛樿閫変腑绗竴涓煡璇嗗簱鐨勭涓�涓瓙鍦烘櫙 break; } } else { @@ -510,9 +476,9 @@ () => activeGroupType.value, async (val) => { if (val == '鍔炲叕鍔╂墜') { - if (state.listInstructExpand) return; await getUserTemplate(); - state.listInstructExpand = true; + } else { + await getSelectListSample(); } tagListClick(sectionAList.value); }, diff --git a/src/layout/component/sidebar/components/MenuList.vue b/src/layout/component/sidebar/components/MenuList.vue index 8cd4165..aa1689e 100644 --- a/src/layout/component/sidebar/components/MenuList.vue +++ b/src/layout/component/sidebar/components/MenuList.vue @@ -75,9 +75,7 @@ <el-form-item prop="verifyCode" label="楠岃瘉鐮�"> <el-input v-model="state.loginPhoneForm.verifyCode" placeholder="璇疯緭鍏ュ洓浣嶉獙璇佺爜" maxlength="6" clearable> <template #append> - <el-button type="primary" @click="handleSendVerifyCode" :disabled="countdown > 0">{{ - countdown > 0 ? `${countdown}绉掑悗閲嶈瘯` : '鑾峰彇楠岃瘉鐮�' - }}</el-button> + <el-button type="primary" @click="handleSendVerifyCode" :disabled="hasSended">{{ sendCodeMsg }}</el-button> </template> </el-input> </el-form-item> @@ -106,7 +104,7 @@ const formPhoneRef = ref(); //鎵嬫満鍙风櫥褰� const isLoginStatus = ref(!!Local.get(accessSessionKey)); const userName = ref(''); -const countdown = ref(0); +const countdown = ref(null); const firstUserCharacter = computed(() => userName.value?.[0]?.toUpperCase()); watchEffect(() => { if (!isLoginStatus.value) return; @@ -162,10 +160,10 @@ verifyCode: [{ required: true, message: '璇疯緭鍏ラ獙璇佺爜', trigger: 'blur' }], }; const handleClick = (item) => { - if(!item.routerName) return; + if (!item.routerName) return; gotoRoute({ name: item.routerName }); }; -const LOGIN_CLIENT = 'Web 鐢ㄦ埛绔�'; +const LOGIN_CLIENT = 'Web绔�'; //鐧诲綍 const openLoginDlg = async () => { @@ -174,6 +172,12 @@ const handleClose = () => { state.isShowLogin = false; }; +const hasSended = computed(() => { + return countdown.value !== null; +}); +const sendCodeMsg = computed(() => { + return !hasSended.value ? '鑾峰彇楠岃瘉鐮�' : `${countdown.value} 绉掑悗閲嶈瘯`; +}); //鐧诲綍 const onSubmit = async () => { if (state.activeLoginName === 'accountUser') { @@ -184,7 +188,6 @@ user: state.loginForm.account, pass: state.loginForm.pwd, client: LOGIN_CLIENT, - }); if (!res.json_ok) { return ElMessage.error(res.json_msg); @@ -199,7 +202,6 @@ phone: state.loginPhoneForm.phoneUser, code: state.loginPhoneForm.verifyCode, client: LOGIN_CLIENT, - }); if (!res.json_ok) { return ElMessage.error(res.json_msg); diff --git a/src/stores/chatRoom.ts b/src/stores/chatRoom.ts index e457409..5e62f01 100644 --- a/src/stores/chatRoom.ts +++ b/src/stores/chatRoom.ts @@ -1,7 +1,6 @@ import { computed, ref } from 'vue'; -import { getSectionList, getUserTemplateList } from '../api/ai/chat'; +import { getSectionList, getSelectSample, getUserTemplateList } from '../api/ai/chat'; import type { ChatRoomItem } from '../layout/component/sidebar/components/types'; - /** * Room 鍏宠仈鐨勪竴浜涢厤缃� */ @@ -74,30 +73,39 @@ export const sceneGroupList = ref([]); // groupType 鍒楄〃 export const groupTypeList = computed(() => Array.from(new Set(sceneGroupList.value.map((item) => item.group_type)))); -// 鍔炲叕 鍒楄〃 +// 鍔炲叕/妯℃澘 鍒楄〃 +export const exampleSceneList = ref([]); export const officeList = ref([]); export const groupTypeMapIcon = { 鍔炲叕鍔╂墜: 'ywicon-bangong', 鐭ヨ瘑搴�: 'ywicon-changyonggongjuzhishisuoyin', 涓氬姟鍦烘櫙: 'ywicon-yewu', }; +//鑾峰彇鍦烘櫙閫夋嫨鍒楄〃 const getSceneGroupList = async () => { const res = await getSectionList(); sceneGroupList.value = res?.groups ?? []; }; -//鑾峰彇鍔炲叕鍒楄〃 -const getOfficeTemplateList = async () => { - const res = await getUserTemplateList(); - console.log('馃殌 ~ res:', res); - const array = []; - res.templates?.forEach((sample, index) => { - sample.Icon = '/static/images/wave/ChatImg.png'; - sample.BgColor = randomHexColor(); - if (index < 4) { - array.push(sample); - } - }); - officeList.value = array; +const getSelectListSample = async () => { + const res1 = getSelectSample({}); + const res2 = getUserTemplateList(); + const [sampleListPromise, templateListPromise] = await Promise.allSettled([res1, res2]); + const samples = (sampleListPromise as any).value?.samples ?? []; + const templateSamples = ((templateListPromise as any).value?.templates ?? []).map((item) => ({ + group_id: item.template_group, + sample_id: item.template_id, + sample_title: item.template_title, + sample_question: item.template_value, + + //#region ====================== template 鐗规湁瀛楁 ====================== + template_create_time: item.create_time, + template_type: item.template_type, + isTemplate: true, + //#endregion + })); + exampleSceneList.value = samples + .concat(templateSamples) + .map((item) => ({ ...item, Icon: '/static/images/wave/ChatImg.png', BgColor: randomHexColor() })); }; //闅忔満鐢熸垚棰滆壊 const randomHexColor = () => { @@ -110,7 +118,7 @@ */ export const getAllData = async () => { getSceneGroupList(); - getOfficeTemplateList(); + getSelectListSample(); }; //#endregion diff --git a/src/views/project/ch/home/Home.vue b/src/views/project/ch/home/Home.vue index cc2ad21..6db92df 100644 --- a/src/views/project/ch/home/Home.vue +++ b/src/views/project/ch/home/Home.vue @@ -38,7 +38,8 @@ import waterBottom from './component/waterRight/bottom.vue'; import waterCenter from './component/waterRight/center.vue'; import waterTop from './component/waterRight/top.vue'; -import { getSelectSample, getUserTemplateList } from '/@/api/ai/chat'; +import { exampleSceneList } from '/@/stores/chatRoom'; + import CustomDrawer from '/@/components/drawer/CustomDrawer.vue'; let state = reactive({ isShowAdvanceExample: false, @@ -58,23 +59,7 @@ }; //鑾峰彇妯$増鍒楄〃 const getSelectListSample = async () => { - const res1 = getSelectSample({}); - const res2 = getUserTemplateList(); - const [sampleListPromise, templateListPromise] = await Promise.allSettled([res1, res2]); - const samples = (sampleListPromise as any).value?.samples ?? []; - const templateSamples = ((templateListPromise as any).value?.templates ?? []).map((item) => ({ - group_id: item.template_group, - sample_id: item.template_id, - sample_title: item.template_title, - sample_question: item.template_value, - - //#region ====================== template 鐗规湁瀛楁 ====================== - template_create_time: item.create_time, - template_type: item.template_type, - isTemplate: true, - //#endregion - })); - exampleList.value = samples.concat(templateSamples).map((item) => ({ ...item, Icon: '/static/images/wave/ChatImg.png' })); + exampleList.value = exampleSceneList.value; }; const tagListClick = (tag) => { isFinishPromise?.then(() => { @@ -159,7 +144,6 @@ .homeBox { font-size: 14px; line-height: 18px; - overflow-y: auto; } .declare { position: absolute; diff --git a/src/views/project/ch/home/component/waterRight/bottom.vue b/src/views/project/ch/home/component/waterRight/bottom.vue index 57bcb97..52f1e79 100644 --- a/src/views/project/ch/home/component/waterRight/bottom.vue +++ b/src/views/project/ch/home/component/waterRight/bottom.vue @@ -4,14 +4,6 @@ <div class="flex item-center"> <span>搴旂敤鍦烘櫙</span> </div> - <!-- <div class="cursor-pointer"> - <el-button link class="changeBatch" @click="lookMore" - >鏌ョ湅鏇村 - <el-icon> - <ArrowRight /> - </el-icon> - </el-button> - </div> --> </div> <div class="main" v-show="state.applicationScenarios && state.applicationScenarios.length <= 3"> @@ -57,9 +49,8 @@ <script setup lang="ts"> import { computed, reactive, ref, watch } from 'vue'; -import { getSectionList } from '/@/api/ai/chat'; import router from '/@/router'; -import { activeGroupType, sectionAList, topGroupId } from '/@/stores/chatRoom'; +import { activeGroupType, sceneGroupList, sectionAList, topGroupId } from '/@/stores/chatRoom'; let state = reactive({ applicationScenarios: [], scenariosIds: [], @@ -106,16 +97,15 @@ return iconList.value[index % iconCount]; }; const getMainSectionList = async () => { - const res = await getSectionList(); let result = []; - res.groups.forEach((sectionItem, index) => { + await sceneGroupList.value.forEach((sectionItem, index) => { sectionItem.Icon = getIconByIndex(index); if (activeGroupType.value == sectionItem.group_type) { result.push(sectionItem); } }); state.applicationScenarios = result; - sectionAList.value = res.groups; + sectionAList.value = sceneGroupList.value; result?.[0] && changeScenarios(result[0]); }; const groupedArray = computed(() => { @@ -190,7 +180,7 @@ &_item { width: 50%; border-radius: 5px; - + height: 100px; padding: 18px 12px; -webkit-transition: background-color 0.1s ease-in-out; -o-transition: background-color 0.1s ease-in-out; diff --git a/src/views/project/ch/home/component/waterRight/center.vue b/src/views/project/ch/home/component/waterRight/center.vue index f24ab45..089f32c 100644 --- a/src/views/project/ch/home/component/waterRight/center.vue +++ b/src/views/project/ch/home/component/waterRight/center.vue @@ -36,14 +36,13 @@ </template> <script setup lang="ts"> -import { reactive, ref } from 'vue'; +import { reactive } from 'vue'; import { activeRoomId, activeSampleId, setRoomConfig } from '/@/stores/chatRoom'; let state = reactive({ exampleContent: [], isShowExample: false, m_groupArr: [], }); -const exampleList = ref([]); //妯$増鍒楄〃 const emits = defineEmits<{ (event: 'advanceExampleClick', data): void; (event: 'updateChatInput', val): void; @@ -90,14 +89,7 @@ }); }); state.exampleContent = result; - initGroupedArr(); -}; -//闅忔満鐢熸垚棰滆壊 -const randomHexColor = () => { - return `#${Math.floor(Math.random() * 16777215) - .toString(16) - .padEnd(6, '0')}`; }; defineExpose({ tagListClick, -- Gitblit v1.9.3