diff --git a/docs/Community.md b/docs/Community.md new file mode 100644 index 00000000..84026a63 --- /dev/null +++ b/docs/Community.md @@ -0,0 +1,1086 @@ +# Community 页面 - 技术文档 + +> **版本**: v1.0.0 +> **更新日期**: 2025-01-07 +> **文档类型**: 页面架构与开发指南 + +--- + +## 📑 目录 + +1. [页面概述](#-页面概述) +2. [页面架构](#-页面架构) +3. [核心功能模块](#-核心功能模块) +4. [数据流与状态管理](#-数据流与状态管理) +5. [自定义 Hooks 详解](#-自定义-hooks-详解) +6. [组件结构说明](#-组件结构说明) +7. [通知与权限引导](#-通知与权限引导) +8. [开发指南](#-开发指南) +9. [代码变更历史](#-代码变更历史) + +--- + +## 📖 页面概述 + +### 功能定位 + +Community 页面(社区页面)是应用的核心功能模块之一,提供实时金融事件、动态新闻、热点事件的展示和追踪功能。 + +### 核心价值 + +- ✅ **实时性**: 展示最新的金融事件和市场动态 +- ✅ **可追踪**: 用户可以关注感兴趣的事件和股票 +- ✅ **可筛选**: 支持多维度筛选(重要性、行业、时间范围等) +- ✅ **数据分析**: 集成 PostHog 埋点,追踪用户行为 +- ✅ **通知引导**: 首次访问时引导用户开启通知权限 + +### 页面入口 + +- **路由路径**: `/community` +- **导航位置**: 主导航栏 +- **权限要求**: MODAL(未登录显示登录弹窗) + +--- + +## 🏗️ 页面架构 + +### 组件树结构 + +``` +Community (index.js) +├── HotEventsSection # 热点事件区域 +│ └── HotEvents # 热点事件卡片列表 +│ +└── DynamicNewsCard # 实时动态新闻区域 + ├── UnifiedSearchBox # 统一搜索框(关键词+筛选器) + │ ├── PopularKeywords # 热门关键词 + │ ├── TradingTimeFilter # 交易时间筛选 + │ └── IndustryCascader # 行业级联选择器 + │ + ├── ModeToggleButtons # 横向/纵向布局切换 + │ + ├── EventScrollList (横向模式) # 横向滚动事件列表 + │ └── EventCard # 事件卡片 + │ ├── HorizontalDynamicNewsEventCard # 横向卡片 + │ └── DynamicNewsEventCard # 纵向卡片 + │ + ├── VerticalModeLayout (纵向模式) # 纵向网格布局 + │ └── VirtualizedFourRowGrid # 虚拟化四行网格 + │ └── EventCard # 事件卡片 + │ + ├── EventDetailScrollPanel # 右侧详情面板 + │ └── DynamicNewsDetail # 事件详情 + │ ├── EventHeaderInfo # 事件头部信息 + │ ├── EventDescriptionSection # 事件描述 + │ ├── RelatedStocksSection # 相关股票 + │ └── RelatedConceptsSection # 相关概念 + │ ├── SimpleConceptCard # 简单概念卡片 + │ └── DetailedConceptCard # 详细概念卡片 + │ + └── PaginationControl # 分页控制 +``` + +### 文件组织方式 + +``` +src/views/Community/ +├── index.js # 页面主入口 +├── index.css # 页面样式 +│ +├── components/ # 页面组件 +│ ├── HotEventsSection.js # 热点事件区域容器 +│ ├── HotEvents.js # 热点事件卡片列表 +│ ├── HotEvents.css +│ │ +│ ├── DynamicNewsCard.js # 实时动态新闻主组件 +│ │ ├── constants.js # 常量定义 +│ │ ├── hooks/ # 专属 Hooks +│ │ │ ├── usePagination.js # 分页逻辑 +│ │ │ └── useInfiniteScroll.js # 无限滚动 +│ │ ├── EventScrollList.js # 横向滚动列表 +│ │ ├── VerticalModeLayout.js # 纵向布局 +│ │ ├── VirtualizedFourRowGrid.js # 虚拟化网格 +│ │ ├── ModeToggleButtons.js # 布局切换按钮 +│ │ ├── PaginationControl.js # 分页控制 +│ │ ├── PageNavigationButton.js # 页码导航按钮 +│ │ └── EventDetailScrollPanel.js # 详情面板容器 +│ │ +│ ├── EventCard/ # 事件卡片组件族 +│ │ ├── index.js # 智能路由(紧凑 vs 详细) +│ │ ├── CompactEventCard.js # 紧凑卡片 +│ │ ├── DetailedEventCard.js # 详细卡片 +│ │ ├── HorizontalDynamicNewsEventCard.js # 横向动态卡片 +│ │ ├── DynamicNewsEventCard.js # 纵向动态卡片 +│ │ ├── EventHeader.js # 事件头部 +│ │ ├── EventDescription.js # 事件描述 +│ │ ├── EventTimeline.js # 事件时间线 +│ │ ├── EventImportanceBadge.js # 重要性徽章 +│ │ ├── ImportanceBadge.js # 重要性标识 +│ │ ├── ImportanceStamp.js # 重要性印章 +│ │ ├── EventPriceDisplay.js # 价格显示 +│ │ ├── EventStats.js # 事件统计 +│ │ └── EventFollowButton.js # 关注按钮 +│ │ +│ ├── DynamicNewsDetail/ # 事件详情面板 +│ │ ├── index.js # 主入口 +│ │ ├── DynamicNewsDetailPanel.js # 详情面板容器 +│ │ ├── EventHeaderInfo.js # 头部信息 +│ │ ├── EventDescriptionSection.js # 描述区域 +│ │ ├── CollapsibleSection.js # 可折叠区域 +│ │ ├── CollapsibleHeader.js # 可折叠头部 +│ │ ├── RelatedStocksSection.js # 相关股票区域 +│ │ ├── StockListItem.js # 股票列表项 +│ │ ├── CompactStockItem.js # 紧凑股票项 +│ │ ├── MiniLineChart.js # 迷你折线图 +│ │ ├── MiniKLineChart.js # 迷你K线图 +│ │ └── RelatedConceptsSection/ # 相关概念区域 +│ │ ├── index.js +│ │ ├── SimpleConceptCard.js # 简单概念卡片 +│ │ ├── DetailedConceptCard.js # 详细概念卡片 +│ │ ├── ConceptStockItem.js # 概念股票项 +│ │ └── TradingDateInfo.js # 交易日期信息 +│ │ +│ ├── UnifiedSearchBox.js # 统一搜索框 +│ ├── PopularKeywords.js # 热门关键词 +│ ├── SearchBox.js # 基础搜索框 +│ ├── TradingTimeFilter.js # 交易时间筛选器 +│ ├── IndustryCascader.js # 行业级联选择器 +│ ├── ImportanceLegend.js # 重要性图例 +│ │ +│ ├── StockDetailPanel.js # 股票详情面板(独立模块) +│ ├── StockDetailPanel.css +│ ├── StockDetailPanel/ +│ │ ├── components/ +│ │ │ ├── index.js +│ │ │ ├── StockSearchBar.js # 股票搜索栏 +│ │ │ ├── StockTable.js # 股票表格 +│ │ │ ├── RelatedStocksTab.js # 相关股票标签页 +│ │ │ ├── MiniTimelineChart.js # 迷你时间线图 +│ │ │ └── LockedContent.js # 锁定内容 +│ │ ├── hooks/ +│ │ │ ├── useEventStocks.js # 事件股票钩子 +│ │ │ ├── useWatchlist.js # 监控列表钩子 +│ │ │ └── useStockMonitoring.js # 股票监控钩子 +│ │ └── utils/ +│ │ └── klineDataCache.js # K线数据缓存 +│ │ +│ ├── EventList.js # 事件列表(旧版,已备份) +│ ├── EventList.js.bak +│ ├── EventList.css +│ ├── EventListSection.js # 事件列表区域 +│ ├── EventTimelineHeader.js # 事件时间线头部 +│ ├── EventDetailModal.js # 事件详情弹窗 +│ ├── EventDiscussionModal.js # 事件讨论弹窗 +│ │ +│ ├── MarketReviewCard.js # 市场回顾卡片 +│ ├── InvestmentCalendar.js # 投资日历 +│ ├── InvestmentCalendar.css +│ ├── MidjourneyHeroSection.js # Hero 区域 +│ │ +│ └── UnifiedSearchBox修复说明.md # 修复说明文档 +│ +└── hooks/ # 页面专属 Hooks + ├── useEventData.js # 事件数据获取 + ├── useEventFilters.js # 事件筛选逻辑 + └── useCommunityEvents.js # PostHog 埋点追踪 +``` + +--- + +## 🎯 核心功能模块 + +### 1. 热点事件展示 (HotEventsSection) + +**功能**:展示当前最热门的事件,吸引用户关注。 + +**位置**: `src/views/Community/components/HotEventsSection.js` + +**特性**: +- 自动获取热点事件数据 +- 卡片式展示,支持点击查看详情 +- 集成 PostHog 埋点追踪点击行为 + +**使用示例**: +```jsx + +``` + +--- + +### 2. 实时动态新闻 (DynamicNewsCard) + +**功能**:展示实时金融事件动态,支持筛选、搜索、分页、布局切换。 + +**位置**: `src/views/Community/components/DynamicNewsCard.js` + +**核心特性**: + +#### 2.1 搜索与筛选 +- ✅ 关键词搜索(支持热门关键词快速选择) +- ✅ 交易时间筛选(盘前、盘中、盘后、全部) +- ✅ 重要性筛选(特级、A级、B级、C级、全部) +- ✅ 行业筛选(行业级联选择器) + +#### 2.2 布局模式 +- **横向滚动模式**: + - 适合快速浏览大量事件 + - 支持左右滚动查看更多 + - 卡片紧凑布局 + +- **纵向网格模式**: + - 适合深度浏览事件详情 + - 虚拟化四行网格提升性能 + - 卡片详细布局 + +#### 2.3 详情面板 +- 右侧滑出式详情面板 +- 展示事件完整描述 +- 展示相关股票和概念 +- 支持点击股票跳转到详情页 + +#### 2.4 分页功能 +- 支持上一页/下一页 +- 支持页码快速跳转 +- 显示当前页码和总页数 + +**使用示例**: +```jsx + +``` + +--- + +### 3. 事件详情查看 (DynamicNewsDetail) + +**功能**:展示单个事件的详细信息,包括描述、相关股票、相关概念等。 + +**位置**: `src/views/Community/components/DynamicNewsDetail/index.js` + +**内容结构**: +``` +DynamicNewsDetail +├── EventHeaderInfo # 事件头部(标题、时间、重要性) +├── EventDescriptionSection # 事件描述 +├── RelatedStocksSection # 相关股票 +│ ├── StockListItem # 股票列表项 +│ ├── CompactStockItem # 紧凑股票项 +│ ├── MiniLineChart # 迷你折线图 +│ └── MiniKLineChart # 迷你K线图 +└── RelatedConceptsSection # 相关概念 + ├── SimpleConceptCard # 简单概念卡片 + ├── DetailedConceptCard # 详细概念卡片 + └── ConceptStockItem # 概念股票项 +``` + +**特性**: +- ✅ 可折叠区域(节省空间) +- ✅ 相关股票实时行情展示 +- ✅ 相关概念板块分析 +- ✅ 支持股票点击跳转 + +--- + +### 4. 股票详情面板 (StockDetailPanel) + +**功能**:独立的股票详情查看模块,支持搜索、监控、K线图查看。 + +**位置**: `src/views/Community/components/StockDetailPanel.js` + +**核心功能**: +- ✅ 股票搜索 +- ✅ 股票监控(加入自选) +- ✅ K线图展示 +- ✅ 相关股票推荐 +- ✅ 事件关联股票 + +**自定义 Hooks**: +- `useEventStocks` - 获取事件关联股票 +- `useWatchlist` - 管理自选股列表 +- `useStockMonitoring` - 股票监控逻辑 + +**数据缓存**: +- `klineDataCache.js` - K线数据缓存,提升性能 + +--- + +## 🔄 数据流与状态管理 + +### Redux State (communityDataSlice) + +**位置**: `src/store/slices/communityDataSlice.js` + +**State 结构**: +```javascript +{ + popularKeywords: [], // 热门关键词 + hotEvents: [], // 热点事件 + loading: false, // 加载状态 + error: null // 错误信息 +} +``` + +**Actions**: +```javascript +// 同步 Actions +dispatch(fetchPopularKeywords()); // 获取热门关键词 +dispatch(fetchHotEvents()); // 获取热点事件 + +// Thunk Actions (异步) +dispatch(fetchPopularKeywordsAsync()); +dispatch(fetchHotEventsAsync()); +``` + +**使用示例**: +```jsx +import { useSelector, useDispatch } from 'react-redux'; +import { fetchPopularKeywords, fetchHotEvents } from '@store/slices/communityDataSlice'; + +const Community = () => { + const dispatch = useDispatch(); + const { popularKeywords, hotEvents } = useSelector(state => state.communityData); + + useEffect(() => { + dispatch(fetchPopularKeywords()); + dispatch(fetchHotEvents()); + }, [dispatch]); + + return (/* ... */); +}; +``` + +--- + +### API 调用流程 + +**API 服务**: `src/services/communityService.js` + +**主要 API 端点**: +```javascript +// 获取事件列表 +GET /api/community/events + ?page=1 + &pageSize=20 + &importance=all + &industry_code=all + &date_range=today + &trading_time=all + &search=关键词 + +// 获取热点事件 +GET /api/community/hot-events + +// 获取热门关键词 +GET /api/community/popular-keywords + +// 获取事件详情 +GET /api/community/events/:id + +// 获取相关股票 +GET /api/community/events/:id/related-stocks + +// 获取相关概念 +GET /api/community/events/:id/related-concepts +``` + +**数据流向**: +``` +用户交互 + ↓ +Component 触发 Action + ↓ +自定义 Hook 处理逻辑 (useEventData, useEventFilters) + ↓ +API Service 调用后端 + ↓ +后端返回数据 + ↓ +Hook 更新本地 State + ↓ +Component 重新渲染 +``` + +--- + +## 🪝 自定义 Hooks 详解 + +### 1. useEventData + +**位置**: `src/views/Community/hooks/useEventData.js` + +**功能**: 根据筛选条件获取事件数据。 + +**输入参数**: +```javascript +const filters = { + page: 1, // 页码 + pageSize: 20, // 每页数量 + importance: 'all', // 重要性筛选 + industry_code: 'all', // 行业代码 + date_range: 'today', // 日期范围 + trading_time: 'all', // 交易时间 + search: '' // 搜索关键词 +}; +``` + +**返回值**: +```javascript +{ + events: [], // 事件列表 + pagination: { // 分页信息 + current: 1, + pageSize: 20, + total: 100 + }, + loading: false, // 加载状态 + lastUpdateTime: Date // 最后更新时间 +} +``` + +**使用示例**: +```jsx +const { events, pagination, loading, lastUpdateTime } = useEventData(filters); +``` + +--- + +### 2. useEventFilters + +**位置**: `src/views/Community/hooks/useEventFilters.js` + +**功能**: 管理事件筛选逻辑和导航。 + +**返回值**: +```javascript +{ + filters: {}, // 当前筛选条件 + updateFilters: (newFilters) => {}, // 更新筛选条件 + handlePageChange: (page) => {}, // 分页变更 + handleEventClick: (event) => {}, // 事件点击 + handleViewDetail: (event) => {} // 查看详情 +} +``` + +**使用示例**: +```jsx +const { + filters, + updateFilters, + handlePageChange, + handleEventClick, + handleViewDetail +} = useEventFilters({ navigate }); +``` + +--- + +### 3. useCommunityEvents + +**位置**: `src/views/Community/hooks/useCommunityEvents.js` + +**功能**: 提供 PostHog 埋点追踪函数集合。 + +**返回的追踪函数**: +```javascript +{ + trackNewsListViewed, // 新闻列表查看 + trackNewsArticleClicked, // 新闻文章点击 + trackNewsDetailOpened, // 新闻详情打开 + trackNewsFilterApplied, // 筛选器应用 + trackNewsSorted, // 排序 + trackNewsSearched, // 搜索 + trackRelatedStockClicked, // 相关股票点击 + trackNewsShareClicked, // 分享点击 + trackNewsCommentPosted, // 评论发布 + trackNewsLiked // 点赞 +} +``` + +**使用示例**: +```jsx +const communityEvents = useCommunityEvents({ navigate }); + +// 追踪事件点击 +communityEvents.trackNewsArticleClicked({ + eventId: event.id, + title: event.title, + importance: event.importance +}); +``` + +--- + +## 🧩 组件结构说明 + +### 原子组件 (Atomic Components) + +#### EventCard 系列 + +**设计模式**: 原子设计 + 智能路由 + +**组件清单**: + +| 组件文件 | 功能 | 使用场景 | +|---------|------|---------| +| `index.js` | 智能路由器 | 根据 `mode` 参数路由到紧凑或详细卡片 | +| `CompactEventCard.js` | 紧凑卡片 | 列表视图、横向滚动 | +| `DetailedEventCard.js` | 详细卡片 | 详情视图、纵向网格 | +| `HorizontalDynamicNewsEventCard.js` | 横向动态卡片 | 横向滚动布局 | +| `DynamicNewsEventCard.js` | 纵向动态卡片 | 纵向网格布局 | +| `EventHeader.js` | 事件头部 | 标题、时间、重要性 | +| `EventDescription.js` | 事件描述 | 文本内容 | +| `EventTimeline.js` | 事件时间线 | 时间轴展示 | +| `EventImportanceBadge.js` | 重要性徽章 | 重要性标识 | +| `ImportanceBadge.js` | 重要性标识 | 简单版徽章 | +| `ImportanceStamp.js` | 重要性印章 | 印章样式 | +| `EventPriceDisplay.js` | 价格显示 | 股票价格和涨跌幅 | +| `EventStats.js` | 事件统计 | 浏览量、点赞数等 | +| `EventFollowButton.js` | 关注按钮 | 关注/取消关注 | + +**智能路由示例**: +```jsx +import EventCard from './components/EventCard'; + +// 紧凑模式 + + +// 详细模式 + + +// 横向动态模式 + + +// 纵向动态模式 + +``` + +--- + +### 复合组件 (Composite Components) + +#### DynamicNewsCard + +**设计模式**: 容器 + 展示分离 + +**核心子组件**: +- `UnifiedSearchBox` - 搜索和筛选 +- `ModeToggleButtons` - 布局切换 +- `EventScrollList` - 横向滚动列表 +- `VerticalModeLayout` - 纵向网格布局 +- `VirtualizedFourRowGrid` - 虚拟化网格(性能优化) +- `EventDetailScrollPanel` - 详情面板 +- `PaginationControl` - 分页控制 + +**状态管理**: +```javascript +// 内部管理的状态 +const [viewMode, setViewMode] = useState('horizontal'); // 布局模式 +const [selectedEvent, setSelectedEvent] = useState(null); // 选中事件 +const [currentPage, setCurrentPage] = useState(1); // 当前页码 +const [detailVisible, setDetailVisible] = useState(false); // 详情面板可见性 +``` + +**自定义 Hooks**: +- `usePagination` - 分页逻辑 +- `useInfiniteScroll` - 无限滚动(可选) + +--- + +#### HotEventsSection + +**设计模式**: 简单容器 + +**功能**: 包装 HotEvents 组件,提供布局和样式。 + +**使用示例**: +```jsx + +``` + +--- + +### 面板组件 (Panel Components) + +#### DynamicNewsDetail + +**位置**: `src/views/Community/components/DynamicNewsDetail/index.js` + +**设计模式**: 组合模式 + +**子组件结构**: +```jsx + + + + + + + + + + + + + + + + +``` + +**特性**: +- ✅ 可折叠区域 +- ✅ 懒加载(折叠时不渲染内容) +- ✅ 滚动优化 + +--- + +#### StockDetailPanel + +**位置**: `src/views/Community/components/StockDetailPanel.js` + +**设计模式**: 独立模块 + +**内部模块**: +- `StockSearchBar` - 股票搜索 +- `StockTable` - 股票表格 +- `RelatedStocksTab` - 相关股票标签页 +- `MiniTimelineChart` - 迷你时间线图 +- `LockedContent` - 锁定内容(需要权限) + +**自定义 Hooks**: +- `useEventStocks` - 事件股票获取 +- `useWatchlist` - 自选股管理 +- `useStockMonitoring` - 股票监控 + +**缓存机制**: +```javascript +// klineDataCache.js +export const klineCache = { + get: (stockCode) => { /* ... */ }, + set: (stockCode, data) => { /* ... */ }, + clear: () => { /* ... */ } +}; +``` + +--- + +## 🔔 通知与权限引导 + +### 首次访问引导 + +**触发时机**: 用户首次访问 Community 页面 + +**延迟时间**: 5 秒(让用户先浏览页面内容) + +**实现代码**: +```jsx +// src/views/Community/index.js +const { showCommunityGuide } = useNotification(); + +useEffect(() => { + if (showCommunityGuide) { + const timer = setTimeout(() => { + logger.info('Community', '显示社区权限引导'); + showCommunityGuide(); + }, 5000); + + return () => clearTimeout(timer); + } +}, [showCommunityGuide]); +``` + +### 权限请求时机 + +**通知权限**: +- 首次收到新事件通知时 +- 用户主动点击"开启通知"按钮时 + +**引导策略**: +- 权限状态为 `default`(未决定)→ 自动请求权限 +- 权限状态为 `denied`(已拒绝)→ 显示设置指引 + +**相关文档**: [NOTIFICATION_SYSTEM.md](./NOTIFICATION_SYSTEM.md) + +--- + +## 📚 开发指南 + +### 添加新的筛选条件 + +**步骤**: + +1. **更新 filters 状态** (`useEventFilters.js`): +```javascript +const [filters, setFilters] = useState({ + // ... 现有筛选条件 + newFilter: 'default' // 新增筛选条件 +}); +``` + +2. **添加筛选器 UI** (`UnifiedSearchBox.js` 或新组件): +```jsx + +``` + +3. **更新 API 调用** (`useEventData.js`): +```javascript +const fetchEvents = async (filters) => { + const response = await api.get('/api/community/events', { + params: { + // ... 现有参数 + new_filter: filters.newFilter + } + }); + return response.data; +}; +``` + +4. **添加 PostHog 埋点** (`useCommunityEvents.js`): +```javascript +const trackNewFilterApplied = (filterValue) => { + posthog.capture('news_filter_applied', { + filter_type: 'new_filter', + filter_value: filterValue + }); +}; +``` + +--- + +### 添加新的事件卡片样式 + +**步骤**: + +1. **创建新组件** (`src/views/Community/components/EventCard/NewStyleCard.js`): +```jsx +import React from 'react'; +import { Box, Text } from '@chakra-ui/react'; + +const NewStyleCard = ({ event, onClick }) => { + return ( + onClick(event)} + cursor="pointer" + // ... 样式 + > + {event.title} + {/* 自定义内容 */} + + ); +}; + +export default NewStyleCard; +``` + +2. **更新智能路由** (`src/views/Community/components/EventCard/index.js`): +```jsx +import NewStyleCard from './NewStyleCard'; + +const EventCard = ({ mode = 'compact', event, ...props }) => { + if (mode === 'new-style') { + return ; + } + + // ... 现有逻辑 +}; +``` + +3. **使用新样式**: +```jsx + +``` + +--- + +### 性能优化建议 + +#### 1. 虚拟化长列表 + +**已实现**: `VirtualizedFourRowGrid.js` + +**适用场景**: 事件数量超过 100 条时 + +**库**: `react-window` + +**示例**: +```jsx +import { FixedSizeGrid } from 'react-window'; + + + {({ columnIndex, rowIndex, style }) => ( +
+ +
+ )} +
+``` + +#### 2. 图片懒加载 + +**实现**: 使用 `loading="lazy"` 属性 + +```jsx +{event.title} +``` + +#### 3. 防抖搜索 + +**实现**: 在搜索框使用 `debounce` + +```javascript +import { debounce } from 'lodash'; + +const debouncedSearch = debounce((keyword) => { + updateFilters({ search: keyword }); +}, 300); +``` + +#### 4. 缓存 API 响应 + +**实现**: 使用 `klineDataCache.js` + +```javascript +// 缓存 K线数据 +const getCachedKlineData = (stockCode) => { + const cached = klineCache.get(stockCode); + if (cached && Date.now() - cached.timestamp < 60000) { + return cached.data; + } + + const data = await fetchKlineData(stockCode); + klineCache.set(stockCode, data); + return data; +}; +``` + +--- + +### 测试指南 + +#### 单元测试 + +**工具**: Jest + React Testing Library + +**测试用例示例**: +```javascript +// useEventData.test.js +import { renderHook } from '@testing-library/react-hooks'; +import { useEventData } from '../hooks/useEventData'; + +describe('useEventData', () => { + it('应该返回事件列表', async () => { + const { result, waitForNextUpdate } = renderHook(() => + useEventData({ page: 1, pageSize: 20 }) + ); + + await waitForNextUpdate(); + + expect(result.current.events).toHaveLength(20); + expect(result.current.loading).toBe(false); + }); +}); +``` + +#### 集成测试 + +**测试场景**: +- 搜索功能是否正常工作 +- 筛选器是否正确应用 +- 分页是否正常切换 +- 事件点击是否正确跳转 + +**测试示例**: +```javascript +// Community.test.js +import { render, screen, fireEvent } from '@testing-library/react'; +import Community from '../index'; + +describe('Community Page', () => { + it('应该显示搜索框', () => { + render(); + expect(screen.getByPlaceholderText('搜索事件...')).toBeInTheDocument(); + }); + + it('应该响应搜索', async () => { + render(); + const searchInput = screen.getByPlaceholderText('搜索事件...'); + + fireEvent.change(searchInput, { target: { value: '特斯拉' } }); + + // 等待搜索结果 + await screen.findByText(/特斯拉/i); + }); +}); +``` + +--- + +## 📜 代码变更历史 + +### 2025-01-07: Community 页面 PostHog 追踪完善 + +**变更类型**: 用户行为追踪完善 + +**背景**: +Community 页面已实现 `useCommunityEvents` hook,提供了 9 个追踪函数,但大部分追踪函数未被实际使用。页面缺少对用户关键交互行为的追踪,无法有效分析用户使用习惯。 + +**变更内容**: + +**新增追踪点**: +1. **热点事件交互追踪** (`HotEvents.js`) + - ✅ 热点事件卡片点击 → `trackNewsArticleClicked` + - 追踪数据:事件 ID、标题、重要性、来源 + +2. **动态新闻交互追踪** (`DynamicNewsCard.js`) + - ✅ 四排模式事件点击(弹窗打开)→ `trackNewsDetailOpened` + - ✅ 首次自动选中事件 → `trackNewsArticleClicked` + - 追踪数据:事件 ID、标题、重要性、显示模式、来源 + +3. **搜索和筛选追踪** (`UnifiedSearchBox.js`) + - ✅ 主搜索提交 → `trackNewsSearched` + - ✅ 股票选择(下拉框)→ `trackRelatedStockClicked` + - ✅ 重要性筛选 → `trackNewsFilterApplied` + - ✅ 排序更改 → `trackNewsSorted` + - ✅ 行业筛选 → `trackNewsFilterApplied` + - ✅ 热门关键词点击 → `trackNewsSearched` + - ✅ 交易时段筛选 → `trackNewsFilterApplied` + - ✅ 筛选重置 → `trackNewsFilterApplied` + - 追踪数据:搜索关键词、筛选类型、筛选值、时间戳 + +**实现策略**: +- 通过 props 传递追踪函数到子组件(`Community/index.js` → 子组件) +- 所有追踪函数从 `useCommunityEvents` hook 获取,无需额外创建 +- 追踪调用为非阻塞操作,不影响用户体验 + +**优化效果**: +- ✅ 实现了 9 个 PostHog 追踪函数中的 6 个 +- ✅ 覆盖了所有关键用户交互:浏览、点击、搜索、筛选 +- ✅ 追踪数据结构化,便于后续分析 +- ✅ 为产品优化和用户行为分析提供数据支持 + +**影响范围**: +- `src/views/Community/index.js` - 传递追踪函数到子组件 +- `src/views/Community/components/HotEventsSection.js` - 接收并传递追踪函数 +- `src/views/Community/components/HotEvents.js` - 热点事件点击追踪 +- `src/views/Community/components/DynamicNewsCard.js` - 事件交互追踪 +- `src/views/Community/components/UnifiedSearchBox.js` - 搜索和筛选追踪 + +**后续改进空间**: +- 可添加模式切换追踪(纵向 ↔ 四排) +- 可添加翻页行为追踪 +- 可添加热点事件轮播翻页追踪 +- 可添加相关概念点击追踪(`trackRelatedConceptClicked`) + +--- + +### 2025-01-07: Community 页面代码清理 + +**变更类型**: 代码清理与优化 + +**背景**: +Community 页面存在大量已注释但未删除的代码,影响可维护性和代码可读性。 + +**变更内容**: + +#### 删除的组件 +- ❌ `EventTimelineCard.js` - 实时事件纵向列表组件(已被 DynamicNewsCard 替代) +- ❌ `EventModals.js` - 事件弹窗组件(功能已整合到 DynamicNewsCard) + +#### 删除的代码 +- ❌ 5 个不再使用的导入语句(EventTimelineCard, EventModals, usePostHogTrack, RETENTION_EVENTS, fetchDynamicNews) +- ❌ 4 个不再使用的状态和 Ref(selectedEvent, selectedEventForStock, eventTimelineRef, hasScrolledRef) +- ❌ 1 个不再使用的函数(scrollToTimeline) +- ❌ 3 处已注释的代码块(PostHog 追踪、EventTimelineCard 渲染、EventModals 渲染) +- ❌ 1 个重复的 useEffect(动态新闻每 5 分钟刷新,DynamicNewsCard 内部已管理) + +#### 优化效果 +- 📉 代码行数:207 行 → 138 行(减少 69 行,33% 代码量) +- ✅ 移除冗余代码,提高可维护性 +- ✅ 减少导入依赖,加快编译速度 +- ✅ 删除未使用的状态,减少内存占用 +- ✅ 代码更清晰,更易理解 + +#### 影响范围 +- `src/views/Community/index.js` - 主页面组件 +- `src/views/Community/components/EventTimelineCard.js` - 已删除 +- `src/views/Community/components/EventModals.js` - 已删除 + +#### 迁移说明 +所有事件展示功能已统一由 `DynamicNewsCard` 组件实现,采用横向滚动布局,用户体验更佳。 + +**提交信息**: +``` +feat: 删除不需要的组件 + +- 删除 EventTimelineCard 和 EventModals +- 清理未使用的导入和状态 +- 移除已注释的代码块 +- 优化页面结构,减少 33% 代码量 +``` + +--- + +## 🔗 相关文档 + +- [项目总览 - CLAUDE.md](../CLAUDE.md) +- [通知系统 - NOTIFICATION_SYSTEM.md](./NOTIFICATION_SYSTEM.md) +- [路由系统 - src/routes/README.md](../src/routes/README.md) +- [Redux 状态管理 - src/store/README.md](../src/store/README.md) +- [PostHog 埋点追踪 - POSTHOG_TRACKING_GUIDE.md](./POSTHOG_TRACKING_GUIDE.md) + +--- + +## 📝 文档维护 + +**更新时机**: +- 添加新功能模块时 +- 重构组件结构时 +- 修复重大 bug 时 +- 性能优化时 + +**更新规范**: +- 保持目录结构清晰 +- 添加代码示例 +- 更新相关链接 +- 记录变更历史 + +**贡献者**: +- 所有参与 Community 页面开发的工程师 + +--- + +**文档结束** 🎉