| | |
| | | <a-scrollbar |
| | | class="left-list" |
| | | style=" |
| | | height: calc(100vh - 160px); |
| | | height: calc(100vh - 250px); |
| | | overflow-y: auto; |
| | | overflow-x: hidden; |
| | | " |
| | | > |
| | | <div |
| | | class="item" |
| | | class="item left-list-item" |
| | | v-for="session in sessionList" |
| | | @click="querySessionDetail(session)" |
| | | :class="{ isLeftActive: activeSessionId === session.id }" |
| | |
| | | maxRows: 5, |
| | | }" |
| | | /> |
| | | </div> |
| | | <div style="margin-left: 10px"> |
| | | <!-- <icon-send size="32" /> --> |
| | | <a-button |
| | | :disabled="chatDis" |
| | | @click="sentClick" |
| | | type="primary" |
| | | size="large" |
| | | >发送</a-button |
| | | > |
| | | <div class="btn-send"> |
| | | <!-- <icon-send size="32" /> --> |
| | | <a-button |
| | | :disabled="chatDis" |
| | | @click="sentClick" |
| | | type="primary" |
| | | style="border-radius: 24px" |
| | | :loading="loading" |
| | | size="large" |
| | | >发送</a-button |
| | | > |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </a-card> |
| | |
| | | </div> |
| | | </div> |
| | | <div class="right-tag"> |
| | | <a-space> |
| | | <a-button type="primary" shape="round" size="mini" class="btn" |
| | | >全部 |
| | | </a-button> |
| | | <a-button type="outline" shape="round" size="mini" class="btn" |
| | | >文档创作 |
| | | </a-button> |
| | | <a-button type="outline" shape="round" size="mini" class="btn" |
| | | >知识学习 |
| | | </a-button> |
| | | <a-button type="outline" shape="round" size="mini" class="btn" |
| | | >效率提升 |
| | | </a-button> |
| | | <!-- <a-space> |
| | | <a-button type="primary" shape="round" size="mini" class="btn" |
| | | >全部 |
| | | </a-button> |
| | |
| | | <a-button type="outline" shape="round" size="mini" class="btn" |
| | | >知识学习 |
| | | </a-button> |
| | | </a-space> |
| | | <a-space style="margin-top: 10px"> |
| | | <a-button type="outline" shape="round" size="mini" class="btn" |
| | | >效率提升 |
| | | </a-button> |
| | | </a-space> |
| | | </a-space> --> |
| | | <!-- <a-space style="margin-top: 10px"> |
| | | |
| | | </a-space> --> |
| | | </div> |
| | | <div class="right-list"> |
| | | <div class="right-item"> |
| | |
| | | import { useAppStore } from '@/store'; |
| | | import { computed, nextTick, onMounted, reactive, ref } from 'vue'; |
| | | import { Message } from '@arco-design/web-vue'; |
| | | import { EventSourceParserStream } from 'eventsource-parser/stream'; |
| | | import moment from 'moment'; |
| | | import AddSession from '@/views/session/sessionManager/components/addSession.vue'; |
| | | import { |
| | |
| | | getSessionDetailsApi, |
| | | sessionListApi, |
| | | } from '@/api/session'; |
| | | import { getAuthorization } from '@/utils/auth'; |
| | | |
| | | const sessionDetailList = ref([]); //根据会话id出来的会话详情 |
| | | const sessionList = ref([]); //会话列表 |
| | | const modalObj = reactive({ add: false }); |
| | | const chatDis = ref(false); |
| | | const loading = ref(false); |
| | | |
| | | const currIndex = ref(0); |
| | | const displayedText = ref(''); // 正在显示的文字 |
| | |
| | | const sendMessage = async (event) => { |
| | | event.preventDefault(); |
| | | chatDis.value = true; |
| | | loading.value = true; |
| | | if (!activeSessionId.value) { |
| | | Message.warning('请选择会话'); |
| | | chatDis.value = false; |
| | | loading.value = false; |
| | | return; |
| | | } |
| | | if (inputMsg.value) { |
| | | const data = await chatApi({ |
| | | conversation_id: activeSessionId.value, |
| | | messages: inputMsg.value, |
| | | }); |
| | | if (data) { |
| | | chatDis.value = false; |
| | | |
| | | // inputMsg.value = ''; |
| | | // querySessionDetail({ id: activeSessionId.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(); |
| | | // if (displayedText.value) { |
| | | // querySessionList(); |
| | | // } |
| | | |
| | | if (inputMsg.value) { |
| | | sessionDetailList.value.push({ content: inputMsg.value, role: 'user' }); |
| | | sessionDetailList.value.push({ role: 'last' }); |
| | | refreshScroll(); |
| | | const response = await fetch( |
| | | '/api/tech/cloudminds/query?modeltype=localragflow', |
| | | { |
| | | method: 'POST', |
| | | headers: { |
| | | 'Authorization': getAuthorization(), |
| | | 'Content-Type': 'application/json', |
| | | }, |
| | | body: JSON.stringify({ |
| | | conversation_id: activeSessionId.value, |
| | | messages: inputMsg.value, |
| | | }), |
| | | } |
| | | ); |
| | | |
| | | 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); |
| | | } |
| | | return item; |
| | | }); |
| | | refreshScroll(); |
| | | if (done) { |
| | | console.info('done'); |
| | | displayedText.value = ''; |
| | | querySessionList(); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | chatDis.value = false; |
| | | loading.value = false; |
| | | inputMsg.value = ''; |
| | | } else { |
| | | Message.warning('消息不能为空'); |
| | |
| | | const { code, data } = await sessionListApi(selectValue.value); |
| | | if (code === 200) { |
| | | sessionList.value = data; |
| | | activeSessionId.value = data[0].id; |
| | | querySessionDetail(data[0]); |
| | | } else { |
| | | Message.warning('查询失败'); |
| | | } |
| | |
| | | displayedText.value += res[currIndex.value]; |
| | | currIndex.value++; |
| | | setTimeout(startDisplayStr, 100); |
| | | refreshScroll(); |
| | | } else { |
| | | clearTimeout(timer!); |
| | | timer = null; |
| | |
| | | </script> |
| | | <style scoped lang="scss"> |
| | | .isLeftActive { |
| | | background-color: lightgrey; |
| | | background-color: #ededf5; |
| | | } |
| | | .left-list-item { |
| | | margin-bottom: 2px; |
| | | } |
| | | .left-list-item:hover { |
| | | background-color: #ededf5; |
| | | } |
| | | |
| | | .light { |
| | |
| | | border-radius: 10px; |
| | | margin-top: 10px; |
| | | padding: 10px; |
| | | height: 120px; |
| | | background-color: lightcyan; |
| | | |
| | | min-height: 120px; |
| | | background-color: #e9f3ff; |
| | | .item-content { |
| | | color: #666; |
| | | } |
| | | .item-title { |
| | | text-align: center; |
| | | line-height: 40px; |
| | | font-size: 20px; |
| | | font-family: 黑体; |
| | | color: black; |
| | | color: #333; |
| | | } |
| | | } |
| | | } |
| | |
| | | flex: 1 1; |
| | | flex-direction: column; |
| | | overflow: hidden; |
| | | position: relative; |
| | | :deep(.arco-textarea-wrapper) { |
| | | border-radius: 24px; |
| | | } |
| | | |
| | | .btn-send { |
| | | position: absolute !important; |
| | | right: 5px; |
| | | bottom: 5px; |
| | | z-index: 10; |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | .right-tag { |
| | | margin-top: 20px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | flex-wrap: wrap; |
| | | :deep(.arco-btn-size-mini.arco-btn-shape-round) { |
| | | margin-bottom: 10px !important; |
| | | } |
| | | } |
| | | |
| | | .right-list { |
| | |
| | | border-radius: 10px; |
| | | margin-top: 10px; |
| | | padding: 10px; |
| | | height: 120px; |
| | | background-color: lightcyan; |
| | | min-height: 120px; |
| | | background-color: #e9f3ff; |
| | | |
| | | .item-title { |
| | | text-align: center; |
| | | line-height: 40px; |
| | | font-size: 20px; |
| | | font-family: 黑体; |
| | | color: black; |
| | | color: #333; |
| | | } |
| | | } |
| | | } |