feat: 优化股票图表 TradingView 链接生成逻辑并使搜索组件中的市场字段可编辑。

This commit is contained in:
xucheng 2026-01-23 10:55:54 +08:00
parent 2a5e471ddb
commit 66f4914c5a
2 changed files with 22 additions and 20 deletions

View File

@ -32,9 +32,10 @@ function SearchResultItem({ result, onSelect }: { result: SearchResult, onSelect
const defaultSource = "Bloomberg" const defaultSource = "Bloomberg"
const [source, setSource] = useState(defaultSource) const [source, setSource] = useState(defaultSource)
const [symbol, setSymbol] = useState(result.symbol) // Editable symbol state const [symbol, setSymbol] = useState(result.symbol) // Editable symbol state
const [market, setMarket] = useState(result.market) // Editable market state
// 根据市场获取可用数据源列表 // 根据市场获取可用数据源列表
const availableSources = result.market === "CN" ? DATA_SOURCES.CN : DATA_SOURCES.GLOBAL const availableSources = market === "CN" ? DATA_SOURCES.CN : DATA_SOURCES.GLOBAL
return ( return (
<Card className="hover:bg-accent/50 transition-colors h-full flex flex-col"> <Card className="hover:bg-accent/50 transition-colors h-full flex flex-col">
@ -54,9 +55,13 @@ function SearchResultItem({ result, onSelect }: { result: SearchResult, onSelect
/> />
</div> </div>
</div> </div>
<Badge variant="secondary" className="shrink-0 text-xs font-mono h-6"> <div className="shrink-0 w-12">
{result.market} <Input
</Badge> value={market}
onChange={(e) => setMarket(e.target.value)}
className="h-6 text-xs font-mono px-1 text-center bg-secondary/50 border-transparent hover:border-input focus:border-input transition-colors"
/>
</div>
</div> </div>
</div> </div>
@ -78,7 +83,7 @@ function SearchResultItem({ result, onSelect }: { result: SearchResult, onSelect
</Select> </Select>
</div> </div>
<Button <Button
onClick={() => onSelect({ ...result, symbol }, source)} onClick={() => onSelect({ ...result, symbol, market }, source)}
size="sm" size="sm"
className="h-8 px-3 shrink-0" className="h-8 px-3 shrink-0"
> >

View File

@ -12,28 +12,25 @@ interface StockChartProps {
export function StockChart({ symbol, market }: StockChartProps) { export function StockChart({ symbol, market }: StockChartProps) {
const getTradingViewUrl = () => { const getTradingViewUrl = () => {
let exchange = "NASDAQ" // 对于特定亚洲市场,需要显式指定交易所前缀
let tvSymbol = symbol
if (market === "CH" || market === "CN") { if (market === "CH" || market === "CN") {
if (symbol.startsWith("6")) exchange = "SSE" let exchange = "SSE" // Default Shanghai
else if (symbol.startsWith("0") || symbol.startsWith("3")) exchange = "SZSE" if (symbol.startsWith("0") || symbol.startsWith("3")) exchange = "SZSE"
else if (symbol.startsWith("4") || symbol.startsWith("8")) exchange = "BSE" else if (symbol.startsWith("4") || symbol.startsWith("8")) exchange = "BSE"
return `https://cn.tradingview.com/chart/?symbol=${exchange}:${symbol}`
} else if (market === "HK") { } else if (market === "HK") {
exchange = "HKEX" // 港股去重前面的0
// Ensure no leading zeros for int conversion check const tvSymbol = parseInt(symbol).toString()
tvSymbol = parseInt(symbol).toString() return `https://cn.tradingview.com/chart/?symbol=HKEX:${tvSymbol}`
} else if (market === "JP") { } else if (market === "JP") {
exchange = "TSE" return `https://cn.tradingview.com/chart/?symbol=TSE:${symbol}`
} else if (market === "VN") { } else if (market === "VN") {
exchange = "HOSE" return `https://cn.tradingview.com/chart/?symbol=HOSE:${symbol}`
} else {
// US
exchange = "NASDAQ" // Default fallback
} }
const fullSymbol = `${exchange}:${tvSymbol}` // 对于其他市场 (US, BZ, UK 等),直接传递 Symbol 让 TradingView 自动匹配
return `https://cn.tradingview.com/chart/?symbol=${fullSymbol}` // 例如 "PETR4" -> Bovespa, "C" -> NYSE, "AAPL" -> NASDAQ
return `https://cn.tradingview.com/chart/?symbol=${symbol}`
} }
useEffect(() => { useEffect(() => {