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