refactor: replace embedded TradingView chart widget with a direct link redirect to the external site.

This commit is contained in:
xucheng 2026-01-19 17:26:22 +08:00
parent 5b501e3984
commit b6222b9b4b

View File

@ -1,7 +1,8 @@
"use client" "use client"
import { useEffect, useRef, useState } from "react" import { useEffect } from "react"
import { ExternalLink } from "lucide-react"
import { Button } from "@/components/ui/button"
interface StockChartProps { interface StockChartProps {
symbol: string symbol: string
@ -9,26 +10,8 @@ interface StockChartProps {
} }
export function StockChart({ symbol, market }: StockChartProps) { export function StockChart({ symbol, market }: StockChartProps) {
const containerRef = useRef<HTMLDivElement>(null)
useEffect(() => { const getTradingViewUrl = () => {
if (!containerRef.current) return
// Clear previous widget
containerRef.current.innerHTML = ""
// Create wrapper for widget
const widgetContainer = document.createElement("div")
widgetContainer.className = "tradingview-widget-container__widget h-full w-full"
containerRef.current.appendChild(widgetContainer)
const script = document.createElement("script")
script.src = "https://s3.tradingview.com/external-embedding/embed-widget-advanced-chart.js"
script.type = "text/javascript"
script.async = true
// Map Market/Symbol to TradingView format
console.log("[StockChart] Received market:", JSON.stringify(market), "symbol:", symbol)
let exchange = "NASDAQ" let exchange = "NASDAQ"
let tvSymbol = symbol let tvSymbol = symbol
@ -38,52 +21,38 @@ export function StockChart({ symbol, market }: StockChartProps) {
else if (symbol.startsWith("4") || symbol.startsWith("8")) exchange = "BSE" else if (symbol.startsWith("4") || symbol.startsWith("8")) exchange = "BSE"
} else if (market === "HK") { } else if (market === "HK") {
exchange = "HKEX" exchange = "HKEX"
// TradingView usually expects HK stocks without leading zeros if they are 4 digits, but let's check. // Ensure no leading zeros for int conversion check
// Actually HKEX:700 works, HKEX:0700 might work too. Let's try to keep it safe.
tvSymbol = parseInt(symbol).toString() tvSymbol = parseInt(symbol).toString()
} else if (market === "JP") { } else if (market === "JP") {
exchange = "TSE" exchange = "TSE"
} else if (market === "VN") { } else if (market === "VN") {
exchange = "HOSE" // Primary VN exchange exchange = "HOSE"
} else { } else {
// US // US
exchange = "NASDAQ" // Default, could be NYSE exchange = "NASDAQ" // Default fallback
// Basic heuristic for US
// If 4 chars or more, likely Nasdaq, <=3 likely NYSE? Not 100% accurate but acceptable default.
} }
const fullSymbol = `${exchange}:${tvSymbol}` const fullSymbol = `${exchange}:${tvSymbol}`
return `https://cn.tradingview.com/chart/?symbol=${fullSymbol}`
}
script.innerHTML = JSON.stringify({ useEffect(() => {
"autosize": true, const url = getTradingViewUrl()
"symbol": fullSymbol, // Attempt to open in new tab automatically
"interval": "D", const win = window.open(url, '_blank')
"range": "12m", if (!win) {
"scale": "log", console.warn("Popup blocked. Please allow popups for this site.")
"timezone": "Asia/Shanghai", }
"theme": "light",
"style": "1",
"locale": "zh_CN",
"enable_publishing": false,
"allow_symbol_change": true,
"calendar": false,
"support_host": "https://www.tradingview.com"
})
containerRef.current.appendChild(script)
}, [symbol, market]) }, [symbol, market])
return ( return (
<div className="h-[calc(100vh-100px)] w-full bg-background rounded-lg border overflow-hidden p-1"> <div className="w-full h-12 bg-muted/30 rounded-lg border border-dashed flex items-center justify-center">
<div className="tradingview-widget-container h-full w-full flex flex-col" ref={containerRef}> <p className="text-xs text-muted-foreground flex items-center gap-1">
<div className="tradingview-widget-copyright text-xs text-center text-muted-foreground p-2 mt-auto border-t bg-muted/20"> <span> TradingView ({symbol})...</span>
<a href={`https://cn.tradingview.com/chart/?symbol=${symbol}`} rel="noopener nofollow" target="_blank" className="hover:text-primary transition-colors flex items-center justify-center gap-1"> <a href={getTradingViewUrl()} target="_blank" rel="noopener noreferrer" className="underline hover:text-primary">
<span className="font-medium"> TradingView </span>
<span className="text-[10px] opacity-70">({symbol})</span> </a>
</a> </p>
</div>
</div>
</div> </div>
) )
} }