bujinyuan
310ea03ce1
fix(im): 修复发送方消息一直卡在"发送中"圆圈、下方不显示已读/未读的 Bug
现象
----
在单聊里发送新消息后,本人气泡左侧一直显示 loop 圆圈(_sending=true),
气泡下方看不到"已读 / 未读"标签;但对端能正常收到消息。刷新页面、
走 fetchHistory 之后才能恢复正常显示。
根因
----
1. services/websocket.js 的 _onMessage:一旦发现 event 以 ".ack" 结尾,
就走 _handleAck(seq→pendingAcks) 处理完后 **直接 return**,不再 _emit。
这样通过 on('im.message.send.ack') / on('im.message.read.ack')
订阅 ACK 的 listener(chat store 的 _onSendACK / _onReadACK)
**永远收不到回调**,导致 _sending 标记一直没被清、id 没被合入,
模板里 getReadLabel() 因为 !msg.id / _sending=true 返回空字符串。
2. store/chat.js 的 _appendMessage:按 client_msg_id 命中旧临时消息时,
只是 isDup=true 直接 return,把服务端权威字段(包括 id)丢弃了,
没有形成有效的兜底路径。
修复
----
- websocket.js: .ack 报文在 _handleAck 之后 **继续走 _emit**,让 Promise
通路(sendWithAck → pendingAcks)与订阅通路(on(...ack))并行分发,
互不冲突。这是真正解决"卡圈"的主修复。
- chat.js _appendMessage: 把 dedup 改成 "就地合并" 语义:
* 同 id 命中 → 真重复丢弃(不回退)
* 同 client_msg_id 命中本地 _sending 临时消息 → 用服务端字段
覆盖 id/created_at/..., 同时清 _sending/_failed
* 其余情况才 push 新条
作为广播帧先于 ACK 到达时的二级兜底,也保证后续再有 ACK/广播
重复到达不会产生重复气泡。
影响面
------
- 单聊/群聊 发送消息后"已读 / 未读 / N人已读"标签恢复实时显示
- im.message.read.ack(对方读到某条)也能正常驱动 readStatusMap 更新
- meeting 等模块的 sendWithAck() 不受影响(走的是 pendingAcks Promise
通路,本次只是在此之后多了一个 _emit 分发,对业务无副作用)
Made-with: Cursor
2026-04-22 17:05:31 +08:00
..
2026-04-22 17:05:31 +08:00
2026-02-27 14:39:03 +08:00
2026-03-02 11:31:24 +08:00
2026-02-27 14:39:03 +08:00
2026-04-22 11:22:49 +08:00
2026-04-22 11:22:49 +08:00
2026-02-27 14:39:03 +08:00
2026-03-13 16:34:28 +08:00