perf(chat): 分页客服会话并拆分统计查询

This commit is contained in:
yml2213
2026-08-25 19:21:38 +08:00
parent d95b95211c
commit 52dcb18c96
16 changed files with 264 additions and 87 deletions
+28 -14
View File
@@ -221,7 +221,7 @@ func (r *Repository) ListConversationsWithFilter(ctx context.Context, principal
}
func (r *Repository) listAdminConversations(ctx context.Context, principal Principal, page, pageSize int, filter string, stage string, keyword string) (*PaginatedResult, error) {
counts, err := r.adminConversationCounts(ctx, principal, filter, stage, keyword)
total, err := r.adminConversationTotal(ctx, principal, filter, stage, keyword)
if err != nil {
return nil, err
}
@@ -243,10 +243,9 @@ func (r *Repository) listAdminConversations(ctx context.Context, principal Princ
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 cm.id > COALESCE(cas.last_read_message_id, 0)
) AS unread_count`, principal.Type, principal.ID)
AND (cm.admin_attention_type <> '' OR cm.sender_type = 'user')
AND cm.id > COALESCE(cas.last_read_message_id, 0)
) AS unread_count`)
applyAdminChatOwnershipFilter(queryDB, filter, principal)
applyAdminChatStageFilter(queryDB, stage, principal)
if err := queryDB.
@@ -269,7 +268,26 @@ func (r *Repository) listAdminConversations(ctx context.Context, principal Princ
for _, row := range rows {
items = append(items, row.toDTO(participantsByConversation[row.ID]))
}
return &PaginatedResult{Items: items, Total: counts.Total, Page: page, PageSize: pageSize, Counts: counts.DTO}, nil
return &PaginatedResult{Items: items, Total: total, Page: page, PageSize: pageSize}, nil
}
func (r *Repository) AdminConversationCounts(ctx context.Context, principal Principal, filter string, stage string, keyword string) (*AdminConversationCountsDTO, error) {
result, err := r.adminConversationCounts(ctx, principal, normalizeAdminChatFilter(filter), normalizeAdminChatStage(stage), strings.TrimSpace(keyword))
if err != nil {
return nil, err
}
return result.DTO, nil
}
func (r *Repository) adminConversationTotal(ctx context.Context, principal Principal, filter string, stage string, keyword string) (int64, error) {
db := r.adminConversationBase(ctx, principal, strings.TrimSpace(keyword))
applyAdminChatOwnershipFilter(db, normalizeAdminChatFilter(filter), principal)
applyAdminChatStageFilter(db, normalizeAdminChatStage(stage), principal)
var total int64
if err := db.Select("COUNT(DISTINCT c.id)").Scan(&total).Error; err != nil {
return 0, err
}
return total, nil
}
func (r *Repository) adminConversationBase(ctx context.Context, principal Principal, keyword string) *gorm.DB {
@@ -396,17 +414,13 @@ func adminChatStageCondition(stage string, principal Principal) (string, []inter
latestRefundStatus := "COALESCE(explicit_lo.refund_status, listing_lo.refund_status)"
switch stage {
case adminChatStagePending:
return `(
lm.sender_type = 'user'
OR EXISTS (
return `EXISTS (
SELECT 1
FROM chat_messages AS cm_pending
WHERE cm_pending.conversation_id = c.id
AND cm_pending.sender_type <> 'system'
AND NOT (cm_pending.sender_type = 'admin' AND cm_pending.sender_id = ?)
AND cm_pending.id > COALESCE(cas.last_read_message_id, 0)
)
)`, []interface{}{principal.ID}
AND (cm_pending.admin_attention_type <> '' OR cm_pending.sender_type = 'user')
AND cm_pending.id > COALESCE(cas.last_read_message_id, 0)
)`, nil
case adminChatStageUnjoined:
return latestID + " IS NULL", nil
case adminChatStageHandoff: