gerson
2025-01-21 c9071fc1d8ae01496f4715adda6989a71b503a3d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import { differenceBy } from 'lodash-es';
import moment from 'moment';
import { onActivated, onDeactivated, unref, type Ref } from 'vue';
import { RoleEnum, type ChatMessage } from '../model/types';
import { QueryHistoryDetail } from '/@/api/ai/chat';
import { sseClient } from '/@/stores/global';
import { Logger } from '/@/model/logger/Logger';
import { ElNotification } from 'element-plus';
 
type UseSyncMsgOptions = {
    updateLoadIndex: (addCount: number) => void;
    msgList: Ref<ChatMessage[]>;
    historyGroupId: string | Ref<string>;
    checkCanSync: (data: any) => boolean;
    loadReplyData: (data: any) => Promise<ChatMessage[]>;
    scrollToBottom: () => void;
    showTip: (data: any) => void;
};
 
export const useSyncMsg = (options: UseSyncMsgOptions) => {
    const { updateLoadIndex, msgList, historyGroupId, checkCanSync, loadReplyData, scrollToBottom, showTip } = options;
 
    const insertSyncMsg = (replayData: any[]) => {
        const insertResult: { index: number; item: any }[] = [];
        for (let i = replayData.length - 1; i >= 0; i--) {
            const insertItem = replayData[i];
            if (insertItem.role === RoleEnum.assistant) continue;
            for (let j = msgList.value.length - 1; j >= 0; j--) {
                const currentItem = msgList.value[j];
                if (currentItem.role === RoleEnum.assistant) continue;
                if (moment(insertItem.createTime).isAfter(currentItem.createTime)) {
                    const insertAssistantItem = replayData[i + 1];
                    insertResult.push({
                        index: j + 2,
                        item: [insertItem, insertAssistantItem],
                    });
                    break;
                }
            }
        }
        insertResult.forEach((resultItem) => {
            msgList.value.splice(resultItem.index, 0, ...resultItem.item);
        });
    };
 
    
    const historyUpdate = async (data: any) => {
        if (!checkCanSync(data)) return;
        if (!data) return;
 
        if (data?.type === 'chat_start') {
            const groupId = unref(historyGroupId);
            const startGroupId = data?.history_group_id;
            if (groupId !== startGroupId) return;
            showTip(data);
        }
        if (data?.type === 'chat_history_id') {
            const groupId = unref(historyGroupId);
            if (!groupId) return;
            const recentIds = data.id_list ?? [];
            const recentGroupHistoryIds = recentIds.filter((item) => item.group_id === groupId);
            if (recentGroupHistoryIds.length === 0) return;
            const userHistoryIds = msgList.value
                .filter((item) => item.role === RoleEnum.user)
                .map((item) => ({ history_id: item.historyId, time: item.createTime }));
            const tmpUnSyncedHistoryIds = differenceBy(recentGroupHistoryIds, userHistoryIds, 'history_id') as any[];
            const latestUserHistory = userHistoryIds[userHistoryIds.length - 1];
            let unSyncedHistoryIds = tmpUnSyncedHistoryIds;
            // 太晚的不需要更新
            if (latestUserHistory) {
                unSyncedHistoryIds = tmpUnSyncedHistoryIds.filter((item) => moment(item.time).isAfter(latestUserHistory.time));
            }
            if (!unSyncedHistoryIds || unSyncedHistoryIds.length === 0) return;
            const res = await QueryHistoryDetail({
                history_group_id: groupId,
                id_list: unSyncedHistoryIds.map((item) => item.history_id).join(','),
            });
            if (!checkCanSync(data)) return;
 
            const result: ChatMessage[] = res.details ?? [];
            if (!result || result.length === 0) return;
            const replayData = await loadReplyData(res.details);
            if (!checkCanSync(data)) return;
            insertSyncMsg(replayData);
            updateLoadIndex(unSyncedHistoryIds.length);
            scrollToBottom();
        }
 
    };
 
    onActivated(() => {
        sseClient?.subscribe(historyUpdate);
    });
 
    onDeactivated(() => {
        sseClient?.unsubscribe(historyUpdate);
    });
 
    // onUnmounted(() => {
    //     sseClient.disconnect();
    // });
};