Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
sdream-ai-fe
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
侯明涛
sdream-ai-fe
Commits
25c91e1f
Commit
25c91e1f
authored
Dec 16, 2025
by
Liu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix:策略/用户中心近入时隐藏收藏按钮
parent
c02dfce9
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
82 additions
and
10 deletions
+82
-10
src/pages/Chat/Chat.module.less
+2
-3
src/pages/Chat/components/ChatItem/ChatAnswerOperate.tsx
+16
-3
src/pages/ChatTactics/TacticsChat.tsx
+64
-4
No files found.
src/pages/Chat/Chat.module.less
View file @
25c91e1f
...
...
@@ -24,9 +24,8 @@
overflow: hidden;
}
.scrollable {
flex-direction: column-reverse;
align-items: center;
justify-content: flex-end;
flex-direction: column;
align-items: stretch;
display: flex;
overflow-x: hidden;
overflow-y: scroll;
...
...
src/pages/Chat/components/ChatItem/ChatAnswerOperate.tsx
View file @
25c91e1f
import
{
Button
,
Tooltip
}
from
'@heroui/react'
import
{
useRef
,
useState
}
from
'react'
import
{
use
Memo
,
use
Ref
,
useState
}
from
'react'
import
{
useLocation
}
from
'react-router-dom'
import
{
useDebounceFn
}
from
'ahooks'
import
type
{
Answer
}
from
'@/types/chat'
...
...
@@ -21,7 +21,20 @@ export const ChatAnswerOperate: React.FC<ChatAnswerOperateProps> = ({ answer })
const
showToast
=
useToast
()
const
location
=
useLocation
()
const
searchParams
=
new
URLSearchParams
(
location
.
search
)
const
isFromTactics
=
searchParams
.
get
(
'from'
)
===
'tactics'
// 路由未携带 from=tactics 时,兜底读取缓存的 tacticsMeta
const
tacticsMetaFromStorage
=
useMemo
(()
=>
{
const
raw
=
sessionStorage
.
getItem
(
'tacticsMeta'
)
if
(
!
raw
)
return
undefined
try
{
return
JSON
.
parse
(
raw
)
}
catch
{
return
undefined
}
},
[])
const
isFromTactics
=
searchParams
.
get
(
'from'
)
===
'tactics'
||
tacticsMetaFromStorage
?.
from
===
'tactics'
const
[
isCollect
,
setIsCollect
]
=
useState
(
answer
.
collectionFlag
)
const
[
isLike
,
setIsLike
]
=
useState
(
answer
.
feedbackStatus
===
'01'
)
const
[
isUnLike
,
setIsUnLike
]
=
useState
(
answer
.
feedbackStatus
===
'02'
)
...
...
@@ -140,7 +153,7 @@ export const ChatAnswerOperate: React.FC<ChatAnswerOperateProps> = ({ answer })
<
Tooltip
color=
"foreground"
content=
"复制"
className=
"capitalize"
>
<
Button
variant=
"light"
isIconOnly
aria
-
label=
"CopyIcon"
onPress=
{
handleCopy
}
><
CopyIcon
/></
Button
>
</
Tooltip
>
{
/* 收藏(当路由未标记 from=tactics 时展示) */
}
{
/* 收藏(当路由未标记 from=tactics 时
不
展示) */
}
{
!
isFromTactics
&&
(
<
Tooltip
color=
"foreground"
content=
{
isCollect
?
'取消收藏'
:
'收藏'
}
className=
"capitalize"
>
<
Button
variant=
"light"
isIconOnly
aria
-
label=
"CollectIcon"
onPress=
{
handleCollect
.
run
}
>
...
...
src/pages/ChatTactics/TacticsChat.tsx
View file @
25c91e1f
...
...
@@ -245,9 +245,19 @@ export const TacticsChat: React.FC = () => {
break
}
}
// eslint-disable-next-line no-console
console
.
log
(
'[TacticsChat] handleStreamMesageData'
,
{
lastAiIndex
,
itemsLength
:
newItems
.
length
,
msgData
:
msg
.
content
?.
data
,
prevItems
:
prevItems
.
map
(
item
=>
({
role
:
item
.
role
,
hasAnswer
:
!!
item
.
answerList
?.[
0
]?.
answer
})),
})
if
(
lastAiIndex
>=
0
)
{
// 确保 answer 字段存在,如果不存在则使用空字符串
const
newAnswer
=
msg
.
content
?.
data
?.
answer
||
''
// 创建最后一项的新对象,合并现有数据和新的 answer
const
originalAnswer
=
(
newItems
[
lastAiIndex
].
answerList
?.[
0
]?.
answer
||
''
)
+
msg
.
content
.
data
.
answer
const
existingAnswer
=
newItems
[
lastAiIndex
].
answerList
?.[
0
]?.
answer
||
''
const
originalAnswer
=
existingAnswer
+
newAnswer
// 移除所有括号及其内容
let
filteredAnswer
=
originalAnswer
.
replace
(
/
\([^
)
]
*
\)
/g
,
''
).
trim
()
// 去除 [参考文档《任意内容》 《任意内容》...] 格式的内容
...
...
@@ -264,6 +274,31 @@ export const TacticsChat: React.FC = () => {
},
],
}
// eslint-disable-next-line no-console
console
.
log
(
'[TacticsChat] handleStreamMesageData:updated'
,
{
filteredAnswer
,
answerList
:
newItems
[
lastAiIndex
].
answerList
,
updatedItem
:
newItems
[
lastAiIndex
],
})
}
else
{
// 如果没有找到 AI 项,创建一个新的 AI 项
console
.
warn
(
'[TacticsChat] handleStreamMesageData: no AI item found, creating new one'
)
const
newAnswer
=
msg
.
content
?.
data
?.
answer
||
''
let
filteredAnswer
=
newAnswer
.
replace
(
/
\([^
)
]
*
\)
/g
,
''
).
trim
()
filteredAnswer
=
filteredAnswer
.
replace
(
/
\[
参考文档
(?:
《
[^
》
]
*》
\s
*
)
+
\]
/g
,
''
).
trim
()
newItems
.
push
({
role
:
'ai'
,
question
,
answerList
:
[
{
...
msg
.
content
.
data
,
isShow
:
false
,
answer
:
filteredAnswer
,
},
],
}
as
ChatRecord
)
}
return
newItems
})
...
...
@@ -418,6 +453,8 @@ export const TacticsChat: React.FC = () => {
if
(
msg
?.
type
===
'DATA'
&&
msg
?.
content
?.
code
===
'00000000'
)
{
// eslint-disable-next-line no-console
console
.
log
(
'[TacticsChat] handleSubmitQuestion:success'
,
msg
)
// eslint-disable-next-line no-console
console
.
log
(
'[TacticsChat] handleSubmitQuestion:data'
,
msg
.
content
?.
data
)
handleStreamMesageData
(
msg
,
question
||
''
)
}
if
(
msg
?.
type
===
'DATA'
&&
msg
?.
content
?.
code
===
'01010005'
)
{
...
...
@@ -464,12 +501,35 @@ export const TacticsChat: React.FC = () => {
}
return
item
})
setAllItems
(
processedMessages
)
// 使用函数式更新,避免覆盖正在进行的流式响应
setAllItems
((
prevItems
)
=>
{
// 如果当前有正在进行的流式响应(存在空的AI项),保留它们
const
hasPendingAi
=
prevItems
.
some
(
item
=>
item
.
role
===
'ai'
&&
(
!
item
.
answerList
?.[
0
]?.
answer
||
item
.
answerList
[
0
].
answer
===
''
))
if
(
hasPendingAi
&&
processedMessages
.
length
>
1
)
{
// 如果历史记录不为空,合并历史记录和正在进行的响应
const
lastPendingAiIndex
=
prevItems
.
length
-
1
const
lastPendingAi
=
prevItems
[
lastPendingAiIndex
]
if
(
lastPendingAi
?.
role
===
'ai'
)
{
return
[...
processedMessages
,
lastPendingAi
]
}
}
return
processedMessages
})
setHasCleared
(
false
)
}
catch
{
// 如果获取失败,至少显示欢迎语
setAllItems
([{
role
:
'system'
}
as
ChatRecord
])
setAllItems
((
prevItems
)
=>
{
const
hasPendingAi
=
prevItems
.
some
(
item
=>
item
.
role
===
'ai'
&&
(
!
item
.
answerList
?.[
0
]?.
answer
||
item
.
answerList
[
0
].
answer
===
''
))
if
(
hasPendingAi
)
{
const
lastPendingAiIndex
=
prevItems
.
length
-
1
const
lastPendingAi
=
prevItems
[
lastPendingAiIndex
]
if
(
lastPendingAi
?.
role
===
'ai'
)
{
return
[{
role
:
'system'
}
as
ChatRecord
,
lastPendingAi
]
}
}
return
[{
role
:
'system'
}
as
ChatRecord
]
})
setHasCleared
(
false
)
setHistoryDividerIndex
(
null
)
setHistoryDividerTime
(
null
)
...
...
@@ -750,7 +810,7 @@ export const TacticsChat: React.FC = () => {
duration
:
0.3
,
opacity
:
{
duration
:
0.1
},
}
}
className=
{
`${styles.scrollable} scrollbar-hide scroll-smooth flex-1 overflow-y-auto px-[16px]`
}
className=
{
`${styles.scrollable} scrollbar-hide scroll-smooth flex-1 overflow-y-auto px-[16px]
min-h-0
`
}
>
<
div
className=
{
`${styles.inter} pt-[8px] pb-[24px]`
}
>
{
allItems
.
map
((
record
,
index
)
=>
{
...
...
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