feat: 实现 Socket 触发的智能列表自动刷新功能(带防抖)
核心改动: - 扩展 NotificationContext,添加事件更新回调注册机制 - VirtualizedFourRowGrid 添加 forwardRef 暴露 getScrollPosition 方法 - DynamicNewsCard 实现智能刷新逻辑(根据模式和滚动位置判断是否刷新) - Community 页面注册 Socket 回调自动触发刷新 - 创建 TypeScript 通用防抖工具函数(debounce.ts) - 集成防抖机制(2秒延迟),避免短时间内频繁请求 智能刷新策略: - 纵向模式 + 第1页:自动刷新列表 - 纵向模式 + 其他页:不刷新(避免打断用户) - 平铺模式 + 滚动在顶部:自动刷新列表 - 平铺模式 + 滚动不在顶部:仅显示 Toast 提示 防抖效果: - 短时间内收到多个新事件,只执行最后一次刷新 - 减少服务器压力,提升用户体验 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
// src/views/Community/components/DynamicNewsCard/VirtualizedFourRowGrid.js
|
||||
// 虚拟化网格组件(支持多列布局 + 纵向滚动 + 无限滚动)
|
||||
|
||||
import React, { useRef, useMemo, useEffect } from 'react';
|
||||
import React, { useRef, useMemo, useEffect, forwardRef, useImperativeHandle } from 'react';
|
||||
import { useVirtualizer } from '@tanstack/react-virtual';
|
||||
import { Box, Grid, Spinner, Text, VStack, Center, HStack, IconButton, useBreakpointValue } from '@chakra-ui/react';
|
||||
import { RepeatIcon } from '@chakra-ui/icons';
|
||||
@@ -25,7 +25,7 @@ import DynamicNewsEventCard from '../EventCard/DynamicNewsEventCard';
|
||||
* @param {boolean} props.hasMore - 是否还有更多数据
|
||||
* @param {boolean} props.loading - 加载状态
|
||||
*/
|
||||
const VirtualizedFourRowGrid = ({
|
||||
const VirtualizedFourRowGrid = forwardRef(({
|
||||
display = 'block',
|
||||
events,
|
||||
columnsPerRow = 4,
|
||||
@@ -42,7 +42,7 @@ const VirtualizedFourRowGrid = ({
|
||||
loading,
|
||||
error, // 新增:错误状态
|
||||
onRetry, // 新增:重试回调
|
||||
}) => {
|
||||
}, ref) => {
|
||||
const parentRef = useRef(null);
|
||||
const isLoadingMore = useRef(false); // 防止重复加载
|
||||
const lastRefreshTime = useRef(0); // 记录上次刷新时间(用于30秒防抖)
|
||||
@@ -81,6 +81,31 @@ const VirtualizedFourRowGrid = ({
|
||||
overscan: 2, // 预加载2行(上下各1行)
|
||||
});
|
||||
|
||||
/**
|
||||
* ⚡ 暴露方法给父组件(用于 Socket 刷新判断)
|
||||
*/
|
||||
useImperativeHandle(ref, () => ({
|
||||
/**
|
||||
* 获取当前滚动位置信息
|
||||
* @returns {Object|null} 滚动位置信息
|
||||
*/
|
||||
getScrollPosition: () => {
|
||||
const scrollElement = parentRef.current;
|
||||
if (!scrollElement) return null;
|
||||
|
||||
const { scrollTop, scrollHeight, clientHeight } = scrollElement;
|
||||
const isNearTop = scrollTop < clientHeight * 0.1; // 顶部 10% 区域
|
||||
|
||||
return {
|
||||
scrollTop,
|
||||
scrollHeight,
|
||||
clientHeight,
|
||||
isNearTop,
|
||||
scrollPercentage: ((scrollTop + clientHeight) / scrollHeight) * 100,
|
||||
};
|
||||
},
|
||||
}), []);
|
||||
|
||||
/**
|
||||
* 【核心逻辑1】无限滚动 + 顶部刷新 - 监听滚动事件,根据滚动位置自动加载数据或刷新
|
||||
*
|
||||
@@ -360,6 +385,8 @@ const VirtualizedFourRowGrid = ({
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
VirtualizedFourRowGrid.displayName = 'VirtualizedFourRowGrid';
|
||||
|
||||
export default VirtualizedFourRowGrid;
|
||||
|
||||
Reference in New Issue
Block a user