From a1e79f764d42bc84245cecba96e3f9ba48c60951 Mon Sep 17 00:00:00 2001 From: ylytdeng Date: Sun, 17 May 2026 18:24:45 +0800 Subject: [PATCH] =?UTF-8?q?fix(monitor=5Fweb):=20=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E6=8C=89=20timestamp=20=E6=8E=92=E5=BA=8F=E6=8F=92=E5=85=A5,?= =?UTF-8?q?=E4=B8=8D=E5=86=8D=E6=8C=89=E5=88=B0=E8=BE=BE=E9=A1=BA=E5=BA=8F?= =?UTF-8?q?=E5=80=92=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 痛点 用户截图显示消息列表完全乱序: 18:13:54 (top) 18:21:59 18:19:46 18:21:51 (bottom) 无法按时间阅读。 ## 根因 addMsg 行 2216: M.insertBefore(d, M.firstChild); 每条新 msg 永远插最前面, **完全按到达顺序倒序**: - SSE 推送的实时消息 (timestamp 大) 跟 hidden 补抓的旧消息 (timestamp 小) 按到达顺序穿插 - /api/history 初始化时按 ASC 顺序 forEach addMsg 也是这种倒序行为 - 结果显示顺序跟 timestamp 没有任何关系 ## 修复 按 timestamp 找正确插入位置 (降序: 大 ts 在顶, 符合"最新在上"日志流惯例): d.dataset.ts = m.timestamp || 0; // 遍历现有 children, 找第一个 ts 比新消息小的位置插入 for(let i=0; i existingTs){ M.insertBefore(d, kids[i]); inserted = true; break; } } if(!inserted) M.appendChild(d); // 比所有都早, 放最底 O(n) 但常见情况 (新消息最大 ts) O(1) 命中。200 条上限 fast enough。 ## 实测 修复前: 18:13:54 / 18:21:59 / 18:19:46 / 18:21:51 ← 乱 修复后预期 (降序): 18:21:59 / 18:21:51 / 18:19:46 / 18:13:54 ← 最新在顶 测试 185/185 通过 (改动只动 addMsg 排序逻辑)。 --- monitor_web.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/monitor_web.py b/monitor_web.py index 3d8eb2c..5b04de7 100644 --- a/monitor_web.py +++ b/monitor_web.py @@ -2204,6 +2204,7 @@ function addMsg(m, animate){ let contentHtml = renderContent(m); const dk=m.timestamp+'|'+(m.username||m.chat); + d.dataset.ts = m.timestamp || 0; // 用于按 timestamp 排序定位 d.innerHTML=`
${m.time}${esc(m.chat)}${sn}
${m.type_icon} ${m.type}${ur}
${contentHtml}
`; // 通知匹配检查 @@ -2213,7 +2214,21 @@ function addMsg(m, animate){ setTimeout(()=>d.classList.remove('notify-hl'), 10000); } - M.insertBefore(d, M.firstChild); + // 按 timestamp 找正确插入位置 (降序: 大 ts 在顶, 小 ts 在底) + // 之前的 bug: insertBefore(d, M.firstChild) 永远插最前面, + // 导致 SSE 实时消息 + hidden 路径补抓的旧消息混在一起时顺序乱。 + const ts = +d.dataset.ts; + const kids = M.children; + let inserted = false; + for(let i=0; i existingTs){ + M.insertBefore(d, kids[i]); + inserted = true; + break; + } + } + if(!inserted) M.appendChild(d); // 比所有现有都早, 放最底 if(animate){ setTimeout(()=>d.classList.remove('hl'), 3000);