Record scroll test (#2783)

* perf: history add scrollList (#2696)

* perf: chatHistorySlider add virtualList

* perf: chat records add scrollList

* delete console

* perf: ScrollData add ref props

* 优化代码

* optimize code && add line breaks

* add total records display

* finish test

* perf: ScrollComponent load data

* perf: Scroll components load

* perf: scroll code

---------

Co-authored-by: papapatrick <109422393+Patrickill@users.noreply.github.com>
This commit is contained in:
Archer
2024-09-24 17:13:32 +08:00
committed by shilin66
parent 8e0edaace1
commit 5f9479e889
46 changed files with 827 additions and 422 deletions

View File

@@ -28,13 +28,15 @@ const ChatHeader = ({
history,
showHistory,
apps,
onRouteToAppDetail
onRouteToAppDetail,
totalRecordsCount
}: {
history: ChatItemType[];
showHistory?: boolean;
chatData: InitChatResponse;
apps?: AppListItemType[];
onRouteToAppDetail?: () => void;
totalRecordsCount: number;
}) => {
const { t } = useTranslation();
const isPlugin = chatData.app.type === AppTypeEnum.plugin;
@@ -52,9 +54,9 @@ const ChatHeader = ({
{isPc ? (
<>
<PcHeader
totalRecordsCount={totalRecordsCount}
title={chatData.title || t('common:core.chat.New Chat')}
chatModels={chatData.app.chatModels}
history={history}
/>
<Box flex={1} />
</>
@@ -91,6 +93,7 @@ const MobileDrawer = ({
const router = useRouter();
const isTeamChat = router.pathname === '/chat/team';
const [currentTab, setCurrentTab] = useState<TabEnum>(TabEnum.recently);
const getAppList = useCallback(async ({ parentId }: GetResourceFolderListProps) => {
return getMyApps({ parentId }).then((res) =>
res.map<GetResourceListItemResponse>((item) => ({
@@ -102,6 +105,7 @@ const MobileDrawer = ({
);
}, []);
const { onChangeAppId } = useContextSelector(ChatContext, (v) => v);
const onclickApp = (id: string) => {
onChangeAppId(id);
onCloseDrawer();
@@ -251,13 +255,14 @@ const MobileHeader = ({
export const PcHeader = ({
title,
chatModels,
history
totalRecordsCount
}: {
title: string;
chatModels?: string[];
history: ChatItemType[];
totalRecordsCount: number;
}) => {
const { t } = useTranslation();
return (
<>
<Box mr={3} maxW={'200px'} className="textEllipsis" color={'myGray.1000'}>
@@ -266,9 +271,9 @@ export const PcHeader = ({
<MyTag>
<MyIcon name={'history'} w={'14px'} />
<Box ml={1}>
{history.length === 0
{totalRecordsCount === 0
? t('common:core.chat.New Chat')
: t('common:core.chat.History Amount', { amount: history.length })}
: t('common:core.chat.History Amount', { amount: totalRecordsCount })}
</Box>
</MyTag>
{!!chatModels && chatModels.length > 0 && (

View File

@@ -1,7 +1,7 @@
import React, { useCallback, useMemo, useState } from 'react';
import NextHead from '@/components/common/NextHead';
import { useRouter } from 'next/router';
import { delChatRecordById, getChatHistories, getInitChatInfo } from '@/web/core/chat/api';
import { delChatRecordById, getInitChatInfo } from '@/web/core/chat/api';
import { Box, Flex, Drawer, DrawerOverlay, DrawerContent, useTheme } from '@chakra-ui/react';
import { streamFetch } from '@/web/common/api/fetch';
import { useChatStore } from '@/web/core/chat/context/storeChat';
@@ -16,17 +16,15 @@ import SliderApps from './components/SliderApps';
import ChatHeader from './components/ChatHeader';
import { useUserStore } from '@/web/support/user/useUserStore';
import { serviceSideProps } from '@/web/common/utils/i18n';
import { checkChatSupportSelectFileByChatModels } from '@/web/core/chat/utils';
import { getChatTitleFromChatMessage } from '@fastgpt/global/core/chat/utils';
import { ChatStatusEnum } from '@fastgpt/global/core/chat/constants';
import { GPTMessages2Chats } from '@fastgpt/global/core/chat/adapt';
import { getMyApps } from '@/web/core/app/api';
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
import { useMount } from 'ahooks';
import { useCreation, useMount } from 'ahooks';
import { getNanoid } from '@fastgpt/global/common/string/tools';
import { InitChatResponse } from '@/global/core/chat/api';
import { defaultChatData } from '@/global/core/chat/constants';
import { defaultChatData, GetChatTypeEnum } from '@/global/core/chat/constants';
import ChatContextProvider, { ChatContext } from '@/web/core/chat/context/chatContext';
import { AppListItemType } from '@fastgpt/global/core/app/type';
import { useContextSelector } from 'use-context-selector';
@@ -35,6 +33,7 @@ import dynamic from 'next/dynamic';
import { useChat } from '@/components/core/chat/ChatContainer/useChat';
import ChatBox from '@/components/core/chat/ChatContainer/ChatBox';
import { useSystem } from '@fastgpt/web/hooks/useSystem';
import { InitChatResponse } from '@/global/core/chat/api';
const CustomPluginRunBox = dynamic(() => import('./components/CustomPluginRunBox'));
@@ -50,12 +49,11 @@ const Chat = ({
const router = useRouter();
const theme = useTheme();
const { t } = useTranslation();
const { userInfo } = useUserStore();
const { isPc } = useSystem();
const { setLastChatAppId } = useChatStore();
const {
setHistories: setRecordHistories,
loadHistories: loadRecordHistories,
histories: recordHistories,
onUpdateHistory,
onClearHistories,
onDelHistory,
@@ -65,39 +63,43 @@ const Chat = ({
onChangeChatId,
onUpdateHistoryTitle
} = useContextSelector(ChatContext, (v) => v);
const params = useCreation(() => {
return {
chatId,
appId,
type: GetChatTypeEnum.normal
};
}, [appId, chatId]);
const {
ChatBoxRef,
chatRecords,
setChatRecords,
variablesForm,
pluginRunTab,
setPluginRunTab,
resetChatRecords
resetVariables,
useChatScrollData
} = useChat();
const { userInfo } = useUserStore();
const { isPc } = useSystem();
const {
data: chatRecords,
ScrollData,
setData: setChatRecords,
total: totalRecordsCount
} = useChatScrollData(params);
// get chat app info
const [chatData, setChatData] = useState<InitChatResponse>(defaultChatData);
const isPlugin = chatData.app.type === AppTypeEnum.plugin;
const { loading } = useRequest2(
// Load chat init data
const { loading: isLoading } = useRequest2(
async () => {
if (!appId || forbidLoadChat.current) return;
const res = await getInitChatInfo({ appId, chatId });
setChatData(res);
const history = res.history.map((item) => ({
...item,
dataId: item.dataId || getNanoid(),
status: ChatStatusEnum.finish
}));
// reset chat records
resetChatRecords({
records: history,
// reset chat variables
resetVariables({
variables: res.variables
});
@@ -162,6 +164,7 @@ const Chat = ({
},
[chatId, appId, onUpdateHistoryTitle, forbidLoadChat, onChangeChatId]
);
const loading = isLoading;
return (
<Flex h={'100%'}>
@@ -223,6 +226,7 @@ const Chat = ({
>
{/* header */}
<ChatHeader
totalRecordsCount={totalRecordsCount}
apps={myApps}
chatData={chatData}
history={chatRecords}
@@ -247,6 +251,7 @@ const Chat = ({
/>
) : (
<ChatBox
ScrollData={ScrollData}
ref={ChatBoxRef}
chatHistories={chatRecords}
setChatHistories={setChatRecords}

View File

@@ -28,7 +28,7 @@ import NextHead from '@/components/common/NextHead';
import { useContextSelector } from 'use-context-selector';
import ChatContextProvider, { ChatContext } from '@/web/core/chat/context/chatContext';
import { InitChatResponse } from '@/global/core/chat/api';
import { defaultChatData } from '@/global/core/chat/constants';
import { defaultChatData, GetChatTypeEnum } from '@/global/core/chat/constants';
import { useMount } from 'ahooks';
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
@@ -92,13 +92,27 @@ const OutLink = ({
const {
ChatBoxRef,
chatRecords,
setChatRecords,
variablesForm,
pluginRunTab,
setPluginRunTab,
resetChatRecords
resetVariables,
useChatScrollData
} = useChat();
const params = useMemo(() => {
return {
chatId,
shareId,
outLinkUid,
appId: chatData.appId,
type: GetChatTypeEnum.outLink
};
}, [chatData.appId, chatId, outLinkUid, shareId]);
const {
data: chatRecords,
ScrollData,
setData: setChatRecords,
total: totalRecordsCount
} = useChatScrollData(params);
const startChat = useCallback(
async ({
@@ -179,7 +193,7 @@ const OutLink = ({
]
);
const { loading } = useRequest2(
const { loading: isLoading } = useRequest2(
async () => {
if (!shareId || !outLinkUid || forbidLoadChat.current) return;
@@ -190,14 +204,7 @@ const OutLink = ({
});
setChatData(res);
const history = res.history.map((item) => ({
...item,
dataId: item.dataId || nanoid(),
status: ChatStatusEnum.finish
}));
resetChatRecords({
records: history,
resetVariables({
variables: res.variables
});
},
@@ -229,6 +236,7 @@ const OutLink = ({
useMount(() => {
setIdEmbed(window !== top);
});
const loading = isLoading;
return (
<>
@@ -303,6 +311,7 @@ const OutLink = ({
<ChatHeader
chatData={chatData}
history={chatRecords}
totalRecordsCount={totalRecordsCount}
showHistory={showHistory === '1'}
/>
) : null}
@@ -322,6 +331,7 @@ const OutLink = ({
/>
) : (
<ChatBox
ScrollData={ScrollData}
ref={ChatBoxRef}
chatHistories={chatRecords}
setChatHistories={setChatRecords}

View File

@@ -26,7 +26,7 @@ import ChatContextProvider, { ChatContext } from '@/web/core/chat/context/chatCo
import { AppListItemType } from '@fastgpt/global/core/app/type';
import { useContextSelector } from 'use-context-selector';
import { InitChatResponse } from '@/global/core/chat/api';
import { defaultChatData } from '@/global/core/chat/constants';
import { defaultChatData, GetChatTypeEnum } from '@/global/core/chat/constants';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import { getNanoid } from '@fastgpt/global/common/string/tools';
import { useChat } from '@/components/core/chat/ChatContainer/useChat';
@@ -58,7 +58,6 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
const {
onUpdateHistoryTitle,
loadHistories,
onUpdateHistory,
onClearHistories,
onDelHistory,
@@ -70,13 +69,27 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
const {
ChatBoxRef,
chatRecords,
setChatRecords,
variablesForm,
pluginRunTab,
setPluginRunTab,
resetChatRecords
resetVariables,
useChatScrollData
} = useChat();
const params = useMemo(() => {
return {
appId,
chatId,
teamId,
teamToken,
type: GetChatTypeEnum.team
};
}, [appId, chatId, teamId, teamToken]);
const {
data: chatRecords,
ScrollData,
setData: setChatRecords,
total: totalRecordsCount
} = useChatScrollData(params);
const startChat = useCallback(
async ({
@@ -138,22 +151,15 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
);
// get chat app info
const { loading } = useRequest2(
const { loading: isLoading } = useRequest2(
async () => {
if (!appId || forbidLoadChat.current) return;
const res = await getTeamChatInfo({ teamId, appId, chatId, teamToken });
setChatData(res);
const history = res.history.map((item) => ({
...item,
dataId: item.dataId || nanoid(),
status: ChatStatusEnum.finish
}));
// reset chat records
resetChatRecords({
records: history,
resetVariables({
variables: res.variables
});
},
@@ -175,6 +181,8 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
}
);
const loading = isLoading;
return (
<Flex h={'100%'}>
<NextHead title={chatData.app.name} icon={chatData.app.avatar}></NextHead>
@@ -235,7 +243,13 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
flexDirection={'column'}
>
{/* header */}
<ChatHeader apps={myApps} chatData={chatData} history={chatRecords} showHistory />
<ChatHeader
totalRecordsCount={totalRecordsCount}
apps={myApps}
chatData={chatData}
history={chatRecords}
showHistory
/>
{/* chat box */}
<Box flex={1}>
{chatData.app.type === AppTypeEnum.plugin ? (
@@ -253,6 +267,7 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
) : (
<ChatBox
ref={ChatBoxRef}
ScrollData={ScrollData}
chatHistories={chatRecords}
setChatHistories={setChatRecords}
variablesForm={variablesForm}