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
1d2038af
Commit
1d2038af
authored
Jan 07, 2026
by
Liu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix:流式输出null处理为\n
parent
84d29dc3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
23 additions
and
32 deletions
+23
-32
src/pages/Chat/Chat.tsx
+1
-1
src/pages/ChatTactics/TacticsChat.tsx
+3
-3
src/pages/Home/HomeNew.tsx
+19
-28
No files found.
src/pages/Chat/Chat.tsx
View file @
1d2038af
...
...
@@ -142,7 +142,7 @@ export const Chat: React.FC = () => {
const
lastIndex
=
newItems
.
length
-
1
if
(
lastIndex
>=
0
)
{
// 创建最后一项的新对象,合并现有数据和新的 answer
const
originalAnswer
=
(
newItems
[
lastIndex
].
answerList
?.[
0
]?.
answer
||
''
)
+
msg
.
content
.
data
.
answer
const
originalAnswer
=
(
newItems
[
lastIndex
].
answerList
?.[
0
]?.
answer
||
''
)
+
(
msg
.
content
.
data
.
answer
??
'
\
n'
)
// 移除所有括号及其内容
let
filteredAnswer
=
originalAnswer
.
replace
(
/
\([^
)
]
*
\)
/g
,
''
)
// 去除 [参考文档《任意内容》 《任意内容》...] 格式的内容
...
...
src/pages/ChatTactics/TacticsChat.tsx
View file @
1d2038af
...
...
@@ -236,8 +236,8 @@ export const TacticsChat: React.FC = () => {
prevItems
:
prevItems
.
map
(
item
=>
({
role
:
item
.
role
,
hasAnswer
:
!!
item
.
answerList
?.[
0
]?.
answer
})),
})
if
(
lastAiIndex
>=
0
)
{
// 确保 answer 字段存在,如果不存在则使用空字符串
const
newAnswer
=
msg
.
content
?.
data
?.
answer
||
'
'
// 确保 answer 字段存在,如果不存在则使用空字符串
,null 替换为 \n
const
newAnswer
=
msg
.
content
?.
data
?.
answer
??
'
\
n
'
// 创建最后一项的新对象,合并现有数据和新的 answer
const
existingAnswer
=
newItems
[
lastAiIndex
].
answerList
?.[
0
]?.
answer
||
''
const
originalAnswer
=
existingAnswer
+
newAnswer
...
...
@@ -272,7 +272,7 @@ export const TacticsChat: React.FC = () => {
// 如果没有找到 AI 项,创建一个新的 AI 项
console
.
warn
(
'[TacticsChat] handleStreamMesageData: no AI item found, creating new one'
)
const
newAnswer
=
msg
.
content
?.
data
?.
answer
||
'
'
const
newAnswer
=
msg
.
content
?.
data
?.
answer
??
'
\
n
'
// 移除 ♪ 符号之后的所有文本(与历史记录保持一致)
let
filteredAnswer
=
newAnswer
.
split
(
'♪'
)[
0
]
// 移除所有括号及其内容
...
...
src/pages/Home/HomeNew.tsx
View file @
1d2038af
...
...
@@ -8,7 +8,7 @@ import { QuestionList } from './components/QuestionList'
import
HomeIcon2
from
'@/assets/homeIcon2.png'
import
SmartIce
from
'@/assets/smart-ice.png'
import
{
clearCurrentToolId
,
fetchConversations
,
setCurrentConversation
,
setCurrentToolId
,
setNavigationFlag
}
from
'@/store/conversationSlice'
import
{
useAppDispatch
}
from
'@/store/hook'
import
{
useAppDispatch
,
useAppSelector
}
from
'@/store/hook'
import
{
fetchEfficiencyQuestionList
}
from
'@/api/home'
import
SdreamLoading
from
'@/components/SdreamLoading'
import
{
fetchLoginByToken
,
fetchLoginByUid
}
from
'@/api/common'
...
...
@@ -67,6 +67,7 @@ export const Home: React.FC = () => {
const
[
isDataLoaded
,
setIsDataLoaded
]
=
useState
(
false
)
const
dispatch
=
useAppDispatch
()
const
location
=
useLocation
()
const
currentConversationId
=
useAppSelector
(
state
=>
state
.
conversation
.
currentConversationId
)
const
hasFetched
=
useRef
(
false
)
const
hasCalledBusinessApis
=
useRef
(
false
)
// 防止业务接口重复调用
const
prevPathRef
=
useRef
<
string
>
(
location
.
pathname
)
// 记录上一次路径,用于检测从收藏页面返回
...
...
@@ -86,7 +87,7 @@ export const Home: React.FC = () => {
})
// 获取会话ID并加载历史记录
const
getSessionConversationId
=
async
(
data
?:
any
)
=>
{
const
getSessionConversationId
=
async
(
data
?:
any
)
:
Promise
<
string
|
null
>
=>
{
try
{
// 等待 token 就绪后再调用接口
await
waitForToken
()
...
...
@@ -104,16 +105,18 @@ export const Home: React.FC = () => {
// 历史记录会在 Chat 页面自动渲染,不需要在这里获取
// 移除重复调用,避免接口被调用两次
return
conversationId
}
return
null
}
catch
(
error
)
{
console
.
error
(
'获取会话ID失败:'
,
error
)
return
null
}
}
// 刷新问题列表
const
handleRefreshQuestions
=
useCallback
(
async
()
=>
{
console
.
log
(
'[HomeNew] handleRefreshQuestions 开始调用 - 刷新常见问题列表'
)
// 先清空旧数据
setOtherQuestions
((
prev
:
any
)
=>
({
...
prev
,
...
...
@@ -126,10 +129,8 @@ export const Home: React.FC = () => {
const
conversationId
=
location
.
pathname
.
startsWith
(
'/chat/'
)
?
location
.
pathname
.
split
(
'/'
)[
2
]
:
null
console
.
log
(
'[HomeNew] handleRefreshQuestions - 当前 conversationId:'
,
conversationId
)
if
(
!
conversationId
)
{
console
.
warn
(
'[HomeNew] handleRefreshQuestions - conversationId 不存在,跳过接口调用'
)
setIsDataLoaded
(
true
)
return
}
...
...
@@ -140,15 +141,11 @@ export const Home: React.FC = () => {
recordType
:
'A14'
,
})
if
(
res
&&
res
.
data
&&
res
.
data
.
questions
)
{
console
.
log
(
'[HomeNew] handleRefreshQuestions - 获取到问题数量:'
,
res
.
data
.
questions
.
length
)
setOtherQuestions
((
prev
:
any
)
=>
({
...
prev
,
content
:
res
.
data
.
questions
||
[],
}))
}
else
{
console
.
log
(
'[HomeNew] handleRefreshQuestions - 未获取到问题数据'
)
}
}
catch
(
error
)
{
console
.
error
(
'[HomeNew] handleRefreshQuestions - 刷新问题列表失败:'
,
error
)
...
...
@@ -156,12 +153,11 @@ export const Home: React.FC = () => {
}
finally
{
setIsDataLoaded
(
true
)
// 无论成功失败都标记为已加载
console
.
log
(
'[HomeNew] handleRefreshQuestions - 调用完成'
)
}
},
[
location
.
search
])
// 处理工具按钮点击
const
_handleToolClick
=
useCallback
(
async
(
isToolBtn
:
boolean
,
toolId
?:
string
,
ignoreUrlToolId
?:
boolean
)
=>
{
const
_handleToolClick
=
useCallback
(
async
(
isToolBtn
:
boolean
,
toolId
?:
string
,
ignoreUrlToolId
?:
boolean
,
conversationIdParam
?:
string
|
null
)
=>
{
// 提质增效模式 / 数据助手 / 制度活化:都先清空数据,重新拉常见问题
setOtherQuestions
((
prev
:
any
)
=>
({
...
prev
,
...
...
@@ -188,13 +184,12 @@ export const Home: React.FC = () => {
finalToolId
=
storedToolId
}
//
从路由中获取 conversationId
const
conversationId
=
location
.
pathname
.
startsWith
(
'/chat/'
)
//
优先使用传入的 conversationId,其次从 Redux 获取,最后从路由中获取
const
conversationId
=
conversationIdParam
||
currentConversationId
||
(
location
.
pathname
.
startsWith
(
'/chat/'
)
?
location
.
pathname
.
split
(
'/'
)[
2
]
:
null
:
null
)
if
(
!
conversationId
)
{
console
.
warn
(
'[HomeNew] _handleToolClick - conversationId 不存在,跳过接口调用'
)
setIsDataLoaded
(
true
)
return
}
...
...
@@ -218,7 +213,7 @@ export const Home: React.FC = () => {
finally
{
setIsDataLoaded
(
true
)
// 无论成功失败都标记为已加载
}
},
[
originalOtherQuestions
,
location
.
search
,
location
.
pathname
])
},
[
originalOtherQuestions
,
location
.
search
,
location
.
pathname
,
currentConversationId
])
// 监听工具按钮点击事件
useEffect
(()
=>
{
...
...
@@ -249,16 +244,12 @@ export const Home: React.FC = () => {
// 监听从收藏返回时刷新问题列表的事件
useEffect
(()
=>
{
const
handleRefreshQuestionsFromCollect
=
(
event
:
CustomEvent
)
=>
{
console
.
log
(
'[HomeNew] 监听到 refreshQuestionsFromCollect 事件 - 从收藏页面返回'
)
const
{
toolId
}
=
event
.
detail
console
.
log
(
'[HomeNew] refreshQuestionsFromCollect - 接收到的 toolId:'
,
toolId
)
// 如果传递了 toolId,先更新 sessionStorage,确保刷新时使用正确的 toolId
if
(
toolId
)
{
console
.
log
(
'[HomeNew] refreshQuestionsFromCollect - 更新 sessionStorage 中的 currentToolId:'
,
toolId
)
safeSessionStorageSetItem
(
'currentToolId'
,
toolId
)
}
// 刷新问题列表,会调用 generate_question 接口
console
.
log
(
'[HomeNew] refreshQuestionsFromCollect - 开始调用 handleRefreshQuestions'
)
handleRefreshQuestions
()
}
window
.
addEventListener
(
'refreshQuestionsFromCollect'
,
handleRefreshQuestionsFromCollect
as
EventListener
)
...
...
@@ -270,7 +261,6 @@ export const Home: React.FC = () => {
const
login
=
useCallback
(
async
()
=>
{
// 防止重复调用(组件级别保护,每次组件挂载时会重置,确保每次打开链接都能调用)
if
(
hasFetched
.
current
)
{
console
.
log
(
'homeNew sso222222'
)
return
}
const
url
=
new
URL
(
window
.
location
.
href
)
...
...
@@ -281,7 +271,6 @@ export const Home: React.FC = () => {
// 如果有 loginCode,执行 SSO 登录(包括 from=tactics 的情况)
if
(
_loginCode
&&
viteOutputObj
===
'inner'
)
{
console
.
log
(
'homeNew sso333333'
)
// 立即设置标志,防止重复执行(仅组件级别,每次组件挂载时会重置)
hasFetched
.
current
=
true
// 每次进入页面调用 sso_login 时,先清空 sessionStorage 中的 currentToolId
...
...
@@ -290,7 +279,6 @@ export const Home: React.FC = () => {
try
{
const
res
=
await
fetchLoginByToken
(
_loginCode
)
if
(
res
.
data
)
{
console
.
log
(
'homeNew sso444444'
)
// 登录成功后先清理旧状态,避免沿用上一次的工具模式
dispatch
(
clearCurrentToolId
())
safeSessionStorageRemoveItem
(
'currentToolId'
)
...
...
@@ -359,10 +347,10 @@ export const Home: React.FC = () => {
hasCalledBusinessApis
.
current
=
true
// 触发自定义事件,通知 ChatEditor 强制重置为制度活化
window
.
dispatchEvent
(
new
CustomEvent
(
'forceResetToGeneralMode'
))
getSessionConversationId
()
const
conversationId
=
await
getSessionConversationId
()
dispatch
(
fetchConversations
())
// 2. 拉取常见问题等业务数据
_handleToolClick
(
false
,
''
,
true
)
_handleToolClick
(
false
,
''
,
true
,
conversationId
)
}
}
}
...
...
@@ -389,8 +377,11 @@ export const Home: React.FC = () => {
await
fetchCheckTokenApi
()
// token 验证成功,调用业务接口
hasCalledBusinessApis
.
current
=
true
getSessionConversationId
()
// 等待获取会话ID后再调用 _handleToolClick
const
conversationId
=
await
getSessionConversationId
()
dispatch
(
fetchConversations
())
// 拉取常见问题等业务数据
_handleToolClick
(
false
,
''
,
true
,
conversationId
)
}
catch
(
error
)
{
// token 验证失败,不调用业务接口
...
...
@@ -469,10 +460,10 @@ export const Home: React.FC = () => {
hasCalledBusinessApis
.
current
=
true
// 触发自定义事件,通知 ChatEditor 强制重置为制度活化
window
.
dispatchEvent
(
new
CustomEvent
(
'forceResetToGeneralMode'
))
getSessionConversationId
()
const
conversationId
=
await
getSessionConversationId
()
dispatch
(
fetchConversations
())
// 2. 拉取常见问题等业务数据
_handleToolClick
(
false
,
''
,
true
)
_handleToolClick
(
false
,
''
,
true
,
conversationId
)
}
}
}
...
...
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