fix: 修复 Socket 新事件通知后不刷新列表的问题

问题描述:
- 用户在第1页时收到新事件 Socket 通知
- 系统调用 handlePageChange(1) 想要刷新列表
- 但列表未刷新,新事件不显示
- 控制台日志显示"⚠️ 重复点击当前页: 1"

根本原因:
- usePagination 的 handlePageChange 函数有"重复点击"检查
- 当 newPage === currentPage 时直接 return(第 169-174 行)
- Socket 新事件触发刷新时,当前在第1页,调用 handlePageChange(1)
- 函数误认为是"用户重复点击分页按钮",阻止了刷新

设计冲突:
- 原始设计:防止用户重复点击分页按钮,避免不必要的 API 请求 
- 副作用:阻止了 Socket 新事件触发的强制刷新逻辑 

修复方案(添加 force 参数):
1. 修改 handlePageChange 函数签名:(newPage, force = false)
   - force = true: 强制刷新(绕过"重复点击"检查)
   - force = false: 正常翻页(保留原有检查)

2. 修改边界检查逻辑(第 173-184 行):
   - 只有在非强制模式下才检查重复点击
   - 强制模式下,即使页码相同也继续执行
   - 添加日志:🔄 [翻页] 强制刷新当前页

3. 修改 Socket 新事件刷新调用(DynamicNewsCard.js:231):
   - 修改前:handlePageChange(1)
   - 修改后:handlePageChange(1, true)  // force = true

修改文件:
- src/views/Community/components/DynamicNewsCard/hooks/usePagination.js
  - 第 161 行:修改函数签名(添加 force 参数)
  - 第 173-184 行:修改边界检查逻辑(添加 force 判断)

- src/views/Community/components/DynamicNewsCard.js
  - 第 230-231 行:修改 handlePageChange 调用(传递 force: true)

修复效果:
-  收到新事件后,第1页强制刷新并显示新事件
-  保留原有的"重复点击"优化(普通翻页)
-  不影响其他页面的用户体验(第2页及以上不打断)
-  清晰的日志区分:
  - 🔄 [翻页] 强制刷新当前页: 1(强制刷新)
  - ⚠️ [翻页] 重复点击当前页: 2(阻止重复点击)

🤖 Generated with Claude Code
This commit is contained in:
zdl
2025-11-17 12:12:01 +08:00
parent d69a32a320
commit 3cadd02492
2 changed files with 15 additions and 5 deletions

View File

@@ -227,8 +227,8 @@ const [currentMode, setCurrentMode] = useState('vertical');
// ========== 纵向模式 ========== // ========== 纵向模式 ==========
// 只在第1页时刷新避免打断用户浏览其他页 // 只在第1页时刷新避免打断用户浏览其他页
if (state.currentPage === 1) { if (state.currentPage === 1) {
console.log('[DynamicNewsCard] 纵向模式 + 第1页 → 刷新列表'); console.log('[DynamicNewsCard] 纵向模式 + 第1页 → 强制刷新列表');
handlePageChange(1); // 清空缓存并刷新第1页 handlePageChange(1, true); // ⚡ 传递 force = true强制刷新第1页
toast({ toast({
title: '检测到新事件', title: '检测到新事件',
status: 'info', status: 'info',

View File

@@ -158,7 +158,11 @@ export const usePagination = ({
}, [dispatch, pageSize, toast, mode]); // 移除 filters 依赖,使用 filtersRef 读取最新值 }, [dispatch, pageSize, toast, mode]); // 移除 filters 依赖,使用 filtersRef 读取最新值
// 翻页处理第1页强制刷新 + 其他页缓存) // 翻页处理第1页强制刷新 + 其他页缓存)
const handlePageChange = useCallback(async (newPage) => { const handlePageChange = useCallback(async (newPage, force = false) => {
// force 参数:是否强制刷新(绕过"重复点击"检查)
// - true: 强制刷新Socket 新事件触发)
// - false: 正常翻页(用户点击分页按钮)
// 边界检查 1: 检查页码范围 // 边界检查 1: 检查页码范围
if (newPage < 1 || newPage > totalPages) { if (newPage < 1 || newPage > totalPages) {
console.log(`%c⚠ [翻页] 页码超出范围: ${newPage}`, 'color: #DC2626; font-weight: bold;'); console.log(`%c⚠ [翻页] 页码超出范围: ${newPage}`, 'color: #DC2626; font-weight: bold;');
@@ -166,13 +170,19 @@ export const usePagination = ({
return; return;
} }
// 边界检查 2: 检查是否重复点击 // 边界检查 2: 检查是否重复点击(强制刷新时绕过此检查)
if (newPage === currentPage) { if (!force && newPage === currentPage) {
console.log(`%c⚠ [翻页] 重复点击当前页: ${newPage}`, 'color: #EAB308; font-weight: bold;'); console.log(`%c⚠ [翻页] 重复点击当前页: ${newPage}`, 'color: #EAB308; font-weight: bold;');
logger.debug('usePagination', '页码未改变', { newPage }); logger.debug('usePagination', '页码未改变', { newPage });
return; return;
} }
// ⚡ 如果是强制刷新force = true即使页码相同也继续执行
if (force && newPage === currentPage) {
console.log(`%c🔄 [翻页] 强制刷新当前页: ${newPage}`, 'color: #10B981; font-weight: bold;');
logger.info('usePagination', '强制刷新当前页', { newPage });
}
// 边界检查 3: 防止竞态条件 - 只拦截相同页面的重复请求 // 边界检查 3: 防止竞态条件 - 只拦截相同页面的重复请求
if (loadingPage === newPage) { if (loadingPage === newPage) {
console.log(`%c⚠ [翻页] 第${newPage}页正在加载中,忽略重复请求`, 'color: #EAB308; font-weight: bold;'); console.log(`%c⚠ [翻页] 第${newPage}页正在加载中,忽略重复请求`, 'color: #EAB308; font-weight: bold;');