perf(query): 优化后台手机号精确查询

This commit is contained in:
yml2213
2026-11-02 18:28:12 +08:00
parent 9c379b7e0c
commit 599e22331d
17 changed files with 254 additions and 62 deletions
@@ -105,6 +105,13 @@ func TestListAdminConversationsUsesPersonalStateAndBatchData(t *testing.T) {
if counts.Ownership[adminChatFilterMine] != 1 || counts.Stages[adminChatStageAll] != 1 {
t.Fatalf("聚合统计异常: ownership=%v stages=%v", counts.Ownership, counts.Stages)
}
result, err = repo.ListConversationsWithFilter(t.Context(), Principal{Type: "admin", ID: admin.ID}, 1, 20, adminChatFilterMine, adminChatStageAll, user.Phone)
if err != nil {
t.Fatalf("按手机号查询订单群失败: %v", err)
}
if result.Total != 1 {
t.Fatalf("按手机号匹配订单群数量 = %d, want 1", result.Total)
}
if err := db.Model(&conversation).Update("type", ConversationTypeGeneralSupport).Error; err != nil {
t.Fatalf("切换咨询会话类型失败: %v", err)
}
@@ -183,6 +190,13 @@ func TestListAdminConversationsUsesListingOrderSnapshot(t *testing.T) {
if items[0].LatestOrderID == nil || *items[0].LatestOrderID != order.ID || items[0].LatestOrderStatus != "pending_handoff" {
t.Fatalf("最新订单快照未生效: %+v", items[0])
}
result, err = repo.ListConversationsWithFilter(t.Context(), Principal{Type: "admin", ID: admin.ID}, 1, 20, adminChatFilterMine, adminChatStageAll, owner.Phone)
if err != nil {
t.Fatalf("按号主手机号查询发布群失败: %v", err)
}
if result.Total != 1 {
t.Fatalf("按号主手机号匹配发布群数量 = %d, want 1", result.Total)
}
order.Status = "renting"
if err := db.Save(&order).Error; err != nil {
+20 -4
View File
@@ -307,10 +307,22 @@ func (r *Repository) adminConversationBase(ctx context.Context, principal Princi
Joins("LEFT JOIN rental_listings AS l ON l.id = COALESCE(explicit_lo.listing_id, c.listing_id)")
if keyword != "" {
upper := strings.ToUpper(keyword)
if len(keyword) == 11 && keyword[0] == '1' && isAllDigits(keyword) {
db = db.Joins("LEFT JOIN users AS renter ON renter.id = explicit_lo.renter_id").
Joins("LEFT JOIN users AS owner ON owner.id = COALESCE(explicit_lo.owner_id, l.owner_id)").
Where("(renter.phone = ? OR owner.phone = ?)", keyword, keyword)
if isPhoneKeyword(keyword) {
// 先由 users(phone) 唯一索引解析用户,再分别从订单群和发布群定位会话。
// 保持原有语义:订单群匹配订单号主/租客,发布群仅匹配商品号主。
db = db.Joins(`JOIN (
SELECT c2.id AS conversation_id
FROM chat_conversations AS c2
JOIN rental_orders AS o2 ON o2.id = c2.order_id
WHERE o2.owner_id = (SELECT id FROM users WHERE phone = ?)
OR o2.renter_id = (SELECT id FROM users WHERE phone = ?)
UNION ALL
SELECT c2.id AS conversation_id
FROM chat_conversations AS c2
JOIN rental_listings AS l2 ON l2.id = c2.listing_id
WHERE c2.order_id IS NULL
AND l2.owner_id = (SELECT id FROM users WHERE phone = ?)
) AS matched_phone ON matched_phone.conversation_id = c.id`, keyword, keyword, keyword)
} else if strings.HasPrefix(upper, "RO") || strings.HasPrefix(upper, "ORD") {
db = db.Where("(explicit_lo.order_no = ? OR c.latest_order_no = ?)", keyword, keyword)
} else if strings.HasPrefix(upper, "L") || (len(keyword) >= 12 && isAllDigits(keyword)) {
@@ -492,3 +504,7 @@ func isAllDigits(s string) bool {
}
return true
}
func isPhoneKeyword(s string) bool {
return len(s) == 11 && s[0] == '1' && isAllDigits(s)
}