fix(chat): 撤回消息时回退未读角标,避免当成新消息

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-17 04:55:17 +08:00
parent c9d27b2b0c
commit d1155cbd64
4 changed files with 58 additions and 16 deletions

View File

@@ -918,30 +918,31 @@ func (s *ChatService) ListMessages(userID, roomID, beforeID uint, size int, over
return msgs, hasMore, nil
}
// RecallMessage 撤回消息:群主可撤自己的;监管者可撤任意;标记 RecalledAt,正文保留供审计
func (s *ChatService) RecallMessage(operatorID, roomID, messageID uint, oversee bool) (*model.ChatMessage, error) {
// RecallMessage 撤回消息:群主可撤自己的;监管者可撤任意;标记 RecalledAt,正文保留供审计。
// newly=true 表示本次刚打上撤回标记(已撤回的幂等调用为 false,避免重复回退角标)。
func (s *ChatService) RecallMessage(operatorID, roomID, messageID uint, oversee bool) (*model.ChatMessage, bool, error) {
if _, err := s.getRoom(roomID); err != nil {
return nil, err
return nil, false, err
}
var msg model.ChatMessage
if err := s.db.Where("id = ? AND room_id = ?", messageID, roomID).First(&msg).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, ErrChatMsgNotFound
return nil, false, ErrChatMsgNotFound
}
return nil, err
return nil, false, err
}
if msg.RecalledAt != nil {
return &msg, nil // 幂等
return &msg, false, nil // 幂等
}
if !oversee {
m, err := s.membership(s.db, roomID, operatorID)
if err != nil {
return nil, err
return nil, false, err
}
// 群主/成员仅可撤回自己的消息;监管者可撤任意
if msg.SenderID != operatorID {
_ = m // 成员校验已通过
return nil, ErrChatRecallDenied
return nil, false, ErrChatRecallDenied
}
}
now := time.Now()
@@ -950,12 +951,12 @@ func (s *ChatService) RecallMessage(operatorID, roomID, messageID uint, oversee
"recalled_at": now,
"recalled_by": operatorID,
}).Error; err != nil {
return nil, err
return nil, false, err
}
msg.RecalledAt = &now
msg.RecalledBy = operatorID
_ = s.db.Preload("Sender").Preload("Recaller").First(&msg, msg.ID)
return &msg, nil
return &msg, true, nil
}
// AdminChatParticipant 管理端私聊双方摘要