/** * @file monitor.js * @brief 实时监控页面 — WebSocket 流量环形缓冲区 */ Router.register('#monitor', function(c) { c.innerHTML = '
' + '
' + I18n.t('mon.title') + '' + '
' + '' + '' + '
' + '
' + '
'; MonitorRing.render(); }); var MonitorRing = { ring: [], max: 500, paused: false, push: function(dir, msg) { if (this.paused) return; var ts = new Date().toLocaleTimeString(); this.ring.push({ dir: dir, ts: ts, msg: typeof msg === 'string' ? msg : JSON.stringify(msg).substring(0, 200) }); if (this.ring.length > this.max) { this.ring.shift(); } this.render(); }, clear: function() { this.ring = []; this.render(); }, togglePause: function() { this.paused = !this.paused; var btn = document.getElementById('mon-pause-btn'); if (btn) { btn.textContent = this.paused ? I18n.t('mon.resume') : I18n.t('mon.pause'); } }, render: function() { var stats = document.getElementById('mon-stats'); var list = document.getElementById('mon-list'); if (!stats || !list) return; var up = 0, down = 0; this.ring.forEach(function(r) { r.dir === '\u2191' ? up++ : down++; }); stats.innerHTML = '
' + (up + down) + '
' + I18n.t('mon.total') + '
' + '
' + up + '
' + I18n.t('mon.sent') + ' \u2191
' + '
' + down + '
' + I18n.t('mon.recv') + ' \u2193
'; list.innerHTML = this.ring.map(function(r) { return '
' + '' + r.dir + '' + '' + r.ts + '' + '' + r.msg + '
'; }).reverse().join(''); list.scrollTop = list.scrollHeight; } };