diff --git a/serve/backend/app/api/screener.py b/serve/backend/app/api/screener.py index 3a40b3b..56fb624 100644 --- a/serve/backend/app/api/screener.py +++ b/serve/backend/app/api/screener.py @@ -296,13 +296,14 @@ def get_cached( @router.get("/market-snapshot") -def market_snapshot(request: Request): - """最新全市场轻量行情快照,供板块/概念聚合分析使用。""" +def market_snapshot(request: Request, as_of: date | None = None): + """全市场轻量行情快照(可选指定日期),供板块/概念聚合分析使用。""" import polars as pl repo = request.app.state.repo svc = ScreenerService(repo) - as_of = svc.latest_date() + if as_of is None: + as_of = svc.latest_date() if not as_of: return {"as_of": None, "rows": []} diff --git a/serve/frontend/src/lib/api.ts b/serve/frontend/src/lib/api.ts index 4fd71e4..0ae9d37 100644 --- a/serve/frontend/src/lib/api.ts +++ b/serve/frontend/src/lib/api.ts @@ -882,8 +882,8 @@ export const api = { ? `/api/screener/cached?ext_columns=${encodeURIComponent(extColumns)}` : '/api/screener/cached', ), - marketSnapshot: () => - request<{ as_of: string | null; rows: MarketSnapshotRow[] }>('/api/screener/market-snapshot'), + marketSnapshot: (asOf?: string) => + request<{ as_of: string | null; rows: MarketSnapshotRow[] }>(`/api/screener/market-snapshot${asOf ? `?as_of=${asOf}` : ''}`), overviewMarket: (asOf?: string) => request(`/api/overview/market${asOf ? `?as_of=${asOf}` : ''}`), // 概念涨幅轮动矩阵: 每列(日期)各自把所有概念按当天涨幅从高到低排序 diff --git a/serve/frontend/src/pages/ConceptAnalysis.tsx b/serve/frontend/src/pages/ConceptAnalysis.tsx index 8d64997..d7142df 100644 --- a/serve/frontend/src/pages/ConceptAnalysis.tsx +++ b/serve/frontend/src/pages/ConceptAnalysis.tsx @@ -15,6 +15,7 @@ import { PageHeader } from '@/components/PageHeader' import { EmptyState } from '@/components/EmptyState' import { type AnalysisFieldConfig } from '@/components/analysis-shared' import { StockPreviewDialog } from '@/components/StockPreviewDialog' +import { DatePicker } from '@/components/DatePicker' import { RpsRotationDialog } from '@/components/RpsRotationDialog' import { api, type MarketSnapshotRow } from '@/lib/api' import { QK } from '@/lib/queryKeys' @@ -238,6 +239,7 @@ export function ConceptAnalysis() { const [previewSymbol, setPreviewSymbol] = useState(null) const [previewName, setPreviewName] = useState('') const [showRps, setShowRps] = useState(false) + const [asOf, setAsOf] = useState('') const configsQuery = useQuery({ queryKey: QK.extData, queryFn: api.extDataList }) const availableConfigs = configsQuery.data?.items ?? [] @@ -249,14 +251,14 @@ export function ConceptAnalysis() { const activeConfig = availableConfigs.find(c => c.id === activeConfigId) const rowsQuery = useQuery({ - queryKey: QK.extDataRows(activeConfigId, undefined, PAGE_LIMIT), - queryFn: () => api.extDataRows(activeConfigId, { limit: PAGE_LIMIT }), + queryKey: QK.extDataRows(activeConfigId, asOf || undefined, PAGE_LIMIT), + queryFn: () => api.extDataRows(activeConfigId, { date: asOf || undefined, limit: PAGE_LIMIT }), enabled: !!activeConfigId, }) const marketQuery = useQuery({ - queryKey: QK.marketSnapshot, - queryFn: api.marketSnapshot, + queryKey: ['market-snapshot', asOf], + queryFn: () => api.marketSnapshot(asOf || undefined), staleTime: 60_000, }) @@ -317,9 +319,10 @@ export function ConceptAnalysis() { <> + {/* RPS 轮动: 打开涨幅轮动矩阵对话框 */}