fix: 跨端消息同步 — 用户消息广播 + 会话隔离 + 去重

后端: handleChatMessage 将用户消息通过 broadcastToUser 广播给同用户所有设备
协议: ClientMessage 新增 ClientMsgID 字段用于跨端去重
前端: 发送消息时携带 client_msg_id,收到回显时跳过本地已添加的消息
前端: handleServerMessage 新增 session_id 过滤,防止不同会话消息串扰

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-26 13:06:44 +08:00
parent 2574f60823
commit 08687bb13d
5 changed files with 62 additions and 2 deletions
@@ -168,8 +168,12 @@ func (h *ChatHandler) handleChatMessage(client *ws.Client, msg ws.ClientMessage)
}
// 缓存用户消息(在 goroutine 前完成,避免竞态)
userMsgID := msg.ClientMsgID
if userMsgID == "" {
userMsgID = "msg_" + generateID()
}
userMsg := ws.Message{
ID: "msg_" + generateID(),
ID: userMsgID,
Role: "user",
Content: msg.Content,
Timestamp: time.Now().UnixMilli(),
@@ -183,6 +187,21 @@ func (h *ChatHandler) handleChatMessage(client *ws.Client, msg ws.ClientMessage)
}
h.hub.CacheMessage(client.UserID, client.SessionID, userMsg)
// 广播用户消息给同用户所有设备(跨端同步)
h.broadcastToUser(client.UserID, ws.ServerMessage{
Type: "response",
MessageID: userMsgID,
Content: msg.Content,
Role: "user",
MsgType: "chat",
SessionID: client.SessionID,
Timestamp: time.Now().UnixMilli(),
ClientInfo: &ws.ClientInfo{
ClientID: client.ClientID,
DeviceName: client.DeviceName,
},
})
// 在 goroutine 中进行 AI-Core 调用和流式发送,避免阻塞 ReadPump
go h.streamResponse(client, mode, reqBody, msg.Content)
}