config/vite.config.dev.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/assets/images/icon-picture.png | 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/sessionManager/components/agentSession.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/sessionManager/components/chatMenu.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/sessionManager/components/smartAi.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/sessionManager/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
config/vite.config.dev.ts
@@ -14,8 +14,8 @@ proxy: { '/base': { // target: 'http://aiotlink.com:8189', //target: 'http://192.168.20.116:8089', target: 'http://192.168.20.158:8089', target: 'http://192.168.20.116:8089', // target: 'http://192.168.20.158:8089', changeOrigin: true, ws: true, // rewrite: (path) => path.replace(new RegExp(`^/basic-api`), ''), @@ -24,16 +24,16 @@ }, '/api': { // target: 'http://aiotlink.com:8189', //target: 'http://192.168.20.116:8089', target: 'http://192.168.20.158:8089', target: 'http://192.168.20.116:8089', // target: 'http://192.168.20.158:8089', changeOrigin: true, ws: true, // rewrite: (path) => path.replace(new RegExp(`^/basic-api`), ''), }, '/api/v1': { // target: 'http://aiotlink.com:8189', //target: 'http://192.168.20.116:8089', target: 'http://192.168.20.158:8089', target: 'http://192.168.20.116:8089', // target: 'http://192.168.20.158:8089', changeOrigin: true, ws: true, // rewrite: (path) => path.replace(new RegExp(`^/basic-api`), ''), src/assets/images/icon-picture.png
src/views/sessionManager/components/agentSession.vue
@@ -3,19 +3,18 @@ <div class="header___lEPyH"> <div class="chatHeader"> <div class="chatHeaderBox"> <!-- <span class="title">{{agentTitle}}</span>--> <a-popover position="bottom" trigger="click" > <a-button border > <span style=" width: 100px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; ">{{ from.name }}</span> <!-- <span class="title">{{agentTitle}}</span>--> <a-popover position="bottom" trigger="click"> <a-button border> <span style=" width: 100px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; " >{{ from.name }}</span > <icon-down style="margin-left: 4px" /> </a-button> <template #content> @@ -41,13 +40,13 @@ id="agentHome" class="chat-list" style=" width: 80%; overflow: auto; height: calc(100vh - 380px); margin: 0px auto 20px; " width: 80%; overflow: auto; height: calc(100vh - 380px); margin: 0px auto 20px; " > <div class="chat-item" v-for="(sessionDetail,index) in sessionDetailList"> <div class="chat-item" v-for="(sessionDetail, index) in sessionDetailList"> <a-comment v-if="sessionDetail.role === 'user'"> <template #avatar> <img @@ -58,7 +57,7 @@ </template> <template #content> <div :class="{ chartUserText: theme === 'light' }" >{{ sessionDetail.content }} >{{ sessionDetail.content }} </div> </template> </a-comment> @@ -66,33 +65,43 @@ <template #avatar> <img class="icon-user-jpg" src="../../../assets/images/icon-chart.png" src="../../../assets/images/icon-picture.png" alt="本地图片" /> </template> <template #content> <!-- <a-card :class="{ chatItemAnswer: theme === 'light' }">--> <!-- <div :class="{ light: theme === 'light' }"--> <!-- >{{ sessionDetail.content }}--> <!-- </div>--> <!-- </a-card>--> <!-- <a-card :class="{ chatItemAnswer: theme === 'light' }">--> <!-- <div :class="{ light: theme === 'light' }"--> <!-- >{{ sessionDetail.content }}--> <!-- </div>--> <!-- </a-card>--> <a-textarea readonly auto-size v-model="sessionDetail.content" :class="{ chatItemAnswer: theme === 'light' }" :style="{ backgroundColor: theme === 'light' ? '#ffffff' : '#000000'}" :style="{ backgroundColor: theme === 'light' ? '#ffffff' : '#000000', }" style="border: none" > </a-textarea> </template> <template #actions> <span class="action" v-if="index != 0" @click="copy(sessionDetail.content)"> <icon-copy /> 复制 </span> <span class="action" v-if="index != 0 && index == sessionDetailList.length - 1" @click="reGenerate()"> <icon-refresh /> 重新生成 </span> <span class="action" v-if="index != 0" @click="copy(sessionDetail.content)" > <icon-copy /> 复制 </span> <span class="action" v-if="index != 0 && index == sessionDetailList.length - 1" @click="reGenerate()" > <icon-refresh /> 重新生成 </span> </template> </a-comment> <a-comment v-else-if="sessionDetail.role === 'last'"> @@ -109,15 +118,23 @@ auto-size v-model="displayedText" :class="{ chatItemAnswer: theme === 'light' }" :style="{backgroundColor: theme === 'light' ? '#ffffff' : '#000000'}" :style="{ backgroundColor: theme === 'light' ? '#ffffff' : '#000000', }" style="border: none" > </a-textarea> </template> <template #actions> <div class="action" @click="stopChat" style="background: var(--color-bg-2);color: var(--color-primary-light-4);" v-if="displayedText != ''"> <div class="action" @click="stopChat" style=" background: var(--color-bg-2); color: var(--color-primary-light-4); " v-if="displayedText != ''" > <icon-record-stop /> 停止生成 </div> @@ -140,14 +157,14 @@ show-word-limit :disabled="chatDis" :class="{ textItemAnswer: theme === 'dark' }" :style="{backgroundColor: theme === 'light' ? '#ffffff' : '#000000'}" :style="{ backgroundColor: theme === 'light' ? '#ffffff' : '#000000' }" style="border: none" :auto-size="{ minRows: 12, maxRows: 5, }" minRows: 12, maxRows: 5, }" /> <div style="width: 100%;display: flex;justify-content: space-between"> <div style="width: 100%; display: flex; justify-content: space-between"> <span></span> <a-button :disabled="chatDis" @@ -156,33 +173,44 @@ style="border-radius: 24px" :loading="loading" > <icon-send size="32" style="color: #0960bd;"/> </a-button > <icon-send size="32" style="color: #0960bd" /> </a-button> </div> <!-- <div class="btn-send">--> <!-- <!– <icon-send size="32" /> –>--> <!-- <a-button--> <!-- :disabled="chatDis"--> <!-- @click="sentClick"--> <!-- type="text"--> <!-- style="border-radius: 24px"--> <!-- :loading="loading"--> <!-- >--> <!-- <icon-send size="32" style="color: #0960bd;"/>--> <!-- </a-button--> <!-- >--> <!-- </div>--> <!-- <div class="btn-send">--> <!-- <!– <icon-send size="32" /> –>--> <!-- <a-button--> <!-- :disabled="chatDis"--> <!-- @click="sentClick"--> <!-- type="text"--> <!-- style="border-radius: 24px"--> <!-- :loading="loading"--> <!-- >--> <!-- <icon-send size="32" style="color: #0960bd;"/>--> <!-- </a-button--> <!-- >--> <!-- </div>--> </div> <a-modal v-model:visible="visible" title="修改名称" @before-open="handleOpened" @cancel="handleCancel" :footer="false" title-align="start"> <a-form ref="formRef" :rules="rules" :model="from" @submit="handleSubmit" > <a-modal v-model:visible="visible" title="修改名称" @before-open="handleOpened" @cancel="handleCancel" :footer="false" title-align="start" > <a-form ref="formRef" :rules="rules" :model="from" @submit="handleSubmit"> <a-form-item field="name" label="名称"> <a-input v-model="from.name" placeholder="请输入名称"/> <a-input v-model="from.name" placeholder="请输入名称" /> </a-form-item> <a-form-item> <div style="width: 100%;text-align: right"> <div style="width: 100%; text-align: right"> <a-button @click="visible = false">取消</a-button> <a-button style="margin-left: 10px" type="primary" html-type="submit">确定</a-button> <a-button style="margin-left: 10px" type="primary" html-type="submit" >确定</a-button > </div> </a-form-item> </a-form> @@ -191,606 +219,610 @@ </template> <script setup lang="ts"> import { defineProps, ref, watch, defineEmits, onMounted, reactive, computed, nextTick, onBeforeUnmount } from "vue"; import { Message } from '@arco-design/web-vue'; import { useAppStore } from "@/store"; import { getAuthorization } from "@/utils/auth"; import { EventSourceParserStream } from 'eventsource-parser/stream'; import { agentResetApi, agentSetApi, getAgentSessionDetailsApi } from "@/api/agentSession"; import EventBus from '@/utils/EventBus'; import useClipboard from "vue-clipboard3"; import { addSessionApi, getSessionDetailsApi } from "@/api/session"; const props = defineProps({ modalObj: Object, }); // const emit = defineEmits(['addSession']); const sessionDetailList = ref([]); //根据会话id出来的会话详情 const sessionList = ref([]); //会话列表 const modalObj = reactive({ }); const dialogId = ref(''); const chatDis = ref(false); const loading = ref(false); const agentTitle = ref("未命名会话"); const currIndex = ref(0); const displayedText = ref(''); // 正在显示的文字 let timer: number | null = null; const streamStr = ref(''); const inputMsg = ref(''); const activeSessionId = ref(''); const conversation_id = ref(''); const fieldNames = { value: 'id', label: 'name' }; const agentObj = reactive({}); const agentList = ref([]); const selectValue = ref(''); const sectionList = ref({}); let chatObj = reactive({}); const isStopChat = ref(false) const appStore = useAppStore(); const theme = computed(() => { return appStore.theme; }); let from = reactive({ name:'未命名会话', }); const visible = ref(false); let isHistory = ref(false);//是否是历史记录 let dsl = reactive({}); const chatDataMeg = reactive({}); const rules = { name: [ { required: true, message:'名称不允许为空', }, ], } const handleSubmit = async({values, errors}) => { if(errors) return; console.log(agentObj, 'agentObj'); let chatData = { id:conversation_id.value, conversation_id:conversation_id.value, name: from.name } const { code, data } = await addSessionApi(chatData); if (data) { Message.success("修改成功"); handleCancel() } } const handleClick = () => { visible.value = true; }; const handleCancel = () => { visible.value = false; } const handleOpened =(el) => { // Object.assign(form,{ // name: '',// 用户名 // }); // formRef.value.resetFields(); } // 初始化页面 const initPage = async () => { agentSet(); }; const createNewAgent = async (session) => { console.log(session,'新建agent会话对象'); Object.assign(agentObj, session); isHistory.value = false; initPage(); } // 调用set方法 const agentSet = async () => { const res = await agentSetApi({ id: agentObj.id, title: agentObj.title, dsl: agentObj.dsl, import { defineProps, ref, watch, defineEmits, onMounted, reactive, computed, nextTick, onBeforeUnmount, } from 'vue'; import { Message } from '@arco-design/web-vue'; import { useAppStore } from '@/store'; import { getAuthorization } from '@/utils/auth'; import { EventSourceParserStream } from 'eventsource-parser/stream'; import { agentResetApi, agentSetApi, getAgentSessionDetailsApi, } from '@/api/agentSession'; import EventBus from '@/utils/EventBus'; import useClipboard from 'vue-clipboard3'; import { addSessionApi, getSessionDetailsApi } from '@/api/session'; const props = defineProps({ modalObj: Object, }); // console.log(res,'agentSet'); if (res.code == 0) { conversation_id.value = res.data.conversation_id; agentReset(); } } // 调用reset方法 const agentReset = async () => { const res = await agentResetApi({ id: agentObj.id, // const emit = defineEmits(['addSession']); const sessionDetailList = ref([]); //根据会话id出来的会话详情 const sessionList = ref([]); //会话列表 const modalObj = reactive({}); const dialogId = ref(''); const chatDis = ref(false); const loading = ref(false); const agentTitle = ref('未命名会话'); const currIndex = ref(0); const displayedText = ref(''); // 正在显示的文字 let timer: number | null = null; const streamStr = ref(''); const inputMsg = ref(''); const activeSessionId = ref(''); const conversation_id = ref(''); const fieldNames = { value: 'id', label: 'name' }; const agentObj = reactive({}); const agentList = ref([]); const selectValue = ref(''); const sectionList = ref({}); let chatObj = reactive({}); const isStopChat = ref(false); const appStore = useAppStore(); const theme = computed(() => { return appStore.theme; }); if (res.code == 0) { // Message.success('修改成功'); agentCompletion(); } } // 调用completion方法 const agentCompletion = async () => { const response = await fetch( '/api/v1/canvas/completion', { let from = reactive({ name: '未命名会话', }); const visible = ref(false); let isHistory = ref(false); //是否是历史记录 let dsl = reactive({}); const chatDataMeg = reactive({}); const rules = { name: [ { required: true, message: '名称不允许为空', }, ], }; const handleSubmit = async ({ values, errors }) => { if (errors) return; console.log(agentObj, 'agentObj'); let chatData = { id: conversation_id.value, conversation_id: conversation_id.value, name: from.name, }; const { code, data } = await addSessionApi(chatData); if (data) { Message.success('修改成功'); handleCancel(); } }; const handleClick = () => { visible.value = true; }; const handleCancel = () => { visible.value = false; }; const handleOpened = (el) => { // Object.assign(form,{ // name: '',// 用户名 // }); // formRef.value.resetFields(); }; // 初始化页面 const initPage = async () => { agentSet(); }; const createNewAgent = async (session) => { console.log(session, '新建agent会话对象'); Object.assign(agentObj, session); isHistory.value = false; initPage(); }; // 调用set方法 const agentSet = async () => { const res = await agentSetApi({ id: agentObj.id, title: agentObj.title, dsl: agentObj.dsl, }); // console.log(res,'agentSet'); if (res.code == 0) { conversation_id.value = res.data.conversation_id; agentReset(); } }; // 调用reset方法 const agentReset = async () => { const res = await agentResetApi({ id: agentObj.id, }); if (res.code == 0) { // Message.success('修改成功'); agentCompletion(); } }; // 调用completion方法 const agentCompletion = async () => { const response = await fetch('/api/v1/canvas/completion', { method: 'POST', headers: { 'Authorization': getAuthorization(), 'Content-Type': 'application/json', }, body: JSON.stringify({ id: agentObj.id id: agentObj.id, }), } ); }); const reader = response?.body ?.pipeThrough(new TextDecoderStream()) .pipeThrough(new EventSourceParserStream()) .getReader(); currIndex.value = 0; while (true) { const x = await reader?.read(); if (x) { const { done, value } = x; console.log(x, 999); try { const val = JSON.parse(value?.data || ''); const d = val?.data; if (typeof d !== 'boolean') { console.info('data:', d); streamStr.value = d.content; startDisplayStr(); const reader = response?.body ?.pipeThrough(new TextDecoderStream()) .pipeThrough(new EventSourceParserStream()) .getReader(); currIndex.value = 0; while (true) { const x = await reader?.read(); if (x) { const { done, value } = x; console.log(x, 999); try { const val = JSON.parse(value?.data || ''); const d = val?.data; if (typeof d !== 'boolean') { console.info('data:', d); streamStr.value = d.content; startDisplayStr(); } } catch (e) { console.warn(e); } } catch (e) { console.warn(e); } if (done) { console.info('done'); displayedText.value = ''; queryAgentSessionDetail(agentObj.id); break; if (done) { console.info('done'); displayedText.value = ''; queryAgentSessionDetail(agentObj.id); break; } } } } chatDis.value = false; loading.value = false; inputMsg.value = ''; } // 调用get方法 const queryAgentSessionDetail = async (id) => { const { code, data } = await getAgentSessionDetailsApi(id); if (code == 0) { console.log(data,'agent会话详情'); Object.assign(chatObj, data); sessionDetailList.value = data.dsl.messages; agentTitle.value = `${data.title}` || '未命名会话'; from.name = `${data.title}` || '未命名会话'; refreshScroll(); //刷新滚动条位置 } }; // 历史记录跳转获取agent会话详情 const querySessionDetail = async (session) => { conversation_id.value = session.id; from.name = session.name; const { code, data } = await getSessionDetailsApi(session.id); if (code == 200) { sessionDetailList.value = data.message.messages; const res = await getAgentSessionDetailsApi(session.dialog_id); if (res.code == 0) { console.log(res.data,'agent会话详情'); Object.assign(agentObj, res.data); Object.assign(chatObj, res.data); Object.assign(dsl, res.data.dsl); chatDis.value = false; loading.value = false; inputMsg.value = ''; }; // 调用get方法 const queryAgentSessionDetail = async (id) => { const { code, data } = await getAgentSessionDetailsApi(id); if (code == 0) { console.log(data, 'agent会话详情'); Object.assign(chatObj, data); sessionDetailList.value = data.dsl.messages; agentTitle.value = `${data.title}` || '未命名会话'; from.name = `${data.title}` || '未命名会话'; refreshScroll(); //刷新滚动条位置 } } }; }; const { toClipboard } = useClipboard(); const copy = async (text) => { await toClipboard(text); //参数为要复制的文本 } const sentClick = () => { sendMessage('click'); }; // 重新生成 const reGenerate = () => { let inputContent = sessionDetailList.value[sessionDetailList.value.length-2].content startChat(inputContent) }; const sendMessage = async (event) => { if (event.keyCode == 13 || event === 'click') { if (!event.shiftKey) { //只有enter没有shift,或进行你的其他逻辑 if (event !== 'click') { event.preventDefault(); // 阻止默认行为,即不换行 } // chatDis.value = true; // loading.value = true; // if (!agentObj.id) { // Message.warning('请选择会话'); // chatDis.value = false; // loading.value = false; // return; // } // if (displayedText.value) { // querySessionList(); // } if (inputMsg.value) { startChat(inputMsg.value) inputMsg.value = ''; } else { Message.warning('消息不能为空'); chatDis.value = false; loading.value = false; // 历史记录跳转获取agent会话详情 const querySessionDetail = async (session) => { conversation_id.value = session.id; from.name = session.name; const { code, data } = await getSessionDetailsApi(session.id); if (code == 200) { sessionDetailList.value = data.message.messages; const res = await getAgentSessionDetailsApi(session.dialog_id); if (res.code == 0) { console.log(res.data, 'agent会话详情'); Object.assign(agentObj, res.data); Object.assign(chatObj, res.data); Object.assign(dsl, res.data.dsl); refreshScroll(); //刷新滚动条位置 } } } }; }; const { toClipboard } = useClipboard(); const copy = async (text) => { await toClipboard(text); //参数为要复制的文本 }; const startChat = async(valMsg)=>{ sessionDetailList.value.push({ content: valMsg, role: 'user', }); sessionDetailList.value.push({ role: 'last' }); refreshScroll(); let chatStr = { id: agentObj.id, message: valMsg, } if(isHistory.value){ chatStr.dsl = dsl; } const response = await fetch( '/api/v1/canvas/completion', { const sentClick = () => { sendMessage('click'); }; // 重新生成 const reGenerate = () => { let inputContent = sessionDetailList.value[sessionDetailList.value.length - 2].content; startChat(inputContent); }; const sendMessage = async (event) => { if (event.keyCode == 13 || event === 'click') { if (!event.shiftKey) { //只有enter没有shift,或进行你的其他逻辑 if (event !== 'click') { event.preventDefault(); // 阻止默认行为,即不换行 } // chatDis.value = true; // loading.value = true; // if (!agentObj.id) { // Message.warning('请选择会话'); // chatDis.value = false; // loading.value = false; // return; // } // if (displayedText.value) { // querySessionList(); // } if (inputMsg.value) { startChat(inputMsg.value); inputMsg.value = ''; } else { Message.warning('消息不能为空'); chatDis.value = false; loading.value = false; } } } }; const startChat = async (valMsg) => { sessionDetailList.value.push({ content: valMsg, role: 'user', }); sessionDetailList.value.push({ role: 'last' }); refreshScroll(); let chatStr = { id: agentObj.id, message: valMsg, }; if (isHistory.value) { chatStr.dsl = dsl; } const response = await fetch('/api/v1/canvas/completion', { method: 'POST', headers: { 'Authorization': getAuthorization(), 'Content-Type': 'application/json', }, body: JSON.stringify(chatStr), }); const reader = response?.body ?.pipeThrough(new TextDecoderStream()) .pipeThrough(new EventSourceParserStream()) .getReader(); currIndex.value = 0; while (true) { const x = await reader?.read(); if (x) { const { done, value } = x; // console.log(x, 999); try { const val = JSON.parse(value?.data || ''); const d = val?.data; if (typeof d !== 'boolean') { console.info('data:', d); streamStr.value = d.content; startDisplayStr(); } } catch (e) { console.warn(e); } if (done) { console.info('done'); displayedText.value = ''; if (isStopChat.value) { isStopChat.value = false; setChatDataMeg(chatDataMeg); } else { queryAgentSessionDetail(agentObj.id); EventBus.emit('queryAppUsageList'); } break; } } } chatDis.value = false; loading.value = false; }; const stopChat = async () => { // const { code, data } = await stopChatApi(agentObj.id); // if (code === 200) { // Message.success("已停止"); // } loading.value = false; chatDis.value = false; isStopChat.value = true; console.log('stopChat'); console.log(displayedText.value, 'displayedText'); console.log(sessionDetailList.value, 'sessionDetailList'); let inputText = sessionDetailList.value[sessionDetailList.value.length - 2].content; // 数组合并 let lastArr = [ { content: inputText, role: 'user', }, { content: displayedText.value, role: 'assistant', }, ]; sessionDetailList.value = sessionDetailList.value .splice(0, sessionDetailList.value.length - 2) .concat(lastArr); console.log(sessionDetailList.value, 'sessionDetailList2'); console.log(chatObj, 'chatObj对象'); chatObj.dsl.messages = chatObj.dsl.messages.concat(lastArr); Object.assign(chatDataMeg, { id: chatObj.id, conversation_id: chatObj.id, message: sessionDetailList.value, }); }; const setChatDataMeg = async (chatData) => { const { code, data } = await addSessionApi(chatData); if (data) { //停止定时器 clearTimeout(timer!); timer = null; // displayedText.value = ""; queryAgentSessionDetail(chatObj.id); } }; const handleShiftEnter = (event) => { event.preventDefault(); inputMsg.value += '\n'; }; //文字动态输出 const startDisplayStr = () => { if (timer) { clearTimeout(timer!); } const res = streamStr.value; // 将数组中的字符串拼接起来 if (currIndex.value < res.length) { displayedText.value += res[currIndex.value]; currIndex.value++; setTimeout(startDisplayStr, 100); refreshScroll(); } else { clearTimeout(timer!); timer = null; } }; const scrollbar = ref(null); const refreshScroll = () => { nextTick(() => { const container = document.getElementById('agentHome'); scrollbar.value.scrollTop(container.scrollHeight); }); }; onMounted(() => { EventBus.on('createAgent', (data) => { createNewAgent(data); }); EventBus.on('queryAgentSessionDetail', (data) => { isHistory.value = true; querySessionDetail(data); }); }); onBeforeUnmount(() => { EventBus.off('createAgent'); EventBus.off('queryAgentSessionDetail'); }); watch( () => props.modalObj, (newVal, oldVal) => { // Object.assign(agentObj, newVal); //调用agent初始化方法 if (JSON.stringify(newVal) != '{}') { // initPage(); } }, { immediate: true, deep: true, } ); const reader = response?.body ?.pipeThrough(new TextDecoderStream()) .pipeThrough(new EventSourceParserStream()) .getReader(); currIndex.value = 0; while (true) { const x = await reader?.read(); if (x) { const { done, value } = x; // console.log(x, 999); try { const val = JSON.parse(value?.data || ''); const d = val?.data; if (typeof d !== 'boolean') { console.info('data:', d); streamStr.value = d.content; startDisplayStr(); } } catch (e) { console.warn(e); } if (done) { console.info('done'); displayedText.value = ''; if (isStopChat.value) { isStopChat.value = false; setChatDataMeg(chatDataMeg); } else { queryAgentSessionDetail(agentObj.id); EventBus.emit('queryAppUsageList'); } break; } } } chatDis.value = false; loading.value = false; } const stopChat=async()=>{ // const { code, data } = await stopChatApi(agentObj.id); // if (code === 200) { // Message.success("已停止"); // } loading.value = false; chatDis.value = false; isStopChat.value = true; console.log('stopChat'); console.log(displayedText.value, 'displayedText'); console.log(sessionDetailList.value, 'sessionDetailList'); let inputText = sessionDetailList.value[sessionDetailList.value.length-2].content // 数组合并 let lastArr = [{ content: inputText, role: "user" },{ content: displayedText.value, role: "assistant" }] sessionDetailList.value = sessionDetailList.value.splice(0, sessionDetailList.value.length-2).concat(lastArr); console.log(sessionDetailList.value, 'sessionDetailList2'); console.log(chatObj, 'chatObj对象'); chatObj.dsl.messages = chatObj.dsl.messages.concat(lastArr); Object.assign(chatDataMeg, { id: chatObj.id, conversation_id: chatObj.id, message: sessionDetailList.value, }); } const setChatDataMeg = async (chatData) => { const { code, data } = await addSessionApi(chatData); if (data) { //停止定时器 clearTimeout(timer!); timer = null; // displayedText.value = ""; queryAgentSessionDetail(chatObj.id); } }; const handleShiftEnter = (event) => { event.preventDefault(); inputMsg.value += '\n'; }; //文字动态输出 const startDisplayStr = () => { if (timer) { clearTimeout(timer!); } const res = streamStr.value; // 将数组中的字符串拼接起来 if (currIndex.value < res.length) { displayedText.value += res[currIndex.value]; currIndex.value++; setTimeout(startDisplayStr, 100); refreshScroll(); } else { clearTimeout(timer!); timer = null; } }; const scrollbar = ref(null); const refreshScroll = () => { nextTick(() => { const container = document.getElementById('agentHome'); scrollbar.value.scrollTop(container.scrollHeight); }); }; onMounted(() => { EventBus.on('createAgent', (data) => { createNewAgent(data); }); EventBus.on('queryAgentSessionDetail', (data) => { isHistory.value = true; querySessionDetail(data); }); }); onBeforeUnmount(() => { EventBus.off('createAgent'); EventBus.off('queryAgentSessionDetail'); }); watch( () => props.modalObj, (newVal, oldVal) => { // Object.assign(agentObj, newVal); //调用agent初始化方法 if(JSON.stringify(newVal) != '{}'){ // initPage(); } },{ immediate: true, deep: true } ); </script> <style scoped lang="scss"> .dark { color: gray !important; } .dark { color: gray !important; } .container { .chatItemAnswer { box-sizing: border-box; background: #f1f1f1; border-radius: 14px; .light { .container { .chatItemAnswer { box-sizing: border-box; background: #f1f1f1; border-radius: 14px; } } .textItemAnswer { background-color: #373739; } .center { box-sizing: border-box; height: calc(100vh - 200px); position: relative; .center-title { line-height: 60px; font-size: 25px; font-family: 黑体; color: deepskyblue; } .center-content { font-size: 14px; color: gray; } .center-question { margin-top: 20px; display: flex; justify-content: space-between; .center-question-left { margin-top: 5px; margin-left: 20px; } .center-question-right { margin-right: 20px; .light { box-sizing: border-box; background: #f1f1f1; border-radius: 14px; } } .center-list { margin-top: 10px; .textItemAnswer { background-color: #373739; } .item { border-radius: 10px; margin-top: 10px; padding: 10px; min-height: 120px; background-color: #e9f3ff; .item-content { color: #666; } .item-title { text-align: center; line-height: 40px; font-size: 20px; font-family: 黑体; color: #333; } .center { box-sizing: border-box; height: calc(100vh - 200px); position: relative; .center-title { line-height: 60px; font-size: 25px; font-family: 黑体; color: deepskyblue; } } .chartStart { color: #4955f5; cursor: pointer; font-family: PingFangSC-Medium; font-size: 12px; font-weight: 500; } .chat_bottom { display: flex; align-items: center; width: 78%; margin: 0 auto; .center-bottom { // position: absolute; // width: 90%; // bottom: 20px; // left: 5%; background: #fff; border: 1px solid #00000014; border-radius: 24px; .center-content { font-size: 14px; color: gray; } .center-question { margin-top: 20px; display: flex; flex: 1 1; flex-direction: column; overflow: hidden; position: relative; // padding-top:10px; :deep(.arco-textarea-wrapper) { justify-content: space-between; .center-question-left { margin-top: 5px; margin-left: 20px; } .center-question-right { margin-right: 20px; } } .center-list { margin-top: 10px; .item { border-radius: 10px; margin-top: 10px; padding: 10px; min-height: 120px; background-color: #e9f3ff; .item-content { color: #666; } .item-title { text-align: center; line-height: 40px; font-size: 20px; font-family: 黑体; color: #333; } } } .chartStart { color: #4955f5; cursor: pointer; font-family: PingFangSC-Medium; font-size: 12px; font-weight: 500; } .chat_bottom { display: flex; align-items: center; width: 78%; margin: 0 auto; .center-bottom { // position: absolute; // width: 90%; // bottom: 20px; // left: 5%; background: #fff; border: 1px solid #00000014; border-radius: 24px; } display: flex; flex: 1 1; flex-direction: column; overflow: hidden; position: relative; // padding-top:10px; :deep(.arco-textarea-wrapper) { border-radius: 24px; } .btn-send { position: absolute !important; right: 4px; top: 80px; z-index: 10; .btn-send { position: absolute !important; right: 4px; top: 80px; z-index: 10; } :deep(.arco-btn-size-large) { height: 28px; width: 50px; } } :deep(.arco-btn-size-large) { height: 28px; width: 50px; :deep(.arco-textarea-wrapper) { padding-top: 5px; } } :deep(.arco-textarea-wrapper) { padding-top: 5px; } .chat-item { padding: 10px 0; .chartUserText { font-weight: 600; font-size: 14px; color: #333; margin-top: 4px; } .icon-user-jpg { border: 1px solid #d9d9d9; } } } .chat-item { padding: 10px 0; .chartUserText { font-weight: 600; font-size: 14px; color: #333; margin-top: 4px; } .icon-user-jpg { border: 1px solid #d9d9d9; } } } .header___lEPyH { width: 100%; height: 46px; position: relative; backdrop-filter: blur(15px); display: flex; align-items: center; justify-content: center; -webkit-backdrop-filter: blur(15px); .chatHeaderBox { width: auto; border-radius: 8px; padding: 4px 20px; transition: all var(--animation-duration) var(--animation-transition); .header___lEPyH { width: 100%; height: 46px; position: relative; backdrop-filter: blur(15px); display: flex; align-items: flex-end; overflow: hidden; /* 隐藏超出的内容 */ text-overflow: ellipsis; /* 使用省略号来代替被隐藏的文字 */ white-space: nowrap; /* 不换行,使内容在一行内显示 */ max-width: 200px; .title{ color: var(--color-text-1); font-size: 12px; align-items: center; justify-content: center; -webkit-backdrop-filter: blur(15px); .chatHeaderBox { width: auto; border-radius: 8px; padding: 4px 20px; transition: all var(--animation-duration) var(--animation-transition); display: flex; align-items: flex-end; overflow: hidden; /* 隐藏超出的内容 */ text-overflow: ellipsis; /* 使用省略号来代替被隐藏的文字 */ white-space: nowrap; /* 不换行,使内容在一行内显示 */ max-width: 200px; .title { color: var(--color-text-1); font-size: 12px; } } } } .action { cursor: pointer; display: inline-block; padding: 0 10px; color: var(--color-text-1); line-height: 24px; background: transparent; border-radius: 2px; cursor: pointer; transition: all 0.1s ease; font-size: 12px; } .action:hover { background: var(--color-fill-3); } .action { cursor: pointer; display: inline-block; padding: 0 10px; color: var(--color-text-1); line-height: 24px; background: transparent; border-radius: 2px; cursor: pointer; transition: all 0.1s ease; font-size: 12px; } .action:hover { background: var(--color-fill-3); } </style> src/views/sessionManager/components/chatMenu.vue
@@ -4,239 +4,256 @@ <div class="myAgent___djnd_ myAgentAnim myAgentlight___yK7Gk"> <div data-testid="msh-sidebar-main" class="myAgentHome___PG6IZ"></div> <div class="myAgentLine___Isl6E"></div> <div class="myAgentTool___Y1_mC" data-testid="msh-sidebar-new" @click="()=>{ EventBus.emit('newChat') }"> <div class="myAgentTool___Y1_mC" data-testid="msh-sidebar-new" @click=" () => { EventBus.emit('newChat'); } " > <div class="myAgentToolIcon___gaAKI myAgentToolIconNew___DBZrW"> <img src="@/assets/images/talk.png" style="width: 24px" alt=""> <img src="@/assets/images/talk.png" style="width: 24px" alt="" /> </div> </div> <div data-testid="msh-sidebar-history" class="myAgentTool___Y1_mC" @click="()=>{ EventBus.emit('history') }"> <div class="myAgentToolIcon___gaAKI myAgentToolIconHistory___GTLWk" > <div data-testid="msh-sidebar-history" class="myAgentTool___Y1_mC" @click=" () => { EventBus.emit('history'); } " > <div class="myAgentToolIcon___gaAKI myAgentToolIconHistory___GTLWk"> <img src="@/assets/images/historybg.png" style="width: 24px" alt=""> alt="" /> </div> </div> <div data-testid="msh-sidebar-square" class="myAgentTool___Y1_mC myAgentToolSquare___dbLm1" @click="()=>{ EventBus.emit('smartAi') }"> <div class="myAgentToolIcon___gaAKI myAgentToolIconSquare___Rj1o_"><img src="@/assets/images/agent.png" style="width: 24px" alt=""></div> <div data-testid="msh-sidebar-square" class="myAgentTool___Y1_mC myAgentToolSquare___dbLm1" @click=" () => { EventBus.emit('smartAi'); } " > <div class="myAgentToolIcon___gaAKI myAgentToolIconSquare___Rj1o_" ><img src="@/assets/images/agent.png" style="width: 24px" alt="" /></div> </div> <div class="myAgentLine___Isl6E" style="margin-top: 4px;"></div> <div class="myAgentLine___Isl6E" style="margin-top: 4px"></div> <div id="myAgentBox"> <!-- <div class="myAgentBox___zrCit">--> <!-- <div class="myAgentBoxImg___Mgu9e">--> <!-- <div class="myAgentBoxImgLayout___u69B_">--> <!-- <div class="MuiBox-root css-5nczy5"><img--> <!-- src="https://kimi-img.moonshot.cn/prod-chat-kimi/avatar/kimiplus/academic.png" alt=""--> <!-- style="border-radius: 50%; width: 100%; height: 100%;"></div>--> <!-- <span class="myAgentBoxImgLayoutTip___xHV4m">学术搜索</span></div>--> <!-- <div data-testid="msh-sidebar-bot-delete" class="myAgentBoxImgDelete___qXZuq">--> <!-- <div class="myAgentBoxImgDeleteInner____Hawc">从侧边栏移除</div>--> <!-- </div>--> <!-- </div>--> <!-- </div>--> <!-- <div class="myAgentBox___zrCit">--> <!-- <div class="myAgentBoxImg___Mgu9e">--> <!-- <div class="myAgentBoxImgLayout___u69B_">--> <!-- <div class="MuiBox-root css-5nczy5"><img--> <!-- src="https://kimi-img.moonshot.cn/prod-chat-kimi/avatar/kimiplus/paper_rewrite.png" alt=""--> <!-- style="border-radius: 50%; width: 100%; height: 100%;"></div>--> <!-- <span class="myAgentBoxImgLayoutTip___xHV4m">论文改写</span></div>--> <!-- <div data-testid="msh-sidebar-bot-delete" class="myAgentBoxImgDelete___qXZuq">--> <!-- <div class="myAgentBoxImgDeleteInner____Hawc">从侧边栏移除</div>--> <!-- </div>--> <!-- </div>--> <!-- </div>--> <!-- <div class="myAgentBox___zrCit">--> <!-- <div class="myAgentBoxImg___Mgu9e">--> <!-- <div class="myAgentBoxImgLayout___u69B_">--> <!-- <div class="MuiBox-root css-5nczy5"><img--> <!-- src="https://kimi-img.moonshot.cn/prod-chat-kimi/avatar/kimiplus/prompt.png" alt=""--> <!-- style="border-radius: 50%; width: 100%; height: 100%;"></div>--> <!-- <span class="myAgentBoxImgLayoutTip___xHV4m">提示词专家</span></div>--> <!-- <div data-testid="msh-sidebar-bot-delete" class="myAgentBoxImgDelete___qXZuq">--> <!-- <div class="myAgentBoxImgDeleteInner____Hawc">从侧边栏移除</div>--> <!-- </div>--> <!-- </div>--> <!-- </div>--> <!-- <div class="myAgentBox___zrCit">--> <!-- <div class="myAgentBoxImg___Mgu9e">--> <!-- <div class="myAgentBoxImgLayout___u69B_">--> <!-- <div class="MuiBox-root css-5nczy5"><img--> <!-- src="https://kimi-img.moonshot.cn/prod-chat-kimi/avatar/kimiplus/taro.png" alt=""--> <!-- style="border-radius: 50%; width: 100%; height: 100%;"></div>--> <!-- <span class="myAgentBoxImgLayoutTip___xHV4m">塔罗师</span></div>--> <!-- <div data-testid="msh-sidebar-bot-delete" class="myAgentBoxImgDelete___qXZuq">--> <!-- <div class="myAgentBoxImgDeleteInner____Hawc">从侧边栏移除</div>--> <!-- </div>--> <!-- </div>--> <!-- </div>--> <!-- <div class="myAgentBox___zrCit">--> <!-- <div class="myAgentBoxImg___Mgu9e">--> <!-- <div class="myAgentBoxImgLayout___u69B_">--> <!-- <div class="MuiBox-root css-5nczy5"><img--> <!-- src="https://kimi-img.moonshot.cn/prod-chat-kimi/avatar/kimiplus/academic.png" alt=""--> <!-- style="border-radius: 50%; width: 100%; height: 100%;"></div>--> <!-- <span class="myAgentBoxImgLayoutTip___xHV4m">学术搜索</span></div>--> <!-- <div data-testid="msh-sidebar-bot-delete" class="myAgentBoxImgDelete___qXZuq">--> <!-- <div class="myAgentBoxImgDeleteInner____Hawc">从侧边栏移除</div>--> <!-- </div>--> <!-- </div>--> <!-- </div>--> <!-- <div class="myAgentBox___zrCit">--> <!-- <div class="myAgentBoxImg___Mgu9e">--> <!-- <div class="myAgentBoxImgLayout___u69B_">--> <!-- <div class="MuiBox-root css-5nczy5"><img--> <!-- src="https://kimi-img.moonshot.cn/prod-chat-kimi/avatar/kimiplus/paper_rewrite.png" alt=""--> <!-- style="border-radius: 50%; width: 100%; height: 100%;"></div>--> <!-- <span class="myAgentBoxImgLayoutTip___xHV4m">论文改写</span></div>--> <!-- <div data-testid="msh-sidebar-bot-delete" class="myAgentBoxImgDelete___qXZuq">--> <!-- <div class="myAgentBoxImgDeleteInner____Hawc">从侧边栏移除</div>--> <!-- </div>--> <!-- </div>--> <!-- </div>--> <!-- <div class="myAgentBox___zrCit">--> <!-- <div class="myAgentBoxImg___Mgu9e">--> <!-- <div class="myAgentBoxImgLayout___u69B_">--> <!-- <div class="MuiBox-root css-5nczy5"><img--> <!-- src="https://kimi-img.moonshot.cn/prod-chat-kimi/avatar/kimiplus/prompt.png" alt=""--> <!-- style="border-radius: 50%; width: 100%; height: 100%;"></div>--> <!-- <span class="myAgentBoxImgLayoutTip___xHV4m">提示词专家</span></div>--> <!-- <div data-testid="msh-sidebar-bot-delete" class="myAgentBoxImgDelete___qXZuq">--> <!-- <div class="myAgentBoxImgDeleteInner____Hawc">从侧边栏移除</div>--> <!-- </div>--> <!-- </div>--> <!-- </div>--> <!-- <div class="myAgentBox___zrCit">--> <!-- <div class="myAgentBoxImg___Mgu9e">--> <!-- <div class="myAgentBoxImgLayout___u69B_">--> <!-- <div class="MuiBox-root css-5nczy5"><img--> <!-- src="https://kimi-img.moonshot.cn/prod-chat-kimi/avatar/kimiplus/taro.png" alt=""--> <!-- style="border-radius: 50%; width: 100%; height: 100%;"></div>--> <!-- <span class="myAgentBoxImgLayoutTip___xHV4m">塔罗师</span></div>--> <!-- <div data-testid="msh-sidebar-bot-delete" class="myAgentBoxImgDelete___qXZuq">--> <!-- <div class="myAgentBoxImgDeleteInner____Hawc">从侧边栏移除</div>--> <!-- </div>--> <!-- </div>--> <!-- </div>--> <div class="myAgentBox___zrCit" v-for="item in sessionList"> <div class="myAgentBoxImg___Mgu9e" @click="createNewSession(item)"> <div class="myAgentBoxImgLayout___u69B_"> <div class="MuiBox-root css-5nczy5"> <img :src="item.icon ? httpUrl + item.icon:imgSrc" :src="item.icon ? httpUrl + item.icon : imgSrc" alt="" style="border-radius: 50%; width: 100%; height: 100%;"> style="border-radius: 50%; width: 100%; height: 100%" /> </div> <span class="myAgentBoxImgLayoutTip___xHV4m">{{item.name}}</span> <span class="myAgentBoxImgLayoutTip___xHV4m">{{ item.name }}</span> </div> <div data-testid="msh-sidebar-bot-delete" class="myAgentBoxImgDelete___qXZuq" @click.stop="deleteSession(item)"> <div class="myAgentBoxImgDeleteInner____Hawc" >从侧边栏移除</div> <div data-testid="msh-sidebar-bot-delete" class="myAgentBoxImgDelete___qXZuq" @click.stop="deleteSession(item)" > <div class="myAgentBoxImgDeleteInner____Hawc">从侧边栏移除</div> </div> </div> </div> </div> <!-- <div class="myAgentLine___Isl6E" style="margin-top: 4px;"></div>--> <!-- <div class="myAgentLine___Isl6E" style="margin-top: 4px;"></div>--> </div> </div> </div> </template> <script setup lang="ts"> import { IconClose, IconSearch, IconTiktokColor } from "@arco-design/web-vue/es/icon"; import { useAppStore, useUserStore } from "@/store"; import { computed, nextTick, onMounted, watch, reactive, ref, onBeforeMount, onBeforeUnmount } from "vue"; import { addSessionApi, chatApi, getDialogListApi, getSessionDetailsApi, deleteSessionApi, sessionListApi } from "@/api/session"; import { Message } from "@arco-design/web-vue"; const httpUrl = localStorage.getItem('httpUrl'); import EventBus from '@/utils/EventBus'; const emit = defineEmits(["querySessionDetail","changeAgentType","createSession"]); import { appUsageSessionListApi, deleteAppUsage } from "@/api/Agent"; import { getAgentSessionDetailsApi } from "@/api/agentSession"; const activeSessionId = ref(""); const fieldNames = { value: "id", label: "name" }; const dialogs = ref([]); const dialogObj = reactive({}); const agentObj = reactive({}); const agentList = ref([]); const searchValue = ref(""); const selectValue = ref(""); const sectionList = ref({}); const sessionList = ref([]); //用户操作会话列表 import img1 from '@/assets/images/talkbg.png' import logo from "@/assets/images/model.png"; const imgSrc = ref(logo); import { IconClose, IconSearch, IconTiktokColor, } from '@arco-design/web-vue/es/icon'; import { useAppStore, useUserStore } from '@/store'; import { computed, nextTick, onMounted, watch, reactive, ref, onBeforeMount, onBeforeUnmount, } from 'vue'; import { addSessionApi, chatApi, getDialogListApi, getSessionDetailsApi, deleteSessionApi, sessionListApi, } from '@/api/session'; import { Message } from '@arco-design/web-vue'; const httpUrl = localStorage.getItem('httpUrl'); import EventBus from '@/utils/EventBus'; const emit = defineEmits([ 'querySessionDetail', 'changeAgentType', 'createSession', ]); import { appUsageSessionListApi, deleteAppUsage } from '@/api/Agent'; import { getAgentSessionDetailsApi } from '@/api/agentSession'; const activeSessionId = ref(''); const fieldNames = { value: 'id', label: 'name' }; const dialogs = ref([]); const dialogObj = reactive({}); const agentObj = reactive({}); const agentList = ref([]); const searchValue = ref(''); const selectValue = ref(''); const sectionList = ref({}); const sessionList = ref([]); //用户操作会话列表 import img1 from '@/assets/images/talkbg.png'; import logo from '@/assets/images/model.png'; const imgSrc = ref(logo); // 查询历史用户习惯会话列表 const querySessionList = async (id) => { const { code, data } = await appUsageSessionListApi(''); if (code === 200) { sessionList.value = data.map((item) => { return { ...item, } }); // sessionList.value.splice(0, 5); console.log(sessionList.value,'用户习惯会话列表'); } else { // Message.warning("查询失败"); } }; // 新增会话 const createNewSession = async (session) => { console.log(session, 'session'); // 查询历史记录 if (session.app_type == '1') { // 生成智能体新的对话 emit('createSession',session.app_id,`和${session.name}的会话`); emit('changeAgentType','1'); } else { // 生成agent新的对话 // agent对象数据封装 const { code, data } = await getAgentSessionDetailsApi(session.app_id); if (code == 0) { console.log(data,'会话详情'); let sessionObj = { id: session.app_id, dsl: data.dsl, title: session.name, } EventBus.emit("createAgent",sessionObj); emit('changeAgentType','2'); } } } //根据会话id删除会话 const deleteSession = async (session) => { const { code } = await deleteAppUsage({ app_id:session.app_id }); if (code === 200) { // Message.success('删除成功'); // 查询历史用户习惯会话列表 const querySessionList = async (id) => { const { code, data } = await appUsageSessionListApi(''); if (code === 200) { sessionList.value = data; sessionList.value = data.map((item) => { return { ...item, }; }); // sessionList.value.splice(0, 5); console.log(sessionList.value,'用户习惯会话列表'); if(sessionList.value.length == 0){ // 生成智能体新的对话 emit('createSession',''); emit('changeAgentType','1'); } console.log(sessionList.value, '用户习惯会话列表'); } else { // Message.warning("查询失败"); } } }; }; // 新增会话 const createNewSession = async (session) => { console.log(session, 'session'); // 查询历史记录 if (session.app_type == '1') { // 生成智能体新的对话 emit('createSession', session.app_id, `和${session.name}的会话`); emit('changeAgentType', '1'); } else { // 生成agent新的对话 // agent对象数据封装 const { code, data } = await getAgentSessionDetailsApi(session.app_id); if (code == 0) { console.log(data, '会话详情'); let sessionObj = { id: session.app_id, dsl: data.dsl, title: session.name, }; EventBus.emit('createAgent', sessionObj); emit('changeAgentType', '2'); } } }; //根据会话id删除会话 const deleteSession = async (session) => { const { code } = await deleteAppUsage({ app_id: session.app_id, }); if (code === 200) { // Message.success('删除成功'); const { code, data } = await appUsageSessionListApi(''); if (code === 200) { sessionList.value = data; // sessionList.value.splice(0, 5); console.log(sessionList.value, '用户习惯会话列表'); if (sessionList.value.length == 0) { // 生成智能体新的对话 emit('createSession', ''); emit('changeAgentType', '1'); } } else { // Message.warning("查询失败"); } } }; onBeforeMount(()=>{ querySessionList(''); }) onMounted(() => { EventBus.on("queryAppUsageList", (data) => { onBeforeMount(() => { querySessionList(''); }) }) onBeforeUnmount(() => { EventBus.off("queryAppUsageList"); }); }); onMounted(() => { EventBus.on('queryAppUsageList', (data) => { querySessionList(''); }); }); onBeforeUnmount(() => { EventBus.off('queryAppUsageList'); }); </script> <style scoped lang="less"> @import "@/views/sessionManager/style/layout.css"; @import '@/views/sessionManager/style/layout.css'; .layoutNavMoveCenter { display: flex; justify-content: center; @@ -244,13 +261,9 @@ height: calc(100vh - 160px); /* 或者指定高度 */ position: relative; } #myAgentBox{ #myAgentBox { //width: 100%; //max-height: 220px; //overflow: hidden; } </style> src/views/sessionManager/components/smartAi.vue
@@ -1,191 +1,188 @@ <template> <div class="layoutAgentCenter"> <a-scrollbar style=" height: calc(100vh - 100px); overflow-y: auto; overflow-x: hidden; " > <div class="search"> <!-- 查询框--> <img src="@/assets/images/his.png" style="width: 100%" alt=""> </div> <div class="agentMainCenter"> <a-row class="agentCenter"> <a-col :span="8" v-for="item in dialogs"> <div class="item agentCenter-box" @click="createNewSession(item)" > <div class="text" > <a-avatar> <img :style="{ width: '100%' }" alt="dessert" :src="item.avatar || imgSrc" /> </a-avatar> <span style="margin-left: 10px;font-weight: 500;color: var(--color-text-1)"> {{ item.name }} </span> </div> <div class="time" > </div> </div> </a-col> <a-col :span="8" v-for="item in agentList"> <div class="item agentCenter-box" @click="createNewSession(item)" > <div class="text" > <a-avatar> <img :style="{ width: '100%' }" alt="dessert" :src="item.avatar || imgSrc" /> </a-avatar> <span style="margin-left: 10px;font-weight: 500;color: var(--color-text-1)"> {{ item.name }} </span> </div> <div class="time" > </div> </div> </a-col> </a-row> </div> </a-scrollbar> <a-scrollbar style="height: calc(100vh - 100px); overflow-y: auto; overflow-x: hidden" > <div class="search"> <!-- 查询框--> <img src="@/assets/images/his.png" style="width: 100%" alt="" /> </div> <div class="agentMainCenter"> <a-row class="agentCenter"> <a-col :span="8" v-for="item in dialogs"> <div class="item agentCenter-box" @click="createNewSession(item)"> <div class="text"> <a-avatar> <img :style="{ width: '100%' }" alt="dessert" :src="item.icon || imgSrc" /> </a-avatar> <span style=" margin-left: 10px; font-weight: 500; color: var(--color-text-1); " > {{ item.name }} </span> </div> <div class="time"> </div> </div> </a-col> <a-col :span="8" v-for="item in agentList"> <div class="item agentCenter-box" @click="createNewSession(item)"> <div class="text"> <a-avatar> <img :style="{ width: '100%' }" alt="dessert" :src="item.avatar || imgSrc" /> </a-avatar> <span style=" margin-left: 10px; font-weight: 500; color: var(--color-text-1); " > {{ item.name }} </span> </div> <div class="time"> </div> </div> </a-col> </a-row> </div> </a-scrollbar> </div> </template> <script setup lang="ts"> import { IconClose, IconSearch, IconTiktokColor } from "@arco-design/web-vue/es/icon"; import { useAppStore, useUserStore } from "@/store"; import { computed, nextTick, onMounted, watch, reactive, ref, onBeforeMount, onBeforeUnmount } from "vue"; import { IconClose, IconSearch, IconTiktokColor, } from '@arco-design/web-vue/es/icon'; import { useAppStore, useUserStore } from '@/store'; import { computed, nextTick, onMounted, watch, reactive, ref, onBeforeMount, onBeforeUnmount, } from 'vue'; import { Message } from "@arco-design/web-vue"; import EventBus from '@/utils/EventBus'; import moment from "moment"; import { addSessionApi, chatApi, getDialogListApi, getSessionDetailsApi, sessionListApi } from "@/api/session"; import { queryCanvasList } from "@/api/Agent"; const emit = defineEmits(["querySessionDetail","changeAgentType","createSession"]); import logo from "@/assets/images/model.png"; const sessionList = ref([]); //会话列表 const activeSessionId = ref(""); const fieldNames = { value: "id", label: "name" }; const dialogs = ref([]); const dialogObj = reactive({}); const agentObj = reactive({}); const agentList = ref([]); const searchValue = ref(""); const selectValue = ref(""); const sectionList = ref({}); const imgSrc = ref(logo); const DialogList = async () => { const { code, data } = await getDialogListApi(); if (code === 200) { if (data?.length>0) { selectValue.value = data[0].id; dialogs.value = data.map((item) => { import { Message } from '@arco-design/web-vue'; import EventBus from '@/utils/EventBus'; import moment from 'moment'; import { addSessionApi, chatApi, getDialogListApi, getSessionDetailsApi, sessionListApi, } from '@/api/session'; import { queryCanvasList } from '@/api/Agent'; const emit = defineEmits([ 'querySessionDetail', 'changeAgentType', 'createSession', ]); import logo from '@/assets/images/model.png'; const sessionList = ref([]); //会话列表 const activeSessionId = ref(''); const fieldNames = { value: 'id', label: 'name' }; const dialogs = ref([]); const dialogObj = reactive({}); const agentObj = reactive({}); const agentList = ref([]); const searchValue = ref(''); const selectValue = ref(''); const sectionList = ref({}); const imgSrc = ref(logo); const DialogList = async () => { const { code, data } = await getDialogListApi(); if (code === 200) { if (data?.length > 0) { selectValue.value = data[0].id; dialogs.value = data.map((item) => { return { ...item, type: 1, //智能体 }; }); // console.log(dialogs, 'dialogs'); } } }; const queryCanvas = async (params = {}) => { try { const { data } = await queryCanvasList(params); agentList.value = data.map((item) => { return { ...item, type: 1 //智能体 name: item.title, type: 2, //agent }; }); // console.log(data, "dialogs"); // console.log(agentList, 'agent'); // 合并数组 // dialogs.value = dialogs.value.concat(agentList.value); } catch (err) { // you can report use errorHandler or other } finally { } } }; }; const queryCanvas = async (params = {}) => { try { const { data } = await queryCanvasList(params); console.log(data, "agent"); agentList.value = data.map((item) => { return { ...item, name: item.title, type: 2 //agent }; }); // 合并数组 // dialogs.value = dialogs.value.concat(agentList.value); } catch (err) { // you can report use errorHandler or other } finally { } }; // 查询会话列表 const querySessionList = async (id) => { const { code, data } = await sessionListApi(id); if (code === 200) { sessionList.value = data; } else { Message.warning("查询失败"); } }; // 生成智能体新建会话 const createNewSession = async (session) => { console.log(session, 'session'); // emit('querySessionDetail',session); if (session.type == '1') { // 生成智能体新的对话 emit('createSession',session.id,`和${session.name}的会话`); emit('changeAgentType','1'); } else { // 生成agent新的对话 EventBus.emit("createAgent",session); emit('changeAgentType','2'); } } onBeforeMount(()=>{ DialogList(); queryCanvas(); }) onMounted(() => { EventBus.on("smartAi", () => { emit('changeAgentType','4'); // 查询会话列表 const querySessionList = async (id) => { const { code, data } = await sessionListApi(id); if (code === 200) { sessionList.value = data; } else { Message.warning('查询失败'); } }; // 生成智能体新建会话 const createNewSession = async (session) => { console.log(session, 'session'); // emit('querySessionDetail',session); if (session.type == '1') { // 生成智能体新的对话 emit('createSession', session.id, `和${session.name}的会话`); emit('changeAgentType', '1'); } else { // 生成agent新的对话 EventBus.emit('createAgent', session); emit('changeAgentType', '2'); } }; onBeforeMount(() => { DialogList(); queryCanvas(); }); }) onBeforeUnmount(() => { EventBus.off("smartAi"); }); onMounted(() => { EventBus.on('smartAi', () => { emit('changeAgentType', '4'); DialogList(); queryCanvas(); }); }); onBeforeUnmount(() => { EventBus.off('smartAi'); }); </script> <style scoped lang="less"> .layoutAgentCenter{ .layoutAgentCenter { width: 100%; //background: #999999; position: absolute; @@ -197,9 +194,9 @@ font-weight: 700; text-align: center; } .search{ .search { width: 100%; .search-box{ .search-box { width: 70%; margin-left: 15%; border: 1px solid var(--color-text-4); @@ -208,19 +205,19 @@ background: var(--color-bg-2); margin-top: 20px; margin-bottom: 20px; :deep(.arco-input-wrapper){ :deep(.arco-input-wrapper) { border: none; background: var(--color-bg-2); } } } .agentMainCenter{ .agentMainCenter { width: 70%; margin: 0 auto; .agentCenter{ .agentCenter { width: 100%; margin-top: 30px; .agentCenter-box{ .agentCenter-box { display: flex; width: 90%; margin: 0 auto; @@ -234,20 +231,14 @@ align-items: center; color: var(--color-text-2); } .agentCenter-box:hover{ .agentCenter-box:hover { color: var(--color-text-2); //border: 1px solid var(--color-neutral-3); background: var(--color-bg-3); box-shadow: 0 1px 2px -2px rgba(0, 0, 0, 0.16), 0 3px 6px 0 rgba(0, 0, 0, 0.12), 0 5px 12px 4px rgba(0, 0, 0, 0.09); box-shadow: 0 1px 2px -2px rgba(0, 0, 0, 0.16), 0 3px 6px 0 rgba(0, 0, 0, 0.12), 0 5px 12px 4px rgba(0, 0, 0, 0.09); } } } } </style> src/views/sessionManager/index.vue
@@ -87,42 +87,65 @@ <template #avatar> <img class="icon-user-jpg" src="../../assets/images/icon-chart.png" src="../../assets/images/icon-picture.png" alt="本地图片" /> </template> <template #content> <a-card v-if="isExistTip(sessionDetail.content)"> <div :class="{ chatItemAnswer: theme === 'light' }" :style="{backgroundColor: theme === 'light' ? '#ffffff' : '#000000'}" style="border: none;display: inline;" v-for="(item,tipIndex) in tipMatch(sessionDetail)" <div :class="{ chatItemAnswer: theme === 'light' }" :style="{ backgroundColor: theme === 'light' ? '#ffffff' : '#000000', }" style="border: none; display: inline" v-for="(item, tipIndex) in tipMatch(sessionDetail)" > <span v-if="tipIndex == 0"> {{ sessionDetail.content.substring(0, item.index) }} <a-tooltip background-color="#3491FA" :content="getTipContent( messagenList.reference, index )"> <img style="width: 20px;height: 20px" :src="tipImage" /> <a-tooltip background-color="#3491FA" :content=" getTipContent(messagenList.reference, index) " > <img style="width: 20px; height: 20px" :src="tipImage" /> </a-tooltip> </span> <span v-else> {{ sessionDetail.content.substring(item.preIndex+item.item.length, item.index) }} <a-tooltip background-color="#3491FA" :content="getTipContent( messagenList.reference, index )"> <img style="width: 20px;height: 20px" :src="tipImage" /> {{ sessionDetail.content.substring( item.preIndex + item.item.length, item.index ) }} <a-tooltip background-color="#3491FA" :content=" getTipContent(messagenList.reference, index) " > <img style="width: 20px; height: 20px" :src="tipImage" /> </a-tooltip> </span> </div> </a-card> <a-card v-else> <div :class="{ chatItemAnswer: theme === 'light' }" :style="{ backgroundColor: theme === 'light' ? '#ffffff' : '#000000', }" style="border: none"> <a-card v-else> <div :class="{ chatItemAnswer: theme === 'light' }" :style="{ backgroundColor: theme === 'light' ? '#ffffff' : '#000000', }" style="border: none" > {{ sessionDetail.content }} </div> </a-card> @@ -174,7 +197,7 @@ <template #avatar> <img class="icon-user-jpg" src="../../assets/images/icon-chart.png" src="../../assets/images/icon-picture.png" alt="本地图片" /> </template> @@ -389,7 +412,7 @@ </div> </template> <script setup lang="ts"> import { useAppStore, userModelState, useUserStore } from "@/store"; import { useAppStore, userModelState, useUserStore } from '@/store'; import { computed, nextTick, @@ -419,20 +442,20 @@ sessionListApi, uploadWithoutKb, } from '@/api/session'; import { getAuthorization } from "@/utils/auth"; import { queryCanvasList } from "@/api/Agent"; import { getAgentSessionDetailsApi } from "@/api/agentSession"; import useClipboard from "vue-clipboard3"; import pdfImg1 from "@/assets/session/PDF.png"; import pdfImg2 from "@/assets/session/wps-write.png"; import pdfImg3 from "@/assets/session/execl.png"; import pdfImg4 from "@/assets/session/icon-txt.png"; import pdfImg5 from "@/assets/session/txt.png"; import tipImage from "@/assets/session/tip.png"; import { getAuthorization } from '@/utils/auth'; import { queryCanvasList } from '@/api/Agent'; import { getAgentSessionDetailsApi } from '@/api/agentSession'; import useClipboard from 'vue-clipboard3'; import pdfImg1 from '@/assets/session/PDF.png'; import pdfImg2 from '@/assets/session/wps-write.png'; import pdfImg3 from '@/assets/session/execl.png'; import pdfImg4 from '@/assets/session/icon-txt.png'; import pdfImg5 from '@/assets/session/txt.png'; import tipImage from '@/assets/session/tip.png'; import docx from "@/views/dmx/knowledgeLib/components/docx.vue"; import excel from "@/views/dmx/knowledgeLib/components/excel.vue"; import txtPdf from "@/views/dmx/knowledgeLib/components/txtPdf.vue"; import docx from '@/views/dmx/knowledgeLib/components/docx.vue'; import excel from '@/views/dmx/knowledgeLib/components/excel.vue'; import txtPdf from '@/views/dmx/knowledgeLib/components/txtPdf.vue'; // const url = ref('../../assets/session/PDF.png'); @@ -481,8 +504,7 @@ let documenttype = ref('docx'); let previewSrc = ref(''); const modelStore = userModelState(); const modelStore = userModelState(); const httpUrl = modelStore.hrefUrl; const rules = { @@ -509,25 +531,25 @@ } }; let dataItem = []; const isExistTip=(message:string):boolean=>{ const isExistTip = (message: string): boolean => { if (/##[0-9]\$\$/.test(message)) { return true; } else { return false; } } }; const tipMatch = (session: any): any[] => { //match session.content中的##[0-9]$$的索引 let indexs: any[] = []; let preTip=0; let preTip = 0; session.content.match(/##([0-9]+)\$\$/g)?.map((item) => { let i = session.content.indexOf(item); indexs.push({ index: i, item: item, preIndex: preTip }); preTip = i; }); return indexs; } }; const getTxt = (data, role, message, index) => { if (isExistTip(message)) { @@ -543,16 +565,15 @@ }; const getTipContent = (data, index): string => { let maxSimilarityContent = ""; let maxSimilarityContent = ''; let i = index / 2 - 1 > 0 ? index / 2 - 1 : 0; let maxSimilarity = 0; data[i].chunks.forEach((chunk) => { if (chunk.similarity > maxSimilarity) { maxSimilarity = chunk.similarity; maxSimilarityContent = chunk.content_with_weight; } if (chunk.similarity > maxSimilarity) { maxSimilarity = chunk.similarity; maxSimilarityContent = chunk.content_with_weight; } ); }); return maxSimilarityContent; }; @@ -623,10 +644,7 @@ const selectFileCallback = (data) => { console.log(data, 'selectFileCallback'); uploaditemList.value = [ ...uploaditemList.value, ...data ]; uploaditemList.value = [...uploaditemList.value, ...data]; }; let onFileSelectedLoading = ref(false); @@ -744,7 +762,9 @@ if (res.code == 200) { // console.log(res.data.conversation_id); activeSessionId.value = res.data?.conversation_id; const { code, data } = await getSessionDetailsApi(res.data?.conversation_id); const { code, data } = await getSessionDetailsApi( res.data?.conversation_id ); if (code === 200) { console.log(data, '新建会话详情'); Object.assign(chatObj, data);