@@ -114,7 +117,12 @@ 金融 -
+
+ +
+
@@ -165,10 +174,16 @@
- +
+ + +
diff --git a/app/static/futures_analysis.js b/app/static/futures_analysis.js index 877740b..c0a6db5 100644 --- a/app/static/futures_analysis.js +++ b/app/static/futures_analysis.js @@ -70,6 +70,16 @@ function initEventListeners() { } }); + // 刷新全部按钮 + document.getElementById('refresh-all-btn').addEventListener('click', refreshAllSymbols); + + // 详情页刷新按钮 + document.getElementById('refresh-symbol-btn').addEventListener('click', function() { + if (currentSymbol) { + refreshSingleSymbol(currentSymbol); + } + }); + const savedTheme = localStorage.getItem('futures-theme'); if (savedTheme === 'dark') { document.body.classList.remove('theme-minimal'); @@ -321,6 +331,9 @@ function renderFuturesGrid(data) { 支撑 ${formatNumber(item.support)}
+ @@ -925,3 +938,169 @@ function calcEMA(data, period) { 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 = ` +
+
+
${title}
+
${message}
+
+ `; + + 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' }); + const data = await response.json(); + + if (data.success) { + pollRefreshStatus(); + } else { + showToast('error', '刷新失败', data.message || '请稍后重试'); + resetRefreshButton(btn); + } + } catch (error) { + console.error('刷新全部失败:', 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 { + btn.innerHTML = `刷新中 ${status.progress}/${status.total}`; + setTimeout(pollRefreshStatus, 2000); + } + } + } catch (error) { + console.error('获取刷新状态失败:', error); + resetRefreshButton(btn); + } +} + +function resetRefreshButton(btn) { + btn.disabled = false; + btn.classList.remove('spinning'); + btn.innerHTML = '刷新全部'; + 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 = ''; + + showToast('info', '检查数据', `正在检查 ${symbol} 数据新鲜度...`); + + try { + const response = await fetch(`${API_BASE}/refresh/${symbol}`, { method: 'POST' }); + const data = await response.json(); + + if (data.success) { + if (data.refreshed) { + btn.innerHTML = ''; + + await loadFuturesDetail(symbol); + await loadKlineData(symbol, currentPeriod); + await loadFuturesList(); + + showToast('success', '数据已更新', `${symbol} 最新数据已同步`); + } else { + btn.innerHTML = ''; + showToast('success', '数据新鲜', `${symbol} 数据仍在有效期内,无需刷新`); + } + + setTimeout(() => { + btn.disabled = false; + btn.innerHTML = originalContent; + }, 1000); + } else { + showToast('error', '刷新失败', data.message || '请稍后重试'); + btn.disabled = false; + btn.innerHTML = originalContent; + } + } catch (error) { + console.error('刷新失败:', error); + showToast('error', '刷新失败', '网络错误,请稍后重试'); + btn.disabled = false; + btn.innerHTML = originalContent; + } +} diff --git a/data/buffer.db b/data/buffer.db index b562d48..76db0f3 100644 Binary files a/data/buffer.db and b/data/buffer.db differ