新增消息已读状态
复用 chat_participants.last_read_at 推导已读,无需新表/迁移。 - 后端:MessageDTO 增加 is_read,toMessageDTOs 按「全部已读」语义计算 (所有其他参与者均已读才算已读,1对1 即对方已读);MarkRead 成功后 推送 conversation_read 事件(含 reader 与 read_at),NotifyConversation 与 NotifyAllAdmins 双通道通知,使发送方/客服实时刷新已读 - 前端:ChatMessage 增加 is_read,ChatView/AdminChatsView/MobileChatView 在自己的消息下渲染「已读/未读」;收到 conversation_read 且本端仍有 未获回执的自己消息时才重载,避免无谓请求 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
cc1c0d33de
commit
e75a39b03a
@@ -160,7 +160,9 @@ func (r *Repository) SendMessage(ctx context.Context, principal Principal, conve
|
||||
return &items[0], nil
|
||||
}
|
||||
func (r *Repository) MarkRead(ctx context.Context, principal Principal, conversationID uint64) error {
|
||||
return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
now := time.Now()
|
||||
updated := false
|
||||
err := r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
// 管理员可以不是 participant,直接返回成功
|
||||
if principal.Type == "admin" {
|
||||
// 尝试查找 participant 记录,如果有就更新
|
||||
@@ -169,7 +171,7 @@ func (r *Repository) MarkRead(ctx context.Context, principal Principal, conversa
|
||||
conversationID, principal.Type, principal.ID).First(&participant).Error
|
||||
if err == nil {
|
||||
// 有 participant 记录,更新已读时间
|
||||
now := time.Now()
|
||||
updated = true
|
||||
return tx.Model(&participant).Update("last_read_at", now).Error
|
||||
} else if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// 没有 participant 记录,直接返回成功(管理员无需记录已读)
|
||||
@@ -183,7 +185,24 @@ func (r *Repository) MarkRead(ctx context.Context, principal Principal, conversa
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
now := time.Now()
|
||||
updated = true
|
||||
return tx.Model(participant).Update("last_read_at", now).Error
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 已读时间发生变化时,通知会话内其他参与者刷新「已读」状态。
|
||||
if updated && r.hub != nil {
|
||||
event := &chathub.ChatEvent{
|
||||
Type: "conversation_read",
|
||||
ConversationID: conversationID,
|
||||
ReaderType: principal.Type,
|
||||
ReaderID: principal.ID,
|
||||
ReadAt: now.Format(time.RFC3339),
|
||||
}
|
||||
r.hub.NotifyConversation(conversationID, event)
|
||||
// 同时广播给所有在线客服,覆盖未分配会话中非参与者客服的「已读」刷新。
|
||||
r.hub.NotifyAllAdmins(event)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user