增强MessageRecord组件以管理消息加载期间的滚动行为。为消息容器和加载状态引入引用,通过在加载更多消息时保留滚动位置来确保平滑的用户体验。

This commit is contained in:
乘风
2025-12-01 14:34:19 +08:00
parent 57c398f537
commit 2cc2184002

View File

@@ -150,6 +150,7 @@ type GroupRenderItem = {
const MessageRecord: React.FC<MessageRecordProps> = ({ contract }) => { const MessageRecord: React.FC<MessageRecordProps> = ({ contract }) => {
const messagesEndRef = useRef<HTMLDivElement>(null); const messagesEndRef = useRef<HTMLDivElement>(null);
const messagesContainerRef = useRef<HTMLDivElement>(null);
// 右键菜单状态 // 右键菜单状态
const [contextMenu, setContextMenu] = useState({ const [contextMenu, setContextMenu] = useState({
visible: false, visible: false,
@@ -171,6 +172,8 @@ const MessageRecord: React.FC<MessageRecordProps> = ({ contract }) => {
const isLoadingData = useWeChatStore(state => state.isLoadingData); const isLoadingData = useWeChatStore(state => state.isLoadingData);
const showCheckbox = useWeChatStore(state => state.showCheckbox); const showCheckbox = useWeChatStore(state => state.showCheckbox);
const prevMessagesRef = useRef(currentMessages); const prevMessagesRef = useRef(currentMessages);
const isLoadingMoreRef = useRef(false);
const scrollPositionRef = useRef<number>(0);
const updateShowCheckbox = useWeChatStore(state => state.updateShowCheckbox); const updateShowCheckbox = useWeChatStore(state => state.updateShowCheckbox);
const updateEnterModule = useWeChatStore(state => state.updateEnterModule); const updateEnterModule = useWeChatStore(state => state.updateEnterModule);
const currentCustomer = useCustomerStore(state => const currentCustomer = useCustomerStore(state =>
@@ -460,7 +463,10 @@ const MessageRecord: React.FC<MessageRecordProps> = ({ contract }) => {
} }
}); });
if (currentMessages.length > prevLength && !hasVideoStateChange) { // 如果正在加载更早的消息,不自动滚动到底部
if (isLoadingMoreRef.current && currentMessages.length > prevLength) {
// 不滚动,等待加载完成后在另一个 useEffect 中恢复滚动位置
} else if (currentMessages.length > prevLength && !hasVideoStateChange) {
scrollToBottom(); scrollToBottom();
} else if (isLoadingData && !hasVideoStateChange) { } else if (isLoadingData && !hasVideoStateChange) {
scrollToBottom(); scrollToBottom();
@@ -470,6 +476,22 @@ const MessageRecord: React.FC<MessageRecordProps> = ({ contract }) => {
prevMessagesRef.current = currentMessages; prevMessagesRef.current = currentMessages;
}, [currentMessages, isLoadingData]); }, [currentMessages, isLoadingData]);
// 监听加载状态,当加载完成时恢复滚动位置
useEffect(() => {
if (!messagesLoading && isLoadingMoreRef.current) {
// 等待DOM更新后恢复滚动位置
requestAnimationFrame(() => {
const container = messagesContainerRef.current;
if (container) {
const scrollHeight = container.scrollHeight;
const newScrollTop = scrollHeight - scrollPositionRef.current;
container.scrollTop = newScrollTop;
}
isLoadingMoreRef.current = false;
});
}
}, [messagesLoading]);
const scrollToBottom = () => { const scrollToBottom = () => {
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
}; };
@@ -762,6 +784,12 @@ const MessageRecord: React.FC<MessageRecordProps> = ({ contract }) => {
if (messagesLoading || !currentMessagesHasMore) { if (messagesLoading || !currentMessagesHasMore) {
return; return;
} }
// 保存当前滚动位置(距离底部的距离)
const container = messagesContainerRef.current;
if (container) {
scrollPositionRef.current = container.scrollHeight - container.scrollTop;
isLoadingMoreRef.current = true;
}
loadChatMessages(false); loadChatMessages(false);
}; };
@@ -840,7 +868,7 @@ const MessageRecord: React.FC<MessageRecordProps> = ({ contract }) => {
}; };
return ( return (
<div className={styles.messagesContainer}> <div ref={messagesContainerRef} className={styles.messagesContainer}>
<div <div
className={styles.loadMore} className={styles.loadMore}
onClick={() => loadMoreMessages()} onClick={() => loadMoreMessages()}