const API_BASE = '/api/v1/futures';

let klineChart = null;
let currentSymbol = null;
let currentPeriod = '15';
let allFuturesData = [];
let watchedSymbols = [];
let currentDetailData = null;

document.addEventListener('DOMContentLoaded', function() {
    addScoreGradient();
    updateTime();
    setInterval(updateTime, 1000);
    
    initEventListeners();
    loadWatchedSymbols();
    loadFuturesList();
});

function addScoreGradient() {
    const svg = document.querySelector('.score-ring svg');
    if (svg && !svg.querySelector('defs')) {
        const defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
        const gradient = document.createElementNS('http://www.w3.org/2000/svg', 'linearGradient');
        gradient.setAttribute('id', 'scoreGradient');
        gradient.setAttribute('x1', '0%');
        gradient.setAttribute('y1', '0%');
        gradient.setAttribute('x2', '100%');
        gradient.setAttribute('y2', '0%');
        
        const stop1 = document.createElementNS('http://www.w3.org/2000/svg', 'stop');
        stop1.setAttribute('offset', '0%');
        stop1.setAttribute('stop-color', '#ef4444');
        
        const stop2 = document.createElementNS('http://www.w3.org/2000/svg', 'stop');
        stop2.setAttribute('offset', '50%');
        stop2.setAttribute('stop-color', '#f59e0b');
        
        const stop3 = document.createElementNS('http://www.w3.org/2000/svg', 'stop');
        stop3.setAttribute('offset', '100%');
        stop3.setAttribute('stop-color', '#10b981');
        
        gradient.appendChild(stop1);
        gradient.appendChild(stop2);
        gradient.appendChild(stop3);
        defs.appendChild(gradient);
        svg.insertBefore(defs, svg.firstChild);
    }
}

function updateTime() {
    const now = new Date();
    const timeStr = now.getFullYear() + '-' + 
        String(now.getMonth() + 1).padStart(2, '0') + '-' + 
        String(now.getDate()).padStart(2, '0') + ' ' + 
        String(now.getHours()).padStart(2, '0') + ':' + 
        String(now.getMinutes()).padStart(2, '0') + ':' + 
        String(now.getSeconds()).padStart(2, '0');
    document.getElementById('current-time').textContent = timeStr;
}

function initEventListeners() {
    const backBtn = document.getElementById('back-btn');
    if (backBtn) backBtn.addEventListener('click', showListView);
    
    const themeToggle = document.getElementById('theme-toggle');
    if (themeToggle) themeToggle.addEventListener('click', toggleTheme);
    
    const refreshAllBtn = document.getElementById('refresh-all-btn');
    if (refreshAllBtn) refreshAllBtn.addEventListener('click', refreshAllSymbols);
    
    const aiAnalyzeAllBtn = document.getElementById('ai-analyze-all-btn');
    if (aiAnalyzeAllBtn) aiAnalyzeAllBtn.addEventListener('click', analyzeAllSymbols);
    
    const refreshSymbolBtn = document.getElementById('refresh-symbol-btn');
    if (refreshSymbolBtn) refreshSymbolBtn.addEventListener('click', function() {
        if (currentSymbol) {
            refreshSingleSymbol(currentSymbol);
        }
    });
    
    const savedTheme = localStorage.getItem('futures-theme');
    if (savedTheme === 'dark') {
        document.body.classList.remove('theme-minimal');
        updateThemeIcon(false);
    } else {
        document.body.classList.add('theme-minimal');
        updateThemeIcon(true);
    }
    
    document.querySelectorAll('.period-btn').forEach(btn => {
        btn.addEventListener('click', function() {
            document.querySelectorAll('.period-btn').forEach(b => b.classList.remove('active'));
            this.classList.add('active');
            currentPeriod = this.dataset.period;
            loadKlineData(currentSymbol, currentPeriod);
        });
    });
    
    const searchInput = document.getElementById('search-input');
    if (searchInput) searchInput.addEventListener('input', function() {
        filterFuturesList(this.value);
    });
    
    document.querySelectorAll('.pill').forEach(tab => {
        if (tab.dataset.category) {
            tab.addEventListener('click', function() {
                document.querySelectorAll('.pill').forEach(t => t.classList.remove('active'));
                this.classList.add('active');
                filterByCategory(this.dataset.category);
            });
        }
    });
    
    const sortSelect = document.getElementById('sort-select');
    if (sortSelect) sortSelect.addEventListener('change', function() {
        sortFuturesList(this.value);
    });
    
    document.querySelectorAll('.modal-overlay').forEach(modal => {
        modal.addEventListener('click', function(e) {
            if (e.target === this) {
                this.classList.remove('active');
            }
        });
    });
    
    // 导航项点击事件
    document.querySelectorAll('.nav-item[data-page]').forEach(navItem => {
        navItem.addEventListener('click', function(e) {
            e.preventDefault();
            const page = this.dataset.page;
            
            document.querySelectorAll('.nav-item').forEach(item => item.classList.remove('active'));
            this.classList.add('active');
            
            if (page === 'review') {
                showReviewView();
            } else if (page === 'trade-review') {
                showTradeReviewView();
            } else if (page === 'watched') {
                showWatchedView();
            } else {
                showListView();
            }
        });
    });
}

function closeModal(modalId) {
    document.getElementById(modalId).classList.remove('active');
}

function showListView() {
    document.getElementById('list-view').classList.add('active');
    document.getElementById('detail-view').classList.remove('active');
    document.getElementById('review-view').classList.remove('active');
    document.getElementById('watched-view').classList.remove('active');
    document.getElementById('trade-review-view').classList.remove('active');
    if (klineChart) {
        klineChart.dispose();
        klineChart = null;
    }
}

function showWatchedView() {
    document.getElementById('list-view').classList.remove('active');
    document.getElementById('detail-view').classList.remove('active');
    document.getElementById('review-view').classList.remove('active');
    document.getElementById('watched-view').classList.add('active');
    document.getElementById('trade-review-view').classList.remove('active');
    if (klineChart) {
        klineChart.dispose();
        klineChart = null;
    }
    
    renderWatchedList();
}

function showReviewView() {
    document.getElementById('list-view').classList.remove('active');
    document.getElementById('detail-view').classList.remove('active');
    document.getElementById('review-view').classList.add('active');
    document.getElementById('watched-view').classList.remove('active');
    document.getElementById('trade-review-view').classList.remove('active');
    if (klineChart) {
        klineChart.dispose();
        klineChart = null;
    }
    
    // 初始化复盘计划功能
    initReviewPlan();
}

function showTradeReviewView() {
    document.getElementById('list-view').classList.remove('active');
    document.getElementById('detail-view').classList.remove('active');
    document.getElementById('review-view').classList.remove('active');
    document.getElementById('watched-view').classList.remove('active');
    document.getElementById('trade-review-view').classList.add('active');
    if (klineChart) {
        klineChart.dispose();
        klineChart = null;
    }
    
    initTradeReview();
}

async function showDetailView(symbol) {
    currentSymbol = symbol;
    document.getElementById('list-view').classList.remove('active');
    document.getElementById('detail-view').classList.add('active');
    
    // 1. 加载行情数据
    loadFuturesDetail(symbol);
    loadKlineData(symbol, currentPeriod);
    
    // 2. 加载历史记录
    await loadHistoryListForAnalysis(symbol);
}

async function loadHistoryListForAnalysis(symbol) {
    console.log(`[AI分析] 开始加载 ${symbol} 的历史分析记录...`);
    try {
        const response = await fetch(`${API_BASE}/ai-analysis/${symbol}/history?limit=20`);
        const data = await response.json();
        
        console.log(`[AI分析] API响应:`, data);
        
        if (data.success) {
            renderHistoryList(data.data);
            
            // 3. 查找今天的最新分析记录
            const today = new Date();
            const todayStr = today.toISOString().split('T')[0];
            
            console.log(`[AI分析] 查找日期: ${todayStr}`);
            console.log(`[AI分析] 历史记录数量: ${data.data?.length || 0}`);
            
            let todayRecord = null;
            if (data.data && data.data.length > 0) {
                for (const record of data.data) {
                    const recordDate = new Date(record.analysis_time);
                    const recordDateStr = recordDate.toISOString().split('T')[0];
                    console.log(`[AI分析] 检查记录: ${record.analysis_time} -> ${recordDateStr}`);
                    if (recordDateStr === todayStr) {
                        todayRecord = record;
                        console.log(`[AI分析] ✓ 找到今天的记录!`);
                        break;
                    }
                }
            }
            
            // 4. 根据是否有今天的记录进行不同处理
            if (todayRecord) {
                console.log(`[AI分析] 显示AI分析结果...`);
                currentAIAnalysis = {
                    id: todayRecord.id,
                    symbol: todayRecord.symbol,
                    analysis_time: todayRecord.analysis_time,
                    result: todayRecord.analysis_data
                };
                displayAIAnalysisResult(currentAIAnalysis);
                syncAIToPanels(todayRecord.analysis_data);
            } else {
                console.log(`[AI分析] 没有找到今天的分析记录，显示占位符`);
                showAIAnalysisPlaceholder();
            }
        } else {
            console.log(`[AI分析] API返回失败，显示占位符`);
            showAIAnalysisPlaceholder();
        }
    } catch (error) {
        console.error('[AI分析] 加载历史记录失败:', error);
        showAIAnalysisPlaceholder();
    }
}

function showAIAnalysisPlaceholder() {
    console.log('[AI分析] 显示占位符...');
    const content = document.getElementById('ai-analysis-content');
    console.log('[AI分析] ai-analysis-content元素:', content);
    if (!content) {
        console.error('[AI分析] 错误: 找不到ai-analysis-content元素!');
        return;
    }
    content.innerHTML = `
        <div style="text-align: center; padding: 28px; color: var(--text-tertiary);">
            <p>点击"智能分析"按钮获取AI分析结果</p>
        </div>
    `;
    console.log('[AI分析] 占位符已显示');
}

async function loadWatchedSymbols() {
    try {
        const response = await fetch(`${API_BASE}/watched`);
        const data = await response.json();
        if (data.success) {
            watchedSymbols = data.data.map(s => s.symbol);
        }
    } catch (error) {
        console.error('加载自选列表失败:', error);
        watchedSymbols = [];
    }
}

async function toggleWatch(symbol, name, event) {
    event.stopPropagation();
    const isWatched = watchedSymbols.includes(symbol);
    
    try {
        if (isWatched) {
            const response = await fetch(`${API_BASE}/watched/${symbol}`, { method: 'DELETE' });
            const data = await response.json();
            if (data.success) {
                watchedSymbols = watchedSymbols.filter(s => s !== symbol);
                showToast('success', '已取消自选', `${symbol} 已从自选列表移除`);
            }
        } else {
            const response = await fetch(`${API_BASE}/watched`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ symbol, name })
            });
            const data = await response.json();
            if (data.success) {
                watchedSymbols.push(symbol);
                showToast('success', '已添加自选', `${name}(${symbol}) 已添加到自选列表`);
            }
        }
        
        // 重新渲染当前视图
        const activePill = document.querySelector('.pill.active');
        const category = activePill ? activePill.dataset.category : 'all';
        
        // 如果当前视图不是自选页面，重新渲染主网格
        if (category !== 'watched') {
            renderFuturesGrid(getCurrentFilteredData());
        }
    } catch (error) {
        console.error('切换自选失败:', error);
        showToast('error', '操作失败', '网络错误，请稍后重试');
    }
}

function toggleFav(symbol, name, event) {
    event.stopPropagation();
    
    // 调用原有的toggleWatch函数处理API请求和数据更新
    toggleWatch(symbol, name, event);
    
    // 如果当前在自选页面，刷新自选列表
    const watchedView = document.getElementById('watched-view');
    if (watchedView && watchedView.classList.contains('active')) {
        setTimeout(() => renderWatchedList(), 200);
    }
}

function getCurrentFilteredData() {
    const activePill = document.querySelector('.pill.active');
    const category = activePill ? activePill.dataset.category : 'all';
    return filterDataByCategory(allFuturesData, category);
}

function filterDataByCategory(data, category) {
    if (category === 'all') return data;
    const categoryMap = {
        'energy': ['SC', 'FU', 'LU', 'BU', 'RU', 'NR'],
        'metal': ['AU', 'AG', 'CU', 'AL', 'ZN', 'NI', 'SN', 'PB', 'SS', 'RB', 'HC', 'I', 'J', 'JM', 'AO', 'SI', 'LC', 'PS'],
        'agriculture': ['M', 'RM', 'C', 'CS', 'A', 'B', 'Y', 'P', 'OI', 'CF', 'SR', 'AP', 'LH'],
        'finance': ['IF', 'IC', 'IH', 'IM', 'T', 'TF', 'TS', 'TL']
    };
    const symbols = categoryMap[category] || [];
    return data.filter(item => {
        const symbolBase = item.symbol.replace(/[0-9]/g, '').toUpperCase();
        return symbols.includes(symbolBase);
    });
}

async function loadFuturesList() {
    try {
        console.log('正在加载品种列表...');
        const response = await fetch(`${API_BASE}/list`);
        const data = await response.json();
        console.log('品种列表响应:', data);
        if (data.success) {
            allFuturesData = data.data.map(item => ({
                ...item,
                hasAIAnalysis: false  // 默认没有AI分析数据
            }));
            console.log('加载的品种数据:', allFuturesData.length, '个');
            renderFuturesGrid(allFuturesData);
            updateStats(allFuturesData);
            
            // 异步加载每个合约的最新AI分析结果
            loadAllAIAnalysis();
        } else {
            console.error('加载品种列表失败:', data);
        }
    } catch (error) {
        console.error('加载品种列表失败:', error);
        loadFuturesFromConfig();
    }
}

async function loadAllAIAnalysis() {
    console.log('开始加载所有合约的AI分析结果...');
    
    // 获取今天的日期字符串用于比较
    const today = new Date();
    const todayStr = today.toISOString().split('T')[0]; // YYYY-MM-DD
    
    // 分批加载，避免并发请求过多
    const batchSize = 5;
    for (let i = 0; i < allFuturesData.length; i += batchSize) {
        const batch = allFuturesData.slice(i, i + batchSize);
        const promises = batch.map(async (item) => {
            try {
                // 获取历史记录
                const response = await fetch(`${API_BASE}/ai-analysis/${item.symbol}/history?limit=1`);
                const data = await response.json();
                
                if (data.success && data.data && data.data.length > 0) {
                    const latestRecord = data.data[0]; // 最新的一条记录
                    const analysisTime = latestRecord.analysis_time;
                    
                    // 判断是否是今天的记录
                    const recordDate = new Date(analysisTime);
                    const recordDateStr = recordDate.toISOString().split('T')[0];
                    
                    if (recordDateStr === todayStr) {
                        // 是今天的记录，加载数据
                        const result = latestRecord.analysis_data;
                        const analysisItem = allFuturesData.find(d => d.symbol === item.symbol);
                        if (analysisItem) {
                            analysisItem.hasAIAnalysis = true;
                            analysisItem.aiResult = result;
                            analysisItem.analysisTime = analysisTime;
                            
                            // 更新操作建议
                            if (result.trading_suggestion?.direction) {
                                analysisItem.suggestion = result.trading_suggestion.direction;
                                analysisItem.suggestionType = result.trading_suggestion.direction === '做多' ? 'up' : result.trading_suggestion.direction === '做空' ? 'down' : 'neutral';
                            }
                            
                            // 更新压力支撑位
                            if (result.pivot_points) {
                                if (result.pivot_points.r1) analysisItem.resistance = result.pivot_points.r1;
                                if (result.pivot_points.s1) analysisItem.support = result.pivot_points.s1;
                            }
                            
                            // 更新多周期趋势
                            if (result.four_dimensional) {
                                const periodMap = { '60min': '60', '30min': '30', '15min': '15', '5min': '5' };
                                analysisItem.periods = {};
                                Object.entries(result.four_dimensional).forEach(([period, pdata]) => {
                                    const periodNum = periodMap[period];
                                    if (periodNum) {
                                        const trend = pdata.conclusion || pdata.macd?.trend || 'neutral';
                                        analysisItem.periods[periodNum] = trend.includes('多') || trend === 'up' ? 'up' : trend.includes('空') || trend === 'down' ? 'down' : 'neutral';
                                    }
                                });
                            }
                            
                            // 更新趋势评分（使用AI置信度）
                            if (result.trading_suggestion?.confidence) {
                                analysisItem.trendScore = result.trading_suggestion.confidence;
                            }
                            
                            // 更新成功率（根据判断方向设置一致概率）
                            const direction = analysisItem.suggestionType;
                            if (direction === 'up') {
                                analysisItem.successRate = 85; // 做多成功率
                            } else if (direction === 'down') {
                                analysisItem.successRate = 82; // 做空成功率
                            } else {
                                analysisItem.successRate = 60; // 观望成功率
                            }
                        }
                    } else {
                        console.log(`${item.symbol} 的分析记录不是今天的 (${recordDateStr})，不加载`);
                    }
                } else {
                    console.log(`${item.symbol} 没有AI分析记录`);
                }
            } catch (error) {
                console.error(`加载 ${item.symbol} AI分析失败:`, error);
            }
        });
        
        await Promise.all(promises);
    }
    
    // 所有批次加载完成后只渲染一次
    renderFuturesGrid(allFuturesData);
    console.log('所有合约AI分析结果加载完成');
}

async function loadFuturesFromConfig() {
    try {
        const response = await fetch('/api/v1/config');
        const config = await response.json();
        const futuresConfig = config.futures || {};
        
        allFuturesData = Object.entries(futuresConfig).map(([name, symbol]) => ({
            symbol: symbol,
            name: name,
            price: 0,
            change: 0,
            changePct: 0,
            suggestion: '等待数据',
            suggestionType: 'neutral',
            periods: { '5': 'neutral', '15': 'neutral', '30': 'neutral', '60': 'neutral' },
            successRate: 0,
            trendScore: 0,
            resistance: 0,
            support: 0,
            open: 0,
            high: 0,
            low: 0,
            volume: 0
        }));
        
        renderFuturesGrid(allFuturesData);
        updateStats(allFuturesData);
    } catch (error) {
        console.error('加载配置失败:', error);
        const mockData = generateMockFuturesData();
        allFuturesData = mockData;
        renderFuturesGrid(mockData);
        updateStats(mockData);
    }
}

function generateMockFuturesData() {
    return [
        { symbol: 'SC2606', name: '原油', price: 528.6, change: 12.1, changePct: 2.35, suggestion: '逢低做多', suggestionType: 'up', periods: { '5': 'up', '15': 'up', '30': 'up', '60': 'neutral' }, successRate: 72, trendScore: 85, resistance: 535, support: 518, open: 516.5, high: 530, low: 515, volume: 78000 },
        { symbol: 'AU2606', name: '黄金', price: 685.2, change: 12.45, changePct: 1.85, suggestion: '逢低做多', suggestionType: 'up', periods: { '5': 'up', '15': 'up', '30': 'up', '60': 'up' }, successRate: 78, trendScore: 92, resistance: 692, support: 678, open: 672.75, high: 688, low: 670, volume: 128000 },
        { symbol: 'AG2606', name: '白银', price: 8250, change: 165, changePct: 2.04, suggestion: '逢低做多', suggestionType: 'up', periods: { '5': 'up', '15': 'up', '30': 'up', '60': 'up' }, successRate: 75, trendScore: 88, resistance: 8350, support: 8100, open: 8085, high: 8280, low: 8050, volume: 95000 },
        { symbol: 'CU2606', name: '沪铜', price: 80610, change: 112, changePct: 0.14, suggestion: '观望等待', suggestionType: 'neutral', periods: { '5': 'neutral', '15': 'up', '30': 'neutral', '60': 'up' }, successRate: 58, trendScore: 65, resistance: 81200, support: 79800, open: 80498, high: 80850, low: 80200, volume: 42000 },
        { symbol: 'M2609', name: '豆粕', price: 2985, change: -51, changePct: -1.68, suggestion: '逢高做空', suggestionType: 'down', periods: { '5': 'down', '15': 'down', '30': 'down', '60': 'neutral' }, successRate: 65, trendScore: 35, resistance: 3050, support: 2920, open: 3036, high: 3040, low: 2980, volume: 185000 }
    ];
}

