import { createFileRoute } from "@tanstack/react-router"; import { useState, useEffect, useMemo } from "react"; import { fetchSectors, type SectorItem, type SectorType } from "@/lib/stock-api"; import { Card, CardContent } from "@/components/ui/card"; import { ArrowLeft, TrendingUp, TrendingDown, RefreshCw } from "lucide-react"; import { Link } from "@tanstack/react-router"; export const Route = createFileRoute("/sectors")({ component: SectorsPage, }); const TABS: { key: SectorType; label: string }[] = [ { key: "industry", label: "行业板块" }, { key: "concept", label: "概念板块" }, ]; type SortMode = "mainNetInflow" | "changePercent"; function SectorsPage() { const [tab, setTab] = useState("industry"); const [data, setData] = useState([]); const [loading, setLoading] = useState(true); const [sort, setSort] = useState("mainNetInflow"); const loadData = (t: SectorType) => { setLoading(true); fetchSectors(t).then((items) => { setData(items); setLoading(false); }); }; useEffect(() => { loadData(tab); }, [tab]); const sorted = useMemo(() => { return [...data].sort((a, b) => { if (sort === "mainNetInflow") return b.mainNetInflow - a.mainNetInflow; return (b.changePercent ?? 0) - (a.changePercent ?? 0); }); }, [data, sort]); return (
{/* 顶栏 */}

板块资金流向

{/* Tab + Sorting 切换 */}
{TABS.map((t) => ( ))}
{/* 数据信息 */}

含 {sorted.length} 个板块 · 按{sort === "mainNetInflow" ? "主力净流入" : "涨跌幅"}降序

{/* 卡片网格 */}
{loading ? (
{Array.from({ length: 20 }).map((_, i) => (
))}
) : (
{sorted.map((item) => ( ))}
)}
); } function formatInflow(val: number | null | undefined): string { if (val == null) return "--"; const abs = Math.abs(val); if (abs >= 1e8) return (val / 1e8).toFixed(2) + "亿"; if (abs >= 1e4) return (val / 1e4).toFixed(0) + "万"; return val.toFixed(0); } function FundFlowBar({ value, maxAbs }: { value: number | null | undefined; maxAbs: number }) { if (value == null) return null; const pct = maxAbs > 0 ? (value / maxAbs) * 100 : 0; const isPos = value >= 0; return (
{formatInflow(value)}
); } function SectorBlock({ item }: { item: SectorItem }) { const inflow = item.mainNetInflow; const isPositive = inflow >= 0; const change = item.changePercent; const maxAbs = Math.max( Math.abs(item.mainNetInflow), Math.abs(item.superLargeInflow ?? 0), Math.abs(item.largeInflow ?? 0), Math.abs(item.mediumInflow ?? 0), Math.abs(item.smallInflow ?? 0), 1 ); return ( {/* 板块名称 */}

{item.name}

{item.code && ( {item.code.replace("BK", "")} )}
{/* 涨跌幅 */}
{change != null ? ( = 0 ? "text-red-500" : "text-green-500" }`} > {change >= 0 ? ( ) : ( )} {change >= 0 ? "+" : ""} {change.toFixed(2)}% ) : ( -- )} {formatInflow(item.turnover)}
{/* 主力净流入 */}
主力净流入 {isPositive ? "+" : ""}{formatInflow(inflow)}
{/* 资金流向明细条 */}
); }