// src/views/Community/hooks/useCommunityEvents.js // 新闻催化分析页面事件追踪 Hook import { useCallback, useEffect } from 'react'; import { usePostHogTrack } from '../../../hooks/usePostHogRedux'; import { RETENTION_EVENTS } from '../../../lib/constants'; import { logger } from '../../../utils/logger'; /** * 新闻催化分析(Community)事件追踪 Hook * @param {Object} options - 配置选项 * @param {Function} options.navigate - 路由导航函数 * @returns {Object} 事件追踪处理函数集合 */ export const useCommunityEvents = ({ navigate } = {}) => { const { track } = usePostHogTrack(); // 🎯 页面浏览事件 - 页面加载时触发 useEffect(() => { track(RETENTION_EVENTS.COMMUNITY_PAGE_VIEWED, { timestamp: new Date().toISOString(), }); logger.debug('useCommunityEvents', '📰 Community Page Viewed'); }, [track]); /** * 追踪新闻列表查看 * @param {Object} params - 列表参数 * @param {number} params.totalCount - 新闻总数 * @param {string} params.sortBy - 排序方式 ('new' | 'hot' | 'returns') * @param {string} params.importance - 重要性筛选 ('all' | 'high' | 'medium' | 'low') * @param {string} params.dateRange - 日期范围 * @param {string} params.industryFilter - 行业筛选 */ const trackNewsListViewed = useCallback((params = {}) => { track(RETENTION_EVENTS.NEWS_LIST_VIEWED, { total_count: params.totalCount || 0, sort_by: params.sortBy || 'new', importance_filter: params.importance || 'all', date_range: params.dateRange || 'all', industry_filter: params.industryFilter || 'all', timestamp: new Date().toISOString(), }); logger.debug('useCommunityEvents', '📋 News List Viewed', params); }, [track]); /** * 追踪新闻文章点击 * @param {Object} news - 新闻对象 * @param {number} news.id - 新闻ID * @param {string} news.title - 新闻标题 * @param {string} news.importance - 重要性等级 * @param {number} position - 在列表中的位置 * @param {string} source - 点击来源 ('list' | 'search' | 'recommendation') */ const trackNewsArticleClicked = useCallback((news, position = 0, source = 'list') => { if (!news || !news.id) { logger.warn('useCommunityEvents', 'trackNewsArticleClicked: news object is required'); return; } track(RETENTION_EVENTS.NEWS_ARTICLE_CLICKED, { news_id: news.id, news_title: news.title || '', importance: news.importance || 'unknown', position, source, timestamp: new Date().toISOString(), }); logger.debug('useCommunityEvents', '🖱️ News Article Clicked', { id: news.id, position, source, }); }, [track]); /** * 追踪新闻详情打开 * @param {Object} news - 新闻对象 * @param {number} news.id - 新闻ID * @param {string} news.title - 新闻标题 * @param {string} news.importance - 重要性等级 * @param {string} viewMode - 查看模式 ('modal' | 'page') */ const trackNewsDetailOpened = useCallback((news, viewMode = 'modal') => { if (!news || !news.id) { logger.warn('useCommunityEvents', 'trackNewsDetailOpened: news object is required'); return; } track(RETENTION_EVENTS.NEWS_DETAIL_OPENED, { news_id: news.id, news_title: news.title || '', importance: news.importance || 'unknown', view_mode: viewMode, timestamp: new Date().toISOString(), }); logger.debug('useCommunityEvents', '📖 News Detail Opened', { id: news.id, viewMode, }); }, [track]); /** * 追踪新闻标签页切换 * @param {string} tabName - 标签名称 ('related_stocks' | 'related_concepts' | 'timeline') * @param {number} newsId - 新闻ID */ const trackNewsTabClicked = useCallback((tabName, newsId = null) => { if (!tabName) { logger.warn('useCommunityEvents', 'trackNewsTabClicked: tabName is required'); return; } track(RETENTION_EVENTS.NEWS_TAB_CLICKED, { tab_name: tabName, news_id: newsId, timestamp: new Date().toISOString(), }); logger.debug('useCommunityEvents', '📑 News Tab Clicked', { tabName, newsId, }); }, [track]); /** * 追踪新闻筛选应用 * @param {Object} filters - 筛选条件 * @param {string} filters.importance - 重要性筛选 * @param {string} filters.dateRange - 日期范围 * @param {string} filters.industryClassification - 行业分类 * @param {string} filters.industryCode - 行业代码 */ const trackNewsFilterApplied = useCallback((filters = {}) => { track(RETENTION_EVENTS.NEWS_FILTER_APPLIED, { importance: filters.importance || 'all', date_range: filters.dateRange || 'all', industry_classification: filters.industryClassification || 'all', industry_code: filters.industryCode || 'all', filter_count: Object.keys(filters).filter(key => filters[key] && filters[key] !== 'all').length, timestamp: new Date().toISOString(), }); logger.debug('useCommunityEvents', '🔍 News Filter Applied', filters); }, [track]); /** * 追踪新闻排序方式变更 * @param {string} sortBy - 排序方式 ('new' | 'hot' | 'returns') * @param {string} previousSort - 之前的排序方式 */ const trackNewsSorted = useCallback((sortBy, previousSort = 'new') => { if (!sortBy) { logger.warn('useCommunityEvents', 'trackNewsSorted: sortBy is required'); return; } track(RETENTION_EVENTS.NEWS_SORTED, { sort_by: sortBy, previous_sort: previousSort, timestamp: new Date().toISOString(), }); logger.debug('useCommunityEvents', '🔄 News Sorted', { sortBy, previousSort, }); }, [track]); /** * 追踪搜索事件(新闻搜索) * @param {string} query - 搜索关键词 * @param {number} resultCount - 搜索结果数量 */ const trackNewsSearched = useCallback((query, resultCount = 0) => { if (!query) return; track(RETENTION_EVENTS.SEARCH_QUERY_SUBMITTED, { query, result_count: resultCount, has_results: resultCount > 0, context: 'community_news', timestamp: new Date().toISOString(), }); // 如果没有搜索结果,额外追踪 if (resultCount === 0) { track(RETENTION_EVENTS.SEARCH_NO_RESULTS, { query, context: 'community_news', timestamp: new Date().toISOString(), }); } logger.debug('useCommunityEvents', '🔍 News Searched', { query, resultCount, }); }, [track]); /** * 追踪相关股票点击(从新闻详情) * @param {Object} stock - 股票对象 * @param {string} stock.code - 股票代码 * @param {string} stock.name - 股票名称 * @param {number} newsId - 关联的新闻ID */ const trackRelatedStockClicked = useCallback((stock, newsId = null) => { if (!stock || !stock.code) { logger.warn('useCommunityEvents', 'trackRelatedStockClicked: stock object is required'); return; } track(RETENTION_EVENTS.STOCK_CLICKED, { stock_code: stock.code, stock_name: stock.name || '', source: 'news_related_stocks', news_id: newsId, timestamp: new Date().toISOString(), }); logger.debug('useCommunityEvents', '🎯 Related Stock Clicked', { stockCode: stock.code, newsId, }); }, [track]); /** * 追踪相关概念点击(从新闻详情) * @param {Object} concept - 概念对象 * @param {string} concept.code - 概念代码 * @param {string} concept.name - 概念名称 * @param {number} newsId - 关联的新闻ID */ const trackRelatedConceptClicked = useCallback((concept, newsId = null) => { if (!concept || !concept.code) { logger.warn('useCommunityEvents', 'trackRelatedConceptClicked: concept object is required'); return; } track(RETENTION_EVENTS.CONCEPT_CLICKED, { concept_code: concept.code, concept_name: concept.name || '', source: 'news_related_concepts', news_id: newsId, timestamp: new Date().toISOString(), }); logger.debug('useCommunityEvents', '🏷️ Related Concept Clicked', { conceptCode: concept.code, newsId, }); }, [track]); return { // 页面级事件 trackNewsListViewed, // 新闻交互事件 trackNewsArticleClicked, trackNewsDetailOpened, trackNewsTabClicked, // 筛选和排序事件 trackNewsFilterApplied, trackNewsSorted, // 搜索事件 trackNewsSearched, // 关联内容点击事件 trackRelatedStockClicked, trackRelatedConceptClicked, }; }; export default useCommunityEvents;