diff --git a/static/index.html b/static/index.html index db7ce3fa..b0bb4a83 100644 --- a/static/index.html +++ b/static/index.html @@ -3077,16 +3077,40 @@ function toggleAlertFloat(ev) { } function renderAlerts(alerts) { + // 首次加载初始化:把当前已有异常标记为"已展开",避免打开页面就弹旧异常 + if (!localStorage.getItem('alertsInitialized')) { + try { + const initKeys = (Array.isArray(alerts)?alerts:[]).map(a => (a.ts||0)+'_'+(a.source||'')+'_'+(a.code||'')); + localStorage.setItem('expandedAlertKeys', JSON.stringify(initKeys)); + localStorage.setItem('alertsInitialized', '1'); + } catch(e) {} + } const el = document.getElementById('alertFloat'); const body = document.getElementById('alertBody'); const countEl = document.getElementById('alertCount'); const list = Array.isArray(alerts) ? alerts : []; // 只显示 error/critical/warning(info 不打扰) const shown = list.filter(a => a.level !== 'info'); - const keys = shown.map(a => a.ts + '_' + a.source + '_' + a.code).join('|'); - if (!shown.length) { - // 无异常 → 整个浮窗隐藏(2026-08-13 老莫反馈:无异常不应显示红底感叹号) + // ── 24小时过滤:只有24小时内的异常才算"最新异常",有资格右上角显示 ── + const nowSec = Date.now() / 1000; + const fresh = shown.filter(a => (a.ts || 0) > nowSec - 86400); + + // 已展开过的异常 keys(localStorage 持久化,跨会话记住,旧异常不再触发展开) + let expandedKeys = new Set(); + try { expandedKeys = new Set(JSON.parse(localStorage.getItem('expandedAlertKeys') || '[]')); } catch(e) {} + // 清理过期的已展开记录(24小时前的清掉,避免无限增长) + const expandedArr = [...expandedKeys]; + + const freshKeys = fresh.map(a => (a.ts||0) + '_' + (a.source||'') + '_' + (a.code||'')); + const freshKeySet = new Set(freshKeys); + + // 找出"新异常":在24小时内,且从未被展开过 + const newKeys = freshKeys.filter(k => !expandedKeys.has(k)); + const hasNew = newKeys.length > 0; + + if (!fresh.length) { + // 无最新异常 → 隐藏浮窗 el.style.display = 'none'; el.classList.add('collapsed'); body.style.display = 'none'; @@ -3096,29 +3120,27 @@ function renderAlerts(alerts) { return; } - // 有异常 → 显示浮窗 + // 有最新异常 → 显示浮窗 el.style.display = ''; - - // 新异常 → 自动展开几秒后折叠 - const isNew = keys !== lastAlertKeys; - lastAlertKeys = keys; - countEl.style.display = 'inline-block'; - countEl.textContent = shown.length; + countEl.textContent = fresh.length; const levelIcon = { critical: '🔴', error: '🟠', warning: '🟡' }; - body.innerHTML = shown.map(a => + body.innerHTML = fresh.map(a => `