From c7d4ffbd9c8aa768277bed8489f042ce313d48e4 Mon Sep 17 00:00:00 2001 From: Yvan <8574526@qq,com> Date: Thu, 5 Nov 2026 11:14:57 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=85=BC=E5=AE=B9MySQL=E6=B8=A0?= =?UTF-8?q?=E9=81=93=E7=8A=B6=E6=80=81=E6=B1=87=E6=80=BB=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E5=B9=B6=E8=A1=A5=E5=85=85=E6=95=B0=E6=8D=AE=E5=BA=93=E5=9B=9E?= =?UTF-8?q?=E5=BD=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/data/business/channel.go | 8 +++---- .../data/business/mysql_rehearsal_test.go | 23 +++++++++++++++++++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/internal/data/business/channel.go b/internal/data/business/channel.go index ae952e7..83c61f7 100644 --- a/internal/data/business/channel.go +++ b/internal/data/business/channel.go @@ -128,12 +128,12 @@ func (r *channelRepo) List(ctx context.Context, scope business.UserScope, filter q = q.Where("e.qualified_at IS NULL") } } - var counts struct{ Total, Normal, Locked, Terminated int64 } - if err := q.Session(&gorm.Session{}).Select("COUNT(*) AS total,COALESCE(SUM(CASE WHEN COALESCE(p.lock_status,0)=0 THEN 1 ELSE 0 END),0) AS normal,COALESCE(SUM(CASE WHEN COALESCE(p.lock_status,0) NOT IN (0,-2) THEN 1 ELSE 0 END),0) AS locked,COALESCE(SUM(CASE WHEN p.lock_status=-2 THEN 1 ELSE 0 END),0) AS terminated").Scan(&counts).Error; err != nil { + var counts struct{ TotalCount, NormalCount, LockedCount, TerminatedCount int64 } + if err := q.Session(&gorm.Session{}).Select("COUNT(*) AS total_count,COALESCE(SUM(CASE WHEN COALESCE(p.lock_status,0)=0 THEN 1 ELSE 0 END),0) AS normal_count,COALESCE(SUM(CASE WHEN COALESCE(p.lock_status,0) NOT IN (0,-2) THEN 1 ELSE 0 END),0) AS locked_count,COALESCE(SUM(CASE WHEN p.lock_status=-2 THEN 1 ELSE 0 END),0) AS terminated_count").Scan(&counts).Error; err != nil { return nil, business.ErrStorage } - page.Total = counts.Total - page.StatusCounts = &business.ChannelStatusCounts{Normal: counts.Normal, Locked: counts.Locked, Terminated: counts.Terminated} + page.Total = counts.TotalCount + page.StatusCounts = &business.ChannelStatusCounts{Normal: counts.NormalCount, Locked: counts.LockedCount, Terminated: counts.TerminatedCount} var pos []channelPO o := business.NewListOptions(options...) order := "p.create_time DESC,p.id DESC,p.source_db ASC" diff --git a/internal/data/business/mysql_rehearsal_test.go b/internal/data/business/mysql_rehearsal_test.go index 747535f..2fe043a 100644 --- a/internal/data/business/mysql_rehearsal_test.go +++ b/internal/data/business/mysql_rehearsal_test.go @@ -128,6 +128,29 @@ func TestMySQLAlertTriggerConcurrentDeduplication(t *testing.T) { } } +func TestMySQLChannelStatusSummaryAndEffectivenessFilter(t *testing.T) { + db := openRehearsalMySQL(t) + if err := db.AutoMigrate(&accountPO{}, &channelPO{}); err != nil { + t.Fatal(err) + } + for i, status := range []int{0, -1, -2} { + created := int64(1000 + i) + if err := db.Create(&channelPO{ID: uint64(i + 1), SourceDB: "lx", Account: fmt.Sprintf("channel-%d", i), LockStatus: &status, CreateTime: &created}).Error; err != nil { + t.Fatal(err) + } + } + r := NewChannelRepo(testData{db}) + page, err := r.List(context.Background(), business.UserScope{All: true}, business.ChannelFilter{Sources: []string{"lx"}}, business.ListLimit(1)) + if err != nil || page.Total != 3 || len(page.Rows) != 1 || page.StatusCounts.Normal != 1 || page.StatusCounts.Locked != 1 || page.StatusCounts.Terminated != 1 { + t.Fatalf("MySQL全量状态汇总与分页不一致: %+v %v", page, err) + } + yes := true + page, err = r.List(context.Background(), business.UserScope{All: true}, business.ChannelFilter{Sources: []string{"lx"}, Effective: &yes}) + if err != nil || page.Total != 0 { + t.Fatalf("有效端筛选不能重复关联表或漏用筛选条件: %+v %v", page, err) + } +} + func TestMySQLRegistrationIndexPreservesCastAndUsesRange(t *testing.T) { db := openRehearsalMySQL(t) for _, statement := range []string{