perf(chat): 优化后台客服会话查询与状态
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user