import React, { useState, useEffect } from 'react'; import { api } from '../services/api'; import './RecommendationsViewer.css'; function RecommendationsViewer() { const [recommendations, setRecommendations] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [directionFilter, setDirectionFilter] = useState(''); const [showDetails, setShowDetails] = useState({}); useEffect(() => { loadRecommendations(); // 每10秒静默更新价格(不触发loading状态) const interval = setInterval(async () => { try { const result = await api.getRecommendations({ type: 'realtime', direction: directionFilter, limit: 50, min_signal_strength: 5 }); const newData = result.data || []; // 使用setState直接更新,不触发loading状态 setRecommendations(prevRecommendations => { if (newData.length === 0) { return prevRecommendations; } // 实时推荐没有id,使用symbol作为key const newDataMap = new Map(newData.map(rec => [rec.symbol, rec])); const prevMap = new Map(prevRecommendations.map(rec => [rec.symbol || rec.id, rec])); // 合并数据:优先使用新数据(包含实时价格更新) const updated = prevRecommendations.map(prevRec => { const key = prevRec.symbol || prevRec.id; const newRec = newDataMap.get(key); if (newRec) { return newRec; } return prevRec; }); // 添加新出现的推荐 const newItems = newData.filter(newRec => !prevMap.has(newRec.symbol)); // 合并并去重(按symbol) const merged = [...updated, ...newItems]; const uniqueMap = new Map(); merged.forEach(rec => { const key = rec.symbol || rec.id; if (!uniqueMap.has(key)) { uniqueMap.set(key, rec); } }); return Array.from(uniqueMap.values()); }); } catch (err) { // 静默失败,不显示错误 console.debug('静默更新价格失败:', err); } }, 10000); // 每10秒刷新 return () => { clearInterval(interval); }; }, [directionFilter]); const loadRecommendations = async () => { try { setLoading(true); setError(null); const params = { type: 'realtime', limit: 50, min_signal_strength: 5 }; if (directionFilter) { params.direction = directionFilter; } const result = await api.getRecommendations(params); const data = result.data || []; setRecommendations(data); } catch (err) { setError(err.message); console.error('加载推荐失败:', err); } finally { setLoading(false); } }; const toggleDetails = (key) => { setShowDetails(prev => ({ ...prev, [key]: !prev[key] })); }; const formatTime = (timeStr) => { if (!timeStr) return '-'; try { const date = new Date(timeStr); if (isNaN(date.getTime())) return timeStr; // 使用北京时间格式化 return date.toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', timeZone: 'Asia/Shanghai' // 明确使用北京时间 }); } catch (e) { return timeStr; } }; const getSignalStrengthColor = (strength) => { if (strength >= 8) return 'signal-strong'; if (strength >= 6) return 'signal-medium'; return 'signal-weak'; }; return (
暂无推荐记录
{rec.recommendation_reason || '-'}
{rec.market_regime === 'trending' ? '趋势市场' : '震荡市场'}
{rec.trend_4h === 'up' ? '上涨' : rec.trend_4h === 'down' ? '下跌' : '中性'}
{parseFloat(rec.volume_24h).toFixed(2)}
{parseFloat(rec.volatility).toFixed(4)}