From 6964e1b5c9c9ba067b6b8f46e1c072b6eb49e84b Mon Sep 17 00:00:00 2001 From: richard Date: Thu, 27 Aug 2026 10:53:33 +0800 Subject: [PATCH] fix(kline): two regressions found in PR review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - EChartsCandlestick: 悬停重置 effect 依赖补上 symbol(_symbol) —— 预取切股到同长度邻股时 data.length 不变, 原 [data.length] 不触发, hoverActiveRef 残留导致切股后「至今/周期」无悬停仍显示 (自愈于下次 mousemove) - Watchlist: DimensionMembersDialog 的 onStockClick 补第三参 navList —— 从成分弹窗打开个股时用成分列表作切股导航 (成员可能不在自选列表, 原实现退回自选列表, 成员不在自选则导航按钮不显示) Co-Authored-By: Claude --- frontend/src/components/EChartsCandlestick.tsx | 7 +++++-- frontend/src/pages/Watchlist.tsx | 11 ++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/frontend/src/components/EChartsCandlestick.tsx b/frontend/src/components/EChartsCandlestick.tsx index 595abbc..3bebb57 100644 --- a/frontend/src/components/EChartsCandlestick.tsx +++ b/frontend/src/components/EChartsCandlestick.tsx @@ -966,14 +966,17 @@ export function EChartsCandlestick({ }, [data, stockInfo, showMA, activeIndicators]) getInfoBarHTMLRef.current = getInfoBarHTML - // data 变化时重置 infoIdx + // data/symbol 变化时重置 infoIdx: + // symbol(_symbol) 进依赖是必要的——预取切股到同长度邻股时 data.length 不变, + // 但悬停上下文来自上一只股票, 必须清掉 hoverActiveRef 以免「至今/周期」残留显示。 + // (同一股的实时刷新 symbol 不变, 不触发, 悬停位置与「至今」保持实时) useEffect(() => { infoIdxRef.current = data.length - 1 compactRef.current = false userZoomRef.current = null // 新数据无悬停上下文, 隐藏「至今」; 下次鼠标移动时由 updateAxisPointer 重新置位 hoverActiveRef.current = false - }, [data.length]) + }, [_symbol, data.length]) // ===== 初始化 chart (只在 chartHeight 变化时重建) ===== useEffect(() => { diff --git a/frontend/src/pages/Watchlist.tsx b/frontend/src/pages/Watchlist.tsx index 7211032..b4e93d1 100644 --- a/frontend/src/pages/Watchlist.tsx +++ b/frontend/src/pages/Watchlist.tsx @@ -13,7 +13,7 @@ import { cn } from '@/lib/cn' import { computeGroupPcts, loadGroupStatsConfig, type GroupStatsConfigPatch } from '@/lib/watchlistGroupStats' import { PageHeader } from '@/components/PageHeader' import { EmptyState } from '@/components/EmptyState' -import { StockPreviewDialog, toNavItems } from '@/components/StockPreviewDialog' +import { StockPreviewDialog, toNavItems, type NavItem } from '@/components/StockPreviewDialog' import { DimensionMembersDialog, dimensionKindForSourceField, @@ -780,11 +780,14 @@ export function Watchlist() { }, []) const [previewSymbol, setPreviewSymbol] = useState(null) const [previewName, setPreviewName] = useState('') + // 切股导航: 默认用 previewNavItems(自选列表); 从成分弹窗打开时用成分列表覆盖 + const [previewNavList, setPreviewNavList] = useState([]) const [dimensionTarget, setDimensionTarget] = useState(null) const [expandedCells, setExpandedCells] = useState>(new Set()) const closePreview = useCallback(() => { setPreviewSymbol(null) setPreviewName('') + setPreviewNavList([]) }, []) const handleToggleExpand = useCallback((cellKey: string) => { @@ -2002,17 +2005,19 @@ export function Watchlist() { symbol={previewSymbol} name={previewName} onClose={closePreview} - navList={previewNavItems} + navList={previewNavList.length > 0 ? previewNavList : previewNavItems} onNavigate={(sym, n) => { setPreviewSymbol(sym); setPreviewName(n ?? '') }} /> setDimensionTarget(null)} - onStockClick={(symbol, name) => { + onStockClick={(symbol, name, navList) => { setDimensionTarget(null) setPreviewSymbol(symbol) setPreviewName(name ?? '') + // 成分列表作为切股导航 (成员可能不在自选列表, 不能退回 previewNavItems) + setPreviewNavList(navList ?? previewNavItems) }} />