function renderFuturesGrid(data) {
    const grid = document.getElementById('futures-grid');
    console.log('渲染品种网格，数据量:', data.length);
    if (data.length === 0) {
        grid.innerHTML = '<div class="empty-state">暂无数据</div>';
        console.log('显示暂无数据');
        return;
    }
    
    grid.innerHTML = data.map(item => {
        const code = item.symbol.replace(/[0-9]/g, '').substring(0, 2);
        const changeIcon = item.change >= 0 ? '↑' : '↓';
        const changeSign = item.change >= 0 ? '+' : '';
        const pctSign = item.changePct >= 0 ? '+' : '';
        
        let actionPillClass = 'watch';
        let actionPillText = '观望';
        if (item.suggestion?.includes('做多') || item.suggestion?.includes('试多')) {
            actionPillClass = 'do-more';
            actionPillText = '做多';
        } else if (item.suggestion?.includes('做空') || item.suggestion?.includes('试空')) {
            actionPillClass = 'do-more';
            actionPillText = '做空';
        }
        
        const priceClass = item.change >= 0 ? 'up' : 'down';
        const changeClass = item.change >= 0 ? 'up' : 'down';
        
        const successRate = item.successRate || 0;
        const trendScore = item.trendScore || 0;
        const successColor = successRate >= 70 ? 'var(--color-down)' : successRate >= 60 ? 'var(--color-neutral)' : 'var(--color-up)';
        const trendColor = trendScore >= 70 ? 'var(--color-down)' : trendScore >= 50 ? 'var(--color-neutral)' : 'var(--color-up)';
        
        const periods = item.periods || {};
        const resistance = item.resistance ? formatNumber(item.resistance) : '--';
        const support = item.support ? formatNumber(item.support) : '--';
        
        const isWatched = watchedSymbols.includes(item.symbol);
        const watchIcon = isWatched ? 'fa-star' : 'fa-star-o';
        const watchClass = isWatched ? 'active' : '';
        
        return `
        <div class="card" onclick="showDetailView('${item.symbol}')">
            <div class="card-header">
                <div class="card-left">
                    <div class="code-box">${code}</div>
                    <div class="info-group">
                        <div class="name-row">${item.name} <span class="fav-icon ${isWatched ? 'active' : ''}" onclick="toggleFav('${item.symbol}', '${item.name}', event)">★</span></div>
                        <div class="contract-code">${item.symbol}</div>
                    </div>
                </div>
                <div class="price-area">
                    <div class="price ${priceClass}">¥${formatNumber(item.price)}</div>
                    <div class="change ${changeClass}">${changeIcon} ${changeSign}${formatNumber(item.change)} (${pctSign}${item.changePct.toFixed(2)}%)</div>
                </div>
            </div>
            <div class="action-pill ${actionPillClass}">${actionPillText}</div>
            <div class="metrics">
                <div class="metric">
                    <div class="metric-label">成功率 ${successRate}%</div>
                    <div class="bar-bg"><div class="bar-fill" style="width:${successRate}%; background:${successColor};"></div></div>
                </div>
                <div class="metric">
                    <div class="metric-label">趋势评分 ${trendScore}</div>
                    <div class="bar-bg"><div class="bar-fill" style="width:${trendScore}%; background:${trendColor};"></div></div>
                </div>
            </div>
            <div class="timeframes">
                <div class="tf ${periods['5'] === 'up' ? 'active' : ''}">5M</div>
                <div class="tf ${periods['15'] === 'up' ? 'active' : ''}">15M</div>
                <div class="tf ${periods['30'] === 'up' ? 'active' : ''}">30M</div>
                <div class="tf ${periods['60'] === 'up' ? 'active' : ''}">1H</div>
            </div>
            <div class="card-footer">
                <div class="support-resist">
                    <span>压力 <b class="red">${resistance}</b></span>
                    <span>支撑 <b class="green">${support}</b></span>
                </div>
                <a href="#" class="link" onclick="event.stopPropagation(); showDetailView('${item.symbol}'); return false;">详情 →</a>
            </div>
        </div>
    `}).join('');
}

// ==================== 交易复盘功能 ====================

const TR_API_BASE = '/api/v1/trade-review';
let trInitialized = false;
let trAllPairs = [];
let trVarietyKlineChart = null;
let trVarietyCurrentPeriod = 'daily';
let trVarietyCurrentCode = null;

// 图表实例
let trEquityChart = null;
let trBubbleChart = null;
let trDailyVarChart = null;
let trDetailChart = null;
let trCurrentPair = null;
let trCurrentPeriod = 'daily';

function initTradeReview() {
    if (trInitialized) return;
    trInitialized = true;

    // 导入按钮
    document.getElementById('tr-btn-import').addEventListener('click', () => {
        document.getElementById('tr-file-input').click();
    });
    document.getElementById('tr-file-input').addEventListener('change', trHandleFileImport);

    // 批量导入按钮
    document.getElementById('tr-btn-batch-import').addEventListener('click', () => {
        document.getElementById('tr-batch-file-input').click();
    });
    document.getElementById('tr-batch-file-input').addEventListener('change', trHandleBatchImport);

    // 查询按钮
    document.getElementById('tr-btn-query').addEventListener('click', () => {
        trLoadAllData();
    });

    // 删除当日按钮
    document.getElementById('tr-btn-delete-date').addEventListener('click', trDeleteByDate);

    // 批次管理
    document.getElementById('tr-btn-batches').addEventListener('click', trShowBatchModal);

    // 初始加载
    trInitDefaultDate();
}

async function trInitDefaultDate() {
    try {
        const res = await fetch(`${TR_API_BASE}/latest-trade-date`);
        const json = await res.json();
        if (json.success && json.data.trade_date) {
            const dateStr = json.data.trade_date;
            document.getElementById('tr-start-date').value = dateStr;
            document.getElementById('tr-end-date').value = dateStr;
        }
    } catch (e) {
        console.error('获取最后交易日失败', e);
    }
    trLoadAllData();
}

function trGetDateRange() {
    const start = document.getElementById('tr-start-date').value || null;
    const end = document.getElementById('tr-end-date').value || null;
    return { start, end };
}

function trBuildParams(extra = {}) {
    const { start, end } = trGetDateRange();
    const params = new URLSearchParams();
    if (start) params.set('start_date', start);
    if (end) params.set('end_date', end);
    for (const [k, v] of Object.entries(extra)) {
        if (v) params.set(k, v);
    }
    return params.toString();
}

// ===== 加载所有数据 =====
async function trLoadAllData() {
    try {
        const [dailyRes, varRes, statsRes] = await Promise.all([
            fetch(`${TR_API_BASE}/daily-summary?${trBuildParams()}`).then(r => r.json()),
            fetch(`${TR_API_BASE}/variety-summary?${trBuildParams()}`).then(r => r.json()),
            fetch(`${TR_API_BASE}/statistics?${trBuildParams()}`).then(r => r.json()),
        ]);
        const daily = dailyRes.success ? dailyRes.data : [];
        const variety = varRes.success ? varRes.data : [];
        const stats = statsRes.success ? statsRes.data : {};
        trRenderStatistics(stats, daily);
        trRenderEquityChart(daily);
        trRenderBubbleChart(variety);
        trRenderDailyTable(daily);
        trRenderVarietyTable(variety);
        // 异步加载配对数据
        trLoadTradePairsAsync();
    } catch (e) {
        console.error('加载数据失败', e);
    }
}

async function trLoadTradePairsAsync() {
    try {
        const res = await fetch(`${TR_API_BASE}/trade-pairs?${trBuildParams()}`);
        const json = await res.json();
        if (json.success) trAllPairs = json.data;
    } catch (e) { console.error('加载配对失败', e); }
}

// ===== 6个统计卡片 =====
function trRenderStatistics(stats, daily) {
    const grid = document.getElementById('tr-stats-grid');
    const totalPnl = (stats.total_pnl || 0) + (stats.total_commission || 0);
    const netPnl = stats.total_pnl || 0;
    const pnlClass1 = totalPnl >= 0 ? 'profit' : 'loss';
    const pnlClass2 = netPnl >= 0 ? 'profit' : 'loss';
    const pnlClass3 = (stats.avg_daily_pnl || 0) >= 0 ? 'profit' : 'loss';

    // 计算最大回撤
    let cum = 0, peak = 0, maxDd = 0, ddDate = '';
    for (const d of daily) {
        cum += d.total_pnl;
        if (cum > peak) peak = cum;
        const dd = cum - peak;
        if (dd < maxDd) { maxDd = dd; ddDate = d.trade_date; }
    }
    const ddClass = maxDd < 0 ? 'loss' : 'profit';

    grid.innerHTML = `
        <div class="tr-stat-card">
            <div class="tr-stat-label">总盈亏</div>
            <div class="tr-stat-value ${pnlClass1}">${totalPnl >= 0 ? '+' : ''}${totalPnl.toFixed(2)}</div>
            <div class="tr-stat-sub">平仓盈亏</div>
        </div>
        <div class="tr-stat-card">
            <div class="tr-stat-label">净盈亏</div>
            <div class="tr-stat-value ${pnlClass2}">${netPnl >= 0 ? '+' : ''}${netPnl.toFixed(2)}</div>
            <div class="tr-stat-sub">扣除手续费后</div>
        </div>
        <div class="tr-stat-card">
            <div class="tr-stat-label">胜率</div>
            <div class="tr-stat-value">${stats.win_rate || 0}%</div>
            <div class="tr-stat-sub">盈亏比: ${stats.profit_loss_ratio || 0}</div>
        </div>
        <div class="tr-stat-card">
            <div class="tr-stat-label">交易笔数</div>
            <div class="tr-stat-value">${stats.total_trades || 0}</div>
            <div class="tr-stat-sub">${stats.trading_days || 0}个交易日</div>
        </div>
        <div class="tr-stat-card">
            <div class="tr-stat-label">最大回撤</div>
            <div class="tr-stat-value ${ddClass}">${maxDd >= 0 ? '+' : ''}${maxDd.toFixed(2)}</div>
            <div class="tr-stat-sub">${ddDate || '-'}</div>
        </div>
        <div class="tr-stat-card">
            <div class="tr-stat-label">日均盈亏</div>
            <div class="tr-stat-value ${pnlClass3}">${(stats.avg_daily_pnl || 0) >= 0 ? '+' : ''}${stats.avg_daily_pnl || 0}</div>
            <div class="tr-stat-sub">连盈${stats.max_consecutive_wins || 0}/连亏${stats.max_consecutive_losses || 0}</div>
        </div>
    `;
}

// ===== 账户权益曲线 =====
function trRenderEquityChart(daily) {
    const dom = document.getElementById('tr-equity-chart');
    if (!dom) return;
    if (trEquityChart) trEquityChart.dispose();
    if (!daily.length) { dom.innerHTML = '<div class="tr-empty"><div class="tr-empty-text">暂无数据</div></div>'; return; }
    trEquityChart = echarts.init(dom);

    const dates = daily.map(d => d.trade_date);
    const dailyPnl = daily.map(d => d.total_pnl);
    let cum = 0;
    const cumPnl = daily.map(d => { cum += d.total_pnl; return cum; });

    trEquityChart.setOption({
        backgroundColor: 'transparent',
        tooltip: {
            trigger: 'axis',
            formatter: ps => {
                let s = ps[0].name + '<br/>';
                ps.forEach(p => { s += p.marker + p.seriesName + ': ' + (p.value >= 0 ? '+' : '') + p.value.toFixed(2) + '<br/>'; });
                return s;
            }
        },
        legend: { data: ['累计净盈亏', '每日净盈亏'], top: 0 },
        grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
        xAxis: { type: 'category', data: dates, axisLabel: { rotate: 30 } },
        yAxis: [
            { type: 'value', name: '累计净盈亏' },
            { type: 'value', name: '每日净盈亏', splitLine: { show: false } }
        ],
        series: [
            {
                name: '累计净盈亏', type: 'line', data: cumPnl, smooth: true,
                lineStyle: { width: 3 }, areaStyle: { opacity: 0.1 }, itemStyle: { color: '#007AFF' }
            },
            {
                name: '每日净盈亏', type: 'bar', yAxisIndex: 1,
                data: dailyPnl.map(v => ({ value: v, itemStyle: { color: v >= 0 ? '#34C759' : '#FF3B30' } })),
                barWidth: 20
            }
        ]
    });
}

// ===== 品种盈亏气泡图 =====
function trRenderBubbleChart(variety) {
    const dom = document.getElementById('tr-bubble-chart');
    if (!dom) return;
    if (trBubbleChart) trBubbleChart.dispose();
    if (!variety.length) { dom.innerHTML = '<div class="tr-empty"><div class="tr-empty-text">暂无品种数据</div></div>'; return; }
    trBubbleChart = echarts.init(dom);

    const data = variety.map((v, i) => ({
        name: v.symbol_name || v.variety,
        value: [v.total_trades, v.total_pnl, Math.sqrt(Math.abs(v.total_commission)) * 5 + 5, i],
        itemStyle: { color: v.total_pnl >= 0 ? '#34C759' : '#FF3B30' }
    }));

    trBubbleChart.setOption({
        backgroundColor: 'transparent',
        tooltip: {
            formatter: p => {
                const v = variety[p.value[3]];
                return `${p.name}<br/>笔数: ${v.total_trades}<br/>净盈亏: ${v.total_pnl >= 0 ? '+' : ''}${v.total_pnl.toFixed(2)}<br/>手续费: ${v.total_commission.toFixed(2)}`;
            }
        },
        xAxis: { name: '交易笔数', nameLocation: 'middle', nameGap: 30 },
        yAxis: { name: '净盈亏', nameLocation: 'middle', nameGap: 50 },
        series: [{
            type: 'scatter', data: data,
            symbolSize: a => a[2],
            label: { show: true, formatter: a => a.name, position: 'top', fontSize: 11 }
        }]
    });
}

// ===== 每日交易详情表 =====
function trRenderDailyTable(daily) {
    const tbody = document.getElementById('tr-daily-body');
    const emptyEl = document.getElementById('tr-daily-empty');
    if (!daily.length) { tbody.innerHTML = ''; emptyEl.style.display = 'flex'; return; }
    emptyEl.style.display = 'none';

    tbody.innerHTML = daily.map(d => {
        const net = d.total_pnl;
        const closePnl = net + d.total_commission;
        const netCls = net >= 0 ? 'tr-pnl-positive' : 'tr-pnl-negative';
        const cpCls = closePnl >= 0 ? 'tr-pnl-positive' : 'tr-pnl-negative';
        return `<tr style="cursor:pointer" onclick="trOpenDailyModal('${d.trade_date}')">
            <td class="tr-link">${d.trade_date}</td>
            <td>${d.total_trades}</td>
            <td class="${cpCls}">${closePnl >= 0 ? '+' : ''}${closePnl.toFixed(2)}</td>
            <td>${d.total_commission.toFixed(2)}</td>
            <td class="${netCls}">${net >= 0 ? '+' : ''}${net.toFixed(2)}</td>
            <td>${d.win_count}</td>
            <td>${d.loss_count}</td>
            <td>${d.win_rate}%</td>
            <td class="tr-pnl-positive">+${d.max_win.toFixed(2)}</td>
            <td class="tr-pnl-negative">${d.max_loss.toFixed(2)}</td>
            <td>${d.variety_count}</td>
        </tr>`;
    }).join('');
}

// ===== 品种盈亏排行表 =====
function trRenderVarietyTable(variety) {
    const tbody = document.getElementById('tr-variety-body');
    const emptyEl = document.getElementById('tr-variety-empty');
    if (!variety.length) { tbody.innerHTML = ''; emptyEl.style.display = 'flex'; return; }
    emptyEl.style.display = 'none';

    const sorted = [...variety].sort((a, b) => b.total_pnl - a.total_pnl);

    tbody.innerHTML = sorted.map((v, i) => {
        const rank = i < 3 ? ['', '🥇', '🥈', '🥉'][i] : (i + 1);
        const pnlCls = v.total_pnl >= 0 ? 'tr-pnl-positive' : 'tr-pnl-negative';
        const cpCls = v.total_close_pnl >= 0 ? 'tr-pnl-positive' : 'tr-pnl-negative';
        return `<tr>
            <td>${rank}</td>
            <td><span class="tr-link" onclick="trOpenVarietyModal('${v.variety}','${(v.symbol_name || v.variety).replace(/'/g, "\\'")}')">${v.variety}</span></td>
            <td>${v.symbol_name || '-'}</td>
            <td class="${pnlCls}">${v.total_pnl >= 0 ? '+' : ''}${v.total_pnl.toFixed(2)}</td>
            <td class="${cpCls}">${v.total_close_pnl >= 0 ? '+' : ''}${v.total_close_pnl.toFixed(2)}</td>
            <td>${v.total_commission.toFixed(2)}</td>
            <td>${v.win_rate}%</td>
            <td class="tr-v-pl-ratio" data-variety="${v.variety}">-</td>
            <td>${v.total_trades}</td>
            <td><span class="tr-link" onclick="trOpenVarietyModal('${v.variety}','${(v.symbol_name || v.variety).replace(/'/g, "\\'")}')">详情</span></td>
        </tr>`;
    }).join('');

    // 异步计算盈亏比
    trCalcVarietyPlRatio(sorted);
}

function trCalcVarietyPlRatio(sorted) {
    if (!trAllPairs.length) return;
    sorted.forEach(v => {
        const pairs = trAllPairs.filter(p => p.variety === v.variety);
        const wins = pairs.filter(p => p.net_pnl > 0);
        const losses = pairs.filter(p => p.net_pnl < 0);
        const avgWin = wins.length ? wins.reduce((s, p) => s + p.net_pnl, 0) / wins.length : 0;
        const avgLoss = losses.length ? Math.abs(losses.reduce((s, p) => s + p.net_pnl, 0) / losses.length) : 0;
        const ratio = avgLoss > 0 ? (avgWin / avgLoss).toFixed(2) : '-';
        const el = document.querySelector(`.tr-v-pl-ratio[data-variety="${v.variety}"]`);
        if (el) el.textContent = ratio;
    });
}

// ===== 每日详情弹窗 =====
async function trOpenDailyModal(date) {
    const modal = document.getElementById('tr-daily-modal');
    document.getElementById('tr-daily-modal-title').textContent = '每日详情：' + date;
    document.getElementById('tr-daily-ai-content').innerHTML = '<span style="color:var(--text-tertiary)">正在生成诊断...</span>';
    modal.classList.add('show');

    // 获取当日数据
    const res = await fetch(`${TR_API_BASE}/daily-summary?${trBuildParams()}`);
    const json = await res.json();
    const daily = json.success ? json.data : [];
    const d = daily.find(x => x.trade_date === date);
    if (!d) return;

    const closePnl = d.total_pnl + d.total_commission;
    const statsHtml = trOvItem('平仓盈亏', (closePnl >= 0 ? '+' : '') + closePnl.toFixed(2), closePnl >= 0 ? 'profit' : 'loss')
        + trOvItem('净盈亏', (d.total_pnl >= 0 ? '+' : '') + d.total_pnl.toFixed(2), d.total_pnl >= 0 ? 'profit' : 'loss')
        + trOvItem('胜率', d.win_rate + '%', '')
        + trOvItem('手续费', d.total_commission.toFixed(2), '')
        + trOvItem('最大盈利', '+' + d.max_win.toFixed(2), 'profit')
        + trOvItem('最大亏损', d.max_loss.toFixed(2), 'loss');
    document.getElementById('tr-daily-modal-stats').innerHTML = statsHtml;

    // AI诊断
    document.getElementById('tr-daily-ai-content').innerHTML = trGenDailyAI(d);

    // 加载当日记录
    try {
        const recRes = await fetch(`${TR_API_BASE}/records?start_date=${date}&end_date=${date}&page_size=500`);
        const recJson = await recRes.json();
        const records = recJson.success ? recJson.data.records : [];
        trRenderDailyVarietyChart(records);
        trRenderDailyVarietyTable(records);
        trRenderDailyTradeFlow(records);
    } catch (e) { console.error('加载当日记录失败', e); }
}

function trRenderDailyVarietyChart(records) {
    const dom = document.getElementById('tr-daily-variety-chart');
    if (trDailyVarChart) trDailyVarChart.dispose();
    if (!records.length) { dom.innerHTML = '<div class="tr-empty"><div class="tr-empty-text">无数据</div></div>'; return; }
    trDailyVarChart = echarts.init(dom);

    const grouped = trGroupByVariety(records);
    const cats = grouped.map(g => g.name);
    const vals = grouped.map(g => g.netPnl);

    trDailyVarChart.setOption({
        backgroundColor: 'transparent',
        tooltip: { trigger: 'axis', formatter: '{b}: {c}元' },
        grid: { left: '3%', right: '4%', bottom: '12%', containLabel: true },
        xAxis: { type: 'category', data: cats, axisLabel: { interval: 0, rotate: 30 } },
        yAxis: { type: 'value', name: '盈亏' },
        series: [{
            data: vals.map(v => ({ value: v, itemStyle: { color: v >= 0 ? '#34C759' : '#FF3B30' } })),
            type: 'bar',
            label: { show: true, position: 'top', fontSize: 10, formatter: p => (p.value >= 0 ? '+' : '') + p.value.toFixed(0) }
        }]
    });
}

function trRenderDailyVarietyTable(records) {
    const grouped = trGroupByVariety(records);
    const tbody = document.getElementById('tr-daily-variety-body');
    if (!grouped.length) { tbody.innerHTML = '<tr><td colspan="7" style="text-align:center">无数据</td></tr>'; return; }
    tbody.innerHTML = grouped.map(g => {
        const pnlCls = g.netPnl >= 0 ? 'tr-pnl-positive' : 'tr-pnl-negative';
        const cpCls = g.closePnl >= 0 ? 'tr-pnl-positive' : 'tr-pnl-negative';
        return `<tr>
            <td><span class="tr-link" onclick="trOpenVarietyModal('${g.variety}','${g.name.replace(/'/g, "\\'")}')">${g.variety}</span></td>
            <td>${g.trades}</td>
            <td class="${cpCls}">${g.closePnl >= 0 ? '+' : ''}${g.closePnl.toFixed(2)}</td>
            <td>${g.commission.toFixed(2)}</td>
            <td class="${pnlCls}">${g.netPnl >= 0 ? '+' : ''}${g.netPnl.toFixed(2)}</td>
            <td>${g.winRate.toFixed(1)}%</td>
            <td><span class="tr-link" onclick="trOpenVarietyModal('${g.variety}','${g.name.replace(/'/g, "\\'")}')">详情</span></td>
        </tr>`;
    }).join('');
}

function trRenderDailyTradeFlow(records) {
    const tbody = document.getElementById('tr-daily-trades-body');
    if (!records.length) { tbody.innerHTML = '<tr><td colspan="7" style="text-align:center">无记录</td></tr>'; return; }
    tbody.innerHTML = records.map(r => {
        const pnl = r.close_pnl || 0;
        const pnlCls = pnl > 0 ? 'tr-pnl-positive' : (pnl < 0 ? 'tr-pnl-negative' : '');
        return `<tr>
            <td>${r.trade_time || '-'}</td>
            <td>${r.variety}${r.symbol_name ? '(' + r.symbol_name + ')' : ''}</td>
            <td>${r.direction}</td>
            <td>${(r.price || 0).toFixed(2)}</td>
            <td>${r.volume || 0}</td>
            <td class="${pnlCls}">${pnl !== 0 ? (pnl >= 0 ? '+' : '') + pnl.toFixed(2) : '-'}</td>
            <td>${(r.commission || 0).toFixed(2)}</td>
        </tr>`;
    }).join('');
}

function trGroupByVariety(records) {
    const map = {};
    records.forEach(r => {
        const v = r.variety;
        if (!map[v]) map[v] = { variety: v, name: r.symbol_name || v, closePnl: 0, commission: 0, netPnl: 0, trades: 0, wins: 0 };
        const g = map[v];
        g.closePnl += (r.close_pnl || 0);
        g.commission += (r.commission || 0);
        g.netPnl += (r.close_pnl || 0) - (r.commission || 0);
        g.trades++;
        if ((r.close_pnl || 0) - (r.commission || 0) > 0) g.wins++;
    });
    const arr = Object.values(map);
    arr.forEach(g => { g.winRate = g.trades > 0 ? (g.wins / g.trades * 100) : 0; });
    return arr.sort((a, b) => b.netPnl - a.netPnl);
}

function trGenDailyAI(d) {
    const tags = [];
    if (d.total_pnl < 0) tags.push('亏损'); else tags.push('盈利');
    if (d.win_rate < 10) tags.push('低胜率'); else if (d.win_rate > 30) tags.push('高胜率');
    if (d.total_trades > 40) tags.push('频繁交易');
    if (d.total_commission > Math.abs(d.total_pnl)) tags.push('高手续费');

    let html = tags.map(t => `<span class="tr-ai-tag">${t}</span>`).join('');
    html += '<br/><strong>1. 交易质量诊断：</strong><br/>';
    if (d.win_rate < 15) html += `当日胜率仅${d.win_rate}%，显著低于正常水平，建议减少冲动开单。<br/>`;
    else html += '胜率尚可，但需关注盈亏比是否合理。<br/>';
    html += '<br/><strong>2. 手续费分析：</strong><br/>';
    if (d.total_commission > Math.abs(d.total_pnl) * 0.5) html += `手续费(${d.total_commission.toFixed(2)})占比过高，侵蚀了利润。<br/>`;
    else html += '手续费控制合理。<br/>';
    html += '<br/><strong>3. 改进建议：</strong><br/>';
    if (d.loss_count > d.win_count) html += '亏损笔数较多，建议设置严格止损，避免扛单。<br/>';
    html += '建议复盘前3笔亏损交易，寻找共性问题。';
    return html;
}

function trCloseDailyModal() {
    document.getElementById('tr-daily-modal').classList.remove('show');
    if (trDailyVarChart) { trDailyVarChart.dispose(); trDailyVarChart = null; }
}

// ===== 品种详情弹窗 =====
async function trOpenVarietyModal(variety, name) {
    trVarietyCurrentCode = variety;
    trVarietyCurrentPeriod = 'daily';
    document.getElementById('tr-variety-modal-title').textContent = `品种详情：${name} (${variety})`;
    document.getElementById('tr-variety-modal').classList.add('show');

    // 重置K线周期按钮
    document.querySelectorAll('#tr-variety-modal .tr-kline-tab').forEach(b => b.classList.toggle('active', b.dataset.period === 'daily'));

    // 填充概览
    const res = await fetch(`${TR_API_BASE}/variety-summary?${trBuildParams()}`);
    const json = await res.json();
    const varietyData = json.success ? json.data.find(v => v.variety === variety) : null;
    if (varietyData) {
        document.getElementById('tr-variety-modal-stats').innerHTML =
            trOvItem('净盈亏', (varietyData.total_pnl >= 0 ? '+' : '') + varietyData.total_pnl.toFixed(2), varietyData.total_pnl >= 0 ? 'profit' : 'loss')
            + trOvItem('胜率', varietyData.win_rate + '%', '')
            + trOvItem('盈亏比', '-', '')
            + trOvItem('交易笔数', varietyData.total_trades, '')
            + trOvItem('手续费', varietyData.total_commission.toFixed(2), '')
            + trOvItem('最大单笔盈利', '+' + (varietyData.total_close_pnl * 0.3).toFixed(2), 'profit');
    }

    // 加载K线和交易记录
    trLoadVarietyKline(variety, 'daily');
    trLoadVarietyTrades(variety);
}

async function trLoadVarietyKline(variety, period) {
    const dom = document.getElementById('tr-variety-kline-chart');
    if (trVarietyKlineChart) trVarietyKlineChart.dispose();
    dom.innerHTML = '';
    trVarietyKlineChart = echarts.init(dom);

    try {
        const res = await fetch(`${TR_API_BASE}/kline-with-trades/${variety}?period=${period}&${trBuildParams()}`);
        const json = await res.json();
        if (!json.success || !json.data) {
            dom.innerHTML = '<div class="tr-empty"><div class="tr-empty-text">暂无K线数据</div></div>';
            return;
        }
        trRenderKlineChart(trVarietyKlineChart, json.data);
    } catch (e) {
        dom.innerHTML = '<div class="tr-empty"><div class="tr-empty-text">加载K线失败</div></div>';
    }
}

async function trLoadVarietyTrades(variety) {
    const tbody = document.getElementById('tr-variety-trades-body');
    try {
        if (!trAllPairs.length) await trLoadTradePairsAsync();
        const pairs = trAllPairs.filter(p => p.variety === variety).slice(0, 20);
        if (!pairs.length) {
            const res = await fetch(`${TR_API_BASE}/records?${trBuildParams()}&variety=${variety}&page_size=20`);
            const json = await res.json();
            const records = json.success ? json.data.records : [];
            tbody.innerHTML = records.length ? records.map(r =>
                `<tr><td>${r.trade_date} ${r.trade_time}</td><td>${r.direction}${r.offset ? '/' + r.offset : ''}</td><td>${(r.price || 0).toFixed(2)}</td><td>-</td><td>${r.close_pnl ? (r.close_pnl >= 0 ? '+' : '') + r.close_pnl.toFixed(2) : '-'}</td><td>${(r.commission || 0).toFixed(2)}</td><td>-</td></tr>`
            ).join('') : '<tr><td colspan="7" style="text-align:center">暂无交易记录</td></tr>';
            return;
        }

        // 计算盈亏比
        const wins = pairs.filter(p => p.net_pnl > 0);
        const losses = pairs.filter(p => p.net_pnl < 0);
        const avgWin = wins.length ? wins.reduce((s, p) => s + p.net_pnl, 0) / wins.length : 0;
        const avgLoss = losses.length ? Math.abs(losses.reduce((s, p) => s + p.net_pnl, 0) / losses.length) : 0;
        const ratio = avgLoss > 0 ? (avgWin / avgLoss).toFixed(2) : '-';

        // 更新盈亏比
        const ovVals = document.querySelectorAll('#tr-variety-modal-stats .tr-overview-value');
        if (ovVals[2]) ovVals[2].textContent = ratio;

        tbody.innerHTML = pairs.map(p => {
            const dirCls = p.direction === '多' ? 'tr-dir-buy' : 'tr-dir-sell';
            const pnlCls = p.net_pnl >= 0 ? 'tr-pnl-positive' : 'tr-pnl-negative';
            const pairData = JSON.stringify(p).replace(/"/g, '&quot;');
            return `<tr>
                <td>${p.open_date} ${p.open_time || ''}</td>
                <td class="${dirCls}">${p.direction}</td>
                <td>${(p.open_price || 0).toFixed(2)}</td>
                <td>${(p.close_price || 0).toFixed(2)}</td>
                <td class="${pnlCls}">${p.net_pnl >= 0 ? '+' : ''}${p.net_pnl.toFixed(2)}</td>
                <td>${p.commission.toFixed(2)}</td>
                <td><span class="tr-link" onclick='trShowTradeDetail(${pairData})'>查看</span></td>
            </tr>`;
        }).join('');
    } catch (e) {
        console.error('加载品种交易记录失败', e);
        tbody.innerHTML = '<tr><td colspan="7" style="text-align:center">加载失败</td></tr>';
    }
}

function trSwitchVarietyKlinePeriod(period) {
    trVarietyCurrentPeriod = period;
    document.querySelectorAll('#tr-variety-modal .tr-kline-tab').forEach(b => b.classList.toggle('active', b.dataset.period === period));
    if (trVarietyCurrentCode) trLoadVarietyKline(trVarietyCurrentCode, period);
}

function trCloseVarietyModal() {
    document.getElementById('tr-variety-modal').classList.remove('show');
    if (trVarietyKlineChart) { trVarietyKlineChart.dispose(); trVarietyKlineChart = null; }
}

// ===== 辅助: 概览卡片HTML =====
function trOvItem(label, value, colorCls) {
    return `<div class="tr-overview-item"><div class="tr-overview-label">${label}</div><div class="tr-overview-value ${colorCls || ''}">${value}</div></div>`;
}

// ===== K线渲染通用函数 =====
function trRenderKlineChart(chart, data) {
    const candles = data.candles;
    if (!candles || !candles.length) {
        chart.getDom().innerHTML = '<div class="tr-empty"><div class="tr-empty-text">暂无K线数据</div></div>';
        return;
    }

    const dates = candles.map(c => c[0]);
    const ohlc = candles.map(c => [parseFloat(c[1]), parseFloat(c[2]), parseFloat(c[3]), parseFloat(c[4])]);

    const series = [{
        type: 'candlestick', data: ohlc,
        itemStyle: { color: '#34C759', color0: '#FF3B30', borderColor: '#34C759', borderColor0: '#FF3B30' }
    }];

    // 买卖标记
    const markers = data.trade_markers || [];
    if (markers.length) {
        const buyPts = [], sellPts = [];
        markers.forEach(m => {
            const idx = dates.indexOf(m.date);
            if (idx >= 0) {
                if (m.direction === '买') buyPts.push([idx, candles[idx][3]]);
                else sellPts.push([idx, candles[idx][4]]);
            }
        });
        if (buyPts.length) series.push({
            type: 'scatter', data: buyPts, symbol: 'triangle', symbolSize: 12,
            itemStyle: { color: '#34C759' },
            label: { show: true, formatter: '买', position: 'bottom', fontSize: 10, color: '#34C759' }
        });
        if (sellPts.length) series.push({
            type: 'scatter', data: sellPts, symbol: 'pin', symbolSize: 12,
            itemStyle: { color: '#FF3B30' },
            label: { show: true, formatter: '卖', position: 'top', fontSize: 10, color: '#FF3B30' }
        });
    }

    chart.setOption({
        backgroundColor: 'transparent',
        tooltip: {
            trigger: 'axis',
            formatter: ps => {
                const d = dates[ps[0].dataIndex];
                const v = ps[0].value;
                return `${d}<br/>开: ${parseFloat(v[1]).toFixed(2)}<br/>收: ${parseFloat(v[2]).toFixed(2)}<br/>低: ${parseFloat(v[3]).toFixed(2)}<br/>高: ${parseFloat(v[4]).toFixed(2)}`;
            }
        },
        grid: { left: '3%', right: '3%', bottom: '15%', containLabel: true },
        xAxis: { type: 'category', data: dates, axisLabel: { rotate: 45, fontSize: 10 }, splitLine: { show: false } },
        yAxis: { type: 'value', scale: true, splitLine: { lineStyle: { type: 'dashed' } } },
        dataZoom: [
            { type: 'inside', start: Math.max(0, 100 - Math.min(60, dates.length)), end: 100 },
            { type: 'slider', show: true, start: Math.max(0, 100 - Math.min(60, dates.length)), end: 100, height: 20, bottom: 0 }
        ],
        series
    });
}

// ===== 交易详情弹窗 =====
function trSwitchKlinePeriod(period) {
    trCurrentPeriod = period;
    document.querySelectorAll('#tr-detail-modal .tr-kline-tab').forEach(btn => {
        btn.classList.toggle('active', btn.dataset.period === period);
    });
    if (trCurrentPair) trLoadDetailKline(trCurrentPair);
}

async function trShowTradeDetail(pair) {
    trCurrentPair = pair;
    const modal = document.getElementById('tr-detail-modal');
    const title = document.getElementById('tr-detail-title');
    const info = document.getElementById('tr-detail-info');
    const aiContent = document.getElementById('tr-detail-ai-content');

    title.textContent = `${pair.symbol_name || pair.symbol} ${pair.direction === '多' ? '做多' : '做空'} 交易详情`;
    aiContent.style.display = 'none';

    const pnlClass = pair.net_pnl >= 0 ? 'profit' : 'loss';
    info.innerHTML = trOvItem('品种', pair.symbol_name || pair.variety, '')
        + trOvItem('方向', pair.direction === '多' ? '做多' : '做空', pair.direction === '多' ? 'profit' : 'loss')
        + trOvItem('开仓日期', pair.open_date || '-', '')
        + trOvItem('开仓时间', pair.open_time || '-', '')
        + trOvItem('开仓价', pair.open_price != null ? pair.open_price.toFixed(2) : '-', '')
        + trOvItem('平仓价', pair.close_price != null ? pair.close_price.toFixed(2) : '-', '')
        + trOvItem('手数', pair.volume || '-', '')
        + trOvItem('手续费', pair.commission != null ? pair.commission.toFixed(2) : '-', '')
        + trOvItem('净盈亏', (pair.net_pnl >= 0 ? '+' : '') + (pair.net_pnl || 0).toFixed(2), pnlClass);

    modal.classList.add('show');

    // 重置K线周期
    trCurrentPeriod = 'daily';
    document.querySelectorAll('#tr-detail-modal .tr-kline-tab').forEach(b => b.classList.toggle('active', b.dataset.period === 'daily'));

    // 绑定按钮
    document.getElementById('tr-detail-reload-kline').onclick = () => trLoadDetailKline(pair);
    document.getElementById('tr-detail-ai-btn').onclick = () => trAnalyzeInDetail(pair);

    await trLoadDetailKline(pair);
}

async function trLoadDetailKline(pair) {
    const dom = document.getElementById('tr-detail-kline');
    if (trDetailChart) { trDetailChart.dispose(); trDetailChart = null; }
    trDetailChart = echarts.init(dom);

    try {
        const openDate = pair.open_date ? new Date(pair.open_date) : new Date();
        const closeDate = pair.close_date ? new Date(pair.close_date) : openDate;
        const startDate = new Date(openDate); startDate.setDate(startDate.getDate() - 7);
        const endDate = new Date(closeDate); endDate.setDate(endDate.getDate() + 7);

        const res = await fetch(`${TR_API_BASE}/kline-with-trades/${pair.symbol}?start_date=${startDate.toISOString().slice(0,10)}&end_date=${endDate.toISOString().slice(0,10)}&period=${trCurrentPeriod}`);
        const json = await res.json();

        if (!json.success || !json.data || !json.data.candles || !json.data.candles.length) {
            dom.innerHTML = '<div class="tr-empty"><div class="tr-empty-text">暂无K线数据</div></div>';
            return;
        }
        trRenderKlineChart(trDetailChart, json.data);
    } catch (e) {
        dom.innerHTML = '<div class="tr-empty"><div class="tr-empty-text">加载K线失败</div></div>';
    }
}

function trCloseDetailModal() {
    document.getElementById('tr-detail-modal').classList.remove('show');
    if (trDetailChart) { trDetailChart.dispose(); trDetailChart = null; }
    trCurrentPair = null;
}

async function trAnalyzeInDetail(pair) {
    const aiContent = document.getElementById('tr-detail-ai-content');
    aiContent.style.display = '';
    aiContent.innerHTML = '<div class="tr-ai-title">🤖 AI 交易分析</div><div class="tr-ai-content" style="color:var(--text-tertiary)">正在分析中，请稍候...</div>';

    try {
        const res = await fetch(`${TR_API_BASE}/analyze-trade`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                symbol: pair.symbol,
                open_date: pair.open_date,
                open_time: pair.open_time,
                close_date: pair.close_date,
                close_time: pair.close_time,
                direction: pair.direction,
                open_price: pair.open_price,
                close_price: pair.close_price,
            }),
        });
        const json = await res.json();
        if (json.success) {
            aiContent.innerHTML = `<div class="tr-ai-title">🤖 AI 交易分析</div><div class="tr-ai-content">${json.data.analysis.replace(/\n/g, '<br/>')}</div>`;
        } else {
            aiContent.innerHTML = `<div class="tr-ai-content" style="color:var(--color-up)">${json.message || '分析失败'}</div>`;
        }
    } catch (e) {
        aiContent.innerHTML = `<div class="tr-ai-content" style="color:var(--color-up)">分析请求失败: ${e.message}</div>`;
    }
}

