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 %}
-
@@ -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 重连中…', '');
+ }
};
})();