diff --git a/static/index.html b/static/index.html
index affd517c..9e01d814 100644
--- a/static/index.html
+++ b/static/index.html
@@ -214,7 +214,7 @@ document.addEventListener('DOMContentLoaded', function() {
if (he) delete he.dataset.rendered;
}
if (name === 'health' && !healthRefreshInterval) {
- healthRefreshInterval = setInterval(refreshHealth, 10000);
+ if (!healthRefreshInterval) healthRefreshInterval = setInterval(refreshHealth, 10000);
}
document.querySelectorAll('.tab-content').forEach(el => el.classList.add('hidden'));
document.querySelectorAll('.tab-btn').forEach(el => el.classList.remove('active'));
@@ -616,9 +616,12 @@ function renderMarket() {
// ── Evaluation Tab ──
let evalTimer = null;
+let evalBusy = false;
function renderEvaluation() {
+ if (evalBusy) return;
+ evalBusy = true;
const el = document.getElementById('tab-evaluation');
- if (evalTimer) clearInterval(evalTimer);
+ if (evalTimer) { clearInterval(evalTimer); evalTimer = null; }
fetchJSON('/api/tracking').then(data => {
const tracks = data.tracks || [];
const stats = data.stats || {};
@@ -709,8 +712,9 @@ function renderEvaluation() {
}).join('')}
`;
- evalTimer = setInterval(renderEvaluation, 30000);
- });
+ if (!evalTimer) evalTimer = setInterval(renderEvaluation, 30000);
+ evalBusy = false;
+ }).catch(() => { evalBusy = false; });
}
function triggerEval() {
const btn = document.querySelector('#tab-evaluation button');
@@ -797,8 +801,9 @@ async function openStock(code) {
const chartCanvas = document.getElementById('modalChart');
chartCanvas.innerHTML = '';
const ctx = document.getElementById('stockChart').getContext('2d');
+ if (window._stockChart) { try { window._stockChart.destroy(); } catch(e) {} window._stockChart = null; }
if (stockData.price_history && stockData.price_history.length > 1) {
- new Chart(ctx, {
+ window._stockChart = new Chart(ctx, {
type: 'line',
data: {
labels: stockData.price_history.map(p => p.date),