@@ -347,6 +347,24 @@ func GetUserListByPageWithAddress(userListReq *model.UserListReq, claims *utils.
347347 if userListReq .Status != nil && * userListReq .Status != "" {
348348 queryBuilder = queryBuilder .Where (q .Status .Eq (* userListReq .Status ))
349349 }
350+ if userListReq .ActivityScope != nil && * userListReq .ActivityScope != "" && claims .Authority == SYS_ADMIN {
351+ now := time .Now ()
352+ todayStart := time .Date (now .Year (), now .Month (), now .Day (), 0 , 0 , 0 , 0 , now .Location ())
353+ tomorrowStart := todayStart .AddDate (0 , 0 , 1 )
354+ last7Start := todayStart .AddDate (0 , 0 , - 6 )
355+ last30Start := todayStart .AddDate (0 , 0 , - 29 )
356+
357+ switch * userListReq .ActivityScope {
358+ case model .TenantActivityScopeToday :
359+ queryBuilder = queryBuilder .Where (q .LastVisitTime .Gte (todayStart ), q .LastVisitTime .Lt (tomorrowStart ))
360+ case model .TenantActivityScopeLast7Days :
361+ queryBuilder = queryBuilder .Where (q .LastVisitTime .Gte (last7Start ), q .LastVisitTime .Lt (tomorrowStart ))
362+ case model .TenantActivityScopeLast30Days :
363+ queryBuilder = queryBuilder .Where (q .LastVisitTime .Gte (last30Start ), q .LastVisitTime .Lt (tomorrowStart ))
364+ case model .TenantActivityScopeInactiveOver30Days :
365+ queryBuilder = queryBuilder .Where (q .Where (q .LastVisitTime .Lt (last30Start )).Or (q .LastVisitTime .IsNull ()))
366+ }
367+ }
350368
351369 // 新增扩展字段过滤
352370 if userListReq .Organization != nil && * userListReq .Organization != "" {
@@ -400,6 +418,89 @@ func GetUserListByPageWithAddress(userListReq *model.UserListReq, claims *utils.
400418 return count , userList , nil
401419}
402420
421+ func GetTenantStatisticsSummary (
422+ ctx context.Context ,
423+ todayStart time.Time ,
424+ tomorrowStart time.Time ,
425+ last7Start time.Time ,
426+ last30Start time.Time ,
427+ ) (model.TenantStatisticsSummaryRes , model.TenantRevisitStatisticsRes , error ) {
428+ type summaryRow struct {
429+ Total int64 `gorm:"column:total"`
430+ ActiveToday int64 `gorm:"column:active_today"`
431+ ActiveLast7Days int64 `gorm:"column:active_last_7_days"`
432+ ActiveLast30Days int64 `gorm:"column:active_last_30_days"`
433+ InactiveOver30Days int64 `gorm:"column:inactive_over_30_days"`
434+ Revisited int64 `gorm:"column:revisited"`
435+ NotRevisited int64 `gorm:"column:not_revisited"`
436+ }
437+
438+ var row summaryRow
439+ err := global .DB .WithContext (ctx ).
440+ Model (& model.User {}).
441+ Select (`
442+ COUNT(*) AS total,
443+ COALESCE(SUM(CASE WHEN last_visit_time >= ? AND last_visit_time < ? THEN 1 ELSE 0 END), 0) AS active_today,
444+ COALESCE(SUM(CASE WHEN last_visit_time >= ? AND last_visit_time < ? THEN 1 ELSE 0 END), 0) AS active_last_7_days,
445+ COALESCE(SUM(CASE WHEN last_visit_time >= ? AND last_visit_time < ? THEN 1 ELSE 0 END), 0) AS active_last_30_days,
446+ COALESCE(SUM(CASE WHEN last_visit_time < ? OR last_visit_time IS NULL THEN 1 ELSE 0 END), 0) AS inactive_over_30_days,
447+ COALESCE(SUM(CASE WHEN last_visit_time IS NOT NULL THEN 1 ELSE 0 END), 0) AS revisited,
448+ COALESCE(SUM(CASE WHEN last_visit_time IS NULL THEN 1 ELSE 0 END), 0) AS not_revisited
449+ ` ,
450+ todayStart , tomorrowStart ,
451+ last7Start , tomorrowStart ,
452+ last30Start , tomorrowStart ,
453+ last30Start ,
454+ ).
455+ Where ("authority = ?" , TENANT_ADMIN ).
456+ Scan (& row ).Error
457+ if err != nil {
458+ return model.TenantStatisticsSummaryRes {}, model.TenantRevisitStatisticsRes {}, err
459+ }
460+
461+ return model.TenantStatisticsSummaryRes {
462+ Total : row .Total ,
463+ ActiveToday : row .ActiveToday ,
464+ ActiveLast7Days : row .ActiveLast7Days ,
465+ ActiveLast30Days : row .ActiveLast30Days ,
466+ InactiveOver30Days : row .InactiveOver30Days ,
467+ }, model.TenantRevisitStatisticsRes {
468+ Revisited : row .Revisited ,
469+ NotRevisited : row .NotRevisited ,
470+ }, nil
471+ }
472+
473+ func GetTenantCountBefore (ctx context.Context , before time.Time ) (int64 , error ) {
474+ return query .User .WithContext (ctx ).
475+ Where (query .User .Authority .Eq (TENANT_ADMIN ), query .User .CreatedAt .Lt (before )).
476+ Count ()
477+ }
478+
479+ func GetTenantDailyNewCounts (ctx context.Context , start time.Time , end time.Time ) (map [string ]int64 , error ) {
480+ type dailyNewCountRow struct {
481+ Date string `gorm:"column:date"`
482+ Total int64 `gorm:"column:total"`
483+ }
484+
485+ var rows []dailyNewCountRow
486+ err := global .DB .WithContext (ctx ).
487+ Model (& model.User {}).
488+ Select ("TO_CHAR(created_at, 'YYYY-MM-DD') AS date, COUNT(*) AS total" ).
489+ Where ("authority = ? AND created_at >= ? AND created_at < ?" , TENANT_ADMIN , start , end ).
490+ Group ("TO_CHAR(created_at, 'YYYY-MM-DD')" ).
491+ Order ("date ASC" ).
492+ Scan (& rows ).Error
493+ if err != nil {
494+ return nil , err
495+ }
496+
497+ result := make (map [string ]int64 , len (rows ))
498+ for _ , row := range rows {
499+ result [row .Date ] = row .Total
500+ }
501+ return result , nil
502+ }
503+
403504func GetUsersCount () int64 {
404505 count , err := query .User .Count ()
405506 if err != nil {
0 commit comments