Files
vf_react/src/views/TradingSimulation/hooks/useTradingSimulationEvents.js
zdl 1cf6169370 feat: 创建了 4个核心埋点Hook
-  覆盖了 45+个追踪事件
  -  补充了 4个核心功能模块的完整埋点
  -  提供了 详细的集成指南和示例代码
  -  提升了 Retention指标覆盖率至90%
  -  建立了 Revenue转化追踪基础
2025-10-29 11:40:32 +08:00

304 lines
9.8 KiB
JavaScript

// src/views/TradingSimulation/hooks/useTradingSimulationEvents.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 {Object} options.portfolio - 账户信息
* @param {number} options.portfolio.totalValue - 总资产
* @param {number} options.portfolio.availableCash - 可用资金
* @param {number} options.portfolio.holdingsCount - 持仓数量
* @param {Function} options.navigate - 路由导航函数
* @returns {Object} 事件追踪处理函数集合
*/
export const useTradingSimulationEvents = ({ portfolio, navigate } = {}) => {
const { track } = usePostHogTrack();
// 🎯 页面浏览事件 - 页面加载时触发
useEffect(() => {
track(RETENTION_EVENTS.TRADING_SIMULATION_ENTERED, {
total_value: portfolio?.totalValue || 0,
available_cash: portfolio?.availableCash || 0,
holdings_count: portfolio?.holdingsCount || 0,
has_holdings: Boolean(portfolio?.holdingsCount && portfolio.holdingsCount > 0),
timestamp: new Date().toISOString(),
});
logger.debug('useTradingSimulationEvents', '🎮 Trading Simulation Entered', {
totalValue: portfolio?.totalValue,
holdingsCount: portfolio?.holdingsCount,
});
}, [track, portfolio]);
/**
* 追踪股票搜索(模拟盘内)
* @param {string} query - 搜索关键词
* @param {number} resultCount - 搜索结果数量
*/
const trackSimulationStockSearched = useCallback((query, resultCount = 0) => {
if (!query) return;
track(RETENTION_EVENTS.SIMULATION_STOCK_SEARCHED, {
query,
result_count: resultCount,
has_results: resultCount > 0,
timestamp: new Date().toISOString(),
});
// 如果没有搜索结果,额外追踪
if (resultCount === 0) {
track(RETENTION_EVENTS.SEARCH_NO_RESULTS, {
query,
context: 'trading_simulation',
timestamp: new Date().toISOString(),
});
}
logger.debug('useTradingSimulationEvents', '🔍 Simulation Stock Searched', {
query,
resultCount,
});
}, [track]);
/**
* 追踪下单操作
* @param {Object} order - 订单信息
* @param {string} order.stockCode - 股票代码
* @param {string} order.stockName - 股票名称
* @param {string} order.direction - 买卖方向 ('buy' | 'sell')
* @param {number} order.quantity - 数量
* @param {number} order.price - 价格
* @param {string} order.orderType - 订单类型 ('market' | 'limit')
* @param {boolean} order.success - 是否成功
*/
const trackSimulationOrderPlaced = useCallback((order) => {
if (!order || !order.stockCode) {
logger.warn('useTradingSimulationEvents', 'Order object is required');
return;
}
track(RETENTION_EVENTS.SIMULATION_ORDER_PLACED, {
stock_code: order.stockCode,
stock_name: order.stockName || '',
direction: order.direction,
quantity: order.quantity,
price: order.price,
order_type: order.orderType || 'market',
order_value: order.quantity * order.price,
success: order.success,
error_message: order.errorMessage || null,
timestamp: new Date().toISOString(),
});
logger.debug('useTradingSimulationEvents', '📝 Simulation Order Placed', {
stockCode: order.stockCode,
direction: order.direction,
quantity: order.quantity,
success: order.success,
});
}, [track]);
/**
* 追踪持仓查看
* @param {Object} holdings - 持仓信息
* @param {number} holdings.count - 持仓数量
* @param {number} holdings.totalValue - 持仓总市值
* @param {number} holdings.totalCost - 持仓总成本
* @param {number} holdings.profitLoss - 总盈亏
*/
const trackSimulationHoldingsViewed = useCallback((holdings = {}) => {
track(RETENTION_EVENTS.SIMULATION_HOLDINGS_VIEWED, {
holdings_count: holdings.count || 0,
total_value: holdings.totalValue || 0,
total_cost: holdings.totalCost || 0,
profit_loss: holdings.profitLoss || 0,
profit_loss_percent: holdings.totalCost ? ((holdings.profitLoss / holdings.totalCost) * 100).toFixed(2) : 0,
has_profit: holdings.profitLoss > 0,
timestamp: new Date().toISOString(),
});
logger.debug('useTradingSimulationEvents', '💼 Simulation Holdings Viewed', {
count: holdings.count,
profitLoss: holdings.profitLoss,
});
}, [track]);
/**
* 追踪持仓股票点击
* @param {Object} holding - 持仓对象
* @param {string} holding.stockCode - 股票代码
* @param {string} holding.stockName - 股票名称
* @param {number} holding.profitLoss - 盈亏金额
* @param {number} position - 在列表中的位置
*/
const trackHoldingClicked = useCallback((holding, position = 0) => {
if (!holding || !holding.stockCode) {
logger.warn('useTradingSimulationEvents', 'Holding object is required');
return;
}
track(RETENTION_EVENTS.STOCK_CLICKED, {
stock_code: holding.stockCode,
stock_name: holding.stockName || '',
source: 'simulation_holdings',
profit_loss: holding.profitLoss || 0,
position,
timestamp: new Date().toISOString(),
});
logger.debug('useTradingSimulationEvents', '🎯 Holding Clicked', {
stockCode: holding.stockCode,
position,
});
}, [track]);
/**
* 追踪历史交易记录查看
* @param {Object} history - 历史记录信息
* @param {number} history.count - 交易记录数量
* @param {string} history.filterBy - 筛选条件 ('all' | 'buy' | 'sell')
* @param {string} history.dateRange - 日期范围
*/
const trackSimulationHistoryViewed = useCallback((history = {}) => {
track(RETENTION_EVENTS.SIMULATION_HISTORY_VIEWED, {
history_count: history.count || 0,
filter_by: history.filterBy || 'all',
date_range: history.dateRange || 'all',
has_history: Boolean(history.count && history.count > 0),
timestamp: new Date().toISOString(),
});
logger.debug('useTradingSimulationEvents', '📜 Simulation History Viewed', {
count: history.count,
filterBy: history.filterBy,
});
}, [track]);
/**
* 追踪买入按钮点击
* @param {Object} stock - 股票对象
* @param {string} stock.code - 股票代码
* @param {string} stock.name - 股票名称
* @param {number} stock.price - 当前价格
* @param {string} source - 来源 ('search' | 'holdings' | 'stock_detail')
*/
const trackBuyButtonClicked = useCallback((stock, source = 'search') => {
if (!stock || !stock.code) {
logger.warn('useTradingSimulationEvents', 'Stock object is required');
return;
}
track('Simulation Buy Button Clicked', {
stock_code: stock.code,
stock_name: stock.name || '',
current_price: stock.price || 0,
source,
timestamp: new Date().toISOString(),
});
logger.debug('useTradingSimulationEvents', '🟢 Buy Button Clicked', {
stockCode: stock.code,
source,
});
}, [track]);
/**
* 追踪卖出按钮点击
* @param {Object} holding - 持仓对象
* @param {string} holding.stockCode - 股票代码
* @param {string} holding.stockName - 股票名称
* @param {number} holding.quantity - 持有数量
* @param {number} holding.profitLoss - 盈亏金额
* @param {string} source - 来源 ('holdings' | 'stock_detail')
*/
const trackSellButtonClicked = useCallback((holding, source = 'holdings') => {
if (!holding || !holding.stockCode) {
logger.warn('useTradingSimulationEvents', 'Holding object is required');
return;
}
track('Simulation Sell Button Clicked', {
stock_code: holding.stockCode,
stock_name: holding.stockName || '',
quantity: holding.quantity || 0,
profit_loss: holding.profitLoss || 0,
source,
timestamp: new Date().toISOString(),
});
logger.debug('useTradingSimulationEvents', '🔴 Sell Button Clicked', {
stockCode: holding.stockCode,
source,
});
}, [track]);
/**
* 追踪账户重置
* @param {Object} beforeReset - 重置前的账户信息
* @param {number} beforeReset.totalValue - 总资产
* @param {number} beforeReset.profitLoss - 总盈亏
*/
const trackAccountReset = useCallback((beforeReset = {}) => {
track('Simulation Account Reset', {
total_value_before: beforeReset.totalValue || 0,
profit_loss_before: beforeReset.profitLoss || 0,
holdings_count_before: beforeReset.holdingsCount || 0,
timestamp: new Date().toISOString(),
});
logger.debug('useTradingSimulationEvents', '🔄 Account Reset', {
totalValueBefore: beforeReset.totalValue,
});
}, [track]);
/**
* 追踪标签页切换
* @param {string} tabName - 标签名称 ('trading' | 'holdings' | 'history')
*/
const trackTabClicked = useCallback((tabName) => {
if (!tabName) {
logger.warn('useTradingSimulationEvents', 'Tab name is required');
return;
}
track('Simulation Tab Clicked', {
tab_name: tabName,
timestamp: new Date().toISOString(),
});
logger.debug('useTradingSimulationEvents', '📑 Tab Clicked', {
tabName,
});
}, [track]);
return {
// 搜索事件
trackSimulationStockSearched,
// 交易事件
trackSimulationOrderPlaced,
trackBuyButtonClicked,
trackSellButtonClicked,
// 持仓事件
trackSimulationHoldingsViewed,
trackHoldingClicked,
// 历史记录事件
trackSimulationHistoryViewed,
// 账户管理事件
trackAccountReset,
// UI交互事件
trackTabClicked,
};
};
export default useTradingSimulationEvents;