.idea/codeStyles/Project.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/api/interceptor.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/api/session.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/dmx/model/components/addModel.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/session/sessionManager/components/addSession.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/session/sessionManager/index.vue | 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/sessionRecords/sessionRecordsManager/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
.idea/codeStyles/Project.xml
@@ -3,7 +3,7 @@ <HTMLCodeStyleSettings> <option name="HTML_SPACE_INSIDE_EMPTY_TAG" value="true" /> </HTMLCodeStyleSettings> <JSCodeStyleSettings version="0"> <JSCodeStyleSettings> <option name="FORCE_SEMICOLON_STYLE" value="true" /> <option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" /> <option name="FORCE_QUOTE_STYlE" value="true" /> @@ -11,7 +11,7 @@ <option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" /> <option name="SPACES_WITHIN_IMPORTS" value="true" /> </JSCodeStyleSettings> <TypeScriptCodeStyleSettings version="0"> <TypeScriptCodeStyleSettings> <option name="FORCE_SEMICOLON_STYLE" value="true" /> <option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" /> <option name="FORCE_QUOTE_STYlE" value="true" /> src/api/interceptor.ts
@@ -55,7 +55,7 @@ const res = response.data; // if the custom code is not 20000, it is judged as an error. if ( /*if ( (res.retcode && res.retcode !== 0) || (res.code && res.code !== 20000) ) { @@ -88,7 +88,7 @@ response.config.url === '/base/login' ) { setAuthorization(response.headers.authorization); } }*/ return res; }, (error) => { src/api/session.ts
@@ -27,3 +27,7 @@ export function getSessionDetailsApi(conversation_id:string) { return axios.get<ISessionListResult>('/api/conversation/get?modeltype=localragflow',{params:{conversation_id}}); } // 获取智能助手列表 export function getDialogListApi() { return axios.get<ISessionListResult>('/api/dialog/list'); } src/views/dmx/model/components/addModel.vue
@@ -1,4 +1,3 @@ <template> <a-button type="primary" @click="handleClick" style="margin-left: 10px"> <template #icon> @@ -138,7 +137,6 @@ done(false) }else { console.log('请求数据'); } }) }; @@ -175,13 +173,4 @@ }) </script> <script lang="ts"> export default { name: 'add', methods: { } }; </script> src/views/session/sessionManager/components/addSession.vue
@@ -1,34 +1,75 @@ <script setup lang="ts"> import { defineProps ,ref,defineEmits} from 'vue'; import { defineProps,ref,defineEmits, onMounted } from 'vue'; import { Message } from '@arco-design/web-vue'; import { addSessionApi }from '@/api/session'; import { addSessionApi ,getDialogListApi }from '@/api/session'; const props=defineProps({ modalObj:Object }); const conversation_name=ref(''); const conversation=ref({ dialog_id:'', conversation_desc:'' }); const dialogList=ref([]); const emit = defineEmits(['addSession']); const handleOk=async ()=>{ if(conversation_name.value){ const {code}=await addSessionApi({conversation_name:conversation_name.value}); const queryDialogList=async ()=>{ const { code, data } = await getDialogListApi(); if(code===200){ dialogList.value = data; } }; const rules = { dialog_id: [ { required: true, message: '智能助手不能为空', }, ], conversation_desc: [ { required: true, message: '描述不能为空', } ] } onMounted(()=>{ queryDialogList(); }); const formRef = ref(); const handleOk=()=>{ formRef.value.validate().then(async(res)=>{ if(!res){ const { code }=await addSessionApi({ ...conversation.value }); if(code===200){ Message.success('添加成功'); emit('addSession') } emit('addSession'); setTimeout(()=>{ props.modalObj.add=false; },500); }else{ Message.warning('会话名称不能为空'); Message.warning('添加失败'); } } }); return false; } const destroyData = ()=>{ formRef.value.resetFields(); } </script> <template> <div> <a-modal v-model:visible="modalObj.add" @ok="handleOk" @cancel="modalObj.add=false"> <a-modal v-model:visible="modalObj.add" @before-ok="handleOk" @cancel="modalObj.add=false" @before-close="destroyData"> <template #title> 新增会话 </template> <a-form> <a-form-item label="会话名称:"> <a-input placeholder="请输入会话名称" v-model="conversation_name" style="width: 80%"></a-input> <a-form ref="formRef" :model="conversation" :rules="rules"> <a-form-item label="助手关联:" field="dialog_id" @submit="handleSubmit"> <a-select style="width: 80%" v-model="conversation.dialog_id" placeholder="请选择关联助手"> <a-option v-for="dialog in dialogList" :key="dialog.id" :value="dialog.id">{{dialog.name}}</a-option> </a-select> </a-form-item> <a-form-item label="描述:" field="conversation_desc"> <a-textarea placeholder="请输入描述" :max-length="100" show-word-limit :auto-size="{minRows:4,maxRows:5}" v-model="conversation.conversation_desc" style="width: 80%"></a-textarea> </a-form-item> </a-form> </a-modal> src/views/session/sessionManager/index.vue
src/views/sessionRecords/sessionRecordsManager/index.vue
@@ -1,13 +1,64 @@ <script setup lang="ts"> import { IconSearch,IconTiktokColor ,IconSend,IconClose} from '@arco-design/web-vue/es/icon'; import { useAppStore} from '@/store'; import {computed,ref,onMounted,reactive} from 'vue'; import {sessionListApi}from '@/api/session'; import { computed, ref, onMounted, reactive, nextTick } from 'vue'; import { Message } from '@arco-design/web-vue'; import moment from 'moment'; import AddSession from '@/views/session/sessionManager/components/addSession.vue'; import { sessionListApi, deleteSessionApi,getSessionDetailsApi,chatApi }from '@/api/session'; const sessionDetailList=ref([]);//根据会话id出来的会话详情 const sessionList=ref([]);//会话列表 const modalObj=reactive({add:false}); const currIndex = ref(0) const displayedText = ref('');// 正在显示的文字 let timer: number|null = null; const streamStr=ref(''); const inputMsg=ref(''); const activeSessionId=ref(''); const sendMessage= async (event)=>{ event.preventDefault(); if(!activeSessionId.value){ Message.warning('请选择会话'); return; } if(inputMsg.value){ const {code,data} =await chatApi({conversation_id:activeSessionId.value,messages:inputMsg.value}); const res= await getSessionDetailsApi(activeSessionId.value); if(res.code===200){ sessionDetailList.value=res.data.message.map((item,index)=>{ if(index===res.data.message.length-1){ item.role='last'; displayedText.value=''; currIndex.value=0; streamStr.value=item.content; startDisplayStr(); } return item; }); refreshScroll(); } inputMsg.value=''; }else{ Message.warning('消息不能为空'); } }; const querySessionDetail=async (session)=>{ activeSessionId.value=session.id; const {code,data}= await getSessionDetailsApi(session.id); if(code===200){ sessionDetailList.value=data.message; refreshScroll();//刷新滚动条位置 } }; const scrollbar = ref(null); const refreshScroll=()=>{ nextTick(()=>{ const container = document.getElementById('home'); scrollbar.value.scrollTop(container.scrollHeight); }); }; //查询会话列表 const querySessionList=async ()=>{ const {code,data} =await sessionListApi(); @@ -28,6 +79,22 @@ const theme = computed(() => { return appStore.theme; }); //文字动态输出 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); } else { clearTimeout(timer!); timer = null } } </script> <template> @@ -50,7 +117,7 @@ </a-card> <a-card class="left"> <a-scrollbar class="left-list" style="height: calc(100vh - 160px);overflow-y: auto;overflow-x: hidden;"> <div class="item" v-for="session in sessionList"> <div class="item" v-for="session in sessionList" @click="querySessionDetail(session)" :class="{ isLeftActive:activeSessionId===session.id }"> <div class="text" :class="{light:theme==='dark'}">{{session.name}}</div> <div class="time">{{moment(new Date(session.create_time)).format('YYYY-MM-DD HH:mm:ss')}}</div> </div> @@ -59,6 +126,7 @@ </a-col> <a-col :span="15"> <a-card class="center"> <div v-if="sessionDetailList.length===0"> <div class="center-title">智能问答</div> <div class="center-content"> 我可以理解和学习人类的语言,具备多轮对话的能力,现在和我开始交流吧~ @@ -119,8 +187,41 @@ </div> </a-col> </a-row> </div> <a-scrollbar ref="scrollbar" id="home" v-else class="chat-list" style="width:90%;overflow:auto;height: 60vh;margin: 0px auto"> <div class="chat-item" v-for="sessionDetail in sessionDetailList"> <a-comment v-if="sessionDetail.role==='user'" avatar="https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/3ee5f13fb09879ecb5185e440cef6eb9.png~tplv-uwbnlip3yd-webp.webp" > <template #content> <div :class="{light:theme==='light'}">{{sessionDetail.content}}</div> </template> </a-comment> <a-comment v-else-if="sessionDetail.role==='assistant'" avatar="https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/9eeb1800d9b78349b24682c3518ac4a3.png~tplv-uwbnlip3yd-webp.webp" > <template #content> <a-card class="chat-item-answer" style="background-color: rgba(63, 64, 79, 1);"> <div :class="{light:theme==='light'}">{{sessionDetail.content}}</div> </a-card> </template> </a-comment> <a-comment v-else-if="sessionDetail.role==='last'" avatar="https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/9eeb1800d9b78349b24682c3518ac4a3.png~tplv-uwbnlip3yd-webp.webp" > <template #content> <a-textarea readonly auto-size v-model="displayedText" class="chat-item-answer" style="background-color: rgba(63, 64, 79, 1);"> </a-textarea> </template> </a-comment> </div> </a-scrollbar> <div class="center-bottom"> <a-textarea style="height: 180px" placeholder="输入您想了解的内容,Shift+Enter换行" :max-length="500" allow-clear show-word-limit> <a-textarea v-model="inputMsg" @keydown.shift.enter="sendMessage" style="height: 180px" placeholder="输入您想了解的内容,Shift+Enter发送" :max-length="500" allow-clear show-word-limit> </a-textarea> </div> </a-card> @@ -181,6 +282,9 @@ </template> <style scoped lang="scss"> .isLeftActive{ background-color:lightgrey; } .light{ color: white !important; } @@ -210,10 +314,12 @@ } .text{ color: black; padding-left: 10px; } .time{ color: gray; font-size: 12px; padding-left: 10px; } } } @@ -269,7 +375,7 @@ .center-bottom{ position: absolute; width: 90%; bottom: 70px; bottom: 20px; left:5%; } }