From c6a6444d9a177f3e21d100be86f13ce5b3f19a99 Mon Sep 17 00:00:00 2001 From: zdl <3489966805@qq.com> Date: Tue, 28 Oct 2025 21:45:51 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=A6=82=E5=BF=B5=E4=B8=AD=E5=BF=83?= =?UTF-8?q?=E7=9A=84=E4=BA=8B=E4=BB=B6=E8=BF=BD=E8=B8=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/Concept/ConceptTimelineModal.js | 25 ++++++++++++ .../Concept/components/ConceptStatsPanel.js | 38 ++++++++++++++++-- .../Concept/hooks/useConceptStatsEvents.js | Bin 0 -> 3189 bytes .../Concept/hooks/useConceptTimelineEvents.js | Bin 0 -> 4124 bytes 4 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 src/views/Concept/hooks/useConceptStatsEvents.js create mode 100644 src/views/Concept/hooks/useConceptTimelineEvents.js diff --git a/src/views/Concept/ConceptTimelineModal.js b/src/views/Concept/ConceptTimelineModal.js index a44049f1..214206e4 100644 --- a/src/views/Concept/ConceptTimelineModal.js +++ b/src/views/Concept/ConceptTimelineModal.js @@ -1,5 +1,6 @@ import React, { useState, useEffect } from 'react'; import { logger } from '../../utils/logger'; +import { useConceptTimelineEvents } from './hooks/useConceptTimelineEvents'; import { Modal, ModalOverlay, @@ -64,6 +65,17 @@ const ConceptTimelineModal = ({ conceptId }) => { const toast = useToast(); + + // 🎯 PostHog 事件追踪 + const { + trackDateToggled, + trackNewsClicked, + trackNewsDetailOpened, + trackReportClicked, + trackReportDetailOpened, + trackModalClosed, + } = useConceptTimelineEvents({ conceptName, conceptId, isOpen }); + const [timelineData, setTimelineData] = useState([]); const [loading, setLoading] = useState(true); const [expandedDates, setExpandedDates] = useState({}); @@ -318,6 +330,11 @@ const ConceptTimelineModal = ({ // 切换日期展开状态 const toggleDateExpand = (date) => { + const willExpand = !expandedDates[date]; + + // 🎯 追踪日期展开/折叠 + trackDateToggled(date, willExpand); + setExpandedDates(prev => ({ ...prev, [date]: !prev[date] @@ -728,6 +745,10 @@ const ConceptTimelineModal = ({ leftIcon={} onClick={() => { if (event.type === 'news') { + // 🎯 追踪新闻点击和详情打开 + trackNewsClicked(event, date); + trackNewsDetailOpened(event); + setSelectedNews({ title: event.title, content: event.content, @@ -737,6 +758,10 @@ const ConceptTimelineModal = ({ }); setIsNewsModalOpen(true); } else if (event.type === 'report') { + // 🎯 追踪研报点击和详情打开 + trackReportClicked(event, date); + trackReportDetailOpened(event); + setSelectedReport({ title: event.title, content: event.content, diff --git a/src/views/Concept/components/ConceptStatsPanel.js b/src/views/Concept/components/ConceptStatsPanel.js index 23117993..68a93935 100644 --- a/src/views/Concept/components/ConceptStatsPanel.js +++ b/src/views/Concept/components/ConceptStatsPanel.js @@ -1,5 +1,6 @@ import React, { useState, useEffect } from 'react'; import { logger } from '../../../utils/logger'; +import { useConceptStatsEvents } from '../hooks/useConceptStatsEvents'; import { Box, SimpleGrid, @@ -54,6 +55,15 @@ const ConceptStatsPanel = ({ apiBaseUrl, onConceptClick }) => { ? '/concept-api' : 'http://111.198.58.126:16801'; + // 🎯 PostHog 事件追踪 + const { + trackTabChanged, + trackTimeRangeChanged, + trackCustomDateRangeSet, + trackRankItemClicked, + trackDataRefreshed, + } = useConceptStatsEvents(); + const [statsData, setStatsData] = useState({}); const [loading, setLoading] = useState(true); const [activeTab, setActiveTab] = useState(0); @@ -180,10 +190,18 @@ const ConceptStatsPanel = ({ apiBaseUrl, onConceptClick }) => { setCustomEndDate(today.toISOString().split('T')[0]); setCustomStartDate(weekAgo.toISOString().split('T')[0]); + + // 🎯 追踪切换到自定义范围 + trackTimeRangeChanged(0, true); } else { setUseCustomRange(false); - setTimeRange(parseInt(newRange)); - fetchStatsData(parseInt(newRange)); + const days = parseInt(newRange); + setTimeRange(days); + + // 🎯 追踪时间范围变化 + trackTimeRangeChanged(days, false); + + fetchStatsData(days); } }; @@ -199,6 +217,10 @@ const ConceptStatsPanel = ({ apiBaseUrl, onConceptClick }) => { }); return; } + + // 🎯 追踪自定义日期范围设置 + trackCustomDateRangeSet(customStartDate, customEndDate); + fetchStatsData(null, customStartDate, customEndDate); } }; @@ -848,7 +870,17 @@ const ConceptStatsPanel = ({ apiBaseUrl, onConceptClick }) => { {/* 主内容卡片 */} - + { + const tabNames = ['涨幅榜', '跌幅榜', '活跃榜', '波动榜', '连涨榜']; + // 🎯 追踪Tab切换 + trackTabChanged(index, tabNames[index]); + setActiveTab(index); + }} + variant="unstyled" + size="sm" + > MiGV3 zTW&cPU3&Ae*Is%l?V;_h_ZAAd^pt}WD8 z3iubosl}1cN76ZrrSU!50W7s0t)FdW5+ zgbC0t7KUBs4`2!hNj!vn!kI7g+Y6xmSjgSD-$}B-a@o!Ia#+-9e~ z*Yw;^@S&Z?N?n9O*YV>>NQP-=w}x@Q&y&>+V;O|P(N@IgoMJHt#g$TV>4SvJaS{ob z>~$Y;UrvFTxOwY*^wTD8adP}vv7y2%Ml`V*9-#__EvVjuNe)2cCLj$NRoas!sIZ0k z0H}-r6F4t+Soe)CE>SikmarjAqVcfHlPO5ntw%k640i!hZ@;yO5;6&*zCtzGkZaKG z7n`T<%=s0++ds^lKTl`Q@29gj)lLV0b%H8AbXhxOQJ?p)gpAmQf{k0E49Is{ALz;o z%c7N=?x$_9v-6=>Yt(BG-1{X(2UbNcynw2xr1g|29b<~ny|PdoYrrfeKb959;}bQq zhvG}&jabCPyhcqmlK@)ha*ub%{X%|iujfmUuigNq8c_+Ra9k(VOfHIRn}Vr)9t&Vv zg3lClpRb7c>TKieLKTA{ZxPR^5aBkrMp}-xso zTIH_j|FX-^$`w2qx&aTXB>Pdl1Bx2Ef8 zn-|c*3_uIGrfpW!(-K~>aZuyucQ($xkCe`7N7%ECZJ)^dOj7UM_~rSX^(Y?o4CXh_ zV3y9h&WS*(kT#dgXFiQo0^{!TL;qT>qD4bh<#NZU(8^GOc^c+iVlu{L(z;Hut3QHf z3KXAObR;WtPpnIjz*p4!Sz~tc-9L*m+R5!rb$INf0wqxrlsiFTwwG_)mWIX z2BJ6OiI49{^APN)?^&BK7lJJ8uzo~5Mi2k*{Q8+Lp#hLoV6@8gr6FOSvSo$%%O;%V zbD5Pn6*OJ{bK;Gn_rATf2iqUtt9+#zQ9+k3B|J8)#SaoL4p-aGDsy?Cz1A(1=y>V0 zqA(Zr!gaia+@za@L0Wc3L0hrzq4fgj*H!b0u+XU-o5uoQNJq7Z4g2bNWOdb?(X}()5$O(OFiRxz+PlV zGmbo#aN}tlpJc{3W9mge7_l&jnE9MVJZn75Duw~CK7RU(AI82L{_^Rv2KRAKr4o#i zIOQ+_+U$nm!1Ye*^k5zzGmpa*j?;JqTFP9HYq#g@kK&BqkB9vf_Y{VWh9N&iOvC?UMFZoZlH2Zxq4lee-+j1( zwdD(2t5vog#Bs>nXy!V|Ithy?1_H_0>+J~hl<{$ju@%8mCSQGhnY{f5*NqB06%dL- z2^eLB^BjN!&?is|zMel=ejU`wQ?!~)t8nl=Oe#PI8Bv2PfDg!f8FamhH3mR#-T6%h z-P^&~@Kr$|T`$}L1jnGOqxSal^F<|RkCtB*hXY>XV11D%jb_Jgnn!)7W%ln`ZRe3? zJ~mtRVwVVW+j6`AVJw%qHR|CH>2PB+0lZx3#m4|30c$YUPT_^uU z+1yKsU~32?`is-I4$Zb@n@+QBH6N52BRob=uV-5pk5iABlv}Q3R6&s~2=a#@9jHQ;_)yMhRw+pg$pJ!Nlxq(BWvE|Y{C+VH zWZpB8^VBe3U;ORP8{{pMfj;M(Tno^!9;x0>x0 z(2^%1a=K{*g~Y{s9`F!x5liAeSB_YvCfli&f~cb@D+Hr7niQiNB8Q+4*vk!hE8N*=Zc^9!Q(MxrLG zvfQ;-Vz(V$yJzdRC9W&!-Lv(QmWN=IE=aNDtzsYf4*8pVRE70Dq35fp-*`K0oFW@JZnqizR|Hy8JY{Q^^mAZ>L zeC3dx4_cZ>(G{xOIC)cPDAO$l>GtCMEDNHEVR-c*R7^#d|3n@r|AwiFdvQjU6M}ea g