mirror of
https://ghfast.top/https://github.com/aeroxw/tick-stock-panel.git
synced 2026-09-12 16:44:15 +08:00
refactor(kline): simplify round 2 — scope flex ratio, single-source guard and default
审查后清理, 无行为变更 (除下述作用域修正): - StockPanel: 日K/分时并排的占宽从硬编码 flex-[1.4] 改为 dailyKlineFlex prop (默认 flex-1) —— 避免静默改变 TradeKlineModal 等其他消费方的并排布局; 仅 StockPreviewDialog 显式传入 flex-[1.4] - lib/kline.ts: klineMinuteRangeQueryOptions 内嵌「仅同 symbol」placeholderData 守卫, 与 klineDailyQueryOptions 同源, 删除 StockMultiDayIntradayChart 的内联副本 - DEFAULT_INTRADAY_DAYS 单源化: StockPanel 默认值与弹窗 loadIntradayDays 回退共用 - StockPreviewDialog: prevSymbolRef 初始值改 null (首次挂载 view 本就是 daily); blur 复用 keydown 的 e.target(t) 替代重复 document.activeElement 查询 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -31,8 +31,6 @@ export function StockMultiDayIntradayChart({
|
||||
const history = useQuery({
|
||||
...klineMinuteRangeQueryOptions(symbol, days),
|
||||
enabled: !!symbol,
|
||||
placeholderData: (previous, previousQuery) =>
|
||||
previousQuery?.queryKey[1] === symbol ? previous : undefined,
|
||||
})
|
||||
const latest = useQuery({
|
||||
// live: 当日盘中直接实时拉取, 不被分钟增量落盘的本地分区(≥60s一轮)拖慢
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useEffect, useState, useCallback, useRef, useMemo } from 'react'
|
||||
import { useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
import { X } from 'lucide-react'
|
||||
import { type KlineRow, type FinancialMetricRecord } from '@/lib/api'
|
||||
import { klineDailyQueryOptions, klineMinuteQueryOptions, klineMinuteRangeQueryOptions } from '@/lib/kline'
|
||||
import { klineDailyQueryOptions, klineMinuteQueryOptions, klineMinuteRangeQueryOptions, DEFAULT_INTRADAY_DAYS } from '@/lib/kline'
|
||||
import { StockInfoBar } from '@/components/StockInfoBar'
|
||||
import { StockDailyKChart, getDefaultRange, toOHLC } from '@/components/StockDailyKChart'
|
||||
import { StockIntradayChart } from '@/components/StockIntradayChart'
|
||||
@@ -46,6 +46,8 @@ interface Props {
|
||||
prefetchSymbols?: string[]
|
||||
/** 多日分时周期 (分时 tab 使用): 预取邻股 klineMinuteRange 时用同一 days, 保证 queryKey 命中 */
|
||||
intradayDays?: number
|
||||
/** 日K/分时并排时日K图占宽 (默认 1:1; 弹窗内图表信息栏较宽需更多空间时传 flex-[1.4] 之类) */
|
||||
dailyKlineFlex?: string
|
||||
}
|
||||
|
||||
export { getDefaultRange }
|
||||
@@ -71,7 +73,8 @@ export function StockPanel({
|
||||
refetchIntervalMs,
|
||||
infoBarOnly = false,
|
||||
prefetchSymbols,
|
||||
intradayDays = 10,
|
||||
intradayDays = DEFAULT_INTRADAY_DAYS,
|
||||
dailyKlineFlex = 'flex-1',
|
||||
}: Props) {
|
||||
const [linkedPrice, setLinkedPrice] = useState<number | null>(null)
|
||||
const [selectedDate, setSelectedDate] = useState<string | null>(null)
|
||||
@@ -196,11 +199,10 @@ export function StockPanel({
|
||||
|
||||
{infoBarOnly ? null : (
|
||||
<div className="flex gap-3 items-start">
|
||||
{/* 日K为主视图占更宽 (与分时约 1.4:1): 图表自带信息栏(悬停含「至今/周期」)需要更宽才能单行容纳 */}
|
||||
<StockDailyKChart
|
||||
symbol={symbol}
|
||||
height={height}
|
||||
className="flex-[1.4] min-w-0"
|
||||
className={`${dailyKlineFlex} min-w-0`}
|
||||
dateRange={dateRange}
|
||||
markers={markers}
|
||||
ranges={ranges}
|
||||
|
||||
@@ -18,6 +18,7 @@ import { usePreferences } from '@/lib/useSharedQueries'
|
||||
import { setFocusSymbol, clearFocusSymbol } from '@/lib/useQuoteStream'
|
||||
import { useDialogBackdrop } from '@/lib/useDialogBackdrop'
|
||||
import { storage } from '@/lib/storage'
|
||||
import { DEFAULT_INTRADAY_DAYS } from '@/lib/kline'
|
||||
import { ExtensionSlot } from '@/extensions/ExtensionSlot'
|
||||
|
||||
interface Props {
|
||||
@@ -79,11 +80,12 @@ interface PriceAlertDraft {
|
||||
}
|
||||
const INTRADAY_DAY_OPTIONS = [1, 5, 10, 20] as const
|
||||
|
||||
function loadIntradayDays(): number | null {
|
||||
const saved = storage.stockPreviewIntradayDays.get(10)
|
||||
function loadIntradayDays(): number {
|
||||
const saved = storage.stockPreviewIntradayDays.get(DEFAULT_INTRADAY_DAYS)
|
||||
return INTRADAY_DAY_OPTIONS.includes(saved as typeof INTRADAY_DAY_OPTIONS[number])
|
||||
? saved
|
||||
: null
|
||||
: DEFAULT_INTRADAY_DAYS
|
||||
}
|
||||
}
|
||||
|
||||
function boardTag(symbol: string): { label: string; color: string } | null {
|
||||
@@ -227,8 +229,9 @@ export function StockPreviewDialog({ symbol, name, onClose, triggerInfo, navList
|
||||
if (go(e.key === 'ArrowRight' ? 1 : -1)) {
|
||||
e.preventDefault()
|
||||
// 切股后清掉控件残留的键盘焦点: 点过分时tab/外链等控件后方向键切股,
|
||||
// 浏览器会给该控件显示 focus-visible 默认蓝色 outline, 切换后 blur 掉避免残留
|
||||
;(document.activeElement as HTMLElement | null)?.blur()
|
||||
// 浏览器会给该控件显示 focus-visible 默认蓝色 outline, 切换后 blur 掉避免残留。
|
||||
// keydown 的 e.target 即聚焦元素, 复用已捕获的 t (已排除输入框/编辑器)。
|
||||
t?.blur()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -238,7 +241,7 @@ export function StockPreviewDialog({ symbol, name, onClose, triggerInfo, navList
|
||||
|
||||
// 弹窗内切股时保留当前视图 (分时 tab 下切股不应跳回日K);
|
||||
// 仅当弹窗首次打开 (symbol 从 null 变非空) 时重置为日K。
|
||||
const prevSymbolRef = useRef<string | null>(symbol)
|
||||
const prevSymbolRef = useRef<string | null>(null)
|
||||
useEffect(() => {
|
||||
if (prevSymbolRef.current == null && symbol != null) setView('daily')
|
||||
prevSymbolRef.current = symbol
|
||||
@@ -612,6 +615,7 @@ export function StockPreviewDialog({ symbol, name, onClose, triggerInfo, navList
|
||||
refetchIntervalMs={intradayRefetchMs}
|
||||
prefetchSymbols={prefetchSymbols}
|
||||
intradayDays={intradayDays}
|
||||
dailyKlineFlex="flex-[1.4]"
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
import { api } from '@/lib/api'
|
||||
import { QK } from '@/lib/queryKeys'
|
||||
|
||||
/** 分时 tab 多日分时默认周期 (StockPanel 预取与弹窗存储回退共用, 避免魔数两处漂移) */
|
||||
export const DEFAULT_INTRADAY_DAYS = 10
|
||||
|
||||
export function klineDailyQueryOptions(
|
||||
symbol: string,
|
||||
dateRange: { start: string; end: string },
|
||||
@@ -39,10 +42,16 @@ export function klineMinuteQueryOptions(symbol: string, date?: string, live?: bo
|
||||
}
|
||||
}
|
||||
|
||||
/** 多日分时查询配置 — 分时 tab 的 StockMultiDayIntradayChart 与 邻近预取 共用。 */
|
||||
/** 多日分时查询配置 — 分时 tab 的 StockMultiDayIntradayChart 与 邻近预取 共用。
|
||||
* 内嵌「仅同 symbol 占位」守卫 (key 结构 ['kline-minute-range', symbol, days], index 1 为 symbol),
|
||||
* 与 klineDailyQueryOptions 同源, 调用点不再各自手写。 */
|
||||
export function klineMinuteRangeQueryOptions(symbol: string, days: number) {
|
||||
return {
|
||||
queryKey: QK.klineMinuteRange(symbol, days),
|
||||
queryFn: () => api.klineMinuteRange(symbol, days),
|
||||
placeholderData: (prev: any, prevQuery: any) => {
|
||||
const prevKey = prevQuery?.queryKey as readonly unknown[] | undefined
|
||||
return prevKey?.[1] === symbol ? prev : undefined
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user