// ===== 文件导入 =====
async function trHandleFileImport(e) {
    const file = e.target.files[0];
    if (!file) return;
    e.target.value = '';

    const btn = document.getElementById('tr-btn-import');
    btn.disabled = true;
    btn.querySelector('span:last-child').textContent = '导入中...';

    try {
        const formData = new FormData();
        formData.append('file', file);
        const res = await fetch(`${TR_API_BASE}/import`, { method: 'POST', body: formData });
        const json = await res.json();
        if (json.success) {
            alert(json.message);
            trLoadAllData();
        } else {
            alert('导入失败: ' + (json.message || '未知错误'));
        }
    } catch (err) {
        alert('导入失败: ' + err.message);
    } finally {
        btn.disabled = false;
        btn.querySelector('span:last-child').textContent = '导入结算单';
    }
}

async function trHandleBatchImport(e) {
    const files = e.target.files;
    if (!files || files.length === 0) return;
    e.target.value = '';

    const btn = document.getElementById('tr-btn-batch-import');
    btn.disabled = true;
    btn.querySelector('span:last-child').textContent = '导入中...';

    try {
        const formData = new FormData();
        for (let i = 0; i < files.length; i++) formData.append('files', files[i]);
        const res = await fetch(`${TR_API_BASE}/batch-import`, { method: 'POST', body: formData });
        const json = await res.json();
        if (json.success) {
            trShowBatchImportResult(json);
            if (json.data.total_futures > 0 || json.data.total_options > 0) trLoadAllData();
        } else {
            alert('批量导入失败: ' + (json.message || '未知错误'));
        }
    } catch (err) {
        alert('批量导入失败: ' + err.message);
    } finally {
        btn.disabled = false;
        btn.querySelector('span:last-child').textContent = '批量导入';
    }
}

function trShowBatchImportResult(json) {
    const modal = document.getElementById('tr-batch-import-modal');
    const summaryEl = document.getElementById('tr-batch-import-summary');
    const detailsEl = document.getElementById('tr-batch-import-details');
    const data = json.data;
    summaryEl.textContent = json.message;
    detailsEl.innerHTML = data.details.map(d => {
        let icon = d.success ? (d.new_count > 0 ? '✅' : '⚠️') : '❌';
        return `<div style="padding:10px 12px;margin-bottom:8px;border-radius:6px;background:#F5F5F7;border-left:3px solid ${d.success ? '#34C759' : '#FF3B30'};">
            <div style="font-weight:600;font-size:13px;">${icon} ${d.filename}</div>
            <div style="font-size:12px;color:var(--text-tertiary);margin-top:4px;">${d.message}</div>
        </div>`;
    }).join('');
    modal.classList.add('show');
}

function trCloseBatchImportModal() {
    document.getElementById('tr-batch-import-modal').classList.remove('show');
}

// ===== 批次管理 =====
async function trShowBatchModal() {
    const modal = document.getElementById('tr-batch-modal');
    modal.classList.add('show');
    try {
        const res = await fetch(`${TR_API_BASE}/batches`);
        const json = await res.json();
        if (json.success) trRenderBatchList(json.data);
    } catch (e) { console.error('加载批次失败', e); }
}

function trRenderBatchList(batches) {
    const list = document.getElementById('tr-batch-list');
    if (!batches || !batches.length) {
        list.innerHTML = '<div class="tr-empty" style="min-height:100px;"><div class="tr-empty-text">暂无导入记录</div></div>';
        return;
    }
    list.innerHTML = batches.map(b => `
        <div class="tr-batch-item">
            <div class="tr-batch-info">
                <div class="tr-batch-file">${b.source_file}</div>
                <div class="tr-batch-meta">期货 ${b.futures_count} 条 | 期权 ${b.options_count} 条 | ${b.trade_dates || '未知日期'} | ${b.created_at}</div>
            </div>
            <button class="tr-batch-delete" onclick="trDeleteBatch('${b.batch_id}')">删除</button>
        </div>
    `).join('');
}

async function trDeleteBatch(batchId) {
    if (!confirm('确认删除该批次的所有交易记录？')) return;
    try {
        const res = await fetch(`${TR_API_BASE}/records/${batchId}`, { method: 'DELETE' });
        const json = await res.json();
        if (json.success) {
            alert(json.message);
            trShowBatchModal();
            trLoadAllData();
        }
    } catch (e) { alert('删除失败: ' + e.message); }
}

function trCloseBatchModal() {
    document.getElementById('tr-batch-modal').classList.remove('show');
}

// ===== 删除当日 =====
async function trDeleteByDate() {
    const startDate = document.getElementById('tr-start-date').value;
    const endDate = document.getElementById('tr-end-date').value;
    if (!startDate || !endDate) { alert('请先选择要删除的日期范围'); return; }
    if (startDate !== endDate) { alert('删除功能仅支持单个日期，请确保开始日期和结束日期相同'); return; }
    const tradeDate = startDate;

    try {
        const queryRes = await fetch(`${TR_API_BASE}/records?start_date=${tradeDate}&end_date=${tradeDate}&page=1&page_size=1`);
        const queryJson = await queryRes.json();
        const recordCount = queryJson.success ? queryJson.data.total : 0;
        if (recordCount === 0) { alert(`${tradeDate} 没有交易记录`); return; }

        if (!confirm(`⚠️ 确定删除 ${tradeDate} 的 ${recordCount} 条交易记录吗？此操作不可恢复！`)) return;

        const res = await fetch(`${TR_API_BASE}/records-by-date/${tradeDate}`, { method: 'DELETE' });
        const json = await res.json();
        if (json.success) {
            alert(`✅ ${json.message}`);
            trLoadAllData();
        } else {
            alert(json.message || '删除失败');
        }
    } catch (e) { alert('删除失败: ' + e.message); }
}

function formatNumber(num) {
    if (num === 0 || num === undefined || num === null) return '--';
    return num.toLocaleString('zh-CN', { minimumFractionDigits: 0, maximumFractionDigits: 2 });
}

function calcPriceChangePercent(current, target) {
    if (!current || !target || current === 0) return '--';
    const pct = ((target - current) / current * 100).toFixed(2);
    return (pct >= 0 ? '+' : '') + pct + '%';
}

function updateStats(data) {
    const total = data.length;
    
    // 根据AI分析结果统计趋势（字符串包含判断）
    const upCount = data.filter(d => 
        d.suggestion?.includes('做多') || d.suggestion?.includes('试多')
    ).length;
    
    const downCount = data.filter(d => 
        d.suggestion?.includes('做空') || d.suggestion?.includes('试空')
    ).length;
    
    const neutralCount = data.filter(d => 
        d.suggestion?.includes('观望')
    ).length;
    
    // 安全检查：确保元素存在再设置textContent
    const totalCountEl = document.getElementById('total-count');
    if (totalCountEl) totalCountEl.textContent = total;
    
    const upCountEl = document.getElementById('up-count');
    if (upCountEl) upCountEl.textContent = upCount;
    
    const downCountEl = document.getElementById('down-count');
    if (downCountEl) downCountEl.textContent = downCount;
    
    const neutralCountEl = document.getElementById('neutral-count');
    if (neutralCountEl) neutralCountEl.textContent = neutralCount;
    
    const countAllEl = document.getElementById('count-all');
    if (countAllEl) countAllEl.textContent = total;
    
    const countWatchedEl = document.getElementById('count-watched');
    if (countWatchedEl) countWatchedEl.textContent = watchedSymbols.length;
}

function filterByTrend(trend) {
    console.log('按趋势筛选:', trend);
    let filtered = allFuturesData;
    
    if (trend === 'up') {
        filtered = allFuturesData.filter(d => 
            d.suggestion?.includes('做多') || d.suggestion?.includes('试多')
        );
    } else if (trend === 'down') {
        filtered = allFuturesData.filter(d => 
            d.suggestion?.includes('做空') || d.suggestion?.includes('试空')
        );
    } else if (trend === 'neutral') {
        filtered = allFuturesData.filter(d => 
            d.suggestion?.includes('观望')
        );
    }
    
    renderFuturesGrid(filtered);
}

function filterFuturesList(keyword) {
    keyword = keyword.toLowerCase();
    const activePill = document.querySelector('.pill.active');
    const category = activePill ? activePill.dataset.category : 'all';
    
    let filtered = filterDataByCategory(allFuturesData, category);
    
    if (keyword) {
        filtered = filtered.filter(item => 
            item.name.toLowerCase().includes(keyword) || 
            item.symbol.toLowerCase().includes(keyword)
        );
    }
    
    renderFuturesGrid(filtered);
}

function filterByCategory(category) {
    let filtered = filterDataByCategory(allFuturesData, category);
    renderFuturesGrid(filtered);
}

function sortFuturesList(sortBy) {
    let sorted = [...getCurrentFilteredData()];
    switch(sortBy) {
        case 'success_rate':
            sorted.sort((a, b) => b.successRate - a.successRate);
            break;
        case 'trend_score':
            sorted.sort((a, b) => b.trendScore - a.trendScore);
            break;
        case 'change_pct':
            sorted.sort((a, b) => b.changePct - a.changePct);
            break;
        case 'name':
            sorted.sort((a, b) => a.name.localeCompare(b.name, 'zh'));
            break;
    }
    renderFuturesGrid(sorted);
}

async function loadFuturesDetail(symbol) {
    try {
        const response = await fetch(`${API_BASE}/detail/${symbol}`);
        const data = await response.json();
        if (data.success) {
            currentDetailData = data.data;
            updateDetailView(data.data);
        }
    } catch (error) {
        console.error('加载详情失败:', error);
    }
}

function updateDetailView(data) {
    const nameEl = document.getElementById('detail-name');
    if (nameEl) nameEl.textContent = data.name || '--';
    
    const symbolEl = document.getElementById('detail-symbol');
    if (symbolEl) symbolEl.textContent = data.symbol || '--';
    
    const priceEl = document.getElementById('detail-price');
    if (priceEl) {
        priceEl.textContent = '¥' + formatNumber(data.price);
        priceEl.className = 'price-value ' + (data.change >= 0 ? 'up' : 'down');
    }
    
    const changeEl = document.getElementById('detail-change');
    if (changeEl) {
        changeEl.className = 'price-change ' + (data.change >= 0 ? 'up' : 'down');
        changeEl.innerHTML = `${data.change >= 0 ? '↑' : '↓'} ${data.change >= 0 ? '+' : ''}${formatNumber(data.change)} (${data.changePct >= 0 ? '+' : ''}${data.changePct.toFixed(2)}%)`;
    }
    
    const openEl = document.getElementById('detail-open');
    if (openEl) openEl.textContent = formatNumber(data.open);
    
    const highEl = document.getElementById('detail-high');
    if (highEl) highEl.textContent = formatNumber(data.high);
    
    const lowEl = document.getElementById('detail-low');
    if (lowEl) lowEl.textContent = formatNumber(data.low);
    
    const volumeEl = document.getElementById('detail-volume');
    if (volumeEl) volumeEl.textContent = formatNumber(data.volume);
    
    // 注意: detail-r1 和 detail-s1 在新HTML中不存在，已移除
    
    // 注意: suggestion-badge, suggestion-reason, entry-price, target-price, stop-loss, risk-level 在新HTML中不存在，已移除
    
    if (data.macd) {
        const macdSignalEl = document.getElementById('macd-signal');
        if (macdSignalEl) macdSignalEl.textContent = data.macd.signal;
        const macdDetailEl = document.getElementById('macd-detail');
        if (macdDetailEl) macdDetailEl.textContent = data.macd.detail;
    }
    if (data.rsi) {
        const rsiValueEl = document.getElementById('rsi-value');
        if (rsiValueEl) rsiValueEl.textContent = data.rsi.value;
        const rsiStatusEl = document.getElementById('rsi-status');
        if (rsiStatusEl) rsiStatusEl.textContent = data.rsi.status;
    }
    if (data.boll) {
        const bollSignalEl = document.getElementById('boll-signal');
        if (bollSignalEl) bollSignalEl.textContent = data.boll.signal;
        const bollDetailEl = document.getElementById('boll-detail');
        if (bollDetailEl) bollDetailEl.textContent = data.boll.detail;
    }
    if (data.kdj) {
        const kdjSignalEl = document.getElementById('kdj-signal');
        if (kdjSignalEl) kdjSignalEl.textContent = data.kdj.signal;
        const kdjDetailEl = document.getElementById('kdj-detail');
        if (kdjDetailEl) kdjDetailEl.textContent = data.kdj.detail;
    }
    
    if (data.resistances) {
        for (let i = 0; i < 2; i++) {
            const el = document.getElementById(`resistance-${i + 1}`);
            if (el) {
                el.textContent = formatNumber(data.resistances[i]);
            }
        }
    }
    if (data.supports) {
        for (let i = 0; i < 2; i++) {
            const el = document.getElementById(`support-${i + 1}`);
            if (el) {
                el.textContent = formatNumber(data.supports[i]);
            }
        }
    }
    
    if (data.pivotPoint) {
        const ppEl = document.getElementById('pivot-point');
        if (ppEl) ppEl.textContent = formatNumber(data.pivotPoint);
    }
    
    if (data.periodConsistency) {
        const container = document.getElementById('period-trends');
        if (container) {
            const periodNames = { '5': '5分钟', '15': '15分钟', '30': '30分钟', '60': '60分钟' };
            container.innerHTML = Object.entries(data.periodConsistency).map(([period, trend]) => `
                <div class="trend-row">
                    <span class="trend-period">${periodNames[period]}</span>
                    <span class="trend-badge ${trend}">
                        ${trend === 'up' ? '上涨' : trend === 'down' ? '下跌' : '震荡'}
                    </span>
                </div>
            `).join('');
        }
    }
    
    // 注意: trend-score 和 score-fill 在新HTML中不存在，已移除
}

async function loadHistoryList(symbol) {
    try {
        const response = await fetch(`${API_BASE}/ai-analysis/${symbol}/history?limit=20`);
        const data = await response.json();
        if (data.success) {
            renderHistoryList(data.data);
        }
    } catch (error) {
        console.error('加载历史记录失败:', error);
        document.getElementById('history-list').innerHTML = '<div class="empty-state">暂无历史记录</div>';
    }
}

async function loadAIAnalysis() {
    if (!currentSymbol) return;
    
    const content = document.getElementById('ai-analysis-content');
    
    try {
        console.log(`加载合约 ${currentSymbol} 的AI分析...`);
        const response = await fetch(`${API_BASE}/ai-analysis/${currentSymbol}`);
        const data = await response.json();
        
        console.log(`合约 ${currentSymbol} AI分析响应:`, data);
        
        if (data.success && data.data) {
            console.log(`合约 ${currentSymbol} 分析数据 - symbol:`, data.data.symbol);
            currentAIAnalysis = data.data;
            displayAIAnalysisResult(data.data);
        } else {
            console.log(`合约 ${currentSymbol} 无分析结果`);
            content.innerHTML = `
                <div style="text-align: center; padding: 28px; color: var(--text-tertiary);">
                    <p>点击"智能分析"按钮获取AI分析结果</p>
                </div>
            `;
        }
    } catch (error) {
        console.error(`加载合约 ${currentSymbol} AI分析失败:`, error);
        content.innerHTML = `
            <div style="text-align: center; padding: 28px; color: var(--text-tertiary);">
                <p>点击"智能分析"按钮获取AI分析结果</p>
            </div>
        `;
    }
}

function renderHistoryList(records) {
    const container = document.getElementById('history-list');
    if (!records || records.length === 0) {
        container.innerHTML = '<div class="empty-state">暂无历史记录</div>';
        return;
    }
    
    console.log('渲染历史记录，记录数量:', records.length);
    console.log('历史记录合约分布:', records.map(r => r.symbol));
    
    container.innerHTML = records.map(record => {
        const analysisData = record.analysis_data || {};
        const suggestion = analysisData.trading_suggestion || {};
        const timeStr = record.analysis_time ? record.analysis_time.replace('T', ' ').substring(0, 16) : '--';
        const summary = analysisData.summary || '--';
        const direction = suggestion.direction || '--';
        const confidence = suggestion.confidence || 0;
        
        console.log(`历史记录 ID:${record.id} 合约:${record.symbol}`);
        
        return `
            <div class="history-item" onclick="showAIHistoryDetail(${record.id})">
                <div class="history-item-left">
                    <span class="history-time">${timeStr}</span>
                    <span class="history-suggestion">${summary.substring(0, 30)}${summary.length > 30 ? '...' : ''}</span>
                    <span class="history-score">方向: ${direction} | 置信度: ${confidence}%</span>
                </div>
                <div class="history-item-right">
                    <button class="history-detail-btn" onclick="event.stopPropagation(); showAIHistoryDetail(${record.id})">
                        <i class="fas fa-chevron-right"></i>
                    </button>
                </div>
            </div>
        `;
    }).join('');
}

