'use client'; import { useEffect, useRef } from 'react'; interface TradingViewWidgetProps { symbol: string; market?: string; height?: number; width?: string; } declare global { interface Window { TradingView: any; } } export function TradingViewWidget({ symbol, market = 'china', height = 400, width = '100%' }: TradingViewWidgetProps) { const containerRef = useRef(null); // 将中国股票代码转换为TradingView格式 const getTradingViewSymbol = (symbol: string, market: string) => { if (market === 'china' || market === 'cn') { // 处理中国股票代码 if (symbol.includes('.')) { const [code, exchange] = symbol.split('.'); if (exchange === 'SH') { return `SSE:${code}`; } else if (exchange === 'SZ') { return `SZSE:${code}`; } } // 如果没有后缀,尝试推断 const onlyDigits = symbol.replace(/\D/g, ''); if (onlyDigits.length === 6) { const first = onlyDigits[0]; if (first === '6') { return `SSE:${onlyDigits}`; } else if (first === '0' || first === '3') { return `SZSE:${onlyDigits}`; } } return symbol; } return symbol; }; useEffect(() => { if (typeof window === 'undefined') return; if (!symbol) return; const tradingViewSymbol = getTradingViewSymbol(symbol, market); const script = document.createElement('script'); script.src = 'https://s3.tradingview.com/external-embedding/embed-widget-advanced-chart.js'; script.async = true; script.innerHTML = JSON.stringify({ autosize: true, symbol: tradingViewSymbol, interval: 'D', timezone: 'Asia/Shanghai', theme: 'light', style: '1', locale: 'zh_CN', toolbar_bg: '#f1f3f6', enable_publishing: false, hide_top_toolbar: false, hide_legend: false, save_image: false, container_id: `tradingview_${symbol}`, studies: [], show_popup_button: false, no_referrer_id: true, referrer_id: 'fundamental-analysis', // 强制启用对数坐标 logarithmic: true, disabled_features: [ 'use_localstorage_for_settings', 'volume_force_overlay', 'create_volume_indicator_by_default' ], enabled_features: [ 'side_toolbar_in_fullscreen_mode', 'header_in_fullscreen_mode' ], overrides: { 'paneProperties.background': '#ffffff', 'paneProperties.vertGridProperties.color': '#e1e3e6', 'paneProperties.horzGridProperties.color': '#e1e3e6', 'symbolWatermarkProperties.transparency': 90, 'scalesProperties.textColor': '#333333', // 对数坐标设置 'scalesProperties.logarithmic': true, 'rightPriceScale.mode': 1, 'leftPriceScale.mode': 1, 'paneProperties.priceScaleProperties.log': true, 'paneProperties.priceScaleProperties.mode': 1 }, // 强制启用对数坐标 studies_overrides: { 'volume.volume.color.0': '#00bcd4', 'volume.volume.color.1': '#ff9800', 'volume.volume.transparency': 70 } }); const container = containerRef.current; if (container) { // 避免重复挂载与 Next 热更新多次执行导致的报错 container.innerHTML = ''; // 延迟到下一帧,确保容器已插入并可获取 iframe.contentWindow requestAnimationFrame(() => { try { if (container.isConnected) { container.appendChild(script); } } catch (e) { // 忽略偶发性 contentWindow 不可用的报错 console.warn('TradingView widget mount error:', e); } }); } return () => { const c = containerRef.current; if (c) { try { c.innerHTML = ''; } catch {} } }; }, [symbol, market]); return (
); }