wujingjing
2025-02-19 404600d8352b4ecac6daf963b63e01bec543fcb3
src/components/chat/Chat.vue
@@ -21,17 +21,20 @@
      <!-- 输入区域 -->
      <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>
      <!-- 抽屉 -->
@@ -47,17 +50,17 @@
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';
@@ -75,9 +78,13 @@
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);
@@ -95,10 +102,19 @@
});
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) {
@@ -116,9 +132,19 @@
      ...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(',');
   }
@@ -147,7 +173,6 @@
      };
      const checkReportEmpty = () => {
         const isEmpty = !questionRes?.reports || questionRes?.reports?.length === 0;
         return isEmpty;
      };
      questionStreamByPost(
@@ -158,22 +183,27 @@
            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 = '准备数据分析';
            }
@@ -233,7 +263,7 @@
               }
            }
            const getLastGroup = () => {
               const lastGroup = computedMessageList.value.at(-1).stepGroup.at(-1);
               const lastGroup = computedMessageList.value.at(-1).stepGroup[0];
               return lastGroup;
            };
            const getLastStepList = () => {
@@ -263,24 +293,27 @@
               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;
            }
@@ -395,15 +428,15 @@
   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(() => {
@@ -423,7 +456,19 @@
   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(() => {
@@ -436,9 +481,6 @@
      values: activeChatRoom.value?.title,
   };
   sendChatMessage();
};
const scrollToBottom = () => {
   containerRef.value?.scrollToBottom();
};
const initHistoryChat = () => {