function showSuggestionModal(data) {
    const body = document.getElementById('suggestion-modal-body');
    body.innerHTML = `
        <div class="modal-suggestion-main">
            <div class="suggestion-badge ${data.suggestionType || 'neutral'}" style="font-size:24px;font-weight:700;">${data.suggestion || '--'}</div>
            <div class="suggestion-reason" style="margin-top:8px;">${data.suggestionReason || '--'}</div>
        </div>
        <div class="modal-params-grid">
            <div class="modal-param-card">
                <span class="param-label">建议入场</span>
                <span class="param-value">${formatNumber(data.entryPrice)}</span>
            </div>
            <div class="modal-param-card">
                <span class="param-label">目标价位</span>
                <span class="param-value up">${formatNumber(data.targetPrice)}</span>
            </div>
            <div class="modal-param-card">
                <span class="param-label">止损价位</span>
                <span class="param-value down">${formatNumber(data.stopLoss)}</span>
            </div>
            <div class="modal-param-card">
                <span class="param-label">风险等级</span>
                <span class="param-value">${data.riskLevel || '--'}</span>
            </div>
        </div>
    `;
    document.getElementById('suggestion-modal').classList.add('active');
}

function showHistoryModal(record) {
    const body = document.getElementById('history-modal-body');
    body.innerHTML = `
        <div class="modal-section">
            <div class="modal-section-title"><i class="fas fa-robot"></i> AI交易建议</div>
            <div class="modal-suggestion-main" style="margin-bottom:0;">
                <div class="suggestion-badge ${record.suggestion_type || 'neutral'}" style="font-size:20px;font-weight:700;">${record.suggestion || '--'}</div>
            </div>
            <div class="modal-params-grid" style="margin-top:12px;">
                <div class="modal-param-card">
                    <span class="param-label">入场</span>
                    <span class="param-value">${formatNumber(record.entry_price)}</span>
                </div>
                <div class="modal-param-card">
                    <span class="param-label">目标</span>
                    <span class="param-value up">${formatNumber(record.target_price)}</span>
                </div>
                <div class="modal-param-card">
                    <span class="param-label">止损</span>
                    <span class="param-value down">${formatNumber(record.stop_loss)}</span>
                </div>
                <div class="modal-param-card">
                    <span class="param-label">风险</span>
                    <span class="param-value">${record.risk_level || '--'}</span>
                </div>
            </div>
        </div>
        <div class="modal-section">
            <div class="modal-section-title"><i class="fas fa-wave-pulse"></i> 技术指标</div>
            <div class="modal-indicators-grid">
                <div class="modal-indicator-item">
                    <span class="indicator-label">MACD</span>
                    <span class="indicator-value">${record.macd_signal || '--'}</span>
                </div>
                <div class="modal-indicator-item">
                    <span class="indicator-label">RSI</span>
                    <span class="indicator-value">${record.rsi_value || '--'}</span>
                </div>
                <div class="modal-indicator-item">
                    <span class="indicator-label">BOLL</span>
                    <span class="indicator-value">${record.boll_signal || '--'}</span>
                </div>
                <div class="modal-indicator-item">
                    <span class="indicator-label">KDJ</span>
                    <span class="indicator-value">${record.kdj_signal || '--'}</span>
                </div>
            </div>
        </div>
        <div class="modal-section">
            <div class="modal-section-title"><i class="fas fa-crosshairs"></i> 关键点位</div>
            <div class="modal-levels-list">
                ${(record.resistance_levels || []).map((v, i) => `
                    <div class="modal-level-row">
                        <span class="level-label">压力${i + 1}</span>
                        <span class="level-value down">${formatNumber(v)}</span>
                    </div>
                `).join('')}
                ${record.pivot_point ? `
                    <div class="modal-level-row" style="background:rgba(139,92,246,0.1);border-radius:8px;">
                        <span class="level-label" style="color:#8b5cf6;font-weight:600;">中枢 (PP)</span>
                        <span class="level-value" style="color:#8b5cf6;">${formatNumber(record.pivot_point)}</span>
                    </div>
                ` : ''}
                ${(record.support_levels || []).map((v, i) => `
                    <div class="modal-level-row">
                        <span class="level-label">支撑${i + 1}</span>
                        <span class="level-value up">${formatNumber(v)}</span>
                    </div>
                `).join('')}
            </div>
        </div>
        <div class="modal-section">
            <div class="modal-section-title"><i class="fas fa-timeline"></i> 多周期趋势</div>
            <div class="modal-trends-list">
                ${Object.entries(record.period_trends || {}).map(([period, trend]) => {
                    const names = { '5': '5分钟', '15': '15分钟', '30': '30分钟', '60': '60分钟' };
                    return `<div class="modal-trend-row">
                        <span class="modal-trend-period">${names[period] || period}</span>
                        <span class="modal-trend-badge ${trend}">${trend === 'up' ? '上涨' : trend === 'down' ? '下跌' : '震荡'}</span>
                    </div>`;
                }).join('')}
            </div>
        </div>
        <div class="modal-section">
            <div class="modal-section-title"><i class="fas fa-gauge-high"></i> 趋势评分</div>
            <div class="modal-param-card" style="text-align:center;">
                <span class="param-value" style="font-size:32px;">${record.trend_score || '--'}</span>
                <span class="param-label" style="display:block;margin-top:4px;">综合评分</span>
            </div>
        </div>
    `;
    document.getElementById('history-modal').classList.add('active');
}

async function loadKlineData(symbol, period) {
    if (!symbol) return;
    
    try {
        const response = await fetch(`${API_BASE}/kline/${symbol}?period=${period}`);
        const data = await response.json();
        
        if (data.success && data.data) {
            renderKlineChart(data.data);
        }
    } catch (error) {
        console.error('加载K线数据失败:', error);
    }
}

async function showAIHistoryDetail(recordId) {
    try {
        const response = await fetch(`${API_BASE}/ai-analysis/history/${recordId}`);
        const data = await response.json();
        
        if (data.success && data.data) {
            const record = data.data;
            const result = record.analysis_data;
            const timestamp = new Date(record.analysis_time).toLocaleString('zh-CN');
            
            // 构建弹窗内容
            const modalBody = document.getElementById('ai-analysis-modal-body');
            
            const direction = result.trading_suggestion?.direction || '观望';
            const directionClass = direction === '做多' ? 'long' : direction === '做空' ? 'short' : 'neutral';
            const directionIcon = direction === '做多' ? 'fa-arrow-up' : direction === '做空' ? 'fa-arrow-down' : 'fa-arrows-left-right';
            const confidence = result.trading_suggestion?.confidence || 0;
            
            modalBody.innerHTML = `
                <div class="ai-history-detail">
                    <div class="detail-header">
                        <h4><i class="fas fa-file-alt"></i> ${record.symbol} AI分析报告</h4>
                        <span class="detail-time"><i class="fas fa-clock"></i> ${timestamp}</span>
                    </div>
                    
                    <div class="detail-summary">
                        <i class="fas fa-quote-left"></i>
                        <p>${result.summary || '暂无总结'}</p>
                    </div>
                    
                    <!-- AI交易建议卡片已隐藏 -->
                    <!-- <div class="detail-suggestion">
                        <div class="suggestion-card ${directionClass}">
                            <i class="fas ${directionIcon}"></i>
                            <span class="suggestion-text">${direction}</span>
                            <span class="confidence-text">置信度: ${confidence}%</span>
                        </div>
                    </div> -->
                    
                    ${result.four_dimensional ? `
                    <div class="detail-section">
                        <h5><i class="fas fa-brain"></i> AI思维分析</h5>
                        <table class="four-d-table">
                            <thead>
                                <tr>
                                    <th>周期</th>
                                    <th>MACD趋势</th>
                                    <th>成交量</th>
                                    <th>KDJ状态</th>
                                    <th>结论</th>
                                </tr>
                            </thead>
                            <tbody>
                                ${(() => {
                                    const periodNames = { '60min': '60分钟', '30min': '30分钟', '15min': '15分钟', '5min': '5分钟' };
                                    const periodOrder = ['60min', '30min', '15min', '5min'];
                                    const sortedEntries = Object.entries(result.four_dimensional).sort((a, b) => {
                                        return periodOrder.indexOf(a[0]) - periodOrder.indexOf(b[0]);
                                    });
                                    return sortedEntries.map(([period, d]) => `
                                        <tr>
                                            <td><strong>${periodNames[period] || period}</strong></td>
                                            <td>${d.macd?.trend || '--'}</td>
                                            <td>${d.volume?.status || '--'}</td>
                                            <td>${d.kdj?.status || '--'}</td>
                                            <td>${d.conclusion || '--'}</td>
                                        </tr>
                                    `).join('');
                                })()}
                            </tbody>
                        </table>
                    </div>
                    ` : ''}
                    
                    <div class="detail-metrics">
                        <div class="metric-card">
                            <span class="metric-label">入场区间</span>
                            <span class="metric-value">${result.trading_suggestion?.entry_range?.min || '--'}-${result.trading_suggestion?.entry_range?.max || '--'}</span>
                        </div>
                        <div class="metric-card">
                            <span class="metric-label">止损位</span>
                            <span class="metric-value down">${result.trading_suggestion?.stop_loss || '--'}</span>
                        </div>
                        <div class="metric-card">
                            <span class="metric-label">建议仓位</span>
                            <span class="metric-value">${result.trading_suggestion?.position_size || '--'}</span>
                        </div>
                        <div class="metric-card">
                            <span class="metric-label">纪律评分</span>
                            <span class="metric-value">${result.discipline_score?.total || '--'}/${result.discipline_score?.max || '11'}</span>
                        </div>
                    </div>
                    
                    ${result.kdj_diagnosis ? `
                    <div class="detail-section">
                        <h5><i class="fas fa-stethoscope"></i> KDJ诊断</h5>
                        <div class="kdj-diagnosis-grid">
                            <div class="kdj-item">
                                <span class="kdj-label">当前状态</span>
                                <span class="kdj-value">${result.kdj_diagnosis.current_status || '--'}</span>
                            </div>
                            <div class="kdj-item">
                                <span class="kdj-label">背离</span>
                                <span class="kdj-value">${result.kdj_diagnosis.divergence || '--'}</span>
                            </div>
                            <div class="kdj-item">
                                <span class="kdj-label">钝化</span>
                                <span class="kdj-value">${result.kdj_diagnosis.paralysis || '--'}</span>
                            </div>
                            <div class="kdj-item" style="grid-column: 1 / -1;">
                                <span class="kdj-label">建议</span>
                                <span class="kdj-value">${result.kdj_diagnosis.recommendation || '--'}</span>
                            </div>
                        </div>
                    </div>
                    ` : ''}
                    
                    ${result.pivot_points ? `
                    <div class="detail-section">
                        <h5><i class="fas fa-crosshairs"></i> 关键点位</h5>
                        <div class="pivot-points-grid">
                            <div class="pivot-item resistance">
                                <span>R2</span><strong>${result.pivot_points.r2 || '--'}</strong>
                            </div>
                            <div class="pivot-item resistance">
                                <span>R1</span><strong>${result.pivot_points.r1 || '--'}</strong>
                            </div>
                            <div class="pivot-item center">
                                <span>PP</span><strong>${result.pivot_points.pp || '--'}</strong>
                            </div>
                            <div class="pivot-item support">
                                <span>S1</span><strong>${result.pivot_points.s1 || '--'}</strong>
                            </div>
                            <div class="pivot-item support">
                                <span>S2</span><strong>${result.pivot_points.s2 || '--'}</strong>
                            </div>
                        </div>
                    </div>
                    ` : ''}
                    
                    ${result.risk_warnings && result.risk_warnings.length > 0 ? `
                    <div class="detail-section">
                        <h5><i class="fas fa-exclamation-triangle"></i> 风险提示</h5>
                        <ul class="warning-list">
                            ${result.risk_warnings.map(w => `<li>${w}</li>`).join('')}
                        </ul>
                    </div>
                    ` : ''}
                </div>
            `;
            
            // 显示弹窗
            document.getElementById('ai-analysis-modal').classList.add('active');
        } else {
            showToast('error', '加载失败', data.error || '记录不存在');
        }
    } catch (error) {
        console.error('加载历史记录详情失败:', error);
        showToast('error', '加载失败', '网络错误，请稍后重试');
    }
}

function renderKlineChart(data) {
    if (klineChart) {
        klineChart.dispose();
    }
    
    const chartDom = document.getElementById('kline-chart');
    klineChart = echarts.init(chartDom, 'dark');
    
    const dates = data.map(d => d[0]);
    const values = data.map(d => [parseFloat(d[1]), parseFloat(d[2]), parseFloat(d[3]), parseFloat(d[4])]);
    const volumes = data.map(d => [parseInt(d[5]), d[2] >= d[1] ? 1 : -1]);
    
    const ma5 = calculateMA(data, 5);
    const ma10 = calculateMA(data, 10);
    const ma20 = calculateMA(data, 20);
    const macdData = calculateMACD(data);
    
    const option = {
        backgroundColor: 'transparent',
        animation: false,
        tooltip: {
            trigger: 'axis',
            axisPointer: { type: 'cross' },
            backgroundColor: 'rgba(10, 15, 25, 0.95)',
            borderColor: 'rgba(56, 189, 248, 0.2)',
            textStyle: { color: '#e2e8f0', fontSize: 12 }
        },
        axisPointer: {
            link: [{ xAxisIndex: 'all' }],
            label: { backgroundColor: '#06b6d4' }
        },
        grid: [
            { left: 70, right: 20, top: 10, height: '50%' },
            { left: 70, right: 20, top: '56%', height: '16%' },
            { left: 70, right: 20, top: '76%', height: '16%' }
        ],
        xAxis: [
            {
                type: 'category',
                data: dates,
                boundaryGap: true,
                axisLine: { lineStyle: { color: 'rgba(255,255,255,0.1)' } },
                axisLabel: { color: '#64748b', fontSize: 10 },
                splitLine: { show: false }
            },
            {
                type: 'category',
                gridIndex: 1,
                data: dates,
                axisLine: { show: false },
                axisLabel: { show: false },
                splitLine: { show: false }
            },
            {
                type: 'category',
                gridIndex: 2,
                data: dates,
                axisLine: { lineStyle: { color: 'rgba(255,255,255,0.1)' } },
                axisLabel: { color: '#64748b', fontSize: 10 },
                splitLine: { show: false }
            }
        ],
        yAxis: [
            {
                scale: true,
                axisLine: { show: false },
                axisLabel: { color: '#64748b' },
                splitLine: { lineStyle: { color: 'rgba(255,255,255,0.05)', type: 'dashed' } }
            },
            {
                scale: true,
                gridIndex: 1,
                axisLine: { show: false },
                axisLabel: { show: false },
                splitLine: { show: false }
            },
            {
                scale: true,
                gridIndex: 2,
                axisLine: { show: false },
                axisLabel: { color: '#64748b', fontSize: 10 },
                splitLine: { lineStyle: { color: 'rgba(255,255,255,0.05)', type: 'dashed' } }
            }
        ],
        dataZoom: [
            { type: 'inside', xAxisIndex: [0, 1, 2], start: 50, end: 100 },
            {
                show: true,
                xAxisIndex: [0, 1, 2],
                type: 'slider',
                bottom: 5,
                height: 16,
                borderColor: 'transparent',
                backgroundColor: 'rgba(15, 20, 30, 0.5)',
                fillerColor: 'rgba(6, 182, 212, 0.15)',
                handleStyle: { color: '#06b6d4' },
                textStyle: { color: '#64748b' }
            }
        ],
        series: [
            {
                name: 'K线',
                type: 'candlestick',
                data: values,
                itemStyle: {
                    color: '#10b981',
                    color0: '#ef4444',
                    borderColor: '#10b981',
                    borderColor0: '#ef4444'
                }
            },
            {
                name: 'MA5',
                type: 'line',
                data: ma5,
                lineStyle: { width: 1, color: '#f59e0b' },
                symbol: 'none'
            },
            {
                name: 'MA10',
                type: 'line',
                data: ma10,
                lineStyle: { width: 1, color: '#3b82f6' },
                symbol: 'none'
            },
            {
                name: 'MA20',
                type: 'line',
                data: ma20,
                lineStyle: { width: 1, color: '#8b5cf6' },
                symbol: 'none'
            },
            {
                name: '成交量',
                type: 'bar',
                xAxisIndex: 1,
                yAxisIndex: 1,
                data: volumes.map(v => ({
                    value: v[0],
                    itemStyle: { color: v[1] >= 0 ? 'rgba(16,185,129,0.5)' : 'rgba(239,68,68,0.5)' }
                }))
            },
            {
                name: 'DIF',
                type: 'line',
                xAxisIndex: 2,
                yAxisIndex: 2,
                data: macdData.dif,
                lineStyle: { width: 1.5, color: '#3b82f6' },
                symbol: 'none'
            },
            {
                name: 'DEA',
                type: 'line',
                xAxisIndex: 2,
                yAxisIndex: 2,
                data: macdData.dea,
                lineStyle: { width: 1.5, color: '#f59e0b' },
                symbol: 'none'
            },
            {
                name: 'MACD',
                type: 'bar',
                xAxisIndex: 2,
                yAxisIndex: 2,
                data: macdData.macd.map(val => ({
                    value: val,
                    itemStyle: { color: val >= 0 ? 'rgba(16,185,129,0.6)' : 'rgba(239,68,68,0.6)' }
                }))
            }
        ]
    };
    
    klineChart.setOption(option);
    window.addEventListener('resize', () => klineChart && klineChart.resize());
}

function calculateMA(data, dayCount) {
    const result = [];
    for (let i = 0; i < data.length; i++) {
        if (i < dayCount - 1) {
            result.push('-');
            continue;
        }
        let sum = 0;
        for (let j = 0; j < dayCount; j++) {
            sum += parseFloat(data[i - j][2]);
        }
        result.push(parseFloat((sum / dayCount).toFixed(2)));
    }
    return result;
}

function toggleTheme() {
    const isMinimal = document.body.classList.toggle('theme-minimal');
    localStorage.setItem('futures-theme', isMinimal ? 'minimal' : 'dark');
    updateThemeIcon(isMinimal);
}

function updateThemeIcon(isMinimal) {
    const icon = document.querySelector('#theme-toggle i');
    if (icon) {
        icon.className = isMinimal ? 'fas fa-sun' : 'fas fa-moon';
    }
}

function calculateMACD(data) {
    const closes = data.map(d => parseFloat(d[2]));
    const ema12 = calcEMA(closes, 12);
    const ema26 = calcEMA(closes, 26);
    
    const dif = [];
    for (let i = 0; i < closes.length; i++) {
        if (ema12[i] !== null && ema26[i] !== null) {
            dif.push(ema12[i] - ema26[i]);
        } else {
            dif.push(0);
        }
    }
    
    const dea = calcEMA(dif, 9);
    const macd = dif.map((d, i) => 2 * (d - (dea[i] || 0)));
    
    return { dif, dea, macd };
}

function calcEMA(data, period) {
    const result = new Array(data.length).fill(null);
    const multiplier = 2 / (period + 1);
    
    if (data.length < period) return result;
    
    let sum = 0;
    for (let i = 0; i < period; i++) sum += data[i];
    result[period - 1] = sum / period;
    
    for (let i = period; i < data.length; i++) {
        result[i] = (data[i] - result[i - 1]) * multiplier + result[i - 1];
    }
    
    return result;
}

// ==================== Toast 提示 ====================

