feat: Company - 5个事件(页面浏览、股票搜索、Tab 切换、自选股管理)
This commit is contained in:
103
src/views/Company/hooks/useCompanyEvents.js
Normal file
103
src/views/Company/hooks/useCompanyEvents.js
Normal file
@@ -0,0 +1,103 @@
|
||||
// src/views/Company/hooks/useCompanyEvents.js
|
||||
// 公司详情页面事件追踪 Hook
|
||||
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { usePostHogTrack } from '../../../hooks/usePostHogRedux';
|
||||
import { RETENTION_EVENTS } from '../../../lib/constants';
|
||||
import { logger } from '../../../utils/logger';
|
||||
|
||||
/**
|
||||
* 公司详情页面事件追踪 Hook
|
||||
* @param {Object} options - 配置选项
|
||||
* @param {string} options.stockCode - 当前股票代码
|
||||
* @returns {Object} 事件追踪处理函数集合
|
||||
*/
|
||||
export const useCompanyEvents = ({ stockCode } = {}) => {
|
||||
const { track } = usePostHogTrack();
|
||||
|
||||
// 🎯 页面浏览事件 - 页面加载时触发
|
||||
useEffect(() => {
|
||||
track(RETENTION_EVENTS.COMPANY_PAGE_VIEWED, {
|
||||
timestamp: new Date().toISOString(),
|
||||
stock_code: stockCode || null,
|
||||
});
|
||||
logger.debug('useCompanyEvents', '📊 Company Page Viewed', { stockCode });
|
||||
}, [track, stockCode]);
|
||||
|
||||
/**
|
||||
* 追踪股票搜索/切换
|
||||
* @param {string} newStockCode - 新的股票代码
|
||||
* @param {string} previousStockCode - 之前的股票代码
|
||||
*/
|
||||
const trackStockSearched = useCallback((newStockCode, previousStockCode = null) => {
|
||||
if (!newStockCode) return;
|
||||
|
||||
track(RETENTION_EVENTS.STOCK_SEARCHED, {
|
||||
query: newStockCode,
|
||||
stock_code: newStockCode,
|
||||
previous_stock_code: previousStockCode,
|
||||
context: 'company_page',
|
||||
});
|
||||
|
||||
logger.debug('useCompanyEvents', '🔍 Stock Searched', {
|
||||
newStockCode,
|
||||
previousStockCode,
|
||||
});
|
||||
}, [track]);
|
||||
|
||||
/**
|
||||
* 追踪 Tab 切换
|
||||
* @param {number} tabIndex - Tab 索引 (0: 公司概览, 1: 股票行情, 2: 财务全景, 3: 盈利预测)
|
||||
* @param {string} tabName - Tab 名称
|
||||
* @param {number} previousTabIndex - 之前的 Tab 索引
|
||||
*/
|
||||
const trackTabChanged = useCallback((tabIndex, tabName, previousTabIndex = null) => {
|
||||
track(RETENTION_EVENTS.TAB_CHANGED, {
|
||||
tab_index: tabIndex,
|
||||
tab_name: tabName,
|
||||
previous_tab_index: previousTabIndex,
|
||||
stock_code: stockCode,
|
||||
context: 'company_page',
|
||||
});
|
||||
|
||||
logger.debug('useCompanyEvents', '🔄 Tab Changed', {
|
||||
tabIndex,
|
||||
tabName,
|
||||
previousTabIndex,
|
||||
stockCode,
|
||||
});
|
||||
}, [track, stockCode]);
|
||||
|
||||
/**
|
||||
* 追踪加入自选股
|
||||
* @param {string} stock_code - 股票代码
|
||||
*/
|
||||
const trackWatchlistAdded = useCallback((stock_code) => {
|
||||
track(RETENTION_EVENTS.WATCHLIST_ADDED, {
|
||||
stock_code,
|
||||
source: 'company_page',
|
||||
});
|
||||
|
||||
logger.debug('useCompanyEvents', '⭐ Watchlist Added', { stock_code });
|
||||
}, [track]);
|
||||
|
||||
/**
|
||||
* 追踪移除自选股
|
||||
* @param {string} stock_code - 股票代码
|
||||
*/
|
||||
const trackWatchlistRemoved = useCallback((stock_code) => {
|
||||
track(RETENTION_EVENTS.WATCHLIST_REMOVED, {
|
||||
stock_code,
|
||||
source: 'company_page',
|
||||
});
|
||||
|
||||
logger.debug('useCompanyEvents', '❌ Watchlist Removed', { stock_code });
|
||||
}, [track]);
|
||||
|
||||
return {
|
||||
trackStockSearched,
|
||||
trackTabChanged,
|
||||
trackWatchlistAdded,
|
||||
trackWatchlistRemoved,
|
||||
};
|
||||
};
|
||||
@@ -34,6 +34,8 @@ import FinancialPanorama from './FinancialPanorama';
|
||||
import ForecastReport from './ForecastReport';
|
||||
import MarketDataView from './MarketDataView';
|
||||
import CompanyOverview from './CompanyOverview';
|
||||
// 导入 PostHog 追踪 Hook
|
||||
import { useCompanyEvents } from './hooks/useCompanyEvents';
|
||||
|
||||
const CompanyIndex = () => {
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
@@ -42,7 +44,18 @@ const CompanyIndex = () => {
|
||||
const { colorMode, toggleColorMode } = useColorMode();
|
||||
const toast = useToast();
|
||||
const { isAuthenticated } = useAuth();
|
||||
|
||||
|
||||
// 🎯 PostHog 事件追踪
|
||||
const {
|
||||
trackStockSearched,
|
||||
trackTabChanged,
|
||||
trackWatchlistAdded,
|
||||
trackWatchlistRemoved,
|
||||
} = useCompanyEvents({ stockCode });
|
||||
|
||||
// Tab 索引状态(用于追踪 Tab 切换)
|
||||
const [currentTabIndex, setCurrentTabIndex] = useState(0);
|
||||
|
||||
const bgColor = useColorModeValue('white', 'gray.800');
|
||||
const tabBg = useColorModeValue('gray.50', 'gray.700');
|
||||
const activeBg = useColorModeValue('blue.500', 'blue.400');
|
||||
@@ -86,6 +99,9 @@ const CompanyIndex = () => {
|
||||
|
||||
const handleSearch = () => {
|
||||
if (inputCode && inputCode !== stockCode) {
|
||||
// 🎯 追踪股票搜索
|
||||
trackStockSearched(inputCode, stockCode);
|
||||
|
||||
setStockCode(inputCode);
|
||||
setSearchParams({ scode: inputCode });
|
||||
}
|
||||
@@ -123,6 +139,10 @@ const CompanyIndex = () => {
|
||||
|
||||
logger.api.response('DELETE', url, resp.status);
|
||||
if (!resp.ok) throw new Error('删除失败');
|
||||
|
||||
// 🎯 追踪移除自选
|
||||
trackWatchlistRemoved(stockCode);
|
||||
|
||||
setIsInWatchlist(false);
|
||||
toast({ title: '已从自选移除', status: 'info', duration: 1500 });
|
||||
} else {
|
||||
@@ -140,6 +160,10 @@ const CompanyIndex = () => {
|
||||
|
||||
logger.api.response('POST', url, resp.status);
|
||||
if (!resp.ok) throw new Error('添加失败');
|
||||
|
||||
// 🎯 追踪加入自选
|
||||
trackWatchlistAdded(stockCode);
|
||||
|
||||
setIsInWatchlist(true);
|
||||
toast({ title: '已加入自选', status: 'success', duration: 1500 });
|
||||
}
|
||||
@@ -226,7 +250,18 @@ const CompanyIndex = () => {
|
||||
{/* 数据展示区域 */}
|
||||
<Card bg={bgColor} shadow="lg">
|
||||
<CardBody p={0}>
|
||||
<Tabs variant="soft-rounded" colorScheme="blue" size="lg">
|
||||
<Tabs
|
||||
variant="soft-rounded"
|
||||
colorScheme="blue"
|
||||
size="lg"
|
||||
index={currentTabIndex}
|
||||
onChange={(index) => {
|
||||
const tabNames = ['公司概览', '股票行情', '财务全景', '盈利预测'];
|
||||
// 🎯 追踪 Tab 切换
|
||||
trackTabChanged(index, tabNames[index], currentTabIndex);
|
||||
setCurrentTabIndex(index);
|
||||
}}
|
||||
>
|
||||
<TabList p={4} bg={tabBg}>
|
||||
<Tab
|
||||
_selected={{
|
||||
|
||||
Reference in New Issue
Block a user