feat: 实现动态新闻筛选功能并优化虚拟滚动

## 主要改进

### 1. 修复筛选功能
- **问题**: 筛选触发了 API 请求但列表未更新
- **根因**: fetchDynamicNews 硬编码 sort: 'new',未支持筛选参数
- **解决**:
  - Redux action 添加筛选参数支持 (sort, importance, q, date_range, industry_code)
  - DynamicNewsCard 监听 filters 变化并重新请求数据
  - 筛选时清空缓存并从第1页开始加载

### 2. 虚拟滚动优化
- 改造 VirtualizedFourRowGrid 支持多列布局
  - 添加 columnsPerRow prop (默认4列,传1实现单列)
  - 添加 CardComponent prop (支持不同卡片组件)
  - 单列模式使用更小的 gap 间距
- 纵向模式使用虚拟滚动 + 无限滚动
  - 左侧事件列表使用 VirtualizedFourRowGrid (columnsPerRow=1)
  - 使用 HorizontalDynamicNewsEventCard 横向卡片
  - 支持滚动到底部自动加载

### 3. UI 交互优化
- 默认模式改为纵向模式 (左侧列表 + 右侧详情)
- 四排/纵向模式不显示全局 loading 遮罩
- 四排模式弹窗在关闭时不渲染 (性能优化)
- 注释掉单排/双排按钮,只保留纵向和平铺模式

## 技术细节

**数据流**:
```
用户筛选 → updateFilters → filters state 更新
→ DynamicNewsCard useEffect 监听
→ dispatch(fetchDynamicNews({ ...filters, clearCache: true }))
→ API 请求(带筛选参数)
→ Redux state 更新 → 列表重新渲染
```

**虚拟滚动**:
- @tanstack/react-virtual 动态高度测量
- 80% 滚动深度触发无限加载
- 底部 loading 指示器(绝对定位)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
zdl
2025-11-05 09:09:03 +08:00
parent d7f27e428b
commit 188783a8d2
2 changed files with 48 additions and 4 deletions

View File

@@ -131,11 +131,36 @@ const DynamicNewsCard = forwardRef(({
page: PAGINATION_CONFIG.INITIAL_PAGE,
per_page: PAGINATION_CONFIG.CAROUSEL_PAGE_SIZE,
pageSize: PAGINATION_CONFIG.CAROUSEL_PAGE_SIZE, // 传递 pageSize 确保索引计算一致
clearCache: true
clearCache: true,
...filters // 应用初始筛选条件
}));
}
}, [dispatch, allCachedEvents.length]);
// 监听筛选条件变化 - 清空缓存并重新请求数据
useEffect(() => {
// 跳过初始加载(由上面的 useEffect 处理)
if (!hasInitialized.current) return;
console.log('%c🔍 [筛选] 筛选条件改变,重新请求数据', 'color: #8B5CF6; font-weight: bold;', filters);
// 筛选条件改变时清空缓存并从第1页开始加载
dispatch(fetchDynamicNews({
page: PAGINATION_CONFIG.INITIAL_PAGE,
per_page: pageSize,
pageSize: pageSize,
clearCache: true, // 清空缓存
...filters // 应用新的筛选条件
}));
}, [
filters.sort,
filters.importance,
filters.q,
filters.date_range,
filters.industry_code,
dispatch
]); // 只监听筛选参数的变化,不监听 page
// 自动选中逻辑 - 只在首次加载时自动选中第一个事件,翻页时不自动选中
useEffect(() => {
if (currentPageEvents.length > 0) {