增强消息视图的SSE连接管理

This commit is contained in:
jxxghp
2025-08-21 09:22:57 +08:00
parent eafe63c886
commit c330aee560
3 changed files with 57 additions and 10 deletions

View File

@@ -50,6 +50,9 @@ const sendButtonDisabled = ref(false)
// 消息对话框引用
const messageDialogRef = ref<any>(null)
// 消息视图引用
const messageViewRef = ref<any>(null)
// 滚动容器引用
const messageContentRef = ref<any>()
@@ -115,6 +118,12 @@ async function openMessageDialog() {
setTimeout(() => {
forceScrollToEnd()
}, 600)
// 等待对话框打开后恢复SSE连接
nextTick(() => {
if (messageViewRef.value && typeof messageViewRef.value.resumeSSE === 'function') {
messageViewRef.value.resumeSSE()
}
})
}
// 智能滚动到底部(只有用户在底部附近时才滚动)
@@ -184,6 +193,14 @@ defineExpose({
openMessageDialog: openMessageDialogFromExternal,
})
// 监听消息对话框状态变化
watch(messageDialog, newValue => {
if (!newValue && messageViewRef.value && typeof messageViewRef.value.pauseSSE === 'function') {
// 对话框关闭时暂停SSE连接
messageViewRef.value.pauseSSE()
}
})
onMounted(() => {
const shortcut = getQueryValue('shortcut')
if (shortcut) {

View File

@@ -69,8 +69,8 @@ export class SSEManager {
this.backgroundCloseTimer = null
}
// 立即重新建立连接
if (!this.eventSource || this.eventSource.readyState === EventSource.CLOSED) {
// 只有在有活跃监听器时才重新建立连接
if (this.listeners.size > 0 && (!this.eventSource || this.eventSource.readyState === EventSource.CLOSED)) {
this.reconnectSSE()
}
}
@@ -84,6 +84,11 @@ export class SSEManager {
return
}
// 如果没有活跃的监听器,不进行重连
if (this.listeners.size === 0) {
return
}
this.isConnecting = true
this.reconnectAttempts = attemptCount
@@ -105,7 +110,7 @@ export class SSEManager {
}
this.reconnectTimer = window.setTimeout(() => {
if (!this.isBackground) {
if (!this.isBackground && this.listeners.size > 0) {
this.reconnectSSE(this.reconnectAttempts + 1)
}
}, this.options.reconnectDelay)
@@ -131,7 +136,7 @@ export class SSEManager {
}
this.reconnectTimer = window.setTimeout(() => {
if (!this.isBackground) {
if (!this.isBackground && this.listeners.size > 0) {
this.reconnectSSE(this.reconnectAttempts + 1)
}
}, this.options.reconnectDelay)
@@ -205,7 +210,7 @@ export class SSEManager {
*/
forceReconnect() {
this.close()
if (!this.isBackground) {
if (!this.isBackground && this.listeners.size > 0) {
this.reconnectSSE()
}
}

View File

@@ -45,11 +45,16 @@ function handleSSEMessage(event: MessageEvent) {
}
// 使用优化的SSE连接
useSSE(`${import.meta.env.VITE_API_BASE_URL}system/message?role=user`, handleSSEMessage, 'message-view', {
backgroundCloseDelay: 5000,
reconnectDelay: 3000,
maxReconnectAttempts: 3,
})
const { manager, isConnected } = useSSE(
`${import.meta.env.VITE_API_BASE_URL}system/message?role=user`,
handleSSEMessage,
'message-view',
{
backgroundCloseDelay: 5000,
reconnectDelay: 3000,
maxReconnectAttempts: 3,
},
)
// 调用API加载存量消息
async function loadMessages({ done }: { done: any }) {
@@ -145,6 +150,26 @@ function handleImageLoad() {
emit('scroll')
}
// 暂停SSE连接
function pauseSSE() {
if (manager) {
manager.removeMessageListener('message-view')
}
}
// 恢复SSE连接
function resumeSSE() {
if (manager) {
manager.addMessageListener('message-view', handleSSEMessage)
}
}
// 暴露方法给父组件
defineExpose({
pauseSSE,
resumeSSE,
})
onMounted(() => {
// 组件挂载后触发一次滚动事件
nextTick(() => {