diff --git a/internal/biz/business/alert_record.go b/internal/biz/business/alert_record.go index 141b41f..75ddc39 100644 --- a/internal/biz/business/alert_record.go +++ b/internal/biz/business/alert_record.go @@ -49,6 +49,7 @@ type AlertRecordScope struct { type AlertRecordFilter struct { PlatformCodes []string TargetPromoteID *uint64 + PlatformBusierID *uint64 BusinessID *uint TargetPromoteName, RuleName, RuleType, BusinessName string MonitorMetric, Status *int diff --git a/internal/data/business/alert_record.go b/internal/data/business/alert_record.go index 591d169..e1a3624 100644 --- a/internal/data/business/alert_record.go +++ b/internal/data/business/alert_record.go @@ -87,6 +87,16 @@ func (r *alertRecordRepo) List(ctx context.Context, scope business.AlertRecordSc if empty || !available { return page, nil } + if filter.PlatformBusierID != nil { + available, err := businessTableAvailable(db, "tab_promote") + if err != nil { + return nil, err + } + if !available { + page.Available = false + return page, nil + } + } base := func() *gorm.DB { q := alertScopedQuery(db, scope) if len(filter.PlatformCodes) > 0 { @@ -95,6 +105,9 @@ func (r *alertRecordRepo) List(ctx context.Context, scope business.AlertRecordSc if filter.TargetPromoteID != nil { q = q.Where("r.target_promote_id = ?", *filter.TargetPromoteID) } + if filter.PlatformBusierID != nil { + q = q.Where("EXISTS (?)", db.Table("tab_promote bp").Select("1").Where("bp.id=r.target_promote_id AND bp.source_db=r.platform_code AND bp.busier_id=?", *filter.PlatformBusierID)) + } return q } q := base() diff --git a/internal/data/business/alert_record_test.go b/internal/data/business/alert_record_test.go index a5007b1..07e8e67 100644 --- a/internal/data/business/alert_record_test.go +++ b/internal/data/business/alert_record_test.go @@ -111,6 +111,41 @@ func TestAlertRecordsMissingChannelsFailClosed(t *testing.T) { } } +func TestBindingPortraitAlertsStayWithinSelectedSDKAccount(t *testing.T) { + db, repo := prepareAlertRecords(t) + if err := db.Exec("INSERT INTO sys_user_bind_platform(user_id,source_db,platform_busier_id,status) VALUES(9,'lx',16,'0')").Error; err != nil { + t.Fatal(err) + } + if err := db.Exec("INSERT INTO tab_promote VALUES(103,'lx',16,1,1)").Error; err != nil { + t.Fatal(err) + } + if err := db.Create(&alertRecordPO{ID: 8, PlatformCode: "lx", TargetPromoteID: 103, BusinessID: 7, Status: 1, CreatedAt: time.Now()}).Error; err != nil { + t.Fatal(err) + } + ctx := context.Background() + for _, sample := range []struct { + busier uint64 + want int64 + }{{14, 2}, {16, 1}, {999, 0}} { + page, err := repo.List(ctx, alertTestScope(9), business.AlertRecordFilter{PlatformCodes: []string{"lx"}, PlatformBusierID: &sample.busier}) + if err != nil || page.Total != sample.want { + t.Fatalf("binding %d: %+v %v", sample.busier, page, err) + } + var total int64 + for _, count := range page.StatusCount { + total += count + } + if total != sample.want { + t.Fatal("binding filter must also constrain status counts") + } + } + busier := uint64(16) + page, err := repo.List(ctx, alertTestScope(10), business.AlertRecordFilter{PlatformCodes: []string{"lx"}, PlatformBusierID: &busier}) + if err != nil || page.Total != 0 { + t.Fatal("binding filter must not expand the viewer's permissions") + } +} + func TestAlertRecordTransactionRollsBackWhenLogFails(t *testing.T) { db, repo := prepareAlertRecords(t) if err := db.Exec("CREATE TRIGGER reject_note BEFORE INSERT ON sys_alert_operation_log WHEN NEW.log_type = 2 BEGIN SELECT RAISE(ABORT, 'test failure'); END").Error; err != nil { diff --git a/internal/service/business/alert_record.go b/internal/service/business/alert_record.go index ed0db1b..525d677 100644 --- a/internal/service/business/alert_record.go +++ b/internal/service/business/alert_record.go @@ -35,6 +35,9 @@ func (s *AlertRecordService) List(ctx context.Context, req *dto.AlertRecordQuery if req == nil { return nil, business.ErrAlertRecordInput } + if req.PlatformBusierID != nil && *req.PlatformBusierID == 0 { + return nil, business.ErrAlertRecordInput + } if req.MonitorMetric != nil && (*req.MonitorMetric < 1 || *req.MonitorMetric > 3) { return nil, business.ErrAlertRecordInput } @@ -56,6 +59,7 @@ func (s *AlertRecordService) List(ctx context.Context, req *dto.AlertRecordQuery } filter := business.AlertRecordFilter{TargetPromoteID: req.TargetPromoteID, BusinessID: req.BusinessID, TargetPromoteName: strings.TrimSpace(req.TargetPromoteName), RuleName: strings.TrimSpace(req.RuleName), RuleType: strings.TrimSpace(req.RuleType), BusinessName: strings.TrimSpace(req.BusinessName), MonitorMetric: req.MonitorMetric, Status: req.Status} seen := map[string]bool{} + filter.PlatformBusierID = req.PlatformBusierID for _, code := range strings.Split(req.PlatformCodes, ",") { code = strings.TrimSpace(code) if code != "" && !seen[code] { diff --git a/internal/service/dto/alert_record.go b/internal/service/dto/alert_record.go index acb22e0..fe28bab 100644 --- a/internal/service/dto/alert_record.go +++ b/internal/service/dto/alert_record.go @@ -7,6 +7,7 @@ type AlertRecordQuery struct { PageSize int `form:"pageSize"` PlatformCodes string `form:"platformCodes"` TargetPromoteID *uint64 `form:"targetPromoteId"` + PlatformBusierID *uint64 `form:"platformBusierId"` BusinessID *uint `form:"businessId"` TargetPromoteName string `form:"targetPromoteName"` RuleName string `form:"ruleName"` diff --git a/web/src/view/sw/components/AddChannelDrawer.vue b/web/src/view/sw/components/AddChannelDrawer.vue index 086fc1f..15aa03a 100644 --- a/web/src/view/sw/components/AddChannelDrawer.vue +++ b/web/src/view/sw/components/AddChannelDrawer.vue @@ -3,7 +3,7 @@ - + diff --git a/web/src/view/sw/components/BusinessProfileDrawer.vue b/web/src/view/sw/components/BusinessProfileDrawer.vue index fd8a88e..7d58209 100644 --- a/web/src/view/sw/components/BusinessProfileDrawer.vue +++ b/web/src/view/sw/components/BusinessProfileDrawer.vue @@ -25,8 +25,8 @@

数据趋势

- - + +

旗下渠道排行

@@ -111,7 +111,7 @@ const loadAlerts = async () => { const request = alertRequests.start() alertsLoading.value = true; alertError.value = '' try { - const res = await listAlertRecords({ platformCodes: sources.value, businessId: props.userId, pageNum: alertPage.value, pageSize: 10 }, { signal: request.signal }) + const res = await listAlertRecords({ platformCodes: sources.value, businessId: props.userId, platformBusierId: props.platformBusierId || undefined, pageNum: alertPage.value, pageSize: 10 }, { signal: request.signal }) if (!request.isCurrent()) return if (res.code === 0 && res.data.available !== false) { alerts.value = res.data.pageData.rows; alertTotal.value = res.data.pageData.total } else { alerts.value = []; alertTotal.value = 0; alertError.value = res.code === 0 ? '渠道数据尚未接入,暂时无法核对关联预警。' : res.msg || '关联预警读取失败' } diff --git a/web/src/view/sw/components/BusinessTrend.vue b/web/src/view/sw/components/BusinessTrend.vue index 68ba5b6..6190a01 100644 --- a/web/src/view/sw/components/BusinessTrend.vue +++ b/web/src/view/sw/components/BusinessTrend.vue @@ -7,7 +7,7 @@ - {{ series[index]?.label }} + {{ hourly ? `${index}:00` : series[index]?.label }}