Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Q
qianjiangb2b
Project
Project
Details
Activity
Releases
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
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
AI-甘富林
qianjiangb2b
Commits
489a5b3c
Commit
489a5b3c
authored
Jun 17, 2026
by
AI-甘富林
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ai对话记忆修复
parent
abf55760
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
54 additions
and
23 deletions
+54
-23
AdminAIAssistant.tsx
src/components/admin/AdminAIAssistant.tsx
+54
-23
No files found.
src/components/admin/AdminAIAssistant.tsx
View file @
489a5b3c
...
@@ -476,6 +476,12 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
...
@@ -476,6 +476,12 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
const
handleWorkbenchMessage
=
useCallback
(
async
(
message
:
string
)
=>
{
const
handleWorkbenchMessage
=
useCallback
(
async
(
message
:
string
)
=>
{
console
.
log
(
'[AI Assistant] Received message from workbench:'
,
message
);
console
.
log
(
'[AI Assistant] Received message from workbench:'
,
message
);
// ★ 生成 session_id(如果还没有),与 handleSendMessage 保持一致
const
currentSessionId
=
conversationId
||
`session_
${
Date
.
now
()}
_
${
Math
.
random
().
toString
(
36
).
substring
(
2
,
9
)}
`
;
if
(
!
conversationId
)
{
setConversationId
(
currentSessionId
);
}
// 添加用户消息到对话
// 添加用户消息到对话
const
newUserMessage
:
Message
=
{
const
newUserMessage
:
Message
=
{
role
:
'user'
,
role
:
'user'
,
...
@@ -487,13 +493,14 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
...
@@ -487,13 +493,14 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
try
{
try
{
const
{
data
:
{
user
}
}
=
await
supabase
.
auth
.
getUser
();
const
{
data
:
{
user
}
}
=
await
supabase
.
auth
.
getUser
();
// 保存用户消息
// 保存用户消息
if
(
user
)
{
if
(
user
)
{
await
supabase
.
from
(
'admin_chat_messages'
).
insert
([{
await
supabase
.
from
(
'admin_chat_messages'
).
insert
([{
user_id
:
user
.
id
,
user_id
:
user
.
id
,
role
:
'user'
,
role
:
'user'
,
content
:
message
,
content
:
message
,
session_id
:
currentSessionId
,
timestamp
:
newUserMessage
.
timestamp
.
toISOString
(),
timestamp
:
newUserMessage
.
timestamp
.
toISOString
(),
}]);
}]);
}
}
...
@@ -502,7 +509,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
...
@@ -502,7 +509,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
const
{
data
:
genUIData
,
error
:
genUIError
}
=
await
supabase
.
functions
.
invoke
(
'service-genui'
,
{
const
{
data
:
genUIData
,
error
:
genUIError
}
=
await
supabase
.
functions
.
invoke
(
'service-genui'
,
{
body
:
{
body
:
{
message
,
message
,
conversation_id
:
c
onversationId
||
undefine
d
,
conversation_id
:
c
urrentSessionI
d
,
},
},
});
});
...
@@ -534,6 +541,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
...
@@ -534,6 +541,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
user_id
:
user
.
id
,
user_id
:
user
.
id
,
role
:
'assistant'
,
role
:
'assistant'
,
content
:
assistantMessage
.
content
,
content
:
assistantMessage
.
content
,
session_id
:
currentSessionId
,
timestamp
:
assistantMessage
.
timestamp
.
toISOString
(),
timestamp
:
assistantMessage
.
timestamp
.
toISOString
(),
}]);
}]);
}
}
...
@@ -670,6 +678,12 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
...
@@ -670,6 +678,12 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
return
;
return
;
}
}
// ★ 在发送前生成 session_id,确保用户消息和助手消息都用同一个 ID 存入数据库
const
currentSessionId
=
conversationId
||
`session_
${
Date
.
now
()}
_
${
Math
.
random
().
toString
(
36
).
substring
(
2
,
9
)}
`
;
if
(
!
conversationId
)
{
setConversationId
(
currentSessionId
);
}
const
messageToSend
=
userMessage
;
const
messageToSend
=
userMessage
;
const
newUserMessage
:
Message
=
{
const
newUserMessage
:
Message
=
{
role
:
'user'
,
role
:
'user'
,
...
@@ -692,23 +706,24 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
...
@@ -692,23 +706,24 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
try
{
try
{
const
{
data
:
{
user
}
}
=
await
supabase
.
auth
.
getUser
();
const
{
data
:
{
user
}
}
=
await
supabase
.
auth
.
getUser
();
// 保存用户消息到数据库
// 保存用户消息到数据库
if
(
user
)
{
if
(
user
)
{
await
supabase
.
from
(
'admin_chat_messages'
).
insert
([{
await
supabase
.
from
(
'admin_chat_messages'
).
insert
([{
user_id
:
user
.
id
,
user_id
:
user
.
id
,
role
:
'user'
,
role
:
'user'
,
content
:
newUserMessage
.
content
,
content
:
newUserMessage
.
content
,
session_id
:
currentSessionId
,
timestamp
:
newUserMessage
.
timestamp
.
toISOString
(),
timestamp
:
newUserMessage
.
timestamp
.
toISOString
(),
}]);
}]);
}
}
// GenUI 模式:使用意图路由调用对应的 GenUI Edge Function
// GenUI 模式:使用意图路由调用对应的 GenUI Edge Function
if
(
useGenUI
)
{
if
(
useGenUI
)
{
console
.
log
(
'[AdminAI] Using GenUI mode'
);
console
.
log
(
'[AdminAI] Using GenUI mode'
);
const
genUIResponse
=
await
routeAndCallGenUI
(
messageToSend
,
{
const
genUIResponse
=
await
routeAndCallGenUI
(
messageToSend
,
{
conversation_id
:
c
onversationId
||
undefine
d
,
conversation_id
:
c
urrentSessionI
d
,
current_page
:
'admin'
,
current_page
:
'admin'
,
});
});
...
@@ -748,6 +763,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
...
@@ -748,6 +763,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
user_id
:
user
.
id
,
user_id
:
user
.
id
,
role
:
'assistant'
,
role
:
'assistant'
,
content
:
genUIResponse
.
answer
||
''
,
content
:
genUIResponse
.
answer
||
''
,
session_id
:
currentSessionId
,
timestamp
:
new
Date
().
toISOString
(),
timestamp
:
new
Date
().
toISOString
(),
}]);
}]);
}
}
...
@@ -766,12 +782,13 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
...
@@ -766,12 +782,13 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
let
streamedAnswer
=
''
;
let
streamedAnswer
=
''
;
let
streamedUISchema
:
any
=
null
;
let
streamedUISchema
:
any
=
null
;
let
streamedUISchemaText
=
''
;
// ui_schema 的 Markdown 表达,用于拼接到 DB content
let
streamedSessionId
=
''
;
let
streamedSessionId
=
''
;
let
streamedAgentType
:
GenUIAgentType
=
'manager'
;
let
streamedAgentType
:
GenUIAgentType
=
'manager'
;
await
handleStreamResponse
(
await
handleStreamResponse
(
'coze-langchain'
,
'coze-langchain'
,
{
text
:
messageToSend
,
session_id
:
c
onversationId
||
undefine
d
},
{
text
:
messageToSend
,
session_id
:
c
urrentSessionI
d
},
// onContent: 增量文本到达时实时更新聊天框
// onContent: 增量文本到达时实时更新聊天框
(
content
)
=>
{
(
content
)
=>
{
streamedAnswer
+=
content
;
streamedAnswer
+=
content
;
...
@@ -785,18 +802,19 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
...
@@ -785,18 +802,19 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
undefined
,
undefined
,
// onDone: 流结束,拿到结构化数据
// onDone: 流结束,拿到结构化数据
(
doneData
:
any
)
=>
{
(
doneData
:
any
)
=>
{
//
优先使用流式累积的完整文本(含代码块),doneData.answer 可能被 parseAIResponse 截断
//
streamedAnswer 是流式累积的完整纯文本,优先保留
streamedAnswer
=
streamedAnswer
||
doneData
.
answer
;
streamedAnswer
=
streamedAnswer
||
doneData
.
answer
;
streamedUISchema
=
doneData
.
ui_schema
||
null
;
streamedUISchema
=
doneData
.
ui_schema
||
null
;
streamedUISchemaText
=
doneData
.
ui_schema_text
||
''
;
streamedSessionId
=
doneData
.
session_id
||
''
;
streamedSessionId
=
doneData
.
session_id
||
''
;
streamedAgentType
=
(
doneData
.
agent_type
as
GenUIAgentType
)
||
'manager'
;
streamedAgentType
=
(
doneData
.
agent_type
as
GenUIAgentType
)
||
'manager'
;
}
}
);
);
// 最终更新消息内容
// 最终更新消息内容
(包含 ui_schema 以在聊天框内渲染组件)
setMessages
(
prev
=>
prev
.
map
((
msg
,
idx
)
=>
setMessages
(
prev
=>
prev
.
map
((
msg
,
idx
)
=>
idx
===
prev
.
length
-
1
idx
===
prev
.
length
-
1
?
{
...
msg
,
content
:
streamedAnswer
||
'已更新工作台视图'
}
?
{
...
msg
,
content
:
streamedAnswer
||
'已更新工作台视图'
,
ui_schema
:
streamedUISchema
}
:
msg
:
msg
));
));
...
@@ -818,12 +836,14 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
...
@@ -818,12 +836,14 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
setConversationId
(
streamedSessionId
);
setConversationId
(
streamedSessionId
);
}
}
// 保存到数据库
// 保存到数据库:content = 纯文本回答 + ui_schema 的 Markdown 表达(确保历史消息可读)
const
dbContent
=
(
streamedAnswer
||
''
)
+
(
streamedUISchemaText
?
'
\
n
\
n'
+
streamedUISchemaText
:
''
);
if
(
user
)
{
if
(
user
)
{
await
supabase
.
from
(
'admin_chat_messages'
).
insert
([{
await
supabase
.
from
(
'admin_chat_messages'
).
insert
([{
user_id
:
user
.
id
,
user_id
:
user
.
id
,
role
:
'assistant'
,
role
:
'assistant'
,
content
:
streamedAnswer
||
''
,
content
:
dbContent
,
session_id
:
currentSessionId
,
timestamp
:
new
Date
().
toISOString
(),
timestamp
:
new
Date
().
toISOString
(),
}]);
}]);
}
}
...
@@ -1504,23 +1524,34 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
...
@@ -1504,23 +1524,34 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
)}
)}
>
>
<MarkdownRenderer content={msg.content} isUser={msg.role === 'user'} />
<MarkdownRenderer content={msg.content} isUser={msg.role === 'user'} />
{/* Gen UI Dynamic Rendering */}
{msg.ui_schema && msg.role === 'assistant' && (
<div className="mt-3 pt-3 border-t border-border/50">
<DynamicRenderer
schema={msg.ui_schema}
context={genUIContext}
className="w-full"
/>
</div>
)}
{msg.actions && msg.actions.length > 0 && (
{msg.actions && msg.actions.length > 0 && (
<div className="mt-2 pt-2 border-t border-border/50">
<div className="mt-2 pt-2 border-t border-border/50">
<p className="text-xs font-medium mb-1">执行的操作:</p>
<p className="text-xs font-medium mb-1">执行的操作:</p>
{msg.actions.map((action, actionIdx) => (
{msg.actions.map((action, actionIdx) => (
<div
<div
key={actionIdx}
key={actionIdx}
className={`
text
-
xs
p
-
2
rounded
mb
-
1
$
{
className={`
text
-
xs
p
-
2
rounded
mb
-
1
$
{
action
.
error
action
.
error
?
'bg-destructive/10 text-destructive'
?
'bg-destructive/10 text-destructive'
:
action
.
executed
:
action
.
executed
?
'bg-green-500/10 text-green-700 dark:text-green-300'
?
'bg-green-500/10 text-green-700 dark:text-green-300'
:
'bg-muted'
:
'bg-muted'
}
`}
}
`}
>
>
<div className="flex items-center gap-2 mb-1">
<div className="flex items-center gap-2 mb-1">
<Badge
<Badge
variant={action.executed ? (action.error ? 'destructive' : 'default') : 'outline'}
variant={action.executed ? (action.error ? 'destructive' : 'default') : 'outline'}
className="text-xs"
className="text-xs"
>
>
...
@@ -1546,7 +1577,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
...
@@ -1546,7 +1577,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
</div>
</div>
</div>
</div>
))}
))}
{isLoading && (
{isLoading && (
<div className="flex justify-start">
<div className="flex justify-start">
<div className="bg-muted rounded-lg px-4 py-3">
<div className="bg-muted rounded-lg px-4 py-3">
...
@@ -1554,7 +1585,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
...
@@ -1554,7 +1585,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
</div>
</div>
</div>
</div>
)}
)}
<div ref={messagesEndRef} />
<div ref={messagesEndRef} />
</div>
</div>
</ScrollArea>
</ScrollArea>
...
@@ -1566,7 +1597,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
...
@@ -1566,7 +1597,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
{interimText}
{interimText}
</div>
</div>
)}
)}
{/* Recording indicator */}
{/* Recording indicator */}
{isRecording && (
{isRecording && (
<div className="flex items-center gap-2 text-xs text-destructive">
<div className="flex items-center gap-2 text-xs text-destructive">
...
@@ -1577,7 +1608,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
...
@@ -1577,7 +1608,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
正在录音...
正在录音...
</div>
</div>
)}
)}
<div className="flex gap-2">
<div className="flex gap-2">
<Textarea
<Textarea
value={userMessage}
value={userMessage}
...
...
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