wujingjing
2024-12-14 1476d27514874e9c95002451a81878bd9bec8382
src/components/chat/hooks/useScrollLoad.ts
@@ -1,13 +1,48 @@
import { Ref, ShallowRef, nextTick, onBeforeUnmount, ref, unref } from 'vue';
import moment from 'moment';
import { Ref, ShallowRef, computed, nextTick, onBeforeUnmount, ref, unref } from 'vue';
import { LOAD_CHAT_LIMIT } from '../constants';
import { AnswerType, ChatContent, ChatMessage, RoleEnum } from '../model/types';
import { GetHistoryAnswer, QueryHistoryDetail } from '/@/api/ai/chat';
import { AnswerType, ChatContent, ChatMessage, MultiChatType, RoleEnum, StepEnum, StepItem } from '../model/types';
import { GetHistoryAnswer, QueryHistoryDetail, getShareChatJsonByPost } from '/@/api/ai/chat';
import router from '/@/router';
import { isSharePage } from '/@/stores/chatRoom';
type UseScrollLoadOption = {
   container: ShallowRef<HTMLDivElement>;
   historyGroupId: string | Ref<string>;
   messageList: Ref<ChatMessage[]>;
   parseAnswerContent: (res: any) => ChatContent;
};
export const convertProcessItem = (processItem: any) => {
   switch (processItem.mode) {
      case 'begin':
         break;
      case 'end':
         break;
   }
   return {
      status: StepEnum.Success,
      title: processItem.value,
   } as StepItem;
};
export const convertProcessToStep = (process: any[]) => {
   const stepList = (process ?? []).reduce((preVal, curVal) => {
      if (curVal.mode === 'question') {
         const last = preVal.at(-1);
         if (!last.subStep) {
            last.subStep = [];
         }
         const sub = {
            data: curVal.value,
            type: MultiChatType.Select,
         };
         last.subStep.push(sub);
      } else {
         const cur = convertProcessItem(curVal);
         preVal.push(cur);
      }
      return preVal;
   }, []);
   return stepList;
};
/**
@@ -28,12 +63,17 @@
         history_id: historyId,
      });
   };
   const formatShowTimeYear = computed(() => {
      return (str) => {
         return moment(str).format('MM月DD日 HH:mm:ss');
      };
   });
   /**
    * 获取用户回复数据,并插入到对话当中去
    */
   const loadReplyData = async (userMsg: any[]) => {
      const sectionAIdMap = new Map();
      const userItemIdMap = new Map();
      // 用户消息
      const tmpMessageList: ChatMessage[] = userMsg.map((item) => {
         return {
            historyId: item.history_id,
@@ -42,11 +82,12 @@
               type: AnswerType.Text,
               values: item.question,
            },
            isChecked: false,
         } as ChatMessage;
      });
      const resList = await Promise.all(
         (userMsg ?? []).map((item) => {
            sectionAIdMap.set(item.history_id, item.section_a_id);
            userItemIdMap.set(item.history_id, item);
            return getAnswerById(item.history_id);
         })
      );
@@ -55,6 +96,10 @@
         const insertIndex = index + 1 + i;
         const currentUserMsg = tmpMessageList[insertIndex - 1];
         currentUserMsg.content.values = item?.answer?.question ?? currentUserMsg.content.values;
         const mapUser = userItemIdMap.get(item.answer?.history_id);
         const answerTime = formatShowTimeYear.value(mapUser?.create_time);
         tmpMessageList.splice(
            insertIndex,
            0,
@@ -65,7 +110,14 @@
                     role: RoleEnum.assistant,
                     content: parseAnswerContent(item.answer),
                     state: item.answer_state,
                     sectionAId: sectionAIdMap.get(item.answer.history_id),
                     sectionAId: mapUser?.section_a_id,
                     createTime: answerTime,
                     stepList: convertProcessToStep(item?.answer?.exec_process),
                     stepIsShow: false,
                     isStopMsg: false,
                     conclusion: item?.answer?.conclusion ?? [],
                     isChecked: false,
                 }
         );
         i++;
@@ -75,9 +127,50 @@
   };
   /**
    * 加载分享数据
    */
   const loadShareData = async () => {
      const res = await getShareChatJsonByPost({
         share_id: router.currentRoute.value.query.id as string,
      });
      const msgValue = res?.values;
      if (!msgValue) {
         messageList.value = [];
         return;
      }
      const userMsg: ChatMessage = {
         historyId: msgValue.history_id,
         role: RoleEnum.user,
         content: {
            type: AnswerType.Text,
            values: msgValue.question,
         },
         isChecked: false,
      };
      const assistantMsg: ChatMessage = {
         historyId: msgValue.history_id,
         role: RoleEnum.assistant,
         content: parseAnswerContent(msgValue),
         stepList: convertProcessToStep(msgValue.exec_process),
         stepIsShow: false,
         isStopMsg: false,
         conclusion: msgValue.conclusion ?? [],
         isChecked: false,
      };
      messageList.value = [userMsg, assistantMsg];
   };
   /**
    * 加载滚动范围数据
    */
   const loadRangeData = async (lastEnd = nextUserMsgEndIndex.value) => {
      if (isSharePage.value) {
         await loadShareData();
         return;
      }
      const res = await QueryHistoryDetail({
         history_group_id: unref(historyGroupId),
         last_end: lastEnd,
@@ -97,7 +190,6 @@
   //滚动监听
   async function onChatListScroll() {
      if (container.value.scrollTop == 0) {
         // 更多数据正在加载时
         if (moreIsLoading.value) {
            return;
@@ -113,9 +205,9 @@
            moreIsLoading.value = false;
         });
         //更新后,等待页面渲染完毕再去拿scrollHeight,否则拿到的是之前的
         nextTick(()=>{
            nextTick(()=>{
               nextTick(()=>{
         nextTick(() => {
            nextTick(() => {
               nextTick(() => {
                  let h2 = container.value.scrollHeight;
                  container.value.scrollTo({
                     //顶部在原先基础上往下滚动50px,露出新加载数据的一点
@@ -123,10 +215,9 @@
                     top: h2 - h1,
                     behavior: 'instant', //auto-自动滚动 instant-瞬间滚动 smooth-平滑滚动
                  });
               })
            })
         })
               });
            });
         });
      }
   }