Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
赵月辉
/
fastgpt-migrated
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Unverified
Commit
7aa75f8e
authored
Sep 24, 2024
by
Archer
Committed by
GitHub
Sep 24, 2024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: chat page render performance (#2784)
* fix: chat page render performance * fix: ts
parent
afd2c394
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
244 additions
and
202 deletions
+244
-202
docSite/content/zh-cn/docs/development/upgrading/4811.md
+1
-0
projects/app/src/components/core/chat/ChatContainer/useChat.ts
+39
-33
projects/app/src/pages/app/detail/components/Logs/DetailLogsModal.tsx
+4
-7
projects/app/src/pages/chat/components/SliderApps.tsx
+1
-1
projects/app/src/pages/chat/index.tsx
+56
-44
projects/app/src/pages/chat/share.tsx
+78
-66
projects/app/src/pages/chat/team.tsx
+65
-51
No files found.
docSite/content/zh-cn/docs/development/upgrading/4811.md
View file @
7aa75f8e
...
...
@@ -103,3 +103,4 @@ weight: 813
17.
修复 - 知识库选择权限问题。
18.
修复 - 空 chatId 发起对话,首轮携带用户选择时会异常。
19.
修复 - createDataset 接口,intro 为赋值。
20.
修复 - 对话框渲染性能问题。
projects/app/src/components/core/chat/ChatContainer/useChat.ts
View file @
7aa75f8e
...
...
@@ -11,12 +11,12 @@ import { eventBus, EventNameEnum } from '@/web/common/utils/eventbus';
import
{
getChatRecords
}
from
'@/web/core/chat/api'
;
import
{
ChatStatusEnum
}
from
'@fastgpt/global/core/chat/constants'
;
import
{
getNanoid
}
from
'@fastgpt/global/common/string/tools'
;
import
{
GetChatRecordsProps
}
from
'@/global/core/chat/api'
;
import
{
useScrollPagination
}
from
'@fastgpt/web/hooks/useScrollPagination'
;
import
{
PaginationResponse
}
from
'
../../../../../../../packages
/web/common/fetch/type'
;
import
{
PaginationResponse
}
from
'
@fastgpt
/web/common/fetch/type'
;
import
type
{
getPaginationRecordsBody
}
from
'@/pages/api/core/chat/getPaginationRecords'
;
import
{
GetChatTypeEnum
}
from
'@/global/core/chat/constants'
;
export
const
useChat
=
()
=>
{
export
const
useChat
=
(
params
?:
{
chatId
?:
string
;
appId
:
string
;
type
?:
GetChatTypeEnum
}
)
=>
{
const
ChatBoxRef
=
useRef
<
ChatComponentRef
>
(
null
);
const
variablesForm
=
useForm
<
ChatBoxInputFormType
>
();
// plugin
...
...
@@ -49,38 +49,41 @@ export const useChat = () => {
ChatBoxRef
.
current
?.
restartChat
?.();
},
[
variablesForm
]);
const
useChatScrollData
=
useCallback
((
params
:
GetChatRecordsProps
)
=>
{
return
useScrollPagination
(
async
(
data
:
getPaginationRecordsBody
):
Promise
<
PaginationResponse
<
ChatSiteItemType
>>
=>
{
const
res
=
await
getChatRecords
(
data
);
const
{
data
:
chatRecords
,
ScrollData
,
setData
:
setChatRecords
,
total
:
totalRecordsCount
}
=
useScrollPagination
(
async
(
data
:
getPaginationRecordsBody
):
Promise
<
PaginationResponse
<
ChatSiteItemType
>>
=>
{
const
res
=
await
getChatRecords
(
data
);
// First load scroll to bottom
if
(
data
.
offset
===
0
)
{
function
scrollToBottom
()
{
requestAnimationFrame
(
ChatBoxRef
?.
current
?
()
=>
ChatBoxRef
?.
current
?.
scrollToBottom
?.()
:
scrollToBottom
);
}
scrollToBottom
();
// First load scroll to bottom
if
(
data
.
offset
===
0
)
{
function
scrollToBottom
()
{
requestAnimationFrame
(
ChatBoxRef
?.
current
?
()
=>
ChatBoxRef
?.
current
?.
scrollToBottom
?.()
:
scrollToBottom
);
}
return
{
...
res
,
list
:
res
.
list
.
map
((
item
)
=>
({
...
item
,
dataId
:
item
.
dataId
||
getNanoid
(),
status
:
ChatStatusEnum
.
finish
}))
};
},
{
pageSize
:
10
,
refreshDeps
:
[
params
],
params
,
scrollLoadType
:
'top'
scrollToBottom
();
}
);
},
[]);
return
{
...
res
,
list
:
res
.
list
.
map
((
item
)
=>
({
...
item
,
dataId
:
item
.
dataId
||
getNanoid
(),
status
:
ChatStatusEnum
.
finish
}))
};
},
{
pageSize
:
10
,
refreshDeps
:
[
params
],
params
,
scrollLoadType
:
'top'
}
);
return
{
ChatBoxRef
,
...
...
@@ -89,7 +92,10 @@ export const useChat = () => {
setPluginRunTab
,
clearChatRecords
,
resetVariables
,
useChatScrollData
chatRecords
,
ScrollData
,
setChatRecords
,
totalRecordsCount
};
};
...
...
projects/app/src/pages/app/detail/components/Logs/DetailLogsModal.tsx
View file @
7aa75f8e
...
...
@@ -47,14 +47,11 @@ const DetailLogsModal = ({
pluginRunTab
,
setPluginRunTab
,
resetVariables
,
useChatScrollData
}
=
useChat
();
const
{
data
:
chatRecords
,
chatRecords
,
ScrollData
,
set
Data
:
set
ChatRecords
,
total
:
total
RecordsCount
}
=
useChat
ScrollData
(
params
);
setChatRecords
,
totalRecordsCount
}
=
useChat
(
params
);
const
{
data
:
chat
,
isFetching
}
=
useQuery
(
[
'getChatDetail'
,
chatId
],
...
...
projects/app/src/pages/chat/components/SliderApps.tsx
View file @
7aa75f8e
...
...
@@ -164,4 +164,4 @@ const SliderApps = ({ apps, activeAppId }: { apps: AppListItemType[]; activeAppI
);
};
export
default
SliderApps
;
export
default
React
.
memo
(
SliderApps
)
;
projects/app/src/pages/chat/index.tsx
View file @
7aa75f8e
...
...
@@ -77,14 +77,11 @@ const Chat = ({
pluginRunTab
,
setPluginRunTab
,
resetVariables
,
useChatScrollData
}
=
useChat
();
const
{
data
:
chatRecords
,
chatRecords
,
ScrollData
,
set
Data
:
set
ChatRecords
,
total
:
total
RecordsCount
}
=
useChat
ScrollData
(
params
);
setChatRecords
,
totalRecordsCount
}
=
useChat
(
params
);
// get chat app info
const
[
chatData
,
setChatData
]
=
useState
<
InitChatResponse
>
(
defaultChatData
);
...
...
@@ -166,6 +163,57 @@ const Chat = ({
);
const
loading
=
isLoading
;
const
RenderHistorySlider
=
useMemo
(()
=>
{
const
Children
=
(
<
ChatHistorySlider
confirmClearText=
{
t
(
'common:core.chat.Confirm to clear history'
)
}
appId=
{
appId
}
appName=
{
chatData
.
app
.
name
}
appAvatar=
{
chatData
.
app
.
avatar
}
onDelHistory=
{
(
e
)
=>
onDelHistory
({
...
e
,
appId
})
}
onClearHistory=
{
()
=>
{
onClearHistories
({
appId
});
}
}
onSetHistoryTop=
{
(
e
)
=>
{
onUpdateHistory
({
...
e
,
appId
});
}
}
onSetCustomTitle=
{
async
(
e
)
=>
{
onUpdateHistory
({
appId
,
chatId
:
e
.
chatId
,
customTitle
:
e
.
title
});
}
}
/>
);
return
isPc
||
!
appId
?
(
<
SideBar
>
{
Children
}
</
SideBar
>
)
:
(
<
Drawer
isOpen=
{
isOpenSlider
}
placement=
"left"
autoFocus=
{
false
}
size=
{
'xs'
}
onClose=
{
onCloseSlider
}
>
<
DrawerOverlay
backgroundColor=
{
'rgba(255,255,255,0.5)'
}
/>
<
DrawerContent
maxWidth=
{
'75vw'
}
>
{
Children
}
</
DrawerContent
>
</
Drawer
>
);
},
[
appId
,
chatData
.
app
.
avatar
,
chatData
.
app
.
name
,
isOpenSlider
,
isPc
,
onClearHistories
,
onCloseSlider
,
onDelHistory
,
onUpdateHistory
,
t
]);
return
(
<
Flex
h=
{
'100%'
}
>
<
NextHead
title=
{
chatData
.
app
.
name
}
icon=
{
chatData
.
app
.
avatar
}
></
NextHead
>
...
...
@@ -179,43 +227,7 @@ const Chat = ({
<
PageContainer
isLoading=
{
loading
}
flex=
{
'1 0 0'
}
w=
{
0
}
p=
{
[
0
,
'16px'
]
}
position=
{
'relative'
}
>
<
Flex
h=
{
'100%'
}
flexDirection=
{
[
'column'
,
'row'
]
}
>
{
/* pc always show history. */
}
{
((
children
:
React
.
ReactNode
)
=>
{
return
isPc
||
!
appId
?
(
<
SideBar
>
{
children
}
</
SideBar
>
)
:
(
<
Drawer
isOpen=
{
isOpenSlider
}
placement=
"left"
autoFocus=
{
false
}
size=
{
'xs'
}
onClose=
{
onCloseSlider
}
>
<
DrawerOverlay
backgroundColor=
{
'rgba(255,255,255,0.5)'
}
/>
<
DrawerContent
maxWidth=
{
'75vw'
}
>
{
children
}
</
DrawerContent
>
</
Drawer
>
);
})(
<
ChatHistorySlider
confirmClearText=
{
t
(
'common:core.chat.Confirm to clear history'
)
}
appId=
{
appId
}
appName=
{
chatData
.
app
.
name
}
appAvatar=
{
chatData
.
app
.
avatar
}
onDelHistory=
{
(
e
)
=>
onDelHistory
({
...
e
,
appId
})
}
onClearHistory=
{
()
=>
{
onClearHistories
({
appId
});
}
}
onSetHistoryTop=
{
(
e
)
=>
{
onUpdateHistory
({
...
e
,
appId
});
}
}
onSetCustomTitle=
{
async
(
e
)
=>
{
onUpdateHistory
({
appId
,
chatId
:
e
.
chatId
,
customTitle
:
e
.
title
});
}
}
/>
)
}
{
RenderHistorySlider
}
{
/* chat container */
}
<
Flex
position=
{
'relative'
}
...
...
projects/app/src/pages/chat/share.tsx
View file @
7aa75f8e
...
...
@@ -4,11 +4,7 @@ import { Box, Flex, Drawer, DrawerOverlay, DrawerContent } from '@chakra-ui/reac
import
{
streamFetch
}
from
'@/web/common/api/fetch'
;
import
SideBar
from
'@/components/SideBar'
;
import
{
GPTMessages2Chats
}
from
'@fastgpt/global/core/chat/adapt'
;
import
{
customAlphabet
}
from
'nanoid'
;
const
nanoid
=
customAlphabet
(
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWSYZ1234567890_'
,
24
);
import
ChatBox
from
'@/components/core/chat/ChatContainer/ChatBox'
;
import
type
{
StartChatFnProps
}
from
'@/components/core/chat/ChatContainer/type'
;
...
...
@@ -19,7 +15,6 @@ import { serviceSideProps } from '@/web/common/utils/i18n';
import
{
useTranslation
}
from
'next-i18next'
;
import
{
delChatRecordById
,
getInitOutLinkChatInfo
}
from
'@/web/core/chat/api'
;
import
{
getChatTitleFromChatMessage
}
from
'@fastgpt/global/core/chat/utils'
;
import
{
ChatStatusEnum
}
from
'@fastgpt/global/core/chat/constants'
;
import
{
MongoOutLink
}
from
'@fastgpt/service/support/outLink/schema'
;
import
{
OutLinkWithAppType
}
from
'@fastgpt/global/support/outLink/type'
;
import
{
addLog
}
from
'@fastgpt/service/common/system/log'
;
...
...
@@ -87,14 +82,6 @@ const OutLink = ({
onChangeChatId
}
=
useContextSelector
(
ChatContext
,
(
v
)
=>
v
);
const
{
ChatBoxRef
,
variablesForm
,
pluginRunTab
,
setPluginRunTab
,
resetVariables
,
useChatScrollData
}
=
useChat
();
const
params
=
useMemo
(()
=>
{
return
{
chatId
,
...
...
@@ -105,11 +92,16 @@ const OutLink = ({
};
},
[
chatData
.
appId
,
chatId
,
outLinkUid
,
shareId
]);
const
{
data
:
chatRecords
,
ChatBoxRef
,
variablesForm
,
pluginRunTab
,
setPluginRunTab
,
resetVariables
,
chatRecords
,
ScrollData
,
set
Data
:
set
ChatRecords
,
total
:
total
RecordsCount
}
=
useChat
ScrollData
(
params
);
setChatRecords
,
totalRecordsCount
}
=
useChat
(
params
);
const
startChat
=
useCallback
(
async
({
...
...
@@ -233,6 +225,73 @@ const OutLink = ({
useMount
(()
=>
{
setIdEmbed
(
window
!==
top
);
});
const
RenderHistoryList
=
useMemo
(()
=>
{
const
Children
=
(
<
ChatHistorySlider
appName=
{
chatData
.
app
.
name
}
appAvatar=
{
chatData
.
app
.
avatar
}
confirmClearText=
{
t
(
'common:core.chat.Confirm to clear share chat history'
)
}
onDelHistory=
{
({
chatId
})
=>
onDelHistory
({
appId
:
chatData
.
appId
,
chatId
,
shareId
,
outLinkUid
})
}
onClearHistory=
{
()
=>
{
onClearHistories
({
shareId
,
outLinkUid
});
}
}
onSetHistoryTop=
{
(
e
)
=>
{
onUpdateHistory
({
...
e
,
appId
:
chatData
.
appId
,
shareId
,
outLinkUid
});
}
}
onSetCustomTitle=
{
(
e
)
=>
{
onUpdateHistory
({
appId
:
chatData
.
appId
,
chatId
:
e
.
chatId
,
customTitle
:
e
.
title
,
shareId
,
outLinkUid
});
}
}
/>
);
if
(
showHistory
!==
'1'
)
return
null
;
return
isPc
?
(
<
SideBar
>
{
Children
}
</
SideBar
>
)
:
(
<
Drawer
isOpen=
{
isOpenSlider
}
placement=
"left"
autoFocus=
{
false
}
size=
{
'xs'
}
onClose=
{
onCloseSlider
}
>
<
DrawerOverlay
backgroundColor=
{
'rgba(255,255,255,0.5)'
}
/>
<
DrawerContent
maxWidth=
{
'75vw'
}
boxShadow=
{
'2px 0 10px rgba(0,0,0,0.15)'
}
>
{
Children
}
</
DrawerContent
>
</
Drawer
>
);
},
[
chatData
.
app
.
avatar
,
chatData
.
app
.
name
,
chatData
.
appId
,
isOpenSlider
,
isPc
,
onClearHistories
,
onCloseSlider
,
onDelHistory
,
onUpdateHistory
,
outLinkUid
,
shareId
,
showHistory
,
t
]);
const
loading
=
isLoading
;
return
(
...
...
@@ -244,54 +303,7 @@ const OutLink = ({
:
{
p
:
[0,
5]
})}
>
<
Flex
h=
{
'100%'
}
flexDirection=
{
[
'column'
,
'row'
]
}
>
{
showHistory
===
'1'
&&
((
children
:
React
.
ReactNode
)
=>
{
return
isPc
?
(
<
SideBar
>
{
children
}
</
SideBar
>
)
:
(
<
Drawer
isOpen=
{
isOpenSlider
}
placement=
"left"
autoFocus=
{
false
}
size=
{
'xs'
}
onClose=
{
onCloseSlider
}
>
<
DrawerOverlay
backgroundColor=
{
'rgba(255,255,255,0.5)'
}
/>
<
DrawerContent
maxWidth=
{
'75vw'
}
boxShadow=
{
'2px 0 10px rgba(0,0,0,0.15)'
}
>
{
children
}
</
DrawerContent
>
</
Drawer
>
);
})(
<
ChatHistorySlider
appName=
{
chatData
.
app
.
name
}
appAvatar=
{
chatData
.
app
.
avatar
}
confirmClearText=
{
t
(
'common:core.chat.Confirm to clear share chat history'
)
}
onDelHistory=
{
({
chatId
})
=>
onDelHistory
({
appId
:
chatData
.
appId
,
chatId
,
shareId
,
outLinkUid
})
}
onClearHistory=
{
()
=>
{
onClearHistories
({
shareId
,
outLinkUid
});
}
}
onSetHistoryTop=
{
(
e
)
=>
{
onUpdateHistory
({
...
e
,
appId
:
chatData
.
appId
,
shareId
,
outLinkUid
});
}
}
onSetCustomTitle=
{
(
e
)
=>
{
onUpdateHistory
({
appId
:
chatData
.
appId
,
chatId
:
e
.
chatId
,
customTitle
:
e
.
title
,
shareId
,
outLinkUid
});
}
}
/>
)
}
{
RenderHistoryList
}
{
/* chat container */
}
<
Flex
...
...
projects/app/src/pages/chat/team.tsx
View file @
7aa75f8e
...
...
@@ -67,14 +67,6 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
onChangeChatId
}
=
useContextSelector
(
ChatContext
,
(
v
)
=>
v
);
const
{
ChatBoxRef
,
variablesForm
,
pluginRunTab
,
setPluginRunTab
,
resetVariables
,
useChatScrollData
}
=
useChat
();
const
params
=
useMemo
(()
=>
{
return
{
appId
,
...
...
@@ -85,11 +77,16 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
};
},
[
appId
,
chatId
,
teamId
,
teamToken
]);
const
{
data
:
chatRecords
,
ChatBoxRef
,
variablesForm
,
pluginRunTab
,
setPluginRunTab
,
resetVariables
,
chatRecords
,
ScrollData
,
set
Data
:
set
ChatRecords
,
total
:
total
RecordsCount
}
=
useChat
ScrollData
(
params
);
setChatRecords
,
totalRecordsCount
}
=
useChat
(
params
);
const
startChat
=
useCallback
(
async
({
...
...
@@ -181,6 +178,61 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
}
);
const
RenderHistoryList
=
useMemo
(()
=>
{
const
Children
=
(
<
ChatHistorySlider
appId=
{
appId
}
appName=
{
chatData
.
app
.
name
}
appAvatar=
{
chatData
.
app
.
avatar
}
confirmClearText=
{
t
(
'common:core.chat.Confirm to clear history'
)
}
onDelHistory=
{
(
e
)
=>
onDelHistory
({
...
e
,
appId
,
teamId
,
teamToken
})
}
onClearHistory=
{
()
=>
{
onClearHistories
({
appId
,
teamId
,
teamToken
});
}
}
onSetHistoryTop=
{
(
e
)
=>
{
onUpdateHistory
({
...
e
,
teamId
,
teamToken
,
appId
});
}
}
onSetCustomTitle=
{
async
(
e
)
=>
{
onUpdateHistory
({
appId
,
chatId
:
e
.
chatId
,
customTitle
:
e
.
title
,
teamId
,
teamToken
});
}
}
/>
);
return
isPc
||
!
appId
?
(
<
SideBar
>
{
Children
}
</
SideBar
>
)
:
(
<
Drawer
isOpen=
{
isOpenSlider
}
placement=
"left"
autoFocus=
{
false
}
size=
{
'xs'
}
onClose=
{
onCloseSlider
}
>
<
DrawerOverlay
backgroundColor=
{
'rgba(255,255,255,0.5)'
}
/>
<
DrawerContent
maxWidth=
{
'75vw'
}
>
{
Children
}
</
DrawerContent
>
</
Drawer
>
);
},
[
appId
,
chatData
.
app
.
avatar
,
chatData
.
app
.
name
,
isOpenSlider
,
isPc
,
onClearHistories
,
onCloseSlider
,
onDelHistory
,
onUpdateHistory
,
t
,
teamId
,
teamToken
]);
const
loading
=
isLoading
;
return
(
...
...
@@ -195,45 +247,7 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
<
PageContainer
isLoading=
{
loading
}
flex=
{
'1 0 0'
}
w=
{
0
}
p=
{
[
0
,
'16px'
]
}
position=
{
'relative'
}
>
<
Flex
h=
{
'100%'
}
flexDirection=
{
[
'column'
,
'row'
]
}
bg=
{
'white'
}
>
{
((
children
:
React
.
ReactNode
)
=>
{
return
isPc
||
!
appId
?
(
<
SideBar
>
{
children
}
</
SideBar
>
)
:
(
<
Drawer
isOpen=
{
isOpenSlider
}
placement=
"left"
autoFocus=
{
false
}
size=
{
'xs'
}
onClose=
{
onCloseSlider
}
>
<
DrawerOverlay
backgroundColor=
{
'rgba(255,255,255,0.5)'
}
/>
<
DrawerContent
maxWidth=
{
'75vw'
}
>
{
children
}
</
DrawerContent
>
</
Drawer
>
);
})(
<
ChatHistorySlider
appId=
{
appId
}
appName=
{
chatData
.
app
.
name
}
appAvatar=
{
chatData
.
app
.
avatar
}
confirmClearText=
{
t
(
'common:core.chat.Confirm to clear history'
)
}
onDelHistory=
{
(
e
)
=>
onDelHistory
({
...
e
,
appId
,
teamId
,
teamToken
})
}
onClearHistory=
{
()
=>
{
onClearHistories
({
appId
,
teamId
,
teamToken
});
}
}
onSetHistoryTop=
{
(
e
)
=>
{
onUpdateHistory
({
...
e
,
teamId
,
teamToken
,
appId
});
}
}
onSetCustomTitle=
{
async
(
e
)
=>
{
onUpdateHistory
({
appId
,
chatId
:
e
.
chatId
,
customTitle
:
e
.
title
,
teamId
,
teamToken
});
}
}
/>
)
}
{
RenderHistoryList
}
{
/* chat container */
}
<
Flex
position=
{
'relative'
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment