# 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% 代码量 ``` --- ### 2025-01-XX: 纵向分栏模式滚动行为优化 **变更类型**: 用户体验优化 **优化内容**: 改进纵向分栏模式(VerticalModeLayout)的滚动交互体验,解决右侧详情面板滚动触发页面滚动以及固定模式切换逻辑的问题。 **改进点**: 1. **右侧详情面板滚动隔离** - `EventDetailScrollPanel.js` - 添加 `overscrollBehavior: 'contain'` 属性,防止滚动传播到页面 - 添加 `data-detail-panel-container` 标识,与左侧列表区分 2. **左侧事件列表明确标识** - `VerticalModeLayout.js` - 将 `data-scroll-container` 改为 `data-event-list-container` - 明确标识左侧事件列表容器,便于固定模式逻辑识别 3. **固定模式进入/退出机制优化** - `DynamicNewsCard.js` - **进入参数**: `TRIGGER_OFFSET = 150px`(原 100px)- 更平滑的视觉过渡 - **退出参数**: - `EXIT_OFFSET = 200px` - 退出比进入更容易(非对称设计) - `EXIT_THRESHOLD = 30px` - 接近顶部 30px 内即可退出(原需精确 0px) - **退出逻辑**: 双重检测机制 - 条件 1: CardHeader 位置超过退出点 → 退出固定模式 - 条件 2: 左侧事件列表滚动到顶部附近 → 退出固定模式 - 任一条件满足即退出,提升用户体验 - **性能优化**: 在 `handleWheel` 中添加 `requestAnimationFrame`,提高滚动性能 **用户体验提升**: - ✅ 右侧详情面板滚动不再触发整个页面滚动 - ✅ 右侧详情面板滚动不再影响固定模式切换 - ✅ 只有左侧事件列表滚动才会触发固定模式退出 - ✅ 固定模式进入/退出更流畅(150px/200px 非对称设计) - ✅ 退出固定模式更容易(接近顶部即可,无需精确到 0px) **技术细节**: - 使用 CSS `overscrollBehavior` 隔离滚动链 - 使用 `data-*` 属性区分不同滚动容器类型 - 非对称触发距离设计(进入 150px,退出 200px) - 双重检测退出条件(位置检测 OR 滚动检测) **影响范围**: - `src/views/Community/components/DynamicNewsCard/EventDetailScrollPanel.js` - `src/views/Community/components/DynamicNewsCard/VerticalModeLayout.js` - `src/views/Community/components/DynamicNewsCard.js` --- ### 2025-01-XX: CollapsibleSection 支持精简/详细模式切换 **变更类型**: 功能增强 **优化内容**: 为事件详情面板的 CollapsibleSection 组件添加精简/详细双模式切换功能,提升用户浏览体验。 **新增功能**: 1. **CollapsibleHeader.js** - 支持模式切换按钮 - 新增 `showModeToggle` prop:是否显示模式切换按钮 - 新增 `currentMode` prop:当前模式('detailed' | 'simple') - 新增 `onModeToggle` prop:模式切换回调 - 按钮样式: - 详细模式展开:`详细模式 ▲` - 详细模式收起:`详细模式 ▼` - 精简模式:`精简模式` - 向后兼容:不提供 `showModeToggle` 时,保持原有的 IconButton 样式 2. **CollapsibleSection.js** - 支持精简/详细模式 - 新增 `simpleContent` prop:精简模式的内容 - 新增 `showModeToggle` prop:是否显示模式切换按钮 - 新增 `defaultMode` prop:默认模式(默认 'detailed') - 模式切换逻辑: - 详细模式 → 精简模式:显示 simpleContent - 精简模式 → 详细模式:自动展开 children - 权限控制:锁定状态下点击模式切换,触发付费弹窗 3. **SimpleStocksList.js** - 新增精简股票列表组件 - 横向展示股票名称和涨跌幅 - 自动根据涨跌幅显示颜色(红涨绿跌) - 支持加载中状态 - 响应式设计,自动折行 4. **DynamicNewsDetailPanel.js** - 相关股票模块启用双模式 - 添加 `showModeToggle={true}` - 添加 `simpleContent`:使用 SimpleStocksList 显示精简股票列表 - `children`:保持原有的 RelatedStocksSection(完整信息) - 默认详细模式展开(PRO 会员) **用户体验提升**: - ✅ 支持精简/详细两种浏览模式,满足不同场景需求 - ✅ 精简模式:快速浏览股票名称和涨跌幅 - ✅ 详细模式:查看完整股票信息(价格、按钮等) - ✅ 一键切换,无需重新加载数据 - ✅ PRO 会员默认展开详细模式,优化会员体验 **技术细节**: - 使用 React useState 管理模式状态 - 模式切换不触发数据重新加载 - 向后兼容:不使用 `showModeToggle` 的 CollapsibleSection 保持原有行为 - 权限控制:锁定状态下切换模式触发付费引导 **影响范围**: - `src/views/Community/components/DynamicNewsDetail/CollapsibleHeader.js` - `src/views/Community/components/DynamicNewsDetail/CollapsibleSection.js` - `src/views/Community/components/DynamicNewsDetail/SimpleStocksList.js`(新增) - `src/views/Community/components/DynamicNewsDetail/DynamicNewsDetailPanel.js` **扩展性**: - 其他模块(历史事件对比、传导链分析)可以复用此功能 - 只需提供对应的 `simpleContent` 即可启用双模式 --- ## 🔗 相关文档 - [项目总览 - 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 页面开发的工程师 --- **文档结束** 🎉