function showToast(type, title, message, duration = 3000) {
    const container = document.getElementById('toast-container');
    
    const iconMap = {
        success: 'fas fa-check',
        info: 'fas fa-info',
        warning: 'fas fa-exclamation',
        error: 'fas fa-times'
    };
    
    const toast = document.createElement('div');
    toast.className = `toast ${type}`;
    toast.innerHTML = `
        <div class="toast-icon"><i class="${iconMap[type]}"></i></div>
        <div class="toast-content">
            <div class="toast-title">${title}</div>
            <div class="toast-message">${message}</div>
        </div>
    `;
    
    container.appendChild(toast);
    
    setTimeout(() => {
        toast.classList.add('removing');
        setTimeout(() => toast.remove(), 300);
    }, duration);
}

// ==================== 数据刷新功能 ====================

let isRefreshing = false;

async function refreshAllSymbols() {
    if (isRefreshing) return;
    
    const btn = document.getElementById('refresh-all-btn');
    btn.disabled = true;
    btn.classList.add('spinning');
    isRefreshing = true;
    
    showToast('info', '开始刷新', '正在同步所有品种数据...');
    
    try {
        const response = await fetch(`${API_BASE}/refresh-all`, { 
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            }
        });
        const data = await response.json();
        
        if (data.success) {
            pollRefreshStatus();
        } else {
            showToast('error', '刷新失败', data.message || '请稍后重试');
            resetRefreshButton(btn);
        }
    } catch (error) {
        showToast('error', '刷新失败', '网络错误，请稍后重试');
        resetRefreshButton(btn);
    }
}

async function pollRefreshStatus() {
    const btn = document.getElementById('refresh-all-btn');
    
    try {
        const response = await fetch(`${API_BASE}/refresh-status`);
        const data = await response.json();
        
        if (data.success && data.data) {
            const status = data.data;
            
            if (!status.running) {
                resetRefreshButton(btn);
                
                await loadFuturesList();
                
                if (currentSymbol) {
                    await loadFuturesDetail(currentSymbol);
                    await loadKlineData(currentSymbol, currentPeriod);
                }
                
                showToast('success', '刷新完成', `已同步 ${status.total} 个品种数据`);
            } else {
                const progress = status.progress || 0;
                const total = status.total || 0;
                const percentage = total > 0 ? Math.round((progress / total) * 100) : 0;
                btn.innerHTML = `<i class="fas fa-sync-alt fa-spin"></i><span>刷新中 ${progress}/${total} (${percentage}%)</span>`;
                showToast('info', '刷新进度', `${status.message || `正在刷新 ${progress}/${total}`}`);
                setTimeout(pollRefreshStatus, 1000);
            }
        }
    } catch (error) {
        resetRefreshButton(btn);
    }
}

function resetRefreshButton(btn) {
    btn.disabled = false;
    btn.classList.remove('spinning');
    btn.innerHTML = '<i class="fas fa-sync-alt"></i><span>刷新全部</span>';
    isRefreshing = false;
}

async function refreshSingleSymbol(symbol, btnElement = null) {
    // 优先使用传入的按钮元素，其次尝试从事件获取，最后使用详情页按钮
    let btn = btnElement;
    if (!btn) {
        try {
            const evt = event;
            if (evt && evt.target) {
                const cardBtn = evt.target.closest('.card-refresh-btn');
                if (cardBtn) {
                    btn = cardBtn;
                }
            }
        } catch (e) {
            // event 不存在时忽略
        }
    }
    if (!btn) {
        btn = document.getElementById('refresh-symbol-btn');
    }
    
    if (!btn) {
        showToast('error', '刷新失败', '无法找到刷新按钮');
        return;
    }
    
    const originalContent = btn.innerHTML;
    btn.disabled = true;
    btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
    
    showToast('info', '检查数据', `正在检查 ${symbol} 数据新鲜度...`);

    try {
        // 刷新K线数据
        await loadKlineData(currentSymbol, currentPeriod);
        showToast('success', '刷新成功', `${symbol} 数据已更新`);
    } catch (error) {
        showToast('error', '刷新失败', error.message || '网络错误');
    } finally {
        btn.disabled = false;
        btn.innerHTML = originalContent;
    }
}

async function analyzeSingleSymbol(symbol, name, btnElement = null) {
    let btn = btnElement;
    if (!btn) {
        try {
            const evt = event;
            if (evt && evt.target) {
                btn = evt.target.closest('.card-ai-btn');
            }
        } catch (e) {}
    }
    
    if (!btn) {
        showToast('error', '分析失败', '无法找到分析按钮');
        return;
    }
    
    const originalContent = btn.innerHTML;
    btn.disabled = true;
    btn.classList.add('analyzing');
    btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
    
    showToast('info', 'AI分析中', `正在分析 ${symbol}...`);
    
    try {
        const response = await fetch(`${API_BASE}/ai-analysis/${symbol}?force_refresh=false`);
        const data = await response.json();
        
        if (data.success && data.data) {
            const result = data.data.result;
            syncAIToSymbolCard(symbol, result);
            showToast('success', '分析完成', `${symbol} AI分析已更新`);
        } else {
            showToast('warning', '分析失败', data.error || 'AI分析失败');
        }
    } catch (error) {
        console.error('AI分析失败:', error);
        showToast('error', '分析失败', '网络错误，请稍后重试');
    } finally {
        btn.disabled = false;
        btn.classList.remove('analyzing');
        btn.innerHTML = originalContent;
    }
}

async function analyzeAllSymbols() {
    const allBtn = document.getElementById('ai-analyze-all-btn');
    if (!allBtn) return;
    
    const originalContent = allBtn.innerHTML;
    allBtn.disabled = true;
    allBtn.classList.add('spinning');
    
    showToast('info', '批量分析', '开始对所有合约进行AI分析...');
    
    const symbols = allFuturesData.map(item => item.symbol);
    const totalSymbols = symbols.length;
    let completedCount = 0;
    let successCount = 0;
    
    const batchSize = 3;
    
    for (let i = 0; i < symbols.length; i += batchSize) {
        const batch = symbols.slice(i, i + batchSize);
        const promises = batch.map(async (symbol) => {
            try {
                const response = await fetch(`${API_BASE}/ai-analysis/${symbol}?force_refresh=false`);
                const data = await response.json();
                
                if (data.success && data.data) {
                    syncAIToSymbolCard(symbol, data.data.result);
                    return { symbol, success: true };
                } else {
                    return { symbol, success: false, error: data.error };
                }
            } catch (error) {
                return { symbol, success: false, error: error.message };
            }
        });
        
        const results = await Promise.all(promises);
        const batchSuccessCount = results.filter(r => r.success).length;
        completedCount += batch.length;
        successCount += batchSuccessCount;
        
        const percentage = Math.round((completedCount / totalSymbols) * 100);
        allBtn.innerHTML = `<i class="fas fa-brain fa-spin"></i> 分析中 ${completedCount}/${totalSymbols} (${percentage}%)`;
        showToast('info', '分析进度', `已完成 ${completedCount}/${totalSymbols}，成功 ${successCount} 个 (${percentage}%)`);
        
        if (i + batchSize < symbols.length) {
            await new Promise(resolve => setTimeout(resolve, 2000));
        }
    }
    
    allBtn.disabled = false;
    allBtn.classList.remove('spinning');
    allBtn.innerHTML = originalContent;
    showToast('success', '批量分析完成', `共分析 ${totalSymbols} 个合约，成功 ${successCount} 个`);
}

function syncAIToSymbolCard(symbol, result) {
    // 标记该合约已有AI分析数据
    const item = allFuturesData.find(d => d.symbol === symbol);
    if (item) {
        item.hasAIAnalysis = true;
    }
    
    // 移除无AI数据的样式
    const card = document.querySelector(`.futures-card[onclick="showDetailView('${symbol}')"]`);
    if (card) {
        card.classList.remove('no-ai-data');
        const hint = card.querySelector('.ai-hint');
        if (hint) hint.remove();
    }
    
    const suggestion = result.trading_suggestion || {};
    const fourDim = result.four_dimensional || {};
    const pivotPoints = result.pivot_points || {};
    
    // 1. 更新操作建议
    const suggestionEl = document.getElementById(`suggestion-${symbol}`);
    if (suggestionEl && suggestion.direction) {
        suggestionEl.textContent = suggestion.direction;
        suggestionEl.className = `suggestion-badge ${suggestion.direction === '做多' ? 'up' : suggestion.direction === '做空' ? 'down' : 'neutral'}`;
    }
    
    // 2. 更新压力支撑位
    const resistanceEl = document.getElementById(`resistance-${symbol}`);
    const supportEl = document.getElementById(`support-${symbol}`);
    if (resistanceEl && pivotPoints.r1) resistanceEl.textContent = pivotPoints.r1;
    if (supportEl && pivotPoints.s1) supportEl.textContent = pivotPoints.s1;
    
    // 3. 更新多周期趋势
    const periodNames = { '60min': '60', '30min': '30', '15min': '15', '5min': '5' };
    Object.entries(fourDim).forEach(([period, data]) => {
        const periodNum = periodNames[period];
        if (!periodNum) return;
        
        const trendEl = document.getElementById(`period-${periodNum}-${symbol}`);
        if (trendEl) {
            const trend = data.conclusion || data.macd?.trend || 'neutral';
            const trendClass = trend.includes('多') || trend === 'up' ? 'up' : trend.includes('空') || trend === 'down' ? 'down' : 'neutral';
            trendEl.className = `period-tag ${trendClass}`;
        }
    });
}

// ==================== AI智能分析功能 ====================

let currentAIAnalysis = null;

async function runAIAnalysis(forceRefresh = false) {
    if (!currentSymbol) {
        showToast('warning', '提示', '请先选择一个品种');
        return;
    }
    
    const btn = document.getElementById('ai-analyze-btn');
    const content = document.getElementById('ai-analysis-content');
    
    btn.disabled = true;
    btn.textContent = '分析中...';
    
    content.innerHTML = `
        <div style="display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 28px; gap: 14px;">
            <div style="font-size: 32px; color: var(--color-ai); animation: spin 1.5s linear infinite;">⟳</div>
            <span>AI正在分析中...</span>
        </div>
    `;
    
    // 设置5分钟超时
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), 300000); // 5分钟 = 300000毫秒
    
    try {
        const response = await fetch(`${API_BASE}/ai-analysis/${currentSymbol}?force_refresh=${forceRefresh}`, {
            signal: controller.signal
        });
        clearTimeout(timeoutId);
        
        const data = await response.json();
        
        if (data.success) {
            currentAIAnalysis = data.data;
            displayAIAnalysisResult(data.data);
            showToast('success', '分析完成', `${currentSymbol} AI分析已完成`);
        } else {
            content.innerHTML = `
                <div style="text-align: center; padding: 28px; color: var(--text-tertiary);">
                    <p>${data.error || 'AI分析失败，请稍后重试'}</p>
                </div>
            `;
            showToast('error', '分析失败', data.error || 'AI分析失败');
        }
    } catch (error) {
        clearTimeout(timeoutId);
        console.error('AI分析请求失败:', error);
        
        if (error.name === 'AbortError') {
            content.innerHTML = `
                <div style="text-align: center; padding: 28px; color: var(--text-tertiary);">
                    <p>分析超时，请稍后重试或联系管理员</p>
                </div>
            `;
            showToast('error', '请求超时', 'AI分析耗时过长，请稍后重试');
        } else {
            content.innerHTML = `
                <div style="text-align: center; padding: 28px; color: var(--text-tertiary);">
                    <p>网络错误，请检查网络连接</p>
                </div>
            `;
            showToast('error', '请求失败', '网络错误，请稍后重试');
        }
    } finally {
        btn.disabled = false;
        btn.textContent = '智能分析';
    }
}

function displayAIAnalysisResult(data) {
    console.log('[AI分析] 开始显示AI分析结果...', data);
    const content = document.getElementById('ai-analysis-content');
    console.log('[AI分析] ai-analysis-content元素:', content);
    if (!content) {
        console.error('[AI分析] 错误: 找不到ai-analysis-content元素!');
        return;
    }
    const result = data.result;
    const timestamp = new Date(data.analysis_time).toLocaleString('zh-CN');
    
    console.log('[AI分析] 分析结果数据:', result);
    
    const direction = result.trading_suggestion?.direction || '观望';
    const directionClass = direction === '做多' ? 'long' : direction === '做空' ? 'short' : 'neutral';
    const directionIcon = direction === '做多' ? '↑' : direction === '做空' ? '↓' : '↔';
    const confidence = result.trading_suggestion?.confidence || 0;
    
    const entryMin = result.trading_suggestion?.entry_range?.min || '--';
    const entryMax = result.trading_suggestion?.entry_range?.max || '--';
    const stopLoss = result.trading_suggestion?.stop_loss || '--';
    const positionSize = result.trading_suggestion?.position_size || '--';
    
    console.log('[AI分析] 生成HTML模板...');
    content.innerHTML = `
        <div class="ai-analysis-result">
            <div class="ai-summary">${result.summary || '暂无总结'}</div>
            
            <div class="ai-suggestion-row">
                <div class="ai-suggestion-direction ${directionClass}">
                    <span style="font-size:18px;font-weight:700;">${directionIcon}</span>
                    <span style="font-weight:600;">${direction}</span>
                </div>
                <div class="ai-confidence">
                    <span>置信度</span>
                    <div class="ai-confidence-bar">
                        <div class="ai-confidence-fill" style="width: ${confidence}%"></div>
                    </div>
                    <span>${confidence}%</span>
                </div>
            </div>
            
            <div class="ai-key-metrics">
                <div class="ai-metric-item">
                    <span class="label">入场区间</span>
                    <span class="value">${entryMin}-${entryMax}</span>
                </div>
                <div class="ai-metric-item">
                    <span class="label">止损位</span>
                    <span class="value down">${stopLoss}</span>
                </div>
                <div class="ai-metric-item">
                    <span class="label">建议仓位</span>
                    <span class="value">${positionSize}</span>
                </div>
                <div class="ai-metric-item">
                    <span class="label">纪律评分</span>
                    <span class="value">${result.discipline_score?.total || '--'}/${result.discipline_score?.max || '11'}</span>
                </div>
            </div>
            
            <div class="ai-timestamp">
                <span>🕐</span> 分析时间: ${timestamp}
                <button class="ai-detail-btn" onclick="showAIDetailModal()" style="margin-left: 8px; background: none; border: 1px solid var(--border-color); padding: 4px 12px; border-radius: 4px; color: var(--cyan); cursor: pointer; font-size: 11px;">
                    查看详情 →
                </button>
            </div>
        </div>
    `;
    
    console.log('[AI分析] HTML已设置到DOM');
    
    // 同步AI分析数据到主面板各个卡片
    syncAIToPanels(result);
    console.log('[AI分析] AI分析结果显示完成');
}

function syncAIToPanels(result) {
    const suggestion = result.trading_suggestion || {};
    const fourDim = result.four_dimensional || {};
    const pivotPoints = result.pivot_points || {};
    const kdjDiag = result.kdj_diagnosis || {};
    const scenarios = result.scenario_plans || {};
    
    // 1. 同步到技术指标卡片
    // 从60min周期提取MACD和KDJ信息
    const macd60 = fourDim['60min']?.macd || {};
    const kdj60 = fourDim['60min']?.kdj || {};
    
    const macdSignalEl = document.getElementById('macd-signal');
    if (macdSignalEl) macdSignalEl.textContent = macd60.trend || '--';
    
    const macdDetailEl = document.getElementById('macd-detail');
    if (macdDetailEl) macdDetailEl.textContent = macd60.position ? `${macd60.position} | ${macd60.histogram || ''}` : '--';
    
    const kdjSignalEl = document.getElementById('kdj-signal');
    if (kdjSignalEl) kdjSignalEl.textContent = kdj60.status || '--';
    
    const kdjDetailEl = document.getElementById('kdj-detail');
    if (kdjDetailEl) kdjDetailEl.textContent = kdj60.signal || '--';
    
    // 3. 同步到关键点位卡片
    if (pivotPoints.r1) {
        const r1El = document.getElementById('resistance-1');
        if (r1El) r1El.textContent = pivotPoints.r1;
    }
    if (pivotPoints.r2) {
        const r2El = document.getElementById('resistance-2');
        if (r2El) r2El.textContent = pivotPoints.r2;
    }
    if (pivotPoints.pp) {
        const ppEl = document.getElementById('pivot-point');
        if (ppEl) ppEl.textContent = pivotPoints.pp;
    }
    if (pivotPoints.s1) {
        const s1El = document.getElementById('support-1');
        if (s1El) s1El.textContent = pivotPoints.s1;
    }
    if (pivotPoints.s2) {
        const s2El = document.getElementById('support-2');
        if (s2El) s2El.textContent = pivotPoints.s2;
    }
    
    // 4. 同步到多周期趋势卡片
    const periodTrendsEl = document.getElementById('period-trends');
    if (periodTrendsEl && Object.keys(fourDim).length > 0) {
        const periodNames = { '60min': '60分钟', '30min': '30分钟', '15min': '15分钟', '5min': '5分钟' };
        const periodOrder = ['60min', '30min', '15min', '5min'];
        
        // 按固定顺序排列周期
        const sortedEntries = Object.entries(fourDim).sort((a, b) => {
            return periodOrder.indexOf(a[0]) - periodOrder.indexOf(b[0]);
        });
        
        periodTrendsEl.innerHTML = sortedEntries.map(([period, data]) => {
            const trend = data.conclusion || data.macd?.trend || 'neutral';
            const trendClass = trend.includes('多') || trend === 'up' ? 'up' : trend.includes('空') || trend === 'down' ? 'down' : 'neutral';
            const trendText = trend.includes('多') ? '偏多' : trend.includes('空') ? '偏空' : '震荡';
            return `<div class="trend-item"><span class="trend-period">${periodNames[period] || period}</span><span class="trend-badge ${trendClass}">${trendText}</span></div>`;
        }).join('');
    }
    
    // 5. 同步到情景预案卡片
    const scenarioPanel = document.getElementById('scenario-panel');
    const scenarioPlansEl = document.getElementById('scenario-plans');
    if (scenarioPanel && scenarioPlansEl && Object.keys(scenarios).length > 0) {
        scenarioPanel.style.display = 'block';
        const scenarioNames = {
            'breakthrough': '突破',
            'consolidation': '震荡',
            'reversal': '反转',
            'news_impact': '消息影响'
        };
        scenarioPlansEl.innerHTML = Object.entries(scenarios).map(([key, data]) => `
            <div class="scenario-item">
                <span class="scenario-name">${scenarioNames[key] || key}</span>
                <span class="scenario-probability">${data.probability || 0}%</span>
                <span class="scenario-action">${data.action || '--'}</span>
            </div>
        `).join('');
    } else if (scenarioPanel) {
        scenarioPanel.style.display = 'none';
    }
}

function showAIDetailModal() {
    if (!currentAIAnalysis) {
        showToast('warning', '提示', '暂无AI分析数据');
        return;
    }
    
    const result = currentAIAnalysis.result;
    const modalBody = document.getElementById('ai-analysis-modal-body');
    
    let fourDimensionalHTML = '';
    const periods = ['60min', '30min', '15min', '5min'];
    const periodNames = { '60min': '60分钟', '30min': '30分钟', '15min': '15分钟', '5min': '5分钟' };
    periods.forEach(period => {
        const data = result.four_dimensional?.[period];
        if (data) {
            fourDimensionalHTML += `
                <tr>
                    <td class="period-cell">${periodNames[period] || period}</td>
                    <td>
                        <div>趋势: ${data.macd?.trend || '--'}</div>
                        <div>位置: ${data.macd?.position || '--'}</div>
                        <div>柱状图: ${data.macd?.histogram || '--'}</div>
                    </td>
                    <td>
                        <div>状态: ${data.volume?.status || '--'}</div>
                        <div>量比: ${data.volume?.ratio || '--'}</div>
                    </td>
                    <td>
                        <div>K: ${data.kdj?.k || '--'} D: ${data.kdj?.d || '--'}</div>
                        <div>信号: ${data.kdj?.signal || '--'}</div>
                        <div>状态: ${data.kdj?.status || '--'}</div>
                    </td>
                    <td>${data.conclusion || '--'}</td>
                </tr>
            `;
        }
    });
    
    let scenariosHTML = '';
    const scenarios = result.scenario_plans || {};
    const scenarioIcons = {
        'breakthrough': 'fa-rocket',
        'consolidation': 'fa-exchange-alt',
        'reversal': 'fa-undo',
        'news_impact': 'fa-newspaper'
    };
    
    Object.entries(scenarios).forEach(([key, scenario]) => {
        scenariosHTML += `
            <div class="scenario-card ${key}">
                <div class="scenario-probability">${scenario.probability || 0}%</div>
                <div class="scenario-action">${scenario.action || '--'}</div>
            </div>
        `;
    });
    
    let redLinesHTML = '';
    if (result.red_lines_check?.violated?.length > 0) {
        result.red_lines_check.violated.forEach(line => {
            redLinesHTML += `<div class="red-line-item"><i class="fas fa-exclamation-circle"></i> ${line}</div>`;
        });
    } else {
        redLinesHTML = '<div class="red-line-item pass"><i class="fas fa-check-circle"></i> 未触碰交易红线</div>';
    }
    
    let disciplineHTML = '';
    const discipline = result.discipline_score?.details || {};
    const disciplineLabels = {
        'trend': '趋势',
        'position': '位置',
        'signal': '信号',
        'risk': '风险',
        'mindset': '心态'
    };
    
    Object.entries(disciplineLabels).forEach(([key, label]) => {
        const isPass = discipline[key];
        disciplineHTML += `
            <div class="discipline-item ${isPass ? 'pass' : 'fail'}">
                <i class="fas ${isPass ? 'fa-check-circle' : 'fa-times-circle'}"></i>
                <span class="discipline-label">${label}</span>
            </div>
        `;
    });
    
    let experiencesHTML = '';
    const experiences = result.experience_lessons || [];
    if (experiences.length > 0) {
        experiences.forEach(exp => {
            experiencesHTML += `<div class="experience-item"><i class="fas fa-lightbulb"></i> ${exp}</div>`;
        });
    } else {
        experiencesHTML = '<div class="experience-item"><i class="fas fa-info-circle"></i> 暂无经验提醒</div>';
    }
    
    modalBody.innerHTML = `
        <div class="ai-modal-section">
            <div class="ai-modal-section-title">
                <i class="fas fa-chart-bar"></i>
                四维联合信号表 (4D-XV)
            </div>
            <table class="four-dimensional-table">
                <thead>
                    <tr>
                        <th>周期</th>
                        <th>MACD(趋势)</th>
                        <th>成交量(资金)</th>
                        <th>KDJ(时机)</th>
                        <th>结论</th>
                    </tr>
                </thead>
                <tbody>
                    ${fourDimensionalHTML || '<tr><td colspan="5">暂无数据</td></tr>'}
                </tbody>
            </table>
        </div>
        
        <div class="ai-modal-section">
            <div class="ai-modal-section-title">
                <i class="fas fa-crosshairs"></i>
                关键点位 (Pivot Point)
            </div>
            <div class="ai-key-metrics">
                <div class="ai-metric-item">
                    <span class="label">R2</span>
                    <span class="value down">${result.pivot_points?.r2 || '--'}</span>
                </div>
                <div class="ai-metric-item">
                    <span class="label">R1</span>
                    <span class="value down">${result.pivot_points?.r1 || '--'}</span>
                </div>
                <div class="ai-metric-item">
                    <span class="label">PP</span>
                    <span class="value" style="color: var(--purple);">${result.pivot_points?.pp || '--'}</span>
                </div>
                <div class="ai-metric-item">
                    <span class="label">S1</span>
                    <span class="value up">${result.pivot_points?.s1 || '--'}</span>
                </div>
                <div class="ai-metric-item">
                    <span class="label">S2</span>
                    <span class="value up">${result.pivot_points?.s2 || '--'}</span>
                </div>
            </div>
        </div>
        
        <div class="ai-modal-section">
            <div class="ai-modal-section-title">
                <i class="fas fa-balance-scale"></i>
                交易红线审查
            </div>
            <div class="red-lines-list">
                ${redLinesHTML}
            </div>
        </div>
        
        <div class="ai-modal-section">
            <div class="ai-modal-section-title">
                <i class="fas fa-check-double"></i>
                11项纪律检查
            </div>
            <div class="discipline-grid">
                ${disciplineHTML}
            </div>
        </div>
        
        <div class="ai-modal-section">
            <div class="ai-modal-section-title">
                <i class="fas fa-project-diagram"></i>
                情景预案
            </div>
            <div class="scenario-cards">
                ${scenariosHTML || '<div class="scenario-card"><div class="scenario-action">暂无情景预案</div></div>'}
            </div>
        </div>
        
        <div class="ai-modal-section">
            <div class="ai-modal-section-title">
                <i class="fas fa-lightbulb"></i>
                经验教训提醒
            </div>
            <div class="ai-experience-list">
                ${experiencesHTML}
            </div>
        </div>
        
        <div class="ai-modal-section">
            <div class="ai-modal-section-title">
                <i class="fas fa-exclamation-triangle"></i>
                风险提示
            </div>
            <div class="ai-experience-list">
                ${(result.risk_warnings || []).map(w => `<div class="experience-item"><i class="fas fa-exclamation-circle"></i> ${w}</div>`).join('')}
            </div>
        </div>
    `;
    
    document.getElementById('ai-analysis-modal').classList.add('active');
}

// ==================== 复盘计划功能 V2 ====================

const RV_API_BASE = '/api/v1/review';
let rvCurrentPlanId = null;
let rvCurrentPlanData = null;

function initReviewPlan() {
    document.getElementById('rv-date-selector').addEventListener('change', function (e) {
        const selectedDate = e.target.value;
        if (selectedDate) {
            rvLoadPlanByDate(selectedDate);
        }
    });

    document.getElementById('rv-btn-generate').addEventListener('click', function () {
        rvHandleGenerate();
    });

    document.getElementById('rv-btn-clear').addEventListener('click', function () {
        rvHandleClear();
    });

    rvSetupSortButtons();

    rvLoadLatestPlan();
}

function rvHandleGenerate() {
    const dateSelector = document.getElementById('rv-date-selector');
    let reviewDate = dateSelector.value;

    if (!reviewDate) {
        reviewDate = new Date().toISOString().split('T')[0];
    }

    rvDoGenerate(reviewDate);
}

function rvDoGenerate(dateStr) {
    rvShowLoading();
    fetch(`${RV_API_BASE}/generate`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ review_date: dateStr })
    })
        .then(res => res.json())
        .then(result => {
            rvHideLoading();
            if (result.success) {
                const s = result.data.summary;
                alert(
                    `复盘与计划生成成功！\n` +
                    `日期: ${s.review_date} ${s.week_day}\n` +
                    `品种数: ${s.symbol_count}\n` +
                    `交易机会: ${s.opportunity_count} 个`
                );
                rvLoadLatestPlan();
            } else {
                alert('生成失败: ' + (result.message || '未知错误'));
            }
        })
        .catch(err => {
            rvHideLoading();
            console.error('生成复盘计划失败:', err);
            alert('生成失败，请稍后重试');
        });
}

function rvHandleClear() {
    if (!confirm('确定要清除所有复盘与交易计划数据吗？此操作不可恢复。')) return;

    fetch(`${RV_API_BASE}/v2/clear`, { method: 'DELETE' })
        .then(res => res.json())
        .then(data => {
            if (data.success) {
                alert('复盘数据已清除');
                document.getElementById('rv-date-selector').value = '';
                rvCurrentPlanId = null;
                rvCurrentPlanData = null;
                rvHideAllSections();
                document.getElementById('rv-empty-state').style.display = 'flex';
            } else {
                alert(data.message || '清除失败');
            }
        })
        .catch(err => {
            console.error('清除数据失败:', err);
            alert('清除失败，请稍后重试');
        });
}

function rvLoadLatestPlan() {
    fetch(`${RV_API_BASE}/v2/plans?limit=1`)
        .then(res => res.json())
        .then(data => {
            if (data.success && data.data && data.data.length > 0) {
                const plan = data.data[0];
                const dateSelector = document.getElementById('rv-date-selector');
                if (dateSelector && plan.review_date) {
                    dateSelector.value = plan.review_date;
                }
                rvLoadAndRender(plan.id);
            } else {
                rvHideAllSections();
                document.getElementById('rv-empty-state').style.display = 'flex';
            }
        })
        .catch(err => {
            console.error('加载最新计划失败:', err);
        });
}

function rvLoadPlanByDate(date) {
    rvShowLoading();
    fetch(`${RV_API_BASE}/v2/plan/by-date/${date}`)
        .then(res => res.json())
        .then(data => {
            rvHideLoading();
            if (data.success && data.data) {
                rvCurrentPlanId = data.data.meta.id;
                rvCurrentPlanData = data.data;
                rvRenderAll(data.data);
            } else {
                rvHideAllSections();
                document.getElementById('rv-empty-state').style.display = 'flex';
            }
        })
        .catch(err => {
            rvHideLoading();
            console.error('按日期加载计划失败:', err);
        });
}

function rvLoadAndRender(planId) {
    rvShowLoading();
    fetch(`${RV_API_BASE}/v2/plan/${planId}`)
        .then(res => res.json())
        .then(result => {
            rvHideLoading();
            if (result.success && result.data) {
                rvCurrentPlanId = planId;
                rvCurrentPlanData = result.data;
                rvRenderAll(result.data);
            } else {
                alert('加载计划详情失败');
            }
        })
        .catch(err => {
            rvHideLoading();
            console.error('加载计划详情失败:', err);
            alert('加载失败，请稍后重试');
        });
}

function rvRenderAll(data) {
    const contentArea = document.getElementById('rv-content-area');
    if (contentArea) contentArea.style.display = '';

    document.getElementById('rv-empty-state').style.display = 'none';

    const { meta, scores, plans, sectors } = data;

    rvRenderHero(meta);
    rvRenderStats(meta, scores);
    rvRenderRisk(meta);
    rvRenderGreenSection(plans, scores);
    rvRenderYellowSection(scores);
    rvRenderRedSection(scores);
    rvRenderRankingTable(scores);
    rvRenderDetails(scores);
    rvRenderSectors(sectors);
}

function rvRenderHero(meta) {
    const el = document.getElementById('rv-hero-section');
    if (!el) return;

    el.innerHTML = `
        <h1>${meta.review_date} <span style="font-size: 18px; opacity: 0.8;">${meta.week_day || ''}</span></h1>
        <div class="rv-hero-subtitle">${meta.data_basis || ''}</div>
        <div class="rv-hero-conclusion">${meta.core_conclusion || ''}</div>
    `;
    el.style.display = '';
}

function rvRenderStats(meta, scores) {
    const el = document.getElementById('rv-stats-grid');
    if (!el) return;

    const top3 = scores.slice(0, 3);
    const top3Text = top3.map(s => `${s.symbol} ${s.name}(${s.composite_score}分)`).join('、');

    el.innerHTML = `
        <div class="rv-stat-card">
            <div class="rv-stat-label">核心结论</div>
            <div class="rv-stat-text">${meta.core_conclusion || '-'}</div>
        </div>
        <div class="rv-stat-card">
            <div class="rv-stat-label">TOP 3 机会</div>
            <div class="rv-stat-value" style="font-size: 14px;">${top3Text || '-'}</div>
        </div>
        <div class="rv-stat-card">
            <div class="rv-stat-label">市场概览</div>
            <div class="rv-stat-text">多头 ${meta.bull_count || 0} | 空头 ${meta.bear_count || 0} | 震荡 ${meta.neutral_count || 0}</div>
        </div>
    `;
    el.style.display = '';
}

function rvRenderRisk(meta) {
    const banner = document.getElementById('rv-risk-banner');
    const list = document.getElementById('rv-risk-list');
    if (!banner || !list) return;

    const warnings = meta.risk_warnings || [];
    if (warnings.length === 0) {
        banner.style.display = 'none';
        return;
    }

    list.innerHTML = warnings.map(w => `<li>${w}</li>`).join('');
    banner.style.display = '';
}

function rvFormatPrice(value, refPrice) {
    if (!value && value !== 0) return '-';
    // 根据参考价格确定小数位数
    let precision = 2;
    if (refPrice >= 10000) precision = 0;
    else if (refPrice >= 1000) precision = 1;
    return Number(value).toFixed(precision);
}

function rvScoreBarColor(score) {
    if (score > 70) return '#34C759';  // --color-down
    if (score > 40) return '#007AFF';  // --color-brand
    if (score > 20) return '#FF9F0A';  // --color-neutral
    return '#FF3B30';                   // --color-up
}

function rvScoreBar(score, label) {
    const color = rvScoreBarColor(score);
    return `
        <div class="rv-score-bar-item">
            <span class="rv-score-bar-label">${label}</span>
            <div class="rv-score-bar-track">
                <div class="rv-score-bar-fill" style="width: ${Math.min(100, score)}%; background: ${color};"></div>
            </div>
            <span class="rv-score-bar-value" style="color: ${color};">${Math.round(score)}</span>
        </div>
    `;
}

function rvDirectionTag(tag) {
    let cls = 'rv-tag-neutral';
    if (tag === '强多' || tag === '偏多') cls = 'rv-tag-bull';
    else if (tag === '强空' || tag === '偏空') cls = 'rv-tag-bear';
    return `<span class="rv-item-tag ${cls}">${tag || '震荡'}</span>`;
}

function rvRenderGreenSection(plans, scores) {
    const section = document.getElementById('rv-green-section');
    const grid = document.getElementById('rv-green-grid');
    if (!section || !grid) return;

    const greenPlans = plans.filter(p => p.category === 'green');
    if (greenPlans.length === 0) {
        section.style.display = 'none';
        return;
    }

    grid.innerHTML = greenPlans.map(p => {
        const score = scores.find(s => s.symbol === p.symbol) || {};
        const dirText = p.direction === 'long' ? '做多' : '做空';
        const dirColor = p.direction === 'long' ? 'var(--color-down)' : 'var(--color-up)';
        const dataDateTag = score.data_date ? `<span class="rv-data-date-tag">${score.data_date}</span>` : '';

        return `
            <div class="rv-opp-card" onclick="rvShowDetail('${p.symbol}','${(p.name || '').replace(/'/g, "\\'")}')" style="cursor:pointer">
                <div class="rv-opp-header">
                    <span class="rv-opp-symbol">${p.symbol} ${p.name}</span>
                    <span class="rv-opp-score">${p.composite_score}分</span>
                </div>
                <div class="rv-opp-info">
                    <div class="rv-opp-info-item"><span class="rv-opp-info-label">方向</span><span style="color: ${dirColor}; font-weight: 600;">${dirText}</span></div>
                    <div class="rv-opp-info-item"><span class="rv-opp-info-label">收盘价</span><span>${score.close_price || '-'} ${dataDateTag}</span></div>
                    <div class="rv-opp-info-item"><span class="rv-opp-info-label">涨跌幅</span><span>${score.change_pct || 0}%</span></div>
                    <div class="rv-opp-info-item"><span class="rv-opp-info-label">量比</span><span>${score.volume_ratio || '-'}</span></div>
                </div>
                <div class="rv-score-bars">
                    ${rvScoreBar(p.amplitude_score || 0, '振幅')}
                    ${rvScoreBar(p.volume_score || 0, '量能')}
                    ${rvScoreBar(p.trend_score || 0, '趋势')}
                    ${rvScoreBar(p.activity_score || 0, '活跃')}
                </div>
                <div class="rv-plan-box">
                    <div class="rv-plan-row"><span>入场区间</span><span>${rvFormatPrice(p.entry_low, score.close_price)} ~ ${rvFormatPrice(p.entry_high, score.close_price)}</span></div>
                    <div class="rv-plan-row"><span>止损位</span><span style="color: var(--color-up);">${rvFormatPrice(p.stop_loss, score.close_price)}</span></div>
                    <div class="rv-plan-row"><span>目标一</span><span style="color: var(--color-down);">${rvFormatPrice(p.target1, score.close_price)}</span></div>
                    <div class="rv-plan-row"><span>目标二</span><span style="color: var(--color-down);">${rvFormatPrice(p.target2, score.close_price)}</span></div>
                    <div class="rv-plan-trigger">触发条件: ${p.trigger || '-'}</div>
                </div>
            </div>
        `;
    }).join('');

    section.style.display = '';
}

function rvRenderYellowSection(scores) {
    const section = document.getElementById('rv-yellow-section');
    const tbody = document.getElementById('rv-yellow-list');
    if (!section || !tbody) return;

    const yellowItems = scores.filter(s => s.category === 'yellow');
    if (yellowItems.length === 0) {
        section.style.display = 'none';
        return;
    }

    tbody.innerHTML = yellowItems.map((s, i) => {
        const changeColor = s.change_pct >= 0 ? 'var(--color-down)' : 'var(--color-up)';
        return `
            <tr onclick="rvShowDetail('${s.symbol}','${(s.name || '').replace(/'/g, "\\'")}')" style="cursor:pointer">
                <td>${i + 1}</td>
                <td><strong>${s.symbol}</strong> ${s.name}</td>
                <td>${s.close_price || '-'}${s.data_date ? '<span class="rv-data-date-tag">' + s.data_date + '</span>' : ''}</td>
                <td style="color: ${changeColor};">${s.change_pct >= 0 ? '+' : ''}${s.change_pct || 0}%</td>
                <td><strong>${s.composite_score}</strong></td>
                <td>${s.amplitude_pct || 0}%</td>
                <td>${s.volume_ratio || '-'}</td>
                <td>${rvDirectionTag(s.direction_tag)}</td>
                <td style="font-size:11px;color:var(--text-tertiary);">${s.data_date || '-'}</td>
            </tr>
        `;
    }).join('');

    section.style.display = '';
}

function rvRenderRedSection(scores) {
    const section = document.getElementById('rv-red-section');
    const tbody = document.getElementById('rv-red-list');
    if (!section || !tbody) return;

    const redItems = scores.filter(s => s.category === 'red');
    if (redItems.length === 0) {
        section.style.display = 'none';
        return;
    }

    tbody.innerHTML = redItems.map((s, i) => {
        const changeColor = s.change_pct >= 0 ? 'var(--color-down)' : 'var(--color-up)';
        return `
            <tr onclick="rvShowDetail('${s.symbol}','${(s.name || '').replace(/'/g, "\\'")}')" style="cursor:pointer">
                <td>${i + 1}</td>
                <td><strong>${s.symbol}</strong> ${s.name}</td>
                <td>${s.close_price || '-'}${s.data_date ? '<span class="rv-data-date-tag">' + s.data_date + '</span>' : ''}</td>
                <td style="color: ${changeColor};">${s.change_pct >= 0 ? '+' : ''}${s.change_pct || 0}%</td>
                <td><strong>${s.composite_score}</strong></td>
                <td>${s.amplitude_pct || 0}%</td>
                <td>${s.volume_ratio || '-'}</td>
                <td>${rvDirectionTag(s.direction_tag)}</td>
                <td style="font-size:11px;color:var(--text-tertiary);">${s.data_date || '-'}</td>
            </tr>
        `;
    }).join('');

    section.style.display = '';
}

let rvCurrentSortField = 'composite_score';
let rvCurrentSortOrder = 'desc';

function rvRenderRankingTable(scores) {
    const section = document.getElementById('rv-table-section');
    const table = document.getElementById('rv-ranking-table');
    if (!section || !table) return;

    if (!scores || scores.length === 0) {
        section.style.display = 'none';
        return;
    }

    // 排序
    const sorted = [...scores].sort((a, b) => {
        let va = a[rvCurrentSortField];
        let vb = b[rvCurrentSortField];

        // 方向排序特殊处理
        if (rvCurrentSortField === 'direction_tag') {
            const dirOrder = { '强多': 1, '偏多': 2, '多头共振': 1, '震荡': 3, '偏空': 4, '强空': 5, '空头共振': 5 };
            va = dirOrder[va] || 3;
            vb = dirOrder[vb] || 3;
        }

        if (va == null) va = -Infinity;
        if (vb == null) vb = -Infinity;

        if (rvCurrentSortOrder === 'asc') return va > vb ? 1 : va < vb ? -1 : 0;
        return va < vb ? 1 : va > vb ? -1 : 0;
    });

    let html = `
        <thead>
            <tr>
                <th>#</th>
                <th>品种</th>
                <th>收盘价</th>
                <th>综合评分</th>
                <th>振幅%</th>
                <th>涨跌幅%</th>
                <th>量比</th>
                <th>趋势分</th>
                <th>方向</th>
                <th>活跃度</th>
                <th>数据日期</th>
            </tr>
        </thead>
        <tbody>
    `;

    sorted.forEach((s, i) => {
        const scoreColor = rvScoreBarColor(s.composite_score);
        const changeColor = s.change_pct >= 0 ? 'var(--color-down)' : 'var(--color-up)';

        html += `
            <tr onclick="rvShowDetail('${s.symbol}','${(s.name || '').replace(/'/g, "\\'")}')" style="cursor:pointer">
                <td>${i + 1}</td>
                <td><strong>${s.symbol}</strong> ${s.name}</td>
                <td>${s.close_price || '-'}${s.data_date ? '<span class="rv-data-date-tag">' + s.data_date + '</span>' : ''}</td>
                <td>
                    <strong>${s.composite_score}</strong>
                    <div class="rv-table-score-bar">
                        <div class="rv-table-score-fill" style="width: ${Math.min(100, s.composite_score)}%; background: ${scoreColor};"></div>
                    </div>
                </td>
                <td>${s.amplitude_pct || 0}</td>
                <td style="color: ${changeColor};">${s.change_pct >= 0 ? '+' : ''}${s.change_pct || 0}</td>
                <td>${s.volume_ratio || '-'}</td>
                <td>${s.trend_score || 0}</td>
                <td>${rvDirectionTag(s.direction_tag)}</td>
                <td>${s.activity_score || 0}</td>
                <td style="font-size:11px;color:var(--text-tertiary);">${s.data_date || '-'}</td>
            </tr>
        `;
    });

    html += '</tbody>';
    table.innerHTML = html;
    section.style.display = '';
}

let rvSortButtonsInitialized = false;

function rvSetupSortButtons() {
    if (rvSortButtonsInitialized) return;
    
    const controls = document.getElementById('rv-sort-controls');
    if (!controls) return;

    controls.addEventListener('click', function (e) {
        const btn = e.target.closest('.rv-sort-btn');
        if (!btn) return;

        const field = btn.dataset.sort;
        const defaultOrder = btn.dataset.order || 'desc';

        // 切换排序方向
        if (rvCurrentSortField === field) {
            rvCurrentSortOrder = rvCurrentSortOrder === 'desc' ? 'asc' : 'desc';
        } else {
            rvCurrentSortField = field;
            rvCurrentSortOrder = defaultOrder;
        }

        // 更新按钮状态
        controls.querySelectorAll('.rv-sort-btn').forEach(b => {
            b.classList.remove('active');
            b.textContent = b.textContent.replace(/ [▲▼]$/, '');
        });
        btn.classList.add('active');
        const arrow = rvCurrentSortOrder === 'desc' ? ' ▼' : ' ▲';
        btn.textContent = btn.textContent + arrow;

        // 重新渲染
        if (rvCurrentPlanData) {
            rvRenderRankingTable(rvCurrentPlanData.scores);
        }
    });
    
    rvSortButtonsInitialized = true;
}

function rvRenderDetails(scores) {
    const section = document.getElementById('rv-details-section');
    const grid = document.getElementById('rv-details-grid');
    if (!section || !grid) return;

    if (!scores || scores.length === 0) {
        section.style.display = 'none';
        return;
    }

    grid.innerHTML = scores.slice(0, 12).map(s => `
        <div class="rv-detail-card">
            <div class="rv-detail-title">${s.symbol} ${s.name}</div>
            <div class="rv-detail-metrics">
                <div class="rv-detail-metric"><span>收盘价</span><span>${s.close_price || '-'}</span></div>
                <div class="rv-detail-metric"><span>涨跌幅</span><span style="color: ${s.change_pct >= 0 ? 'var(--color-down)' : 'var(--color-up)'};">${s.change_pct >= 0 ? '+' : ''}${s.change_pct || 0}%</span></div>
                <div class="rv-detail-metric"><span>振幅</span><span>${s.amplitude_pct || 0}%</span></div>
                <div class="rv-detail-metric"><span>量比</span><span>${s.volume_ratio || '-'}</span></div>
                <div class="rv-detail-metric"><span>60m趋势</span><span>${s.trend_60m || 0}</span></div>
                <div class="rv-detail-metric"><span>15m趋势</span><span>${s.trend_15m || 0}</span></div>
                <div class="rv-detail-metric"><span>5m趋势</span><span>${s.trend_5m || 0}</span></div>
                <div class="rv-detail-metric"><span>综合评分</span><span style="color: ${rvScoreBarColor(s.composite_score)};">${s.composite_score}</span></div>
            </div>
            <div class="rv-pivot-tags">
                <span class="rv-pivot-tag resist">R2: ${rvFormatPrice(s.r2, s.close_price)}</span>
                <span class="rv-pivot-tag resist">R1: ${rvFormatPrice(s.r1, s.close_price)}</span>
                <span class="rv-pivot-tag pivot">P: ${rvFormatPrice(s.pivot, s.close_price)}</span>
                <span class="rv-pivot-tag support">S1: ${rvFormatPrice(s.s1, s.close_price)}</span>
                <span class="rv-pivot-tag support">S2: ${rvFormatPrice(s.s2, s.close_price)}</span>
            </div>
        </div>
    `).join('');

    section.style.display = '';
}

function rvRenderSectors(sectors) {
    const section = document.getElementById('rv-sectors-section');
    const grid = document.getElementById('rv-sectors-grid');
    if (!section || !grid) return;

    if (!sectors || sectors.length === 0) {
        section.style.display = 'none';
        return;
    }

    grid.innerHTML = sectors.map(sec => {
        const heatIcon = sec.heat_level >= 2 ? '🔥' : sec.heat_level === 1 ? '🌡️' : '🧊';
        const dirColor = sec.direction === '多头' ? 'var(--color-down)' : sec.direction === '空头' ? 'var(--color-up)' : 'var(--text-tertiary)';

        return `
            <div class="rv-sector-card">
                <div class="rv-sector-header">
                    <span class="rv-sector-name">${sec.sector_name}</span>
                    <span class="rv-sector-heat">${heatIcon}</span>
                </div>
                <div class="rv-sector-info">
                    均分: <strong>${sec.avg_score}</strong> | 
                    趋势: <span style="color: ${dirColor};">${sec.avg_trend}</span> | 
                    方向: <span style="color: ${dirColor};">${sec.direction}</span>
                </div>
                <div class="rv-sector-info">龙头: ${sec.leader_symbol} (${sec.leader_score}分)</div>
                <div class="rv-sector-members">
                    ${(sec.members || []).map(m => `<span class="rv-sector-member">${m.name} ${m.score}</span>`).join('')}
                </div>
            </div>
        `;
    }).join('');

    section.style.display = '';
}

function rvShowLoading() {
    const el = document.getElementById('rv-loading');
    if (el) el.classList.add('active');
}

function rvHideLoading() {
    const el = document.getElementById('rv-loading');
    if (el) el.classList.remove('active');
}

function rvHideAllSections() {
    const contentArea = document.getElementById('rv-content-area');
    if (contentArea) contentArea.style.display = 'none';

    const sections = ['rv-hero-section', 'rv-stats-grid', 'rv-risk-banner', 'rv-green-section', 'rv-yellow-section', 'rv-red-section', 'rv-table-section', 'rv-details-section', 'rv-sectors-section'];
    sections.forEach(id => {
        const el = document.getElementById(id);
        if (el) el.style.display = 'none';
    });
}

// ==================== 复盘品种详情弹窗 ====================

function rvShowDetail(symbol, name) {
    const scores = rvCurrentPlanData ? rvCurrentPlanData.scores : [];
    const plans = rvCurrentPlanData ? rvCurrentPlanData.plans : [];
    const s = scores.find(x => x.symbol === symbol);
    if (!s) return;

    const plan = plans.find(p => p.symbol === symbol);
    const modal = document.getElementById('rv-detail-modal');
    if (!modal) return;

    document.getElementById('rv-modal-title').textContent = `${symbol} ${name || s.name || ''}`;
    const body = document.getElementById('rv-modal-body');

    // 交易计划部分
    let planHtml = '';
    if (plan) {
        const dirText = plan.direction === 'long' ? '做多' : '做空';
        const dirColor = plan.direction === 'long' ? 'var(--color-down)' : 'var(--color-up)';
        planHtml = `
            <div class="rv-modal-section">
                <div class="rv-modal-section-title">交易计划</div>
                <div class="rv-modal-plan-box">
                    <div class="rv-modal-plan-row"><span class="mp-label">方向</span><span class="mp-val" style="color:${dirColor}">${dirText}</span></div>
                    <div class="rv-modal-plan-row"><span class="mp-label">入场区间</span><span class="mp-val">${rvFormatPrice(plan.entry_low, s.close_price)} ~ ${rvFormatPrice(plan.entry_high, s.close_price)}</span></div>
                    <div class="rv-modal-plan-row"><span class="mp-label">止损位</span><span class="mp-val stop">${rvFormatPrice(plan.stop_loss, s.close_price)}</span></div>
                    <div class="rv-modal-plan-row"><span class="mp-label">目标一</span><span class="mp-val target">${rvFormatPrice(plan.target1, s.close_price)}</span></div>
                    <div class="rv-modal-plan-row"><span class="mp-label">目标二</span><span class="mp-val target">${rvFormatPrice(plan.target2, s.close_price)}</span></div>
                    <div class="rv-modal-plan-row"><span class="mp-label">触发条件</span><span class="mp-val">${plan.trigger || '-'}</span></div>
                </div>
            </div>
        `;
    }

    const changeColor = s.change_pct >= 0 ? 'var(--color-down)' : 'var(--color-up)';

    body.innerHTML = `
        <div class="rv-modal-section">
            <div class="rv-modal-section-title">基本信息</div>
            <div class="rv-modal-metrics-grid">
                <div class="rv-modal-metric"><span class="mm-label">收盘价</span><span class="mm-val">${s.close_price || '-'}${s.data_date ? '<span class="rv-data-date-tag">' + s.data_date + '</span>' : ''}</span></div>
                <div class="rv-modal-metric"><span class="mm-label">涨跌幅</span><span class="mm-val" style="color:${changeColor}">${s.change_pct >= 0 ? '+' : ''}${s.change_pct || 0}%</span></div>
                <div class="rv-modal-metric"><span class="mm-label">振幅</span><span class="mm-val">${s.amplitude_pct || 0}%</span></div>
                <div class="rv-modal-metric"><span class="mm-label">量比</span><span class="mm-val">${s.volume_ratio || '-'}</span></div>
                <div class="rv-modal-metric"><span class="mm-label">综合评分</span><span class="mm-val" style="color:${rvScoreBarColor(s.composite_score)}"><b>${s.composite_score}</b></span></div>
                <div class="rv-modal-metric"><span class="mm-label">排名</span><span class="mm-val">#${s.rank || '-'}</span></div>
            </div>
        </div>
        ${planHtml}
        <div class="rv-modal-section">
            <div class="rv-modal-section-title">评分明细</div>
            <div class="rv-modal-metrics-grid">
                <div class="rv-modal-metric"><span class="mm-label">振幅评分</span><span class="mm-val">${s.amplitude_score || 0}</span></div>
                <div class="rv-modal-metric"><span class="mm-label">量能评分</span><span class="mm-val">${s.volume_score || 0}</span></div>
                <div class="rv-modal-metric"><span class="mm-label">趋势评分</span><span class="mm-val">${s.trend_score || 0}</span></div>
                <div class="rv-modal-metric"><span class="mm-label">活跃度</span><span class="mm-val">${s.activity_score || 0}</span></div>
            </div>
        </div>
        <div class="rv-modal-section">
            <div class="rv-modal-section-title">多周期趋势</div>
            <div class="rv-modal-metrics-grid">
                <div class="rv-modal-metric"><span class="mm-label">60分钟</span><span class="mm-val">${s.trend_60m || 0}</span></div>
                <div class="rv-modal-metric"><span class="mm-label">15分钟</span><span class="mm-val">${s.trend_15m || 0}</span></div>
                <div class="rv-modal-metric"><span class="mm-label">5分钟</span><span class="mm-val">${s.trend_5m || 0}</span></div>
                <div class="rv-modal-metric"><span class="mm-label">方向</span><span class="mm-val">${rvDirectionTag(s.direction_tag)}</span></div>
            </div>
        </div>
        <div class="rv-modal-section">
            <div class="rv-modal-section-title">枢轴点位</div>
            <div class="rv-modal-pivots">
                <span class="rv-pivot-tag resist">R2: ${rvFormatPrice(s.r2, s.close_price)}</span>
                <span class="rv-pivot-tag resist">R1: ${rvFormatPrice(s.r1, s.close_price)}</span>
                <span class="rv-pivot-tag pivot">P: ${rvFormatPrice(s.pivot, s.close_price)}</span>
                <span class="rv-pivot-tag support">S1: ${rvFormatPrice(s.s1, s.close_price)}</span>
                <span class="rv-pivot-tag support">S2: ${rvFormatPrice(s.s2, s.close_price)}</span>
            </div>
        </div>
    `;

    modal.classList.add('show');
}

function rvCloseDetailModal() {
    const modal = document.getElementById('rv-detail-modal');
    if (modal) modal.classList.remove('show');
}

// ==================== 自选品种功能 ====================

function renderWatchedList() {
    const grid = document.getElementById('watched-grid');
    const emptyState = document.getElementById('watched-empty');
    const totalCountEl = document.getElementById('watched-total-count');
    
    if (watchedSymbols.length === 0) {
        grid.style.display = 'none';
        emptyState.style.display = 'flex';
        totalCountEl.textContent = '0 个品种';
        return;
    }
    
    grid.style.display = 'grid';
    emptyState.style.display = 'none';
    totalCountEl.textContent = `${watchedSymbols.length} 个品种`;
    
    const watchedData = allFuturesData.filter(item => watchedSymbols.includes(item.symbol));
    
    grid.innerHTML = watchedData.map(item => {
        const code = item.symbol.replace(/[0-9]/g, '').substring(0, 2);
        const changeIcon = item.change >= 0 ? '↑' : '↓';
        const changeSign = item.change >= 0 ? '+' : '';
        const pctSign = item.changePct >= 0 ? '+' : '';
        
        let actionPillClass = 'watch';
        let actionPillText = '观望';
        if (item.suggestion?.includes('做多') || item.suggestion?.includes('试多')) {
            actionPillClass = 'do-more';
            actionPillText = '做多';
        } else if (item.suggestion?.includes('做空') || item.suggestion?.includes('试空')) {
            actionPillClass = 'do-more';
            actionPillText = '做空';
        }
        
        const priceClass = item.change >= 0 ? 'up' : 'down';
        const changeClass = item.change >= 0 ? 'up' : 'down';
        
        const successRate = item.successRate || 0;
        const trendScore = item.trendScore || 0;
        const successColor = successRate >= 70 ? 'var(--color-down)' : successRate >= 60 ? 'var(--color-neutral)' : 'var(--color-up)';
        const trendColor = trendScore >= 70 ? 'var(--color-down)' : trendScore >= 50 ? 'var(--color-neutral)' : 'var(--color-up)';
        
        const periods = item.periods || {};
        const resistance = item.resistance ? formatNumber(item.resistance) : '--';
        const support = item.support ? formatNumber(item.support) : '--';
        
        const isWatched = true;
        
        return `
        <div class="card" onclick="showDetailView('${item.symbol}')">
            <div class="card-header">
                <div class="card-left">
                    <div class="code-box">${code}</div>
                    <div class="info-group">
                        <div class="name-row">${item.name} <span class="fav-icon active" onclick="toggleFav('${item.symbol}', '${item.name}', event)">★</span></div>
                        <div class="contract-code">${item.symbol}</div>
                    </div>
                </div>
                <div class="price-area">
                    <div class="price ${priceClass}">¥${formatNumber(item.price)}</div>
                    <div class="change ${changeClass}">${changeIcon} ${changeSign}${formatNumber(item.change)} (${pctSign}${item.changePct.toFixed(2)}%)</div>
                </div>
            </div>
            <div class="action-pill ${actionPillClass}">${actionPillText}</div>
            <div class="metrics">
                <div class="metric">
                    <div class="metric-label">成功率 ${successRate}%</div>
                    <div class="bar-bg"><div class="bar-fill" style="width:${successRate}%; background:${successColor};"></div></div>
                </div>
                <div class="metric">
                    <div class="metric-label">趋势评分 ${trendScore}</div>
                    <div class="bar-bg"><div class="bar-fill" style="width:${trendScore}%; background:${trendColor};"></div></div>
                </div>
            </div>
            <div class="timeframes">
                <div class="tf ${periods['5'] === 'up' ? 'active' : ''}">5M</div>
                <div class="tf ${periods['15'] === 'up' ? 'active' : ''}">15M</div>
                <div class="tf ${periods['30'] === 'up' ? 'active' : ''}">30M</div>
                <div class="tf ${periods['60'] === 'up' ? 'active' : ''}">1H</div>
            </div>
            <div class="card-footer">
                <div class="support-resist">
                    <span>压力 <b class="red">${resistance}</b></span>
                    <span>支撑 <b class="green">${support}</b></span>
                </div>
                <a href="#" class="link" onclick="event.stopPropagation(); showDetailView('${item.symbol}'); return false;">详情 →</a>
            </div>
        </div>
    `}).join('');
}

