perf(customerservice): debounce SSE-driven refreshLists at 300ms

A burst of INCOMING_MESSAGE on a chatty conversation otherwise fires
2 list APIs per message (mine + unassigned). With 300ms trailing
debounce, 5 messages within 100ms of each other collapse to 1 refresh.

onMounted / onReconnect keep using refreshLists() directly — they
need data immediately, not 300ms later.
This commit is contained in:
i548450 2026-06-09 23:07:36 +08:00
parent 7942def291
commit a65e4ad0db

View File

@ -1,5 +1,6 @@
import { defineStore } from 'pinia';
import { ref } from 'vue';
import { useDebounceFn } from '@vueuse/core';
import type { Conversation, ConversationListItem, Message } from '@/chat-core';
import {
listConversation,
@ -64,6 +65,12 @@ export const useConversationStore = defineStore('customerservice-conversation',
await Promise.all([fetchList('mine'), fetchList('unassigned')]);
}
// SSE-driven path collapses a burst of events into one refresh. Bursts of
// INCOMING_MESSAGE on a chatty conversation would otherwise fire 2 list
// APIs per message. onMounted / onReconnect keep using refreshLists()
// directly — they need the data immediately, not 300ms later.
const debouncedRefreshLists = useDebounceFn(refreshLists, 300);
async function openConversation(id: number) {
const [detailRes, msgRes] = await Promise.all([
getConversation(id),
@ -138,7 +145,7 @@ export const useConversationStore = defineStore('customerservice-conversation',
if (openedConversation.value?.id === p.conversationId) {
appendMessage(p.message);
}
refreshLists();
debouncedRefreshLists();
}
function onOutgoingMessageState(p: OutgoingMessageStatePayload) {
@ -156,21 +163,21 @@ export const useConversationStore = defineStore('customerservice-conversation',
}
function onConversationNew(_: ConversationNewPayload) {
refreshLists();
debouncedRefreshLists();
}
function onConversationClosed(p: ConversationClosedPayload) {
if (openedConversation.value?.id === p.conversationId) {
openedConversation.value = { ...openedConversation.value, status: 'CLOSED', closedAt: p.closedAt };
}
refreshLists();
debouncedRefreshLists();
}
function onConversationTransferred(p: ConversationTransferredPayload) {
if (openedConversation.value?.id === p.conversationId) {
openedConversation.value = { ...openedConversation.value, currentAgentId: p.toAgentId };
}
refreshLists();
debouncedRefreshLists();
}
function onAgentOnlineStatusChanged(p: AgentOnlineStatusPayload) {