perf(chat): 优化后台客服会话查询与状态

This commit is contained in:
yml2213
2026-08-25 15:53:10 +08:00
parent 87327fbd91
commit 417f7398e4
14 changed files with 461 additions and 141 deletions
+39 -13
View File
@@ -40,12 +40,15 @@ func (r *Repository) Messages(ctx context.Context, principal Principal, conversa
offset := (page - 1) * pageSize
var rows []model.ChatMessage
if err := query.Order("id ASC").
if err := query.Order("id DESC").
Offset(offset).
Limit(pageSize).
Find(&rows).Error; err != nil {
return nil, err
}
for left, right := 0, len(rows)-1; left < right; left, right = left+1, right-1 {
rows[left], rows[right] = rows[right], rows[left]
}
items, err := r.toMessageDTOs(ctx, principal, rows)
if err != nil {
return nil, err
@@ -166,21 +169,44 @@ func (r *Repository) MarkRead(ctx context.Context, principal Principal, conversa
now := time.Now()
updated := false
err := r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
// 管理员可以不是 participant,直接返回成功
if principal.Type == "admin" {
// 尝试查找 participant 记录,如果有就更新
var participant model.ChatParticipant
err := tx.Where("conversation_id = ? AND participant_type = ? AND participant_id = ?",
conversationID, principal.Type, principal.ID).First(&participant).Error
if err == nil {
// 有 participant 记录,更新已读时间
updated = true
return tx.Model(&participant).Update("last_read_at", now).Error
} else if errors.Is(err, gorm.ErrRecordNotFound) {
// 没有 participant 记录,直接返回成功(管理员无需记录已读)
var conversation model.ChatConversation
if err := tx.Select("id", "last_message_id").First(&conversation, conversationID).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return ErrConversationNotFound
}
return err
}
lastMessageID := uint64(0)
if conversation.LastMessageID != nil {
lastMessageID = *conversation.LastMessageID
}
var existing model.ChatAdminConversationState
err := tx.Where("conversation_id = ? AND admin_user_id = ?", conversationID, principal.ID).
First(&existing).Error
if err == nil && existing.LastReadMessageID >= lastMessageID {
return nil
}
return err
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return err
}
state := model.ChatAdminConversationState{
ConversationID: conversationID,
AdminUserID: principal.ID,
LastReadMessageID: lastMessageID,
LastReadAt: &now,
}
if err := tx.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "conversation_id"}, {Name: "admin_user_id"}},
DoUpdates: clause.Assignments(map[string]interface{}{
"last_read_message_id": lastMessageID,
"last_read_at": now,
}),
}).Create(&state).Error; err != nil {
return err
}
updated = true
return nil
}
// 普通用户必须是 participant