fix(monitor_web): 消息按 timestamp 排序插入,不再按到达顺序倒序
## 痛点
用户截图显示消息列表完全乱序:
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<kids.length; i++){
const existingTs = +(kids[i].dataset.ts || 0);
if(ts > 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 排序逻辑)。
This commit is contained in:
@@ -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=`<div class="msg-header"><span class="msg-time">${m.time}</span><span class="${cc}">${esc(m.chat)}</span>${sn}<div class="msg-r"><span class="msg-type">${m.type_icon} ${m.type}</span>${ur}</div></div><div class="msg-content" data-key="${dk}">${contentHtml}</div>`;
|
||||
|
||||
// 通知匹配检查
|
||||
@@ -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<kids.length; i++){
|
||||
const existingTs = +(kids[i].dataset.ts || 0);
|
||||
if(ts > existingTs){
|
||||
M.insertBefore(d, kids[i]);
|
||||
inserted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!inserted) M.appendChild(d); // 比所有现有都早, 放最底
|
||||
|
||||
if(animate){
|
||||
setTimeout(()=>d.classList.remove('hl'), 3000);
|
||||
|
||||
Reference in New Issue
Block a user