wujingjing
2025-01-14 d5c759fb1c54679a27c20a3a2ed2c7e082820462
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
import moment from 'moment';
import type { Ref, ShallowRef } from 'vue';
import { nextTick, onBeforeUnmount, ref, unref } from 'vue';
import { LOAD_CHAT_LIMIT } from '../constants';
import type { ChatMessage } from '../model/types';
import { useLoadData } from './useLoadData';
import { QueryHistoryDetail } from '/@/api/ai/chat';
type UseScrollLoadOption = {
    container: ShallowRef<HTMLDivElement>;
    historyGroupId: string | Ref<string>;
    messageList: Ref<ChatMessage[]>;
    loadReplyData: (res: any) => Promise<ChatMessage[]>;
};
 
/**
 * 滚动加载数据
 * @returns
 */
export const useScrollLoad = (option: UseScrollLoadOption) => {
    const { container, historyGroupId, messageList, loadReplyData } = option;
    const moreIsLoading = ref(false);
 
    /** @description 下次需要加载的用户结束索引(倒着数) */
    let nextUserMsgEndIndex = 0;
 
    // 是否没有更多数据了
    let isNoMore = false;
 
    /**
     * 更新加载索引
     */
    const updateLoadIndex = (addCount = 1) => {
        nextUserMsgEndIndex += addCount;
    };
 
    /**
     * 加载滚动范围数据
     */
    const loadRangeData = async (lastEnd = nextUserMsgEndIndex) => {
        const res = await QueryHistoryDetail({
            history_group_id: unref(historyGroupId),
            last_end: lastEnd,
            last_count: LOAD_CHAT_LIMIT,
        });
        const result: ChatMessage[] = res.details ?? [];
        if (result.length) {
            nextUserMsgEndIndex += result.length;
            const rangeMsgList = await loadReplyData(res.details);
            messageList.value.unshift(...rangeMsgList);
        } else {
            isNoMore = true;
        }
 
        return result;
    };
 
    //滚动监听
    async function onChatListScroll() {
        if (container.value.scrollTop == 0) {
            // 更多数据正在加载时
            if (moreIsLoading.value) {
                return;
            }
 
            if (isNoMore) {
                return;
            }
 
            const h1 = container.value.scrollHeight;
            moreIsLoading.value = true;
            await loadRangeData(nextUserMsgEndIndex).finally(() => {
                moreIsLoading.value = false;
            });
            //更新后,等待页面渲染完毕再去拿scrollHeight,否则拿到的是之前的
            nextTick(() => {
                nextTick(() => {
                    nextTick(() => {
                        const h2 = container.value.scrollHeight;
                        container.value.scrollTo({
                            //顶部在原先基础上往下滚动50px,露出新加载数据的一点
                            // top: h2 - h1 - 50,
                            top: h2 - h1,
                            behavior: 'instant', //auto-自动滚动 instant-瞬间滚动 smooth-平滑滚动
                        });
                    });
                });
            });
        }
    }
 
    onBeforeUnmount(() => {
        container.value.removeEventListener('scroll', onChatListScroll);
    });
 
    return {
        loadRangeData,
        onChatListScroll,
        moreIsLoading,
        updateLoadIndex,
    };
};