customer_list/common/static/fonts/ywiconfont/iconfont.css | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
customer_list/common/static/fonts/ywiconfont/iconfont.ttf | 补丁 | 查看 | 原始文档 | blame | 历史 | |
customer_list/common/static/fonts/ywiconfont/iconfont.woff | 补丁 | 查看 | 原始文档 | blame | 历史 | |
customer_list/common/static/fonts/ywiconfont/iconfont.woff2 | 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/components/chat/Chat.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/components/chat/components/playBar/PlayBar.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/stores/chatRoom.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/project/ch/home/component/waterRight/top.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
customer_list/common/static/fonts/ywiconfont/iconfont.css
@@ -1,8 +1,8 @@ @font-face { font-family: "ywifont"; /* Project id 4655417 */ src: url('iconfont.woff2?t=1729665723269') format('woff2'), url('iconfont.woff?t=1729665723269') format('woff'), url('iconfont.ttf?t=1729665723269') format('truetype'); src: url('iconfont.woff2?t=1730084434771') format('woff2'), url('iconfont.woff?t=1730084434771') format('woff'), url('iconfont.ttf?t=1730084434771') format('truetype'); } .ywifont { @@ -13,6 +13,30 @@ -moz-osx-font-smoothing: grayscale; } .ywicon-bangong:before { content: "\e683"; } .ywicon-yewu:before { content: "\e8a0"; } .ywicon-quanxian:before { content: "\e60c"; } .ywicon-mima:before { content: "\e608"; } .ywicon-shezhi:before { content: "\e7eb"; } .ywicon-xitongtongzhi1:before { content: "\e647"; } .ywicon-bingzhuangtu:before { content: "\e70e"; } customer_list/common/static/fonts/ywiconfont/iconfont.ttfBinary files differ
customer_list/common/static/fonts/ywiconfont/iconfont.woffBinary files differ
customer_list/common/static/fonts/ywiconfont/iconfont.woff2Binary files differ
src/components/chat/Chat.vue
@@ -1,7 +1,7 @@ <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" @@ -127,7 +127,7 @@ </div> </div> </div> <div v-if="showAskMore" class="ml-4 mt-5 text-sm"> <div v-if="showAskMore" class="ml-4 mt-5 text-sm pb-10"> <div class="text-gray-600 mb-5">你可以继续问我:</div> <div class="space-y-2 inline-flex flex-col"> <div @@ -143,7 +143,7 @@ </div> </div> <div class="sticky bottom-0 w-full p-6 pb-8 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" @@ -175,7 +175,7 @@ import PlayBar from '/@/components/chat/components/playBar/PlayBar.vue'; import CustomDrawer from '/@/components/drawer/CustomDrawer.vue'; import router from '/@/router'; import { activeChatRoom, activeLLMId, 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%'; @@ -187,6 +187,7 @@ }); const currentRoute = router.currentRoute; const currentRouteId = currentRoute.value.query.id as string; activeRoomId.value = currentRouteId; const chatListDom = ref<HTMLDivElement>(); const messageList = ref<ChatMessage[]>([]); const computedMessageList = computed(() => { @@ -294,12 +295,16 @@ process_id: processId.value, question: text, // FIXME: 暂时这样 section_a_id: currentSectionAId, // section_a_id: currentSectionAId, history_group_id: currentRouteId, raw_mode: roomConfig.value?.[currentRouteId]?.isAnswerByLLM ?? false, ...judgeParams, } as any; if(activeGroupType.value){ params.group_type = activeGroupType.value; } if (currentSampleId) { params.sample_id = currentSampleId; currentSampleId = ''; src/components/chat/components/playBar/PlayBar.vue
@@ -1,5 +1,35 @@ <template> <div class="playInput hl_input"> <div class="playInput hl_input rounded-b-[22px] input-border input-shadow" :class="{ 'rounded-t-[22px]': !currentGroupTypeIsShow }"> <!-- 应用场景 --> <div v-if="!currentGroupTypeIsShow" class="application-scenarios absolute bottom-[114%] left-4"> <div class="flex-items-center space-x-2"> <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-[#c5e0ff] hover:text-[#1c86ff]" v-for="item in groupTypeList" @click="groupTypeClick(item)" > <span :class="['ywifont', groupTypeMapIcon[item]]"></span> <div class="">{{ item }}</div> </div> </div> </div> <!-- 当前应用场景 --> <div v-else 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> <div class="assembly flex"> <el-button title="插件菜单" class="label flex items-center cursor-pointer" link> <img src="/static/images/wave/PlugIn.png" class="set-icon box-border" /> @@ -9,7 +39,6 @@ <div class="set-input"> <!-- @input="inputText" --> <el-input ref="inputRef" class="relative align-bottom set-inputAnswer" @@ -41,11 +70,7 @@ <span class="text-sm text-gray-500 pr-1.5">{{ index + 1 }}</span> <template v-if="sentenceSplitMap?.[item.question]"> <template v-for="part in sentenceSplitMap[item.question]"> <span v-if="part.isKeyword" class="text-blue-400 font-bold cursor-pointer" >{{ part.partStr }}</span > <span v-if="part.isKeyword" class="text-blue-400 font-bold cursor-pointer">{{ part.partStr }}</span> <span v-else>{{ part.partStr }}</span> </template> </template> @@ -57,11 +82,11 @@ <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> --> <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> --> <img src="/static/images/wave/HeadImg.png" class="set-img-icon box-border" /> </el-button> --> <el-button title="发送" :disabled="isTalking" class="cursor-pointer" link @click="emits('sendClick')"> <div class="send"> @@ -85,13 +110,14 @@ import type { InputInstance } from 'element-plus'; import { ElMessage } from 'element-plus'; import getCaretCoordinates from 'textarea-caret'; import { computed, nextTick, ref } from 'vue'; import { computed, nextTick, ref, triggerRef } from 'vue'; import InfoDetail from './InfoDetail.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', { @@ -217,7 +243,7 @@ */ const getSentenceMatchMap = (sentences: string[], keywords: any[]) => { if (!sentences || sentences.length === 0) return null; if (!keywords || keywords.length===0) { if (!keywords || keywords.length === 0) { return sentences.map((item) => ({ partStr: item, startIndex: 0, @@ -375,6 +401,21 @@ infoDetailIsShow.value = true; }; //#endregion //#region ====================== 当前应用场景 ====================== const currentGroupTypeIsShow = computed(() => !!activeGroupType.value); const groupTypeClick = (item) => { activeGroupType.value = item; inputRef.value.focus(); }; // 关闭当前 groupType 面板 const closeCurrentGroupType = () => { activeGroupType.value = null; }; //#endregion </script> <style scoped lang="scss"> .set-waterTitle { @@ -426,6 +467,21 @@ 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; @@ -438,15 +494,7 @@ align-items: flex-end; -webkit-box-sizing: border-box; box-sizing: border-box; border-radius: 22px; border: 1px solid #00000030; -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; -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; background-color: #fff; .assembly { position: relative; src/main.ts
@@ -12,6 +12,7 @@ import { initBackEndControlRoutes } from './router/backEnd'; import '/@/theme/index.scss'; import '@amap/amap-jsapi-types'; import { getAllData } from './stores/chatRoom'; const app = createApp(App); for (const [key, component] of Object.entries(ElementPlusIconsVue)) { @@ -24,3 +25,6 @@ await initBackEndControlRoutes(); app.use(pinia).use(router).use(ElementPlus).use(i18n).use(VueGridLayout).mount('#app'); })(); // 获取全局数据 getAllData(); src/stores/chatRoom.ts
@@ -1,17 +1,24 @@ import { computed, ref } from 'vue'; import type { ChatRoomItem } from '../layout/component/sidebar/components/types'; import { getSectionList } from '../api/ai/chat'; /** * Room 关联的一些配置 */ export type RoomConfig = { /** 是否直接调用大模型(通义千问)回答 */ isAnswerByLLM: boolean; /** @description 从首页进去获取的第一个回复,回调函数 */ firstResCb: any; /** @description 当前聊天室的 group_type */ activeGroupType: string; }; export type RoomConfigKey = keyof RoomConfig; export const roomConfig = ref<Record<string, RoomConfig>>(null); export const setRoomConfig = <T extends RoomConfigKey>(roomId: string, key: T, value: RoomConfig[T]) => { if (!roomId) return; if (!roomConfig.value) { roomConfig.value = {}; } @@ -25,6 +32,7 @@ }; export const getRoomConfig = <T extends RoomConfigKey>(roomId: string, key: T) => { if (!roomId) return; if (!roomConfig.value) { return null; } @@ -43,9 +51,39 @@ export const activeSectionAId = ref(null); export const activeLLMId = ref(null); /** @description 当前聊天室 groupType */ export const activeGroupType = computed({ get: () => { const result = getRoomConfig(activeRoomId.value, 'activeGroupType'); return result; }, set: (value) => { setRoomConfig(activeRoomId.value, 'activeGroupType', value); }, }); /** * 全局使用的 ref */ export const sectionAList = ref([]); export const sectionAList = ref([]); //#region ====================== 全局使用数据 ====================== // group 列表 export const sceneGroupList = ref([]); // groupType 列表 export const groupTypeList = computed(() => Array.from(new Set(sceneGroupList.value.map((item) => item.group_type)))); export const groupTypeMapIcon = { 办公助手: 'ywicon-bangong', 知识库: 'ywicon-changyonggongjuzhishisuoyin', 业务场景: 'ywicon-yewu', }; /** * 获取全局所有数据 */ export const getAllData = async () => { const res = await getSectionList(); sceneGroupList.value = res?.groups ?? []; }; //#endregion src/views/project/ch/home/component/waterRight/top.vue
@@ -153,77 +153,6 @@ border-color: #1c86ff; color: #fff; } .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; border-radius: 22px; border: 1px solid #00000030; -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; -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; 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 { min-height: 36px; height: 36px; padding: 3px 0; line-height: 20px; border: none; background-color: transparent; color: #333; font-size: 15px; } :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; } } } } } </style> <style lang="scss"> .my-pop {