| | |
| | | |
| | | <!-- 输入区域 --> |
| | | <template #input-area> |
| | | <PlayBar |
| | | ref="playBarRef" |
| | | v-model:voicePageIsShow="voicePageIsShow" |
| | | :isTalking="isTalking" |
| | | :isHome="false" |
| | | :msgList="computedMessageList" |
| | | v-model="messageContent.values" |
| | | @sendClick="sendClick" |
| | | @stopGenClick="stopGenClick" |
| | | :style="{ width: chatWidth }" |
| | | /> |
| | | <div class="w-full"> |
| | | <PlayBar |
| | | ref="playBarRef" |
| | | v-model:voicePageIsShow="voicePageIsShow" |
| | | :isTalking="isTalking" |
| | | :isHome="false" |
| | | :msgList="computedMessageList" |
| | | v-model="messageContent.values" |
| | | @sendClick="sendClick" |
| | | @stopGenClick="stopGenClick" |
| | | :style="{ width: chatWidth }" |
| | | class="mx-auto" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <!-- 抽屉 --> |
| | |
| | | import axios from 'axios'; |
| | | import { orderBy } from 'lodash-es'; |
| | | import moment from 'moment'; |
| | | import { computed, onActivated, onMounted, ref } from 'vue'; |
| | | import { computed, nextTick, onActivated, onMounted, ref } from 'vue'; |
| | | import { loadAmisSource } from '../amis/load'; |
| | | import { useScrollLoad } from './hooks/useScrollLoad'; |
| | | import { useScrollLoad } from './hooks/useScrollLoad'; |
| | | import type { ChatContent } from './model/types'; |
| | | import { AnswerState, AnswerType, RoleEnum, type ChatMessage } from './model/types'; |
| | | import { getShareChatJsonByPost, questionStreamByPost } from '/@/api/ai/chat'; |
| | | import PlayBar from '/@/components/chat/components/playBar/PlayBar.vue'; |
| | | import CustomDrawer from '/@/components/drawer/CustomDrawer.vue'; |
| | | import { Logger } from '/@/model/logger/Logger'; |
| | | |
| | | import { ElMessage } from 'element-plus'; |
| | | import { triggerRef } from 'vue'; |
| | | import { ElLoadingService, ElMessage } from 'element-plus'; |
| | | import ChatContainer from './components/ChatContainer.vue'; |
| | | import ShareLinkDlg from './components/shareLink/index.vue'; |
| | | import router from '/@/router'; |
| | |
| | | import { useCompRef } from '/@/utils/types'; |
| | | import { toMyFixed } from '/@/utils/util'; |
| | | import { useLoadData } from './hooks/useLoadData'; |
| | | import { useSyncMsg } from './hooks/useSyncMsg'; |
| | | import { getCurrentPosition } from '/@/utils/brower'; |
| | | const containerRef = useCompRef(ChatContainer); |
| | | const chatListDom = computed(() => containerRef.value?.chatListDom); |
| | | |
| | | const scrollToBottom = () => { |
| | | containerRef.value?.scrollToBottom(); |
| | | }; |
| | | const { loadReplyData, parseContent, parseExtraContent, convertProcessItem, convertProcessToStep, formatShowTimeYear } = useLoadData(); |
| | | const voicePageIsShow = ref(false); |
| | | let isTalking = ref(false); |
| | |
| | | }); |
| | | |
| | | let questionRes = null; |
| | | let position = null; |
| | | const preQuestion = ref(null); |
| | | |
| | | let lastAxiosSource: CancelTokenSource = null; |
| | | |
| | | // 通过修改 isTalking 来触发更新 |
| | | const triggerRefresh = () => { |
| | | isTalking.value = !isTalking.value; |
| | | |
| | | nextTick(() => { |
| | | isTalking.value = !isTalking.value; |
| | | }); |
| | | }; |
| | | let position: Position = null; |
| | | const questionAi = async (text) => { |
| | | let judgeParams = null; |
| | | if (!preQuestion.value) { |
| | |
| | | ...judgeParams, |
| | | } as any; |
| | | |
| | | if (!position) { |
| | | const loadingInstance = ElLoadingService({ |
| | | text: '获取位置中...', |
| | | target: '.layout-parent', |
| | | fullscreen:false, |
| | | }); |
| | | position = await getCurrentPosition().finally(() => { |
| | | loadingInstance.close(); |
| | | }); |
| | | } |
| | | |
| | | if (position) { |
| | | const longitude = position.coords.longitude; |
| | | const latitude = position.coords.latitude; |
| | | const { latitude, longitude } = position; |
| | | params.cur_pos = [longitude, latitude].join(','); |
| | | } |
| | | |
| | |
| | | }; |
| | | const checkReportEmpty = () => { |
| | | const isEmpty = !questionRes?.reports || questionRes?.reports?.length === 0; |
| | | |
| | | return isEmpty; |
| | | }; |
| | | questionStreamByPost( |
| | |
| | | if (chunkRes.mode === 'result') { |
| | | lastIsResult = true; |
| | | const res = chunkRes.value; |
| | | |
| | | if (checkReportEmpty()) { |
| | | const resReport = getResReport(); |
| | | resReport.reports.push(res); |
| | | questionRes = resReport; |
| | | // resReport.reports = resReport.reports.concat([]); |
| | | resolve(resReport); |
| | | } else { |
| | | const lastMsg = computedMessageList.value.at(-1); |
| | | |
| | | // lastMsg.content.values = lastMsg.content.values.concat([]); |
| | | // 已经解析过一次 reports |
| | | if (!lastMsg.content.values) { |
| | | lastMsg.content.values = []; |
| | | } |
| | | |
| | | lastMsg.content.values.push({ |
| | | content: parseContent(res, true, { |
| | | origin: res, |
| | | }), |
| | | }); |
| | | } |
| | | triggerRefresh(); |
| | | return; |
| | | // chunkRes.value = '准备数据分析'; |
| | | } |
| | |
| | | } |
| | | } |
| | | const getLastGroup = () => { |
| | | const lastGroup = computedMessageList.value.at(-1).stepGroup.at(-1); |
| | | const lastGroup = computedMessageList.value.at(-1).stepGroup[0]; |
| | | return lastGroup; |
| | | }; |
| | | const getLastStepList = () => { |
| | |
| | | return; |
| | | } |
| | | |
| | | // 暂时不考虑多个 report情况 |
| | | // 暂时不考虑多个 report 情况 |
| | | |
| | | // if (lastIsResult && chunkRes.mode !== 'finish') { |
| | | // // 开始增加新的 stepGroup |
| | | // computedMessageList.value.at(-1).stepGroup.push({ |
| | | // value: [], |
| | | // isShow: true, |
| | | // }); |
| | | // lastIsResult = false; |
| | | // } |
| | | const lastGroup = computedMessageList.value.at(-1).stepGroup.at(-1); |
| | | if (lastIsResult && chunkRes.mode !== 'finish') { |
| | | // const lastTow = computedMessageList.value.at(-1); |
| | | // lastTow.stepGroup.at(-1).value.at(-1).finishLoading = true; |
| | | // lastTow.content.values = lastTow.content.values.concat([]); |
| | | |
| | | // 开始增加新的 stepGroup,后续的 stepGroup 并没有实际作用,只是为了做迭代用,迭代出组件,屎山代码实在太难改了!!! |
| | | computedMessageList.value.at(-1).stepGroup.push({ |
| | | value: [], |
| | | isShow: true, |
| | | }); |
| | | lastIsResult = false; |
| | | } |
| | | const lastGroup = computedMessageList.value.at(-1).stepGroup[0]; |
| | | const stepList = lastGroup?.value ?? []; |
| | | const currentTimeStamp = new Date().getTime(); |
| | | const ms = toMyFixed(currentTimeStamp - lastTimestamp, 2) + ' ms'; |
| | | if (chunkRes.mode === 'finish') { |
| | | stepList.at(-1).ms = ms; |
| | | isTalking.value = false; |
| | | |
| | | return; |
| | | } |
| | | |
| | |
| | | |
| | | try { |
| | | const [userItem, assistantItem] = addChatItem(content); |
| | | |
| | | resMsgContent = await questionAi(content.values); |
| | | |
| | | updateLoadIndex(); |
| | | |
| | | userItem.historyId = questionRes?.history_id; |
| | | const current = moment().format('YYYY-MM-DD HH:mm:ss'); |
| | | userItem.createTime = current; |
| | | userItem.content.values = questionRes?.question ?? userItem.content.values; |
| | | assistantItem.historyId = questionRes?.history_id; |
| | | const currentTime = formatShowTimeYear(moment().format('YYYY-MM-DD HH:mm:ss')); |
| | | const currentTime = formatShowTimeYear(current); |
| | | assistantItem.createTime = currentTime; |
| | | assistantItem.content = resMsgContent; |
| | | setTimeout(() => { |
| | |
| | | messageList, |
| | | loadReplyData, |
| | | }); |
| | | |
| | | useSyncMsg({ |
| | | msgList: messageList, |
| | | updateLoadIndex, |
| | | historyGroupId: currentRouteId, |
| | | checkCanSync: (data) => { |
| | | return !isTalking.value && !moreIsLoading.value; |
| | | }, |
| | | showTip: (data) => { |
| | | playBarRef.value.showSyncTip(data); |
| | | }, |
| | | loadReplyData, |
| | | scrollToBottom, |
| | | }); |
| | | const chatListLoading = ref(true); |
| | | |
| | | onActivated(() => { |
| | |
| | | values: activeChatRoom.value?.title, |
| | | }; |
| | | sendChatMessage(); |
| | | }; |
| | | const scrollToBottom = () => { |
| | | containerRef.value?.scrollToBottom(); |
| | | }; |
| | | |
| | | const initHistoryChat = () => { |