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
+23 -4
View File
@@ -25,6 +25,7 @@ type conversationRow struct {
Title string
Status string
Role string
AdminRemark string
LastMessageID *uint64
LastMessagePreview string
LastMessageAt *time.Time
@@ -44,6 +45,7 @@ func (r *Repository) conversationQuery(ctx context.Context, principal Principal)
SELECT COUNT(1)
FROM chat_messages AS cm
WHERE cm.conversation_id = c.id
AND cm.sender_type <> 'system'
AND NOT (cm.sender_type = ? AND cm.sender_id = ?)
AND (cp.last_read_at IS NULL OR cm.created_at > cp.last_read_at)
) AS unread_count`, principal.Type, principal.ID).
@@ -59,6 +61,7 @@ func (r *Repository) CountUnreadMessages(ctx context.Context, principal Principa
Where("cp.participant_type = ? AND cp.participant_id = ?", principal.Type, principal.ID).
Where("c.status = ?", "active").
Where("NOT (cm.sender_type = ? AND cm.sender_id = ?)", principal.Type, principal.ID).
Where("cm.sender_type <> ?", "system").
Where("(cp.last_read_at IS NULL OR cm.created_at > cp.last_read_at)").
Count(&total).Error
return total, err
@@ -81,15 +84,29 @@ func (r *Repository) findParticipant(tx *gorm.DB, principal Principal, conversat
return &participant, nil
}
func (r *Repository) participants(ctx context.Context, conversationID uint64) ([]ParticipantDTO, error) {
grouped, err := r.participantsForConversations(ctx, []uint64{conversationID})
if err != nil {
return nil, err
}
return grouped[conversationID], nil
}
func (r *Repository) participantsForConversations(ctx context.Context, conversationIDs []uint64) (map[uint64][]ParticipantDTO, error) {
result := make(map[uint64][]ParticipantDTO, len(conversationIDs))
if len(conversationIDs) == 0 {
return result, nil
}
var rows []model.ChatParticipant
if err := r.db.WithContext(ctx).Where("conversation_id = ?", conversationID).Order("id ASC").Find(&rows).Error; err != nil {
if err := r.db.WithContext(ctx).
Where("conversation_id IN ?", uniqueIDs(conversationIDs)).
Order("conversation_id ASC, id ASC").
Find(&rows).Error; err != nil {
return nil, err
}
userNames, userAvatars, adminNames, err := r.participantNames(ctx, rows)
if err != nil {
return nil, err
}
items := make([]ParticipantDTO, 0, len(rows))
for _, row := range rows {
name := "系统"
avatar := ""
@@ -100,19 +117,20 @@ func (r *Repository) participants(ctx context.Context, conversationID uint64) ([
if row.ParticipantType == "admin" {
name = adminNames[row.ParticipantID]
}
items = append(items, ParticipantDTO{
result[row.ConversationID] = append(result[row.ConversationID], ParticipantDTO{
ID: row.ID,
ConversationID: row.ConversationID,
ParticipantType: row.ParticipantType,
ParticipantID: row.ParticipantID,
Role: row.Role,
Remark: row.Remark,
DisplayName: fallbackName(row.ParticipantType, row.ParticipantID, name),
AvatarURL: avatar,
LastReadAt: row.LastReadAt,
JoinedAt: row.JoinedAt,
})
}
return items, nil
return result, nil
}
func (r *Repository) toMessageDTOs(ctx context.Context, principal Principal, rows []model.ChatMessage) ([]MessageDTO, error) {
userIDs := make([]uint64, 0)
@@ -305,6 +323,7 @@ func (row conversationRow) toDTO(participants []ParticipantDTO) ConversationDTO
Title: row.Title,
Status: row.Status,
Role: row.Role,
AdminRemark: row.AdminRemark,
Participants: participants,
LastMessageID: row.LastMessageID,
LastMessagePreview: row.LastMessagePreview,