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,
|
};
|
};
|