修正流式聊天状态保持

This commit is contained in:
2026-05-30 00:54:01 +08:00
parent 4bf5195bfd
commit a3330a5937
2 changed files with 66 additions and 5 deletions
+62 -5
View File
@@ -342,6 +342,8 @@ bool PetWindow::submitChatMessage(const QString &message)
playState(QStringLiteral("think"), false); playState(QStringLiteral("think"), false);
m_streamingAssistantText.clear(); m_streamingAssistantText.clear();
m_streamBubbleUpdateTimer.stop(); m_streamBubbleUpdateTimer.stop();
m_streamingChatActive = true;
m_streamingTalkStarted = false;
m_chatBubble->showMessage(QStringLiteral("正在思考..."), bubbleAnchorPosition(), 0); m_chatBubble->showMessage(QStringLiteral("正在思考..."), bubbleAnchorPosition(), 0);
QPointer<PetWindow> window(this); QPointer<PetWindow> window(this);
@@ -362,13 +364,14 @@ bool PetWindow::submitChatMessage(const QString &message)
window->m_streamBubbleUpdateTimer.stop(); window->m_streamBubbleUpdateTimer.stop();
if (response.success) if (response.success)
{ {
window->finishStreamingChat();
window->m_streamingAssistantText = response.content; window->m_streamingAssistantText = response.content;
window->flushStreamingBubble(true); window->flushStreamingBubble(true);
window->playState(QStringLiteral("talk"), false);
window->refreshChatHistoryPanel(); window->refreshChatHistoryPanel();
return; return;
} }
window->cancelStreamingChat();
window->m_streamingAssistantText.clear(); window->m_streamingAssistantText.clear();
window->playState(QStringLiteral("error"), false); window->playState(QStringLiteral("error"), false);
window->showBubbleMessage(QStringLiteral("AI 回复失败:") + userVisibleErrorMessage(response)); window->showBubbleMessage(QStringLiteral("AI 回复失败:") + userVisibleErrorMessage(response));
@@ -386,8 +389,7 @@ void PetWindow::clearConversation()
const bool hadActiveRequest = hasActiveAIRequest(); const bool hadActiveRequest = hasActiveAIRequest();
m_conversationManager->clear(); m_conversationManager->clear();
m_streamBubbleUpdateTimer.stop(); cancelStreamingChat();
m_streamingAssistantText.clear();
refreshChatHistoryPanel(); refreshChatHistoryPanel();
showBubbleMessage(hadActiveRequest showBubbleMessage(hadActiveRequest
? QStringLiteral("已取消 AI 请求,并清空对话。") ? QStringLiteral("已取消 AI 请求,并清空对话。")
@@ -400,8 +402,7 @@ void PetWindow::cancelActiveAIRequest()
if (m_conversationManager && m_conversationManager->isBusy()) if (m_conversationManager && m_conversationManager->isBusy())
{ {
m_conversationManager->cancel(); m_conversationManager->cancel();
m_streamBubbleUpdateTimer.stop(); cancelStreamingChat();
m_streamingAssistantText.clear();
showBubbleMessage(QStringLiteral("AI 请求已取消。")); showBubbleMessage(QStringLiteral("AI 请求已取消。"));
playState(QStringLiteral("idle"), false); playState(QStringLiteral("idle"), false);
return; return;
@@ -441,6 +442,16 @@ void PetWindow::handleChatStreamDelta(const QString &delta)
} }
m_streamingAssistantText += delta; m_streamingAssistantText += delta;
if (m_streamingChatActive && !m_streamingTalkStarted)
{
m_streamingTalkStarted = true;
playState(QStringLiteral("talk"), false);
if (m_stateMachine.currentState() == QStringLiteral("talk"))
{
m_returnToIdleAfterResume = false;
}
}
if (!isVisible()) if (!isVisible())
{ {
return; return;
@@ -466,6 +477,20 @@ void PetWindow::flushStreamingBubble(bool finalUpdate)
true); true);
} }
void PetWindow::finishStreamingChat()
{
m_streamingChatActive = false;
m_streamingTalkStarted = false;
}
void PetWindow::cancelStreamingChat()
{
m_streamBubbleUpdateTimer.stop();
m_streamingAssistantText.clear();
m_streamingChatActive = false;
m_streamingTalkStarted = false;
}
void PetWindow::resetBubbleAutoHideTimer() void PetWindow::resetBubbleAutoHideTimer()
{ {
if (m_chatBubble) if (m_chatBubble)
@@ -654,6 +679,25 @@ void PetWindow::playResolvedState(const QString &stateName, bool centerWindow)
return; return;
} }
if (m_streamingChatActive
&& stateName != QStringLiteral("error")
&& stateName != QStringLiteral("drag"))
{
const QString heldState = m_streamingTalkStarted
? QStringLiteral("talk")
: QStringLiteral("think");
if (stateName != heldState && m_clips.contains(heldState))
{
playResolvedState(heldState, centerWindow);
}
if (stateName != heldState)
{
return;
}
}
if (m_frameAnimator.currentStateName() == stateName && m_frameAnimator.isPlaying()) if (m_frameAnimator.currentStateName() == stateName && m_frameAnimator.isPlaying())
{ {
return; return;
@@ -727,6 +771,19 @@ void PetWindow::playIdleBehavior()
void PetWindow::returnToIdleFromBehavior() void PetWindow::returnToIdleFromBehavior()
{ {
if (m_streamingChatActive)
{
const QString heldState = m_streamingTalkStarted
? QStringLiteral("talk")
: QStringLiteral("think");
if (m_clips.contains(heldState))
{
playResolvedState(heldState, false);
}
return;
}
if (!m_dragging) if (!m_dragging)
{ {
playResolvedState(m_stateMachine.finishState(QStringLiteral("idle")), false); playResolvedState(m_stateMachine.finishState(QStringLiteral("idle")), false);
+4
View File
@@ -56,6 +56,8 @@ private:
void refreshChatHistoryPanel(); void refreshChatHistoryPanel();
void handleChatStreamDelta(const QString &delta); void handleChatStreamDelta(const QString &delta);
void flushStreamingBubble(bool finalUpdate); void flushStreamingBubble(bool finalUpdate);
void finishStreamingChat();
void cancelStreamingChat();
bool hasActiveAIRequest() const; bool hasActiveAIRequest() const;
void resetBubbleAutoHideTimer(); void resetBubbleAutoHideTimer();
QPoint chatInputAnchorPosition() const; QPoint chatInputAnchorPosition() const;
@@ -89,4 +91,6 @@ private:
bool m_alwaysOnTop; bool m_alwaysOnTop;
bool m_centerNextFrame; bool m_centerNextFrame;
bool m_returnToIdleAfterResume = false; bool m_returnToIdleAfterResume = false;
bool m_streamingChatActive = false;
bool m_streamingTalkStarted = false;
}; };