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
+34 -15
View File
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { computed, nextTick, onBeforeUnmount, onMounted, ref } from 'vue'
import { computed, nextTick, onMounted, ref } from 'vue'
import { ElMessage } from 'element-plus'
import {
fetchAdminChat,
@@ -10,8 +10,11 @@ import {
type ChatConversation,
type ChatMessage,
} from '@/api/chats'
import { useChatSSE, type ChatEvent } from '@/composables/useChatSSE'
import { formatDateMinute } from '@/utils/time'
const currentAdminId = Number(localStorage.getItem('admin_id') || 0)
const conversations = ref<ChatConversation[]>([])
const active = ref<ChatConversation | null>(null)
const messages = ref<ChatMessage[]>([])
@@ -20,23 +23,43 @@ const messageLoading = ref(false)
const sending = ref(false)
const content = ref('')
const listRef = ref<HTMLElement | null>(null)
let timer: number | undefined
const activeMembers = computed(() => {
const participants = active.value?.participants || []
return participants.map(item => `${roleLabel(item.role)}:${item.display_name}`).join(' / ')
})
function handleSSEEvent(event: ChatEvent) {
if (event.type === 'conversation_updated') {
loadConversations(false)
}
if (event.type === 'new_message' && active.value && event.conversation_id === active.value.id) {
const msg = event.message
if (msg && !messages.value.some(m => m.id === msg.id)) {
messages.value = [...messages.value, {
id: msg.id,
conversation_id: msg.conversation_id,
sender_type: msg.sender_type as ChatMessage['sender_type'],
sender_id: msg.sender_id,
sender_role: msg.sender_role as ChatMessage['sender_role'],
sender_name: msg.sender_name,
sender_avatar: '',
is_self: msg.sender_type === 'admin' && msg.sender_id === currentAdminId,
content_type: msg.content_type as ChatMessage['content_type'],
content: msg.content,
attachment_urls: msg.attachment_urls || [],
created_at: msg.created_at,
}]
nextTick(() => scrollBottom())
}
}
}
const { onEvent } = useChatSSE('admin', '/api/admin/chats/events')
onEvent(handleSSEEvent)
onMounted(async () => {
await loadConversations()
timer = window.setInterval(async () => {
await loadConversations(false)
if (active.value) await loadMessages(active.value.id, false)
}, 5000)
})
onBeforeUnmount(() => {
if (timer) window.clearInterval(timer)
})
async function loadConversations(showLoading = true) {
@@ -83,12 +106,8 @@ async function handleSend() {
if (!active.value || !text || sending.value) return
sending.value = true
try {
const message = await sendAdminChatMessage(active.value.id, text)
messages.value = [...messages.value, message]
await sendAdminChatMessage(active.value.id, text)
content.value = ''
await nextTick()
scrollBottom()
await loadConversations(false)
} catch {
ElMessage.error('发送失败')
} finally {