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
29f5cf05
authored
Jun 06, 2026
by
Xianquan
Committed by
GitHub
Jun 06, 2026
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chore: polish chat ui behavior (#7068)
parent
7fe33fb2
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
42 additions
and
89 deletions
+42
-89
projects/app/src/components/Markdown/chat/Guide.tsx
+2
-2
projects/app/src/components/Markdown/index.tsx
+4
-4
projects/app/src/components/core/chat/ChatContainer/ChatBox/Input/ChatInput.tsx
+1
-1
projects/app/src/components/core/chat/ChatContainer/ChatBox/components/WelcomeBox.tsx
+11
-21
projects/app/src/pageComponents/chat/ChatWindow/AppChatWindow.tsx
+1
-5
projects/app/src/pageComponents/chat/ChatWindow/ChatAIModelSelector.tsx
+7
-37
projects/app/src/pageComponents/chat/ChatWindow/HomeChatWindow.tsx
+1
-4
projects/app/src/pageComponents/chat/ChatWindow/MobileModelSelectorDrawer.tsx
+15
-7
projects/app/src/web/core/chat/context/chatPageContext.tsx
+0
-8
No files found.
projects/app/src/components/Markdown/chat/Guide.tsx
View file @
29f5cf05
...
...
@@ -42,7 +42,7 @@ function MyLink(e: any) {
);
}
const
Guide
=
({
text
}:
{
text
:
string
})
=>
{
const
Guide
=
({
text
,
className
}:
{
text
:
string
;
className
?
:
string
})
=>
{
const
formatText
=
useMemo
(
()
=>
text
.
replace
(
/
\[(
.*
?)\](
$|
\n)
/g
,
'[$1]()'
).
replace
(
/
\\
n/g
,
'\n '
),
[
text
]
...
...
@@ -50,7 +50,7 @@ const Guide = ({ text }: { text: string }) => {
return
(
<
ReactMarkdown
className=
{
`markdown ${styles.markdown}`
}
className=
{
`markdown ${styles.markdown}
${className || ''}
`
}
remarkPlugins=
{
[
RemarkGfm
,
RemarkMath
,
RemarkBreaks
]
}
rehypePlugins=
{
[
RehypeKatex
]
}
components=
{
{
...
...
projects/app/src/components/Markdown/index.tsx
View file @
29f5cf05
...
...
@@ -59,7 +59,7 @@ const MarkdownRender = ({
return
{
img
:
(
props
:
any
)
=>
<
Image
{
...
props
}
alt=
{
props
.
alt
}
chatAuthData=
{
chatAuthData
}
/>,
pre
:
RewritePre
,
code
:
Code
,
code
:
(
props
:
any
)
=>
<
Code
{
...
props
}
markdownClassName=
{
className
}
/>
,
table
:
MarkdownTable
as
any
,
a
:
(
props
:
any
)
=>
(
<
A
...
...
@@ -104,7 +104,7 @@ export default React.memo(Markdown);
/* Custom dom */
function
Code
(
e
:
any
)
{
const
{
className
,
codeBlock
,
children
}
=
e
;
const
{
className
,
codeBlock
,
children
,
markdownClassName
}
=
e
;
const
match
=
/language-
(\w
+
)
/
.
exec
(
className
||
''
);
const
codeType
=
match
?.[
1
]?.
toLowerCase
();
...
...
@@ -115,7 +115,7 @@ function Code(e: any) {
return
<
MermaidCodeBlock
code=
{
strChildren
}
/>;
}
if
(
codeType
===
CodeClassNameEnum
.
guide
)
{
return
<
ChatGuide
text=
{
strChildren
}
/>;
return
<
ChatGuide
text=
{
strChildren
}
className=
{
markdownClassName
}
/>;
}
if
(
codeType
===
CodeClassNameEnum
.
questionguide
)
{
return
<
QuestionGuide
text=
{
strChildren
}
/>;
...
...
@@ -145,7 +145,7 @@ function Code(e: any) {
{
children
}
</
CodeLight
>
);
},
[
codeType
,
className
,
codeBlock
,
match
,
children
,
strChildren
]);
},
[
codeType
,
className
,
codeBlock
,
match
,
children
,
strChildren
,
markdownClassName
]);
return
Component
;
}
...
...
projects/app/src/components/core/chat/ChatContainer/ChatBox/Input/ChatInput.tsx
View file @
29f5cf05
...
...
@@ -527,7 +527,7 @@ const ChatInput = ({
{
!
mobilePreSpeak
&&
<
Box
>
{
RenderButtonGroup
}
</
Box
>
}
</
Flex
>
<
ComplianceTip
type=
{
'chat'
}
pt=
{
0
}
pb=
{
[
0
,
6
]
}
/>
<
ComplianceTip
type=
{
'chat'
}
pt=
{
0
}
pb=
{
0
}
/>
</
Box
>
);
};
...
...
projects/app/src/components/core/chat/ChatContainer/ChatBox/components/WelcomeBox.tsx
View file @
29f5cf05
import
{
Box
,
Card
}
from
'@chakra-ui/react'
;
import
{
Box
}
from
'@chakra-ui/react'
;
import
React
from
'react'
;
import
{
MessageCardStyle
}
from
'../constants'
;
import
Markdown
from
'@/components/Markdown'
;
import
ChatAvatar
from
'./ChatAvatar'
;
import
{
useContextSelector
}
from
'use-context-selector'
;
import
{
ChatItemContext
}
from
'@/web/core/chat/context/chatItemContext'
;
import
styles
from
'./AIChatBubble/index.module.scss'
;
const
WelcomeBox
=
({
welcomeText
}:
{
welcomeText
:
string
})
=>
{
const
appAvatar
=
useContextSelector
(
ChatItemContext
,
(
v
)
=>
v
.
chatBoxData
?.
app
?.
avatar
);
return
(
<
Box
py=
{
3
}
>
{
/* avatar */
}
<
ChatAvatar
src=
{
appAvatar
}
type=
{
'AI'
}
/>
{
/* message */
}
<
Box
textAlign=
{
'left'
}
>
<
Card
order=
{
2
}
mt=
{
2
}
{
...
MessageCardStyle
}
bg=
{
'white'
}
boxShadow=
{
'0 0 8px rgba(0,0,0,0.15)'
}
>
<
Markdown
source=
{
`~~~guide \n${welcomeText}`
}
forbidZhFormat
/>
</
Card
>
<
Box
py=
{
3
}
w=
{
'100%'
}
>
<
Box
className=
"chat-box-card"
w=
{
'100%'
}
maxW=
{
[
'calc(100% - 25px)'
,
'700px'
]
}
mx=
{
'auto'
}
>
<
Box
color=
{
'myGray.900'
}
textAlign=
{
'left'
}
fontSize=
{
'16px'
}
lineHeight=
{
1.75
}
>
<
Markdown
className=
{
styles
.
markdown
}
source=
{
`~~~guide \n${welcomeText}`
}
forbidZhFormat
/>
</
Box
>
</
Box
>
</
Box
>
);
...
...
projects/app/src/pageComponents/chat/ChatWindow/AppChatWindow.tsx
View file @
29f5cf05
...
...
@@ -63,7 +63,6 @@ const AppChatWindow = () => {
const
chatSettings
=
useContextSelector
(
ChatPageContext
,
(
v
)
=>
v
.
chatSettings
);
const
handlePaneChange
=
useContextSelector
(
ChatPageContext
,
(
v
)
=>
v
.
handlePaneChange
);
const
refreshRecentlyUsed
=
useContextSelector
(
ChatPageContext
,
(
v
)
=>
v
.
refreshRecentlyUsed
);
const
collapseSidebar
=
useContextSelector
(
ChatPageContext
,
(
v
)
=>
v
.
collapseSidebar
);
const
{
loading
}
=
useRequest
(
async
()
=>
{
...
...
@@ -113,8 +112,6 @@ const AppChatWindow = () => {
return
Promise
.
reject
(
'appId is empty'
);
}
collapseSidebar
();
const
histories
=
messages
.
slice
(
-
1
);
const
{
responseText
}
=
await
streamFetch
({
data
:
{
...
...
@@ -150,8 +147,7 @@ const AppChatWindow = () => {
forbidLoadChatRef
,
isShowCite
,
showSkillReferences
,
refreshRecentlyUsed
,
collapseSidebar
refreshRecentlyUsed
]
);
...
...
projects/app/src/pageComponents/chat/ChatWindow/ChatAIModelSelector.tsx
View file @
29f5cf05
...
...
@@ -41,33 +41,6 @@ const isMultimodalEmbeddingModel = (model?: SystemModelItemType) => {
return
model
?.
type
===
ModelTypeEnum
.
embedding
&&
!!
model
.
vision
;
};
const
SelectorActiveModelTags
=
React
.
memo
(
function
SelectorActiveModelTags
({
model
}:
{
model
?:
SystemModelItemType
;
})
{
const
showTestModeTip
=
isTestModeModel
(
model
);
const
showMultimodalTip
=
isMultimodalEmbeddingModel
(
model
);
if
(
!
showTestModeTip
&&
!
showMultimodalTip
)
return
null
;
return
(
<
Box
position=
{
'absolute'
}
top=
{
'50%'
}
right=
{
'40px'
}
transform=
{
'translateY(-50%)'
}
zIndex=
{
3
}
display=
{
'flex'
}
alignItems=
{
'center'
}
gap=
{
1
}
>
{
showTestModeTip
&&
<
TestModeBetaTag
/>
}
{
showMultimodalTip
&&
<
MultimodalTag
/>
}
</
Box
>
);
});
const
ModelOptionLabel
=
React
.
memo
(
function
ModelOptionLabel
({
name
,
showTestModeTip
,
...
...
@@ -80,7 +53,7 @@ const ModelOptionLabel = React.memo(function ModelOptionLabel({
noOfLines
?:
ResponsiveValue
<
number
>
;
})
{
return
(
<
Flex
alignItems=
{
'center'
}
flex=
{
'1 1 0'
}
w=
{
'100%'
}
minW=
{
0
}
overflow=
{
'hidden'
}
>
<
Flex
alignItems=
{
'center'
}
flex=
{
'1 1 0'
}
minW=
{
0
}
overflow=
{
'hidden'
}
>
<
Box
noOfLines=
{
noOfLines
??
1
}
flex=
{
'1 1 0'
}
minW=
{
0
}
overflow=
{
'hidden'
}
>
{
name
}
</
Box
>
...
...
@@ -200,12 +173,12 @@ const OneRowSelector = ({
list=
{
avatarList
}
valueLabel=
{
selectedModelData
?
(
<
Flex
alignItems=
{
'center'
}
py=
{
1
}
minW=
{
0
}
overflow=
{
'hidden'
}
>
<
Flex
alignItems=
{
'center'
}
py=
{
1
}
minW=
{
0
}
overflow=
{
'hidden'
}
w=
{
'100%'
}
>
<
ModelOptionLabel
name=
{
selectedModelData
.
name
}
noOfLines=
{
noOfLines
}
showTestModeTip=
{
false
}
showMultimodalTip=
{
false
}
showTestModeTip=
{
isTestModeModel
(
selectedModelData
)
}
showMultimodalTip=
{
isMultimodalEmbeddingModel
(
selectedModelData
)
}
/>
</
Flex
>
)
:
undefined
...
...
@@ -220,7 +193,6 @@ const OneRowSelector = ({
}
}
/>
</
MyTooltip
>
<
SelectorActiveModelTags
model=
{
selectedModelData
}
/>
</
Box
>
);
};
...
...
@@ -240,7 +212,6 @@ const MultipleRowSelector = ({
ttsModelList
,
sttModelList
,
reRankModelList
,
getModelProvider
,
getModelProviders
,
getMyModelList
}
=
useSystemStore
();
...
...
@@ -340,12 +311,12 @@ const MultipleRowSelector = ({
if
(
!
selectedModelData
)
return
<>
{
t
(
'common:not_model_config'
)
}
</>;
return
(
<
Flex
alignItems=
{
'center'
}
py=
{
1
}
minW=
{
0
}
overflow=
{
'hidden'
}
>
<
Flex
alignItems=
{
'center'
}
py=
{
1
}
minW=
{
0
}
overflow=
{
'hidden'
}
w=
{
'100%'
}
>
<
ModelOptionLabel
name=
{
selectedModelData
.
name
}
noOfLines=
{
noOfLines
}
showTestModeTip=
{
false
}
showMultimodalTip=
{
false
}
showTestModeTip=
{
isTestModeModel
(
selectedModelData
)
}
showMultimodalTip=
{
isMultimodalEmbeddingModel
(
selectedModelData
)
}
/>
</
Flex
>
);
...
...
@@ -377,7 +348,6 @@ const MultipleRowSelector = ({
}
}
/>
</
MyTooltip
>
<
SelectorActiveModelTags
model=
{
selectedModelData
}
/>
</
Box
>
);
};
...
...
projects/app/src/pageComponents/chat/ChatWindow/HomeChatWindow.tsx
View file @
29f5cf05
...
...
@@ -96,7 +96,6 @@ const HomeChatWindow = () => {
const
handlePaneChange
=
useContextSelector
(
ChatPageContext
,
(
v
)
=>
v
.
handlePaneChange
);
const
homeAppId
=
useContextSelector
(
ChatPageContext
,
(
v
)
=>
v
.
chatSettings
?.
appId
||
''
);
const
refreshRecentlyUsed
=
useContextSelector
(
ChatPageContext
,
(
v
)
=>
v
.
refreshRecentlyUsed
);
const
collapseSidebar
=
useContextSelector
(
ChatPageContext
,
(
v
)
=>
v
.
collapseSidebar
);
const
chatRecords
=
useContextSelector
(
ChatRecordContext
,
(
v
)
=>
v
.
chatRecords
);
...
...
@@ -230,8 +229,6 @@ const HomeChatWindow = () => {
return
Promise
.
reject
(
'appId is empty'
);
}
collapseSidebar
();
const
histories
=
messages
.
slice
(
-
1
);
// Home chat uses the selected model and tools. Quick apps enter the normal app chat pane.
...
...
@@ -294,7 +291,7 @@ const HomeChatWindow = () => {
<>
{
/* 模型选择 */
}
{
isPc
&&
availableModels
.
length
>
0
&&
(
<
Box
w=
{
[
0
,
'auto'
]
}
flex=
{
[
'1 0 0'
,
'0 0 auto'
]
}
>
<
Box
w=
{
[
'0'
,
'128px'
]
}
flex=
{
[
'1 1 0'
,
'0 0 128px'
]
}
minW=
{
0
}
>
<
ChatAIModelSelector
cacheModel=
{
false
}
h=
{
'36px'
}
...
...
projects/app/src/pageComponents/chat/ChatWindow/MobileModelSelectorDrawer.tsx
View file @
29f5cf05
...
...
@@ -80,13 +80,21 @@ const MobileModelSelectorDrawer = ({ isOpen, modelList, value, onChange, onClose
outline
:
'none'
}
}
>
<
Box
bg=
"white"
borderTopRadius=
"16px"
px=
{
4
}
pb=
"42px"
>
<
Flex
justifyContent=
"center"
py=
"16px"
>
<
Box
bg=
"white"
borderTopRadius=
"16px"
px=
{
4
}
pb=
"42px"
maxH=
"min(72dvh, 560px)"
display=
"flex"
flexDirection=
"column"
>
<
Flex
justifyContent=
"center"
py=
"16px"
flexShrink=
{
0
}
>
<
Drawer
.
Handle
style=
{
{
backgroundColor
:
'var(--chakra-colors-myGray-400)'
}
}
/>
</
Flex
>
{
!
activeProvider
?
(
<
Box
pb=
{
4
}
>
<
Box
pb=
{
4
}
flex=
"1 1 0"
minH=
{
0
}
overflowY=
"auto"
>
{
providerGroups
.
map
((
provider
)
=>
(
<
Flex
key=
{
provider
.
id
}
...
...
@@ -116,8 +124,8 @@ const MobileModelSelectorDrawer = ({ isOpen, modelList, value, onChange, onClose
))
}
</
Box
>
)
:
(
<>
<
Flex
h=
"48px"
alignItems=
"center"
>
<
Flex
flexDirection=
"column"
flex=
"1 1 0"
minH=
{
0
}
>
<
Flex
h=
"48px"
alignItems=
"center"
flexShrink=
{
0
}
>
<
IconButton
aria
-
label=
"Back"
icon=
{
...
...
@@ -156,7 +164,7 @@ const MobileModelSelectorDrawer = ({ isOpen, modelList, value, onChange, onClose
onClick=
{
onClose
}
/>
</
Flex
>
<
Box
pb=
{
4
}
>
<
Box
pb=
{
4
}
flex=
"1 1 0"
minH=
{
0
}
overflowY=
"auto"
>
{
activeProvider
.
children
.
map
((
model
)
=>
{
const
isSelected
=
model
.
model
===
value
;
...
...
@@ -184,7 +192,7 @@ const MobileModelSelectorDrawer = ({ isOpen, modelList, value, onChange, onClose
);
})
}
</
Box
>
</>
</
Flex
>
)
}
</
Box
>
</
Drawer
.
Content
>
...
...
projects/app/src/web/core/chat/context/chatPageContext.tsx
View file @
29f5cf05
...
...
@@ -29,8 +29,6 @@ export type ChatPageContextValue = {
)
=>
void
;
collapse
:
CollapseStatusType
;
onTriggerCollapse
:
()
=>
void
;
/** 收起 /chat 页面左侧应用侧边栏;用于会话生成等需要扩大对话区域的场景。 */
collapseSidebar
:
()
=>
void
;
// Chat settings
chatSettings
:
ChatSettingType
|
undefined
;
refreshChatSetting
:
()
=>
Promise
<
ChatSettingType
|
undefined
>
;
...
...
@@ -48,7 +46,6 @@ export const ChatPageContext = createContext<ChatPageContextValue>({
handlePaneChange
:
()
=>
{},
collapse
:
defaultCollapseStatus
,
onTriggerCollapse
:
()
=>
{},
collapseSidebar
:
()
=>
{},
chatSettings
:
undefined
,
logos
:
{
wideLogoUrl
:
''
,
squareLogoUrl
:
''
},
refreshChatSetting
:
function
():
Promise
<
ChatSettingType
|
undefined
>
{
...
...
@@ -185,9 +182,6 @@ export const ChatPageContextProvider = ({
const
onTriggerCollapse
=
useCallback
(()
=>
{
setCollapse
(
collapse
===
0
?
1
:
0
);
},
[
collapse
]);
const
collapseSidebar
=
useCallback
(()
=>
{
setCollapse
(
1
);
},
[]);
const
value
:
ChatPageContextValue
=
useMemoEnhance
(
()
=>
({
...
...
@@ -195,7 +189,6 @@ export const ChatPageContextProvider = ({
handlePaneChange
,
collapse
,
onTriggerCollapse
,
collapseSidebar
,
chatSettings
,
refreshChatSetting
,
logos
,
...
...
@@ -209,7 +202,6 @@ export const ChatPageContextProvider = ({
handlePaneChange
,
collapse
,
onTriggerCollapse
,
collapseSidebar
,
chatSettings
,
refreshChatSetting
,
logos
,
...
...
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