SSE 推送替代轮训

This commit is contained in:
yml2213
2026-05-27 06:18:55 +08:00
parent 1458fc279c
commit a002987784
9 changed files with 493 additions and 42 deletions
+91
View File
@@ -0,0 +1,91 @@
import { onBeforeUnmount, ref, type Ref } from 'vue'
import { getAccessToken, type AuthScope } from '@/utils/authStorage'
export interface SSEMessage {
id: number
conversation_id: number
sender_type: string
sender_id: number
sender_role: string
sender_name: string
content_type: string
content: string
attachment_urls: string[]
created_at: string
}
export interface ChatEvent {
type: 'new_message' | 'conversation_updated'
conversation_id: number
message?: SSEMessage
}
type EventHandler = (event: ChatEvent) => void
const reconnectDelay = 3000
export function useChatSSE(scope: AuthScope, endpoint: string) {
const connected: Ref<boolean> = ref(false)
let source: EventSource | null = null
let reconnectTimer: ReturnType<typeof setTimeout> | null = null
let stopped = false
const handlers: EventHandler[] = []
function onEvent(handler: EventHandler) {
handlers.push(handler)
}
function connect() {
const token = getAccessToken(scope)
if (!token) return
const url = `${endpoint}?token=${encodeURIComponent(token)}`
source = new EventSource(url)
source.addEventListener('connected', () => {
connected.value = true
})
source.addEventListener('new_message', (e) => {
try {
const data = JSON.parse((e as MessageEvent).data) as ChatEvent
handlers.forEach(h => h(data))
} catch { /* ignore */ }
})
source.addEventListener('conversation_updated', (e) => {
try {
const data = JSON.parse((e as MessageEvent).data) as ChatEvent
handlers.forEach(h => h(data))
} catch { /* ignore */ }
})
source.onerror = () => {
connected.value = false
source?.close()
source = null
if (!stopped) {
reconnectTimer = setTimeout(connect, reconnectDelay)
}
}
}
function disconnect() {
stopped = true
if (reconnectTimer) {
clearTimeout(reconnectTimer)
reconnectTimer = null
}
source?.close()
source = null
connected.value = false
}
onBeforeUnmount(() => {
disconnect()
})
connect()
return { connected, onEvent, disconnect }
}