diff --git a/app/templates/dashboard.html b/app/templates/dashboard.html index 6babdb9..ccee60d 100644 --- a/app/templates/dashboard.html +++ b/app/templates/dashboard.html @@ -1,7 +1,10 @@ {% extends "base.html" %} {% block title %}总览 · {{ app_name }}{% endblock %} {% block content %} -

总览 · 秒级推送

+

+ 总览 + 连接中… +

账户
{{ accounts|length }}
@@ -78,6 +81,29 @@ var liveUrl = {{ url_for('dashboard_live')|tojson }}; var detailBase = {{ url_for('record_detail', tid=0)|tojson }}.replace(/0$/, ''); var hint = document.getElementById('live-hint'); + var mode = 'connecting'; + var pollStarted = false; + var msgCount = 0; + + function pad(n) { return n < 10 ? '0' + n : String(n); } + function nowClock() { + var d = new Date(); + return pad(d.getHours()) + ':' + pad(d.getMinutes()) + ':' + pad(d.getSeconds()); + } + + function setHint(text, kind) { + if (!hint) return; + hint.textContent = text; + hint.className = 'tag' + (kind ? ' ' + kind : ''); + } + + function markUpdated() { + if (mode === 'sse') { + setHint('SSE · 更新于 ' + nowClock(), 'green'); + } else if (mode === 'poll') { + setHint('轮询 1s · 更新于 ' + nowClock(), ''); + } + } function esc(s) { return String(s == null ? '' : s) @@ -136,30 +162,46 @@ document.getElementById('stat-online').textContent = String(data.online_count); renderMachines(data.online_machines || []); renderTrades(data.trades || []); + markUpdated(); } - function startPollFallback() { - if (hint) hint.textContent = '· 轮询 1s(SSE 不可用)'; + function startPollFallback(reason) { + if (pollStarted) return; + pollStarted = true; + mode = 'poll'; + setHint(reason || '轮询 1s(SSE 不可用)', ''); setInterval(function () { fetch(liveUrl, { credentials: 'same-origin' }) .then(function (r) { return r.json(); }) .then(apply) - .catch(function () {}); + .catch(function () { setHint('轮询失败 · 重试中', 'red'); }); }, 1000); } if (typeof EventSource === 'undefined') { - startPollFallback(); + startPollFallback('轮询 1s(浏览器不支持 SSE)'); return; } + setHint('SSE 连接中…', ''); var es = new EventSource(streamUrl); + es.onopen = function () { + mode = 'sse'; + setHint('SSE 已连接', 'green'); + }; es.onmessage = function (ev) { + msgCount += 1; + mode = 'sse'; try { apply(JSON.parse(ev.data)); } catch (e) {} }; es.onerror = function () { - es.close(); - startPollFallback(); + // 已收到过数据则让浏览器自行重连;长时间无数据再降级轮询 + if (msgCount === 0 || es.readyState === EventSource.CLOSED) { + try { es.close(); } catch (e) {} + startPollFallback('轮询 1s(SSE 断开)'); + } else { + setHint('SSE 重连中…', ''); + } }; })();