| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | package statistics | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | import ( | 
					
						
							|  |  |  |  | 	"context" | 
					
						
							|  |  |  |  | 	"fmt" | 
					
						
							|  |  |  |  | 	"time" | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	"go.uber.org/zap" | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	"tyapi-server/internal/domains/statistics/entities" | 
					
						
							|  |  |  |  | 	"tyapi-server/internal/domains/statistics/repositories" | 
					
						
							|  |  |  |  | 	"tyapi-server/internal/domains/statistics/services" | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 认证领域 | 
					
						
							|  |  |  |  | 	certificationEntities "tyapi-server/internal/domains/certification/entities" | 
					
						
							|  |  |  |  | 	certificationEnums "tyapi-server/internal/domains/certification/enums" | 
					
						
							|  |  |  |  | 	certificationQueries "tyapi-server/internal/domains/certification/repositories/queries" | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 添加其他领域的仓储接口 | 
					
						
							|  |  |  |  | 	apiRepos "tyapi-server/internal/domains/api/repositories" | 
					
						
							|  |  |  |  | 	certificationRepos "tyapi-server/internal/domains/certification/repositories" | 
					
						
							|  |  |  |  | 	financeRepos "tyapi-server/internal/domains/finance/repositories" | 
					
						
							|  |  |  |  | 	productRepos "tyapi-server/internal/domains/product/repositories" | 
					
						
							|  |  |  |  | 	productQueries "tyapi-server/internal/domains/product/repositories/queries" | 
					
						
							|  |  |  |  | 	userRepos "tyapi-server/internal/domains/user/repositories" | 
					
						
							|  |  |  |  | ) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // StatisticsApplicationServiceImpl 统计应用服务实现 | 
					
						
							|  |  |  |  | type StatisticsApplicationServiceImpl struct { | 
					
						
							|  |  |  |  | 	// 领域服务 | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 	aggregateService   services.StatisticsAggregateService | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	calculationService services.StatisticsCalculationService | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 	reportService      services.StatisticsReportService | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	// 统计仓储 | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 	metricRepo    repositories.StatisticsRepository | 
					
						
							|  |  |  |  | 	reportRepo    repositories.StatisticsReportRepository | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	dashboardRepo repositories.StatisticsDashboardRepository | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	// 其他领域仓储 | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 	userRepo              userRepos.UserRepository | 
					
						
							|  |  |  |  | 	enterpriseInfoRepo    userRepos.EnterpriseInfoRepository | 
					
						
							|  |  |  |  | 	apiCallRepo           apiRepos.ApiCallRepository | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	walletTransactionRepo financeRepos.WalletTransactionRepository | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 	rechargeRecordRepo    financeRepos.RechargeRecordRepository | 
					
						
							|  |  |  |  | 	productRepo           productRepos.ProductRepository | 
					
						
							|  |  |  |  | 	certificationRepo     certificationRepos.CertificationQueryRepository | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	// 日志 | 
					
						
							|  |  |  |  | 	logger *zap.Logger | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // NewStatisticsApplicationService 创建统计应用服务 | 
					
						
							|  |  |  |  | func NewStatisticsApplicationService( | 
					
						
							|  |  |  |  | 	aggregateService services.StatisticsAggregateService, | 
					
						
							|  |  |  |  | 	calculationService services.StatisticsCalculationService, | 
					
						
							|  |  |  |  | 	reportService services.StatisticsReportService, | 
					
						
							|  |  |  |  | 	metricRepo repositories.StatisticsRepository, | 
					
						
							|  |  |  |  | 	reportRepo repositories.StatisticsReportRepository, | 
					
						
							|  |  |  |  | 	dashboardRepo repositories.StatisticsDashboardRepository, | 
					
						
							|  |  |  |  | 	userRepo userRepos.UserRepository, | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 	enterpriseInfoRepo userRepos.EnterpriseInfoRepository, | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	apiCallRepo apiRepos.ApiCallRepository, | 
					
						
							|  |  |  |  | 	walletTransactionRepo financeRepos.WalletTransactionRepository, | 
					
						
							|  |  |  |  | 	rechargeRecordRepo financeRepos.RechargeRecordRepository, | 
					
						
							|  |  |  |  | 	productRepo productRepos.ProductRepository, | 
					
						
							|  |  |  |  | 	certificationRepo certificationRepos.CertificationQueryRepository, | 
					
						
							|  |  |  |  | 	logger *zap.Logger, | 
					
						
							|  |  |  |  | ) StatisticsApplicationService { | 
					
						
							|  |  |  |  | 	return &StatisticsApplicationServiceImpl{ | 
					
						
							|  |  |  |  | 		aggregateService:      aggregateService, | 
					
						
							|  |  |  |  | 		calculationService:    calculationService, | 
					
						
							|  |  |  |  | 		reportService:         reportService, | 
					
						
							|  |  |  |  | 		metricRepo:            metricRepo, | 
					
						
							|  |  |  |  | 		reportRepo:            reportRepo, | 
					
						
							|  |  |  |  | 		dashboardRepo:         dashboardRepo, | 
					
						
							|  |  |  |  | 		userRepo:              userRepo, | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 		enterpriseInfoRepo:    enterpriseInfoRepo, | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 		apiCallRepo:           apiCallRepo, | 
					
						
							|  |  |  |  | 		walletTransactionRepo: walletTransactionRepo, | 
					
						
							|  |  |  |  | 		rechargeRecordRepo:    rechargeRecordRepo, | 
					
						
							|  |  |  |  | 		productRepo:           productRepo, | 
					
						
							|  |  |  |  | 		certificationRepo:     certificationRepo, | 
					
						
							|  |  |  |  | 		logger:                logger, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ================ 指标管理 ================ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // CreateMetric 创建统计指标 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) CreateMetric(ctx context.Context, cmd *CreateMetricCommand) (*CommandResponse, error) { | 
					
						
							|  |  |  |  | 	// 验证命令 | 
					
						
							|  |  |  |  | 	if err := cmd.Validate(); err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("创建指标命令验证失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &CommandResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "命令验证失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 创建指标实体 | 
					
						
							|  |  |  |  | 	metric, err := entities.NewStatisticsMetric( | 
					
						
							|  |  |  |  | 		cmd.MetricType, | 
					
						
							|  |  |  |  | 		cmd.MetricName, | 
					
						
							|  |  |  |  | 		cmd.Dimension, | 
					
						
							|  |  |  |  | 		cmd.Value, | 
					
						
							|  |  |  |  | 		cmd.Date, | 
					
						
							|  |  |  |  | 	) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("创建指标实体失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &CommandResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "创建指标失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 保存指标 | 
					
						
							|  |  |  |  | 	err = s.metricRepo.Save(ctx, metric) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("保存指标失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &CommandResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "保存指标失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 转换为DTO | 
					
						
							|  |  |  |  | 	dto := s.convertMetricToDTO(metric) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	s.logger.Info("指标创建成功", zap.String("metric_id", metric.ID)) | 
					
						
							|  |  |  |  | 	return &CommandResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "指标创建成功", | 
					
						
							|  |  |  |  | 		Data:    dto, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // UpdateMetric 更新统计指标 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) UpdateMetric(ctx context.Context, cmd *UpdateMetricCommand) (*CommandResponse, error) { | 
					
						
							|  |  |  |  | 	// 验证命令 | 
					
						
							|  |  |  |  | 	if err := cmd.Validate(); err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("更新指标命令验证失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &CommandResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "命令验证失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取指标 | 
					
						
							|  |  |  |  | 	metric, err := s.metricRepo.FindByID(ctx, cmd.ID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("查询指标失败", zap.String("metric_id", cmd.ID), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &CommandResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "查询指标失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 更新指标值 | 
					
						
							|  |  |  |  | 	err = metric.UpdateValue(cmd.Value) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("更新指标值失败", zap.String("metric_id", cmd.ID), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &CommandResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "更新指标值失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 保存更新 | 
					
						
							|  |  |  |  | 	err = s.metricRepo.Update(ctx, metric) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("保存指标更新失败", zap.String("metric_id", cmd.ID), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &CommandResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "保存指标更新失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 转换为DTO | 
					
						
							|  |  |  |  | 	dto := s.convertMetricToDTO(metric) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	s.logger.Info("指标更新成功", zap.String("metric_id", metric.ID)) | 
					
						
							|  |  |  |  | 	return &CommandResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "指标更新成功", | 
					
						
							|  |  |  |  | 		Data:    dto, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // DeleteMetric 删除统计指标 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) DeleteMetric(ctx context.Context, cmd *DeleteMetricCommand) (*CommandResponse, error) { | 
					
						
							|  |  |  |  | 	// 验证命令 | 
					
						
							|  |  |  |  | 	if cmd.ID == "" { | 
					
						
							|  |  |  |  | 		return &CommandResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "指标ID不能为空", | 
					
						
							|  |  |  |  | 			Error:   "指标ID不能为空", | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 删除指标 | 
					
						
							|  |  |  |  | 	err := s.metricRepo.Delete(ctx, cmd.ID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("删除指标失败", zap.String("metric_id", cmd.ID), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &CommandResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "删除指标失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	s.logger.Info("指标删除成功", zap.String("metric_id", cmd.ID)) | 
					
						
							|  |  |  |  | 	return &CommandResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "指标删除成功", | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // GetMetric 获取单个指标 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) GetMetric(ctx context.Context, query *GetMetricQuery) (*QueryResponse, error) { | 
					
						
							|  |  |  |  | 	// 验证查询 | 
					
						
							|  |  |  |  | 	if query.MetricID == "" { | 
					
						
							|  |  |  |  | 		return &QueryResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "指标ID不能为空", | 
					
						
							|  |  |  |  | 			Error:   "指标ID不能为空", | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 查询指标 | 
					
						
							|  |  |  |  | 	metric, err := s.metricRepo.FindByID(ctx, query.MetricID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("查询指标失败", zap.String("metric_id", query.MetricID), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &QueryResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "查询指标失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 转换为DTO | 
					
						
							|  |  |  |  | 	dto := s.convertMetricToDTO(metric) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &QueryResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "查询成功", | 
					
						
							|  |  |  |  | 		Data:    dto, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // GetMetrics 获取指标列表 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) GetMetrics(ctx context.Context, query *GetMetricsQuery) (*ListResponse, error) { | 
					
						
							|  |  |  |  | 	// 设置默认值 | 
					
						
							|  |  |  |  | 	if query.Limit <= 0 { | 
					
						
							|  |  |  |  | 		query.Limit = 20 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if query.Limit > 1000 { | 
					
						
							|  |  |  |  | 		query.Limit = 1000 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 查询指标 | 
					
						
							|  |  |  |  | 	var metrics []*entities.StatisticsMetric | 
					
						
							|  |  |  |  | 	var err error | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if query.MetricType != "" && !query.StartDate.IsZero() && !query.EndDate.IsZero() { | 
					
						
							|  |  |  |  | 		metrics, err = s.metricRepo.FindByTypeAndDateRange(ctx, query.MetricType, query.StartDate, query.EndDate) | 
					
						
							|  |  |  |  | 	} else if query.MetricType != "" { | 
					
						
							|  |  |  |  | 		metrics, err = s.metricRepo.FindByType(ctx, query.MetricType, query.Limit, query.Offset) | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		return &ListResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "查询条件不完整", | 
					
						
							|  |  |  |  | 			Data:    ListDataDTO{}, | 
					
						
							|  |  |  |  | 			Error:   "查询条件不完整", | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("查询指标列表失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &ListResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "查询指标列表失败", | 
					
						
							|  |  |  |  | 			Data:    ListDataDTO{}, | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 转换为DTO | 
					
						
							|  |  |  |  | 	var dtos []interface{} | 
					
						
							|  |  |  |  | 	for _, metric := range metrics { | 
					
						
							|  |  |  |  | 		dtos = append(dtos, s.convertMetricToDTO(metric)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 计算分页信息 | 
					
						
							|  |  |  |  | 	total := int64(len(metrics)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &ListResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "查询成功", | 
					
						
							|  |  |  |  | 		Data: ListDataDTO{ | 
					
						
							|  |  |  |  | 			Total: total, | 
					
						
							|  |  |  |  | 			Page:  query.Offset/query.Limit + 1, | 
					
						
							|  |  |  |  | 			Size:  query.Limit, | 
					
						
							|  |  |  |  | 			Items: dtos, | 
					
						
							|  |  |  |  | 		}, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ================ 实时统计 ================ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // GetRealtimeMetrics 获取实时指标 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) GetRealtimeMetrics(ctx context.Context, query *GetRealtimeMetricsQuery) (*QueryResponse, error) { | 
					
						
							|  |  |  |  | 	// 验证查询 | 
					
						
							|  |  |  |  | 	if query.MetricType == "" { | 
					
						
							|  |  |  |  | 		return &QueryResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "指标类型不能为空", | 
					
						
							|  |  |  |  | 			Error:   "指标类型不能为空", | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取实时指标 | 
					
						
							|  |  |  |  | 	metrics, err := s.aggregateService.GetRealtimeMetrics(ctx, query.MetricType) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取实时指标失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &QueryResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "获取实时指标失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 构建响应 | 
					
						
							|  |  |  |  | 	dto := &RealtimeMetricsDTO{ | 
					
						
							|  |  |  |  | 		MetricType: query.MetricType, | 
					
						
							|  |  |  |  | 		Metrics:    metrics, | 
					
						
							|  |  |  |  | 		Timestamp:  time.Now(), | 
					
						
							|  |  |  |  | 		Metadata: map[string]interface{}{ | 
					
						
							|  |  |  |  | 			"time_range": query.TimeRange, | 
					
						
							|  |  |  |  | 			"dimension":  query.Dimension, | 
					
						
							|  |  |  |  | 		}, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &QueryResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "获取实时指标成功", | 
					
						
							|  |  |  |  | 		Data:    dto, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // UpdateRealtimeMetric 更新实时指标 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) UpdateRealtimeMetric(ctx context.Context, metricType, metricName string, value float64) error { | 
					
						
							|  |  |  |  | 	return s.aggregateService.UpdateRealtimeMetric(ctx, metricType, metricName, value) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ================ 历史统计 ================ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // GetHistoricalMetrics 获取历史指标 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) GetHistoricalMetrics(ctx context.Context, query *GetHistoricalMetricsQuery) (*QueryResponse, error) { | 
					
						
							|  |  |  |  | 	// 验证查询 | 
					
						
							|  |  |  |  | 	if query.MetricType == "" { | 
					
						
							|  |  |  |  | 		return &QueryResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "指标类型不能为空", | 
					
						
							|  |  |  |  | 			Error:   "指标类型不能为空", | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取历史指标 | 
					
						
							|  |  |  |  | 	var metrics []*entities.StatisticsMetric | 
					
						
							|  |  |  |  | 	var err error | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if query.MetricName != "" { | 
					
						
							|  |  |  |  | 		metrics, err = s.metricRepo.FindByTypeNameAndDateRange(ctx, query.MetricType, query.MetricName, query.StartDate, query.EndDate) | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		metrics, err = s.metricRepo.FindByTypeAndDateRange(ctx, query.MetricType, query.StartDate, query.EndDate) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取历史指标失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &QueryResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "获取历史指标失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 转换为DTO | 
					
						
							|  |  |  |  | 	var dataPoints []DataPointDTO | 
					
						
							|  |  |  |  | 	var total, sum float64 | 
					
						
							|  |  |  |  | 	var count int64 | 
					
						
							|  |  |  |  | 	var max, min float64 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if len(metrics) > 0 { | 
					
						
							|  |  |  |  | 		max = metrics[0].Value | 
					
						
							|  |  |  |  | 		min = metrics[0].Value | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	for _, metric := range metrics { | 
					
						
							|  |  |  |  | 		dataPoints = append(dataPoints, DataPointDTO{ | 
					
						
							|  |  |  |  | 			Date:  metric.Date, | 
					
						
							|  |  |  |  | 			Value: metric.Value, | 
					
						
							|  |  |  |  | 			Label: metric.MetricName, | 
					
						
							|  |  |  |  | 		}) | 
					
						
							|  |  |  |  | 		total += metric.Value | 
					
						
							|  |  |  |  | 		sum += metric.Value | 
					
						
							|  |  |  |  | 		count++ | 
					
						
							|  |  |  |  | 		if metric.Value > max { | 
					
						
							|  |  |  |  | 			max = metric.Value | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		if metric.Value < min { | 
					
						
							|  |  |  |  | 			min = metric.Value | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 计算汇总信息 | 
					
						
							|  |  |  |  | 	summary := MetricsSummaryDTO{ | 
					
						
							|  |  |  |  | 		Total:   total, | 
					
						
							|  |  |  |  | 		Average: sum / float64(count), | 
					
						
							|  |  |  |  | 		Max:     max, | 
					
						
							|  |  |  |  | 		Min:     min, | 
					
						
							|  |  |  |  | 		Count:   count, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 构建响应 | 
					
						
							|  |  |  |  | 	dto := &HistoricalMetricsDTO{ | 
					
						
							|  |  |  |  | 		MetricType: query.MetricType, | 
					
						
							|  |  |  |  | 		MetricName: query.MetricName, | 
					
						
							|  |  |  |  | 		Dimension:  query.Dimension, | 
					
						
							|  |  |  |  | 		DataPoints: dataPoints, | 
					
						
							|  |  |  |  | 		Summary:    summary, | 
					
						
							|  |  |  |  | 		Metadata: map[string]interface{}{ | 
					
						
							|  |  |  |  | 			"period":       query.Period, | 
					
						
							|  |  |  |  | 			"aggregate_by": query.AggregateBy, | 
					
						
							|  |  |  |  | 			"group_by":     query.GroupBy, | 
					
						
							|  |  |  |  | 		}, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &QueryResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "获取历史指标成功", | 
					
						
							|  |  |  |  | 		Data:    dto, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // AggregateMetrics 聚合指标 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) AggregateMetrics(ctx context.Context, metricType, dimension string, startDate, endDate time.Time) error { | 
					
						
							|  |  |  |  | 	return s.aggregateService.AggregateHourlyMetrics(ctx, startDate) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ================ 仪表板管理 ================ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // CreateDashboard 创建仪表板 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) CreateDashboard(ctx context.Context, cmd *CreateDashboardCommand) (*CommandResponse, error) { | 
					
						
							|  |  |  |  | 	// 验证命令 | 
					
						
							|  |  |  |  | 	if err := cmd.Validate(); err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("创建仪表板命令验证失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &CommandResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "命令验证失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 创建仪表板实体 | 
					
						
							|  |  |  |  | 	dashboard, err := entities.NewStatisticsDashboard( | 
					
						
							|  |  |  |  | 		cmd.Name, | 
					
						
							|  |  |  |  | 		cmd.Description, | 
					
						
							|  |  |  |  | 		cmd.UserRole, | 
					
						
							|  |  |  |  | 		cmd.CreatedBy, | 
					
						
							|  |  |  |  | 	) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("创建仪表板实体失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &CommandResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "创建仪表板失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 设置配置 | 
					
						
							|  |  |  |  | 	if cmd.Layout != "" { | 
					
						
							|  |  |  |  | 		dashboard.UpdateLayout(cmd.Layout) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if cmd.Widgets != "" { | 
					
						
							|  |  |  |  | 		dashboard.UpdateWidgets(cmd.Widgets) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if cmd.Settings != "" { | 
					
						
							|  |  |  |  | 		dashboard.UpdateSettings(cmd.Settings) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if cmd.RefreshInterval > 0 { | 
					
						
							|  |  |  |  | 		dashboard.UpdateRefreshInterval(cmd.RefreshInterval) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if cmd.AccessLevel != "" { | 
					
						
							|  |  |  |  | 		dashboard.AccessLevel = cmd.AccessLevel | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 保存仪表板 | 
					
						
							|  |  |  |  | 	err = s.dashboardRepo.Save(ctx, dashboard) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("保存仪表板失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &CommandResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "保存仪表板失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 转换为DTO | 
					
						
							|  |  |  |  | 	dto := s.convertDashboardToDTO(dashboard) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	s.logger.Info("仪表板创建成功", zap.String("dashboard_id", dashboard.ID)) | 
					
						
							|  |  |  |  | 	return &CommandResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "仪表板创建成功", | 
					
						
							|  |  |  |  | 		Data:    dto, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // GetDashboardData 获取仪表板数据 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) GetDashboardData(ctx context.Context, query *GetDashboardDataQuery) (*QueryResponse, error) { | 
					
						
							|  |  |  |  | 	// 验证查询 | 
					
						
							|  |  |  |  | 	if query.UserRole == "" { | 
					
						
							|  |  |  |  | 		return &QueryResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "用户角色不能为空", | 
					
						
							|  |  |  |  | 			Error:   "用户角色不能为空", | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 设置默认时间范围 | 
					
						
							|  |  |  |  | 	if query.StartDate.IsZero() || query.EndDate.IsZero() { | 
					
						
							|  |  |  |  | 		now := time.Now() | 
					
						
							|  |  |  |  | 		switch query.Period { | 
					
						
							|  |  |  |  | 		case "today": | 
					
						
							|  |  |  |  | 			query.StartDate = now.Truncate(24 * time.Hour) | 
					
						
							|  |  |  |  | 			query.EndDate = query.StartDate.Add(24 * time.Hour) | 
					
						
							|  |  |  |  | 		case "week": | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 			query.StartDate = now.Truncate(24*time.Hour).AddDate(0, 0, -7) | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 			query.EndDate = now | 
					
						
							|  |  |  |  | 		case "month": | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 			query.StartDate = now.Truncate(24*time.Hour).AddDate(0, 0, -30) | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 			query.EndDate = now | 
					
						
							|  |  |  |  | 		default: | 
					
						
							|  |  |  |  | 			query.StartDate = now.Truncate(24 * time.Hour) | 
					
						
							|  |  |  |  | 			query.EndDate = query.StartDate.Add(24 * time.Hour) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 构建仪表板数据 | 
					
						
							|  |  |  |  | 	dto := &DashboardDataDTO{} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// API调用统计 | 
					
						
							|  |  |  |  | 	apiCallsTotal, _ := s.calculationService.CalculateTotal(ctx, "api_calls", "total_count", query.StartDate, query.EndDate) | 
					
						
							|  |  |  |  | 	apiCallsSuccess, _ := s.calculationService.CalculateTotal(ctx, "api_calls", "success_count", query.StartDate, query.EndDate) | 
					
						
							|  |  |  |  | 	apiCallsFailed, _ := s.calculationService.CalculateTotal(ctx, "api_calls", "failed_count", query.StartDate, query.EndDate) | 
					
						
							|  |  |  |  | 	avgResponseTime, _ := s.calculationService.CalculateAverage(ctx, "api_calls", "response_time", query.StartDate, query.EndDate) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	dto.APICalls.TotalCount = int64(apiCallsTotal) | 
					
						
							|  |  |  |  | 	dto.APICalls.SuccessCount = int64(apiCallsSuccess) | 
					
						
							|  |  |  |  | 	dto.APICalls.FailedCount = int64(apiCallsFailed) | 
					
						
							|  |  |  |  | 	dto.APICalls.SuccessRate = s.calculateRate(apiCallsSuccess, apiCallsTotal) | 
					
						
							|  |  |  |  | 	dto.APICalls.AvgResponseTime = avgResponseTime | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 用户统计 | 
					
						
							|  |  |  |  | 	usersTotal, _ := s.calculationService.CalculateTotal(ctx, "users", "total_count", query.StartDate, query.EndDate) | 
					
						
							|  |  |  |  | 	usersCertified, _ := s.calculationService.CalculateTotal(ctx, "users", "certified_count", query.StartDate, query.EndDate) | 
					
						
							|  |  |  |  | 	usersActive, _ := s.calculationService.CalculateTotal(ctx, "users", "active_count", query.StartDate, query.EndDate) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	dto.Users.TotalCount = int64(usersTotal) | 
					
						
							|  |  |  |  | 	dto.Users.CertifiedCount = int64(usersCertified) | 
					
						
							|  |  |  |  | 	dto.Users.ActiveCount = int64(usersActive) | 
					
						
							|  |  |  |  | 	dto.Users.CertificationRate = s.calculateRate(usersCertified, usersTotal) | 
					
						
							|  |  |  |  | 	dto.Users.RetentionRate = s.calculateRate(usersActive, usersTotal) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 财务统计 | 
					
						
							|  |  |  |  | 	financeTotal, _ := s.calculationService.CalculateTotal(ctx, "finance", "total_amount", query.StartDate, query.EndDate) | 
					
						
							|  |  |  |  | 	rechargeAmount, _ := s.calculationService.CalculateTotal(ctx, "finance", "recharge_amount", query.StartDate, query.EndDate) | 
					
						
							|  |  |  |  | 	deductAmount, _ := s.calculationService.CalculateTotal(ctx, "finance", "deduct_amount", query.StartDate, query.EndDate) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	dto.Finance.TotalAmount = financeTotal | 
					
						
							|  |  |  |  | 	dto.Finance.RechargeAmount = rechargeAmount | 
					
						
							|  |  |  |  | 	dto.Finance.DeductAmount = deductAmount | 
					
						
							|  |  |  |  | 	dto.Finance.NetAmount = rechargeAmount - deductAmount | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 设置时间信息 | 
					
						
							|  |  |  |  | 	dto.Period.StartDate = query.StartDate.Format("2006-01-02") | 
					
						
							|  |  |  |  | 	dto.Period.EndDate = query.EndDate.Format("2006-01-02") | 
					
						
							|  |  |  |  | 	dto.Period.Period = query.Period | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 设置元数据 | 
					
						
							|  |  |  |  | 	dto.Metadata.GeneratedAt = time.Now().Format("2006-01-02 15:04:05") | 
					
						
							|  |  |  |  | 	dto.Metadata.UserRole = query.UserRole | 
					
						
							|  |  |  |  | 	dto.Metadata.DataVersion = "1.0" | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &QueryResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "获取仪表板数据成功", | 
					
						
							|  |  |  |  | 		Data:    dto, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ================ 报告管理 ================ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // GenerateReport 生成报告 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) GenerateReport(ctx context.Context, cmd *GenerateReportCommand) (*CommandResponse, error) { | 
					
						
							|  |  |  |  | 	// 验证命令 | 
					
						
							|  |  |  |  | 	if err := cmd.Validate(); err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("生成报告命令验证失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &CommandResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "命令验证失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 生成报告 | 
					
						
							|  |  |  |  | 	var report *entities.StatisticsReport | 
					
						
							|  |  |  |  | 	var err error | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	switch cmd.ReportType { | 
					
						
							|  |  |  |  | 	case "dashboard": | 
					
						
							|  |  |  |  | 		report, err = s.reportService.GenerateDashboardReport(ctx, cmd.UserRole, cmd.Period) | 
					
						
							|  |  |  |  | 	case "summary": | 
					
						
							|  |  |  |  | 		report, err = s.reportService.GenerateSummaryReport(ctx, cmd.Period, cmd.StartDate, cmd.EndDate) | 
					
						
							|  |  |  |  | 	case "detailed": | 
					
						
							|  |  |  |  | 		report, err = s.reportService.GenerateDetailedReport(ctx, cmd.Title, cmd.StartDate, cmd.EndDate, cmd.Filters) | 
					
						
							|  |  |  |  | 	default: | 
					
						
							|  |  |  |  | 		return &CommandResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "不支持的报告类型", | 
					
						
							|  |  |  |  | 			Error:   "不支持的报告类型", | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("生成报告失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &CommandResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "生成报告失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 转换为DTO | 
					
						
							|  |  |  |  | 	dto := s.convertReportToDTO(report) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	s.logger.Info("报告生成成功", zap.String("report_id", report.ID)) | 
					
						
							|  |  |  |  | 	return &CommandResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "报告生成成功", | 
					
						
							|  |  |  |  | 		Data:    dto, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ================ 定时任务 ================ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ProcessHourlyAggregation 处理小时级聚合 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) ProcessHourlyAggregation(ctx context.Context, date time.Time) error { | 
					
						
							|  |  |  |  | 	return s.aggregateService.AggregateHourlyMetrics(ctx, date) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ProcessDailyAggregation 处理日级聚合 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) ProcessDailyAggregation(ctx context.Context, date time.Time) error { | 
					
						
							|  |  |  |  | 	return s.aggregateService.AggregateDailyMetrics(ctx, date) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ProcessWeeklyAggregation 处理周级聚合 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) ProcessWeeklyAggregation(ctx context.Context, date time.Time) error { | 
					
						
							|  |  |  |  | 	return s.aggregateService.AggregateWeeklyMetrics(ctx, date) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ProcessMonthlyAggregation 处理月级聚合 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) ProcessMonthlyAggregation(ctx context.Context, date time.Time) error { | 
					
						
							|  |  |  |  | 	return s.aggregateService.AggregateMonthlyMetrics(ctx, date) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // CleanupExpiredData 清理过期数据 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) CleanupExpiredData(ctx context.Context) error { | 
					
						
							|  |  |  |  | 	return s.reportService.CleanupExpiredReports(ctx) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ================ 辅助方法 ================ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // convertMetricToDTO 转换指标实体为DTO | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) convertMetricToDTO(metric *entities.StatisticsMetric) *StatisticsMetricDTO { | 
					
						
							|  |  |  |  | 	return &StatisticsMetricDTO{ | 
					
						
							|  |  |  |  | 		ID:         metric.ID, | 
					
						
							|  |  |  |  | 		MetricType: metric.MetricType, | 
					
						
							|  |  |  |  | 		MetricName: metric.MetricName, | 
					
						
							|  |  |  |  | 		Dimension:  metric.Dimension, | 
					
						
							|  |  |  |  | 		Value:      metric.Value, | 
					
						
							|  |  |  |  | 		Metadata:   metric.Metadata, | 
					
						
							|  |  |  |  | 		Date:       metric.Date, | 
					
						
							|  |  |  |  | 		CreatedAt:  metric.CreatedAt, | 
					
						
							|  |  |  |  | 		UpdatedAt:  metric.UpdatedAt, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // convertReportToDTO 转换报告实体为DTO | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) convertReportToDTO(report *entities.StatisticsReport) *StatisticsReportDTO { | 
					
						
							|  |  |  |  | 	return &StatisticsReportDTO{ | 
					
						
							|  |  |  |  | 		ID:          report.ID, | 
					
						
							|  |  |  |  | 		ReportType:  report.ReportType, | 
					
						
							|  |  |  |  | 		Title:       report.Title, | 
					
						
							|  |  |  |  | 		Content:     report.Content, | 
					
						
							|  |  |  |  | 		Period:      report.Period, | 
					
						
							|  |  |  |  | 		UserRole:    report.UserRole, | 
					
						
							|  |  |  |  | 		Status:      report.Status, | 
					
						
							|  |  |  |  | 		GeneratedBy: report.GeneratedBy, | 
					
						
							|  |  |  |  | 		GeneratedAt: report.GeneratedAt, | 
					
						
							|  |  |  |  | 		ExpiresAt:   report.ExpiresAt, | 
					
						
							|  |  |  |  | 		CreatedAt:   report.CreatedAt, | 
					
						
							|  |  |  |  | 		UpdatedAt:   report.UpdatedAt, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // convertDashboardToDTO 转换仪表板实体为DTO | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) convertDashboardToDTO(dashboard *entities.StatisticsDashboard) *StatisticsDashboardDTO { | 
					
						
							|  |  |  |  | 	return &StatisticsDashboardDTO{ | 
					
						
							|  |  |  |  | 		ID:              dashboard.ID, | 
					
						
							|  |  |  |  | 		Name:            dashboard.Name, | 
					
						
							|  |  |  |  | 		Description:     dashboard.Description, | 
					
						
							|  |  |  |  | 		UserRole:        dashboard.UserRole, | 
					
						
							|  |  |  |  | 		IsDefault:       dashboard.IsDefault, | 
					
						
							|  |  |  |  | 		IsActive:        dashboard.IsActive, | 
					
						
							|  |  |  |  | 		Layout:          dashboard.Layout, | 
					
						
							|  |  |  |  | 		Widgets:         dashboard.Widgets, | 
					
						
							|  |  |  |  | 		Settings:        dashboard.Settings, | 
					
						
							|  |  |  |  | 		RefreshInterval: dashboard.RefreshInterval, | 
					
						
							|  |  |  |  | 		CreatedBy:       dashboard.CreatedBy, | 
					
						
							|  |  |  |  | 		AccessLevel:     dashboard.AccessLevel, | 
					
						
							|  |  |  |  | 		CreatedAt:       dashboard.CreatedAt, | 
					
						
							|  |  |  |  | 		UpdatedAt:       dashboard.UpdatedAt, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // calculateRate 计算比率 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) calculateRate(numerator, denominator float64) float64 { | 
					
						
							|  |  |  |  | 	if denominator == 0 { | 
					
						
							|  |  |  |  | 		return 0 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return (numerator / denominator) * 100 | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ================ 其他方法的简化实现 ================ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // UpdateDashboard 更新仪表板 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) UpdateDashboard(ctx context.Context, cmd *UpdateDashboardCommand) (*CommandResponse, error) { | 
					
						
							|  |  |  |  | 	// 验证命令 | 
					
						
							|  |  |  |  | 	if err := cmd.Validate(); err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("更新仪表板命令验证失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &CommandResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "命令验证失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取仪表板 | 
					
						
							|  |  |  |  | 	dashboard, err := s.dashboardRepo.FindByID(ctx, cmd.ID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("查询仪表板失败", zap.String("dashboard_id", cmd.ID), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &CommandResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "查询仪表板失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 更新仪表板信息 | 
					
						
							|  |  |  |  | 	if cmd.Name != "" { | 
					
						
							|  |  |  |  | 		// 直接设置字段值,因为实体没有UpdateName方法 | 
					
						
							|  |  |  |  | 		dashboard.Name = cmd.Name | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if cmd.Description != "" { | 
					
						
							|  |  |  |  | 		// 直接设置字段值,因为实体没有UpdateDescription方法 | 
					
						
							|  |  |  |  | 		dashboard.Description = cmd.Description | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if cmd.Layout != "" { | 
					
						
							|  |  |  |  | 		dashboard.UpdateLayout(cmd.Layout) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if cmd.Widgets != "" { | 
					
						
							|  |  |  |  | 		dashboard.UpdateWidgets(cmd.Widgets) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if cmd.Settings != "" { | 
					
						
							|  |  |  |  | 		dashboard.UpdateSettings(cmd.Settings) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if cmd.RefreshInterval > 0 { | 
					
						
							|  |  |  |  | 		dashboard.UpdateRefreshInterval(cmd.RefreshInterval) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if cmd.AccessLevel != "" { | 
					
						
							|  |  |  |  | 		dashboard.AccessLevel = cmd.AccessLevel | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 保存更新 | 
					
						
							|  |  |  |  | 	err = s.dashboardRepo.Update(ctx, dashboard) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("保存仪表板更新失败", zap.String("dashboard_id", cmd.ID), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &CommandResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "保存仪表板更新失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 转换为DTO | 
					
						
							|  |  |  |  | 	dto := s.convertDashboardToDTO(dashboard) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	s.logger.Info("仪表板更新成功", zap.String("dashboard_id", cmd.ID)) | 
					
						
							|  |  |  |  | 	return &CommandResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "仪表板更新成功", | 
					
						
							|  |  |  |  | 		Data:    dto, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // DeleteDashboard 删除仪表板 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) DeleteDashboard(ctx context.Context, cmd *DeleteDashboardCommand) (*CommandResponse, error) { | 
					
						
							|  |  |  |  | 	// 验证命令 | 
					
						
							|  |  |  |  | 	if cmd.DashboardID == "" { | 
					
						
							|  |  |  |  | 		return &CommandResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "仪表板ID不能为空", | 
					
						
							|  |  |  |  | 			Error:   "仪表板ID不能为空", | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 检查仪表板是否存在 | 
					
						
							|  |  |  |  | 	_, err := s.dashboardRepo.FindByID(ctx, cmd.DashboardID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("查询仪表板失败", zap.String("dashboard_id", cmd.DashboardID), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &CommandResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "仪表板不存在", | 
					
						
							|  |  |  |  | 			Error:   "仪表板不存在", | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 删除仪表板 | 
					
						
							|  |  |  |  | 	err = s.dashboardRepo.Delete(ctx, cmd.DashboardID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("删除仪表板失败", zap.String("dashboard_id", cmd.DashboardID), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &CommandResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "删除仪表板失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	s.logger.Info("仪表板删除成功", zap.String("dashboard_id", cmd.DashboardID)) | 
					
						
							|  |  |  |  | 	return &CommandResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "仪表板删除成功", | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // GetDashboard 获取单个仪表板 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) GetDashboard(ctx context.Context, query *GetDashboardQuery) (*QueryResponse, error) { | 
					
						
							|  |  |  |  | 	// 验证查询 | 
					
						
							|  |  |  |  | 	if query.DashboardID == "" { | 
					
						
							|  |  |  |  | 		return &QueryResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "仪表板ID不能为空", | 
					
						
							|  |  |  |  | 			Error:   "仪表板ID不能为空", | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 查询仪表板 | 
					
						
							|  |  |  |  | 	dashboard, err := s.dashboardRepo.FindByID(ctx, query.DashboardID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("查询仪表板失败", zap.String("dashboard_id", query.DashboardID), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &QueryResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "查询仪表板失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 转换为DTO | 
					
						
							|  |  |  |  | 	dto := s.convertDashboardToDTO(dashboard) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &QueryResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "查询成功", | 
					
						
							|  |  |  |  | 		Data:    dto, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // GetDashboards 获取仪表板列表 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) GetDashboards(ctx context.Context, query *GetDashboardsQuery) (*ListResponse, error) { | 
					
						
							|  |  |  |  | 	// 设置默认值 | 
					
						
							|  |  |  |  | 	if query.Limit <= 0 { | 
					
						
							|  |  |  |  | 		query.Limit = 20 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if query.Limit > 1000 { | 
					
						
							|  |  |  |  | 		query.Limit = 1000 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 查询仪表板列表 | 
					
						
							|  |  |  |  | 	var dashboards []*entities.StatisticsDashboard | 
					
						
							|  |  |  |  | 	var err error | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if query.UserRole != "" { | 
					
						
							|  |  |  |  | 		dashboards, err = s.dashboardRepo.FindByUserRole(ctx, query.UserRole, query.Limit, query.Offset) | 
					
						
							|  |  |  |  | 	} else if query.CreatedBy != "" { | 
					
						
							|  |  |  |  | 		dashboards, err = s.dashboardRepo.FindByUser(ctx, query.CreatedBy, query.Limit, query.Offset) | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		// 如果没有指定条件,返回空列表 | 
					
						
							|  |  |  |  | 		dashboards = []*entities.StatisticsDashboard{} | 
					
						
							|  |  |  |  | 		err = nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("查询仪表板列表失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &ListResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "查询仪表板列表失败", | 
					
						
							|  |  |  |  | 			Data:    ListDataDTO{}, | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 转换为DTO | 
					
						
							|  |  |  |  | 	var dtos []interface{} | 
					
						
							|  |  |  |  | 	for _, dashboard := range dashboards { | 
					
						
							|  |  |  |  | 		dtos = append(dtos, s.convertDashboardToDTO(dashboard)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 计算分页信息 | 
					
						
							|  |  |  |  | 	total := int64(len(dashboards)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &ListResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "查询成功", | 
					
						
							|  |  |  |  | 		Data: ListDataDTO{ | 
					
						
							|  |  |  |  | 			Total: total, | 
					
						
							|  |  |  |  | 			Page:  query.Offset/query.Limit + 1, | 
					
						
							|  |  |  |  | 			Size:  query.Limit, | 
					
						
							|  |  |  |  | 			Items: dtos, | 
					
						
							|  |  |  |  | 		}, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // SetDefaultDashboard 设置默认仪表板 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) SetDefaultDashboard(ctx context.Context, cmd *SetDefaultDashboardCommand) (*CommandResponse, error) { | 
					
						
							|  |  |  |  | 	// 简化实现,实际应该完整实现 | 
					
						
							|  |  |  |  | 	return &CommandResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "设置默认仪表板成功", | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ActivateDashboard 激活仪表板 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) ActivateDashboard(ctx context.Context, cmd *ActivateDashboardCommand) (*CommandResponse, error) { | 
					
						
							|  |  |  |  | 	// 简化实现,实际应该完整实现 | 
					
						
							|  |  |  |  | 	return &CommandResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "激活仪表板成功", | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // DeactivateDashboard 停用仪表板 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) DeactivateDashboard(ctx context.Context, cmd *DeactivateDashboardCommand) (*CommandResponse, error) { | 
					
						
							|  |  |  |  | 	// 简化实现,实际应该完整实现 | 
					
						
							|  |  |  |  | 	return &CommandResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "停用仪表板成功", | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // GetReport 获取单个报告 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) GetReport(ctx context.Context, query *GetReportQuery) (*QueryResponse, error) { | 
					
						
							|  |  |  |  | 	// 简化实现,实际应该完整实现 | 
					
						
							|  |  |  |  | 	return &QueryResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "查询成功", | 
					
						
							|  |  |  |  | 		Data:    map[string]interface{}{}, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // GetReports 获取报告列表 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) GetReports(ctx context.Context, query *GetReportsQuery) (*ListResponse, error) { | 
					
						
							|  |  |  |  | 	// 简化实现,实际应该完整实现 | 
					
						
							|  |  |  |  | 	return &ListResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "查询成功", | 
					
						
							|  |  |  |  | 		Data: ListDataDTO{ | 
					
						
							|  |  |  |  | 			Total: 0, | 
					
						
							|  |  |  |  | 			Page:  1, | 
					
						
							|  |  |  |  | 			Size:  query.Limit, | 
					
						
							|  |  |  |  | 			Items: []interface{}{}, | 
					
						
							|  |  |  |  | 		}, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // DeleteReport 删除报告 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) DeleteReport(ctx context.Context, reportID string) (*CommandResponse, error) { | 
					
						
							|  |  |  |  | 	// 简化实现,实际应该完整实现 | 
					
						
							|  |  |  |  | 	return &CommandResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "报告删除成功", | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // CalculateGrowthRate 计算增长率 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) CalculateGrowthRate(ctx context.Context, query *CalculateGrowthRateQuery) (*QueryResponse, error) { | 
					
						
							|  |  |  |  | 	// 简化实现,实际应该完整实现 | 
					
						
							|  |  |  |  | 	return &QueryResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "计算增长率成功", | 
					
						
							|  |  |  |  | 		Data:    map[string]interface{}{"growth_rate": 0.0}, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // CalculateTrend 计算趋势 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) CalculateTrend(ctx context.Context, query *CalculateTrendQuery) (*QueryResponse, error) { | 
					
						
							|  |  |  |  | 	// 简化实现,实际应该完整实现 | 
					
						
							|  |  |  |  | 	return &QueryResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "计算趋势成功", | 
					
						
							|  |  |  |  | 		Data:    map[string]interface{}{"trend": "stable"}, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // CalculateCorrelation 计算相关性 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) CalculateCorrelation(ctx context.Context, query *CalculateCorrelationQuery) (*QueryResponse, error) { | 
					
						
							|  |  |  |  | 	// 简化实现,实际应该完整实现 | 
					
						
							|  |  |  |  | 	return &QueryResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "计算相关性成功", | 
					
						
							|  |  |  |  | 		Data:    map[string]interface{}{"correlation": 0.0}, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // CalculateMovingAverage 计算移动平均 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) CalculateMovingAverage(ctx context.Context, query *CalculateMovingAverageQuery) (*QueryResponse, error) { | 
					
						
							|  |  |  |  | 	// 简化实现,实际应该完整实现 | 
					
						
							|  |  |  |  | 	return &QueryResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "计算移动平均成功", | 
					
						
							|  |  |  |  | 		Data:    map[string]interface{}{"moving_averages": []float64{}}, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // CalculateSeasonality 计算季节性 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) CalculateSeasonality(ctx context.Context, query *CalculateSeasonalityQuery) (*QueryResponse, error) { | 
					
						
							|  |  |  |  | 	// 简化实现,实际应该完整实现 | 
					
						
							|  |  |  |  | 	return &QueryResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "计算季节性成功", | 
					
						
							|  |  |  |  | 		Data:    map[string]interface{}{"seasonality": map[string]float64{}}, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ExportData 导出数据 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) ExportData(ctx context.Context, cmd *ExportDataCommand) (*CommandResponse, error) { | 
					
						
							|  |  |  |  | 	// 简化实现,实际应该完整实现 | 
					
						
							|  |  |  |  | 	return &CommandResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "数据导出成功", | 
					
						
							|  |  |  |  | 		Data:    map[string]interface{}{"download_url": ""}, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ================ 管理员专用方法 ================ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // AdminGetSystemStatistics 管理员获取系统统计 - 简化版 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) AdminGetSystemStatistics(ctx context.Context, period, startDate, endDate string) (*QueryResponse, error) { | 
					
						
							|  |  |  |  | 	// 解析时间参数 | 
					
						
							|  |  |  |  | 	var startTime, endTime time.Time | 
					
						
							|  |  |  |  | 	var err error | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	if startDate != "" { | 
					
						
							|  |  |  |  | 		startTime, err = time.Parse("2006-01-02", startDate) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("开始日期格式错误", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return &QueryResponse{ | 
					
						
							|  |  |  |  | 				Success: false, | 
					
						
							|  |  |  |  | 				Message: "开始日期格式错误", | 
					
						
							|  |  |  |  | 				Error:   err.Error(), | 
					
						
							|  |  |  |  | 			}, nil | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	if endDate != "" { | 
					
						
							|  |  |  |  | 		endTime, err = time.Parse("2006-01-02", endDate) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("结束日期格式错误", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return &QueryResponse{ | 
					
						
							|  |  |  |  | 				Success: false, | 
					
						
							|  |  |  |  | 				Message: "结束日期格式错误", | 
					
						
							|  |  |  |  | 				Error:   err.Error(), | 
					
						
							|  |  |  |  | 			}, nil | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取系统统计数据,传递时间参数 | 
					
						
							|  |  |  |  | 	systemStats, err := s.getAdminSystemStats(ctx, period, startTime, endTime) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取系统统计失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &QueryResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "获取系统统计失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 添加查询参数 | 
					
						
							|  |  |  |  | 	systemStats["period"] = period | 
					
						
							|  |  |  |  | 	systemStats["start_date"] = startDate | 
					
						
							|  |  |  |  | 	systemStats["end_date"] = endDate | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	s.logger.Info("管理员获取系统统计", zap.String("period", period), zap.String("start_date", startDate), zap.String("end_date", endDate)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &QueryResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "获取系统统计成功", | 
					
						
							|  |  |  |  | 		Data:    systemStats, | 
					
						
							|  |  |  |  | 		Meta: map[string]interface{}{ | 
					
						
							|  |  |  |  | 			"generated_at": time.Now(), | 
					
						
							|  |  |  |  | 			"period_type":  period, | 
					
						
							|  |  |  |  | 		}, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // AdminTriggerAggregation 管理员触发数据聚合 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) AdminTriggerAggregation(ctx context.Context, cmd *TriggerAggregationCommand) (*CommandResponse, error) { | 
					
						
							|  |  |  |  | 	// 验证命令 | 
					
						
							|  |  |  |  | 	if err := cmd.Validate(); err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("触发聚合命令验证失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &CommandResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "命令验证失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 根据周期类型执行不同的聚合任务 | 
					
						
							|  |  |  |  | 	var err error | 
					
						
							|  |  |  |  | 	switch cmd.Period { | 
					
						
							|  |  |  |  | 	case "hourly": | 
					
						
							|  |  |  |  | 		err = s.ProcessHourlyAggregation(ctx, cmd.StartDate) | 
					
						
							|  |  |  |  | 	case "daily": | 
					
						
							|  |  |  |  | 		err = s.ProcessDailyAggregation(ctx, cmd.StartDate) | 
					
						
							|  |  |  |  | 	case "weekly": | 
					
						
							|  |  |  |  | 		err = s.ProcessWeeklyAggregation(ctx, cmd.StartDate) | 
					
						
							|  |  |  |  | 	case "monthly": | 
					
						
							|  |  |  |  | 		err = s.ProcessMonthlyAggregation(ctx, cmd.StartDate) | 
					
						
							|  |  |  |  | 	default: | 
					
						
							|  |  |  |  | 		return &CommandResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "不支持的聚合周期", | 
					
						
							|  |  |  |  | 			Error:   "不支持的聚合周期", | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("触发聚合失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &CommandResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "触发聚合失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 	s.logger.Info("管理员触发聚合成功", | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 		zap.String("metric_type", cmd.MetricType), | 
					
						
							|  |  |  |  | 		zap.String("period", cmd.Period), | 
					
						
							|  |  |  |  | 		zap.String("triggered_by", cmd.TriggeredBy)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &CommandResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "触发数据聚合成功", | 
					
						
							|  |  |  |  | 		Data: map[string]interface{}{ | 
					
						
							|  |  |  |  | 			"metric_type": cmd.MetricType, | 
					
						
							|  |  |  |  | 			"period":      cmd.Period, | 
					
						
							|  |  |  |  | 			"start_date":  cmd.StartDate, | 
					
						
							|  |  |  |  | 			"end_date":    cmd.EndDate, | 
					
						
							|  |  |  |  | 			"force":       cmd.Force, | 
					
						
							|  |  |  |  | 		}, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ================ 公开和用户统计方法 ================ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // GetPublicStatistics 获取公开统计信息 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) GetPublicStatistics(ctx context.Context) (*QueryResponse, error) { | 
					
						
							|  |  |  |  | 	// 获取公开的统计信息 | 
					
						
							|  |  |  |  | 	publicStats := map[string]interface{}{ | 
					
						
							|  |  |  |  | 		"total_users":      0, | 
					
						
							|  |  |  |  | 		"total_products":   0, | 
					
						
							|  |  |  |  | 		"total_categories": 0, | 
					
						
							|  |  |  |  | 		"total_api_calls":  0, | 
					
						
							|  |  |  |  | 		"system_uptime":    "0天", | 
					
						
							|  |  |  |  | 		"last_updated":     time.Now(), | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 实际实现中应该查询数据库获取真实数据 | 
					
						
							|  |  |  |  | 	// 这里暂时返回模拟数据 | 
					
						
							|  |  |  |  | 	s.logger.Info("获取公开统计信息") | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &QueryResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "获取公开统计信息成功", | 
					
						
							|  |  |  |  | 		Data:    publicStats, | 
					
						
							|  |  |  |  | 		Meta: map[string]interface{}{ | 
					
						
							|  |  |  |  | 			"generated_at": time.Now(), | 
					
						
							|  |  |  |  | 			"cache_ttl":    300, // 5分钟缓存 | 
					
						
							|  |  |  |  | 		}, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // GetUserStatistics 获取用户统计信息 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) GetUserStatistics(ctx context.Context, userID string) (*QueryResponse, error) { | 
					
						
							|  |  |  |  | 	// 验证用户ID | 
					
						
							|  |  |  |  | 	if userID == "" { | 
					
						
							|  |  |  |  | 		return &QueryResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "用户ID不能为空", | 
					
						
							|  |  |  |  | 			Error:   "用户ID不能为空", | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取用户API调用统计 | 
					
						
							|  |  |  |  | 	apiCalls, err := s.getUserApiCallsStats(ctx, userID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取用户API调用统计失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &QueryResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "获取API调用统计失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取用户消费统计 | 
					
						
							|  |  |  |  | 	consumption, err := s.getUserConsumptionStats(ctx, userID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取用户消费统计失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &QueryResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "获取消费统计失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取用户充值统计 | 
					
						
							|  |  |  |  | 	recharge, err := s.getUserRechargeStats(ctx, userID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取用户充值统计失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &QueryResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "获取充值统计失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 组装用户统计数据 | 
					
						
							|  |  |  |  | 	userStats := map[string]interface{}{ | 
					
						
							|  |  |  |  | 		"user_id":     userID, | 
					
						
							|  |  |  |  | 		"api_calls":   apiCalls, | 
					
						
							|  |  |  |  | 		"consumption": consumption, | 
					
						
							|  |  |  |  | 		"recharge":    recharge, | 
					
						
							|  |  |  |  | 		"summary": map[string]interface{}{ | 
					
						
							|  |  |  |  | 			"total_calls":     apiCalls["total_calls"], | 
					
						
							|  |  |  |  | 			"total_consumed":  consumption["total_amount"], | 
					
						
							|  |  |  |  | 			"total_recharged": recharge["total_amount"], | 
					
						
							|  |  |  |  | 			"balance":         recharge["total_amount"].(float64) - consumption["total_amount"].(float64), | 
					
						
							|  |  |  |  | 		}, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	s.logger.Info("获取用户统计信息", zap.String("user_id", userID)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &QueryResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "获取用户统计信息成功", | 
					
						
							|  |  |  |  | 		Data:    userStats, | 
					
						
							|  |  |  |  | 		Meta: map[string]interface{}{ | 
					
						
							|  |  |  |  | 			"generated_at": time.Now(), | 
					
						
							|  |  |  |  | 			"user_id":      userID, | 
					
						
							|  |  |  |  | 		}, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ================ 简化版统计辅助方法 ================ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // getUserApiCallsStats 获取用户API调用统计 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) getUserApiCallsStats(ctx context.Context, userID string) (map[string]interface{}, error) { | 
					
						
							|  |  |  |  | 	// 获取总调用次数 | 
					
						
							|  |  |  |  | 	totalCalls, err := s.apiCallRepo.CountByUserId(ctx, userID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取用户API调用总数失败", zap.String("user_id", userID), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取今日调用次数 | 
					
						
							|  |  |  |  | 	today := time.Now().Truncate(24 * time.Hour) | 
					
						
							|  |  |  |  | 	tomorrow := today.Add(24 * time.Hour) | 
					
						
							|  |  |  |  | 	todayCalls, err := s.getApiCallsCountByDateRange(ctx, userID, today, tomorrow) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取今日API调用次数失败", zap.String("user_id", userID), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取本月调用次数 | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 	monthStart := time.Now().Truncate(24*time.Hour).AddDate(0, 0, -time.Now().Day()+1) | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	monthEnd := monthStart.AddDate(0, 1, 0) | 
					
						
							|  |  |  |  | 	monthCalls, err := s.getApiCallsCountByDateRange(ctx, userID, monthStart, monthEnd) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取本月API调用次数失败", zap.String("user_id", userID), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取每日趋势(最近7天) | 
					
						
							|  |  |  |  | 	endDate := time.Now() | 
					
						
							|  |  |  |  | 	startDate := endDate.AddDate(0, 0, -7) | 
					
						
							|  |  |  |  | 	dailyTrend, err := s.getApiCallsDailyTrend(ctx, userID, startDate, endDate) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取API调用每日趋势失败", zap.String("user_id", userID), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取每月趋势(最近6个月) | 
					
						
							|  |  |  |  | 	endDate = time.Now() | 
					
						
							|  |  |  |  | 	startDate = endDate.AddDate(0, -6, 0) | 
					
						
							|  |  |  |  | 	monthlyTrend, err := s.getApiCallsMonthlyTrend(ctx, userID, startDate, endDate) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取API调用每月趋势失败", zap.String("user_id", userID), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	stats := map[string]interface{}{ | 
					
						
							|  |  |  |  | 		"total_calls":      totalCalls, | 
					
						
							|  |  |  |  | 		"today_calls":      todayCalls, | 
					
						
							|  |  |  |  | 		"this_month_calls": monthCalls, | 
					
						
							|  |  |  |  | 		"daily_trend":      dailyTrend, | 
					
						
							|  |  |  |  | 		"monthly_trend":    monthlyTrend, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return stats, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // getUserConsumptionStats 获取用户消费统计 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) getUserConsumptionStats(ctx context.Context, userID string) (map[string]interface{}, error) { | 
					
						
							|  |  |  |  | 	// 获取总消费金额 | 
					
						
							|  |  |  |  | 	totalAmount, err := s.getTotalWalletTransactionAmount(ctx, userID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取用户总消费金额失败", zap.String("user_id", userID), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取今日消费金额 | 
					
						
							|  |  |  |  | 	today := time.Now().Truncate(24 * time.Hour) | 
					
						
							|  |  |  |  | 	tomorrow := today.Add(24 * time.Hour) | 
					
						
							|  |  |  |  | 	todayAmount, err := s.getWalletTransactionsByDateRange(ctx, userID, today, tomorrow) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取今日消费金额失败", zap.String("user_id", userID), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取本月消费金额 | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 	monthStart := time.Now().Truncate(24*time.Hour).AddDate(0, 0, -time.Now().Day()+1) | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	monthEnd := monthStart.AddDate(0, 1, 0) | 
					
						
							|  |  |  |  | 	monthAmount, err := s.getWalletTransactionsByDateRange(ctx, userID, monthStart, monthEnd) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取本月消费金额失败", zap.String("user_id", userID), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取每日趋势(最近7天) | 
					
						
							|  |  |  |  | 	endDate := time.Now() | 
					
						
							|  |  |  |  | 	startDate := endDate.AddDate(0, 0, -7) | 
					
						
							|  |  |  |  | 	dailyTrend, err := s.getConsumptionDailyTrend(ctx, userID, startDate, endDate) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取消费每日趋势失败", zap.String("user_id", userID), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取每月趋势(最近6个月) | 
					
						
							|  |  |  |  | 	endDate = time.Now() | 
					
						
							|  |  |  |  | 	startDate = endDate.AddDate(0, -6, 0) | 
					
						
							|  |  |  |  | 	monthlyTrend, err := s.getConsumptionMonthlyTrend(ctx, userID, startDate, endDate) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取消费每月趋势失败", zap.String("user_id", userID), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	stats := map[string]interface{}{ | 
					
						
							|  |  |  |  | 		"total_amount":      totalAmount, | 
					
						
							|  |  |  |  | 		"today_amount":      todayAmount, | 
					
						
							|  |  |  |  | 		"this_month_amount": monthAmount, | 
					
						
							|  |  |  |  | 		"daily_trend":       dailyTrend, | 
					
						
							|  |  |  |  | 		"monthly_trend":     monthlyTrend, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return stats, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // getUserRechargeStats 获取用户充值统计 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) getUserRechargeStats(ctx context.Context, userID string) (map[string]interface{}, error) { | 
					
						
							|  |  |  |  | 	// 获取总充值金额 | 
					
						
							|  |  |  |  | 	totalAmount, err := s.getTotalRechargeAmount(ctx, userID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取用户总充值金额失败", zap.String("user_id", userID), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取今日充值金额 | 
					
						
							|  |  |  |  | 	today := time.Now().Truncate(24 * time.Hour) | 
					
						
							|  |  |  |  | 	tomorrow := today.Add(24 * time.Hour) | 
					
						
							|  |  |  |  | 	todayAmount, err := s.getRechargeRecordsByDateRange(ctx, userID, today, tomorrow) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取今日充值金额失败", zap.String("user_id", userID), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取本月充值金额 | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 	monthStart := time.Now().Truncate(24*time.Hour).AddDate(0, 0, -time.Now().Day()+1) | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	monthEnd := monthStart.AddDate(0, 1, 0) | 
					
						
							|  |  |  |  | 	monthAmount, err := s.getRechargeRecordsByDateRange(ctx, userID, monthStart, monthEnd) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取本月充值金额失败", zap.String("user_id", userID), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取每日趋势(最近7天) | 
					
						
							|  |  |  |  | 	endDate := time.Now() | 
					
						
							|  |  |  |  | 	startDate := endDate.AddDate(0, 0, -7) | 
					
						
							|  |  |  |  | 	dailyTrend, err := s.getRechargeDailyTrend(ctx, userID, startDate, endDate) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取充值每日趋势失败", zap.String("user_id", userID), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取每月趋势(最近6个月) | 
					
						
							|  |  |  |  | 	endDate = time.Now() | 
					
						
							|  |  |  |  | 	startDate = endDate.AddDate(0, -6, 0) | 
					
						
							|  |  |  |  | 	monthlyTrend, err := s.getRechargeMonthlyTrend(ctx, userID, startDate, endDate) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取充值每月趋势失败", zap.String("user_id", userID), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	stats := map[string]interface{}{ | 
					
						
							|  |  |  |  | 		"total_amount":      totalAmount, | 
					
						
							|  |  |  |  | 		"today_amount":      todayAmount, | 
					
						
							|  |  |  |  | 		"this_month_amount": monthAmount, | 
					
						
							|  |  |  |  | 		"daily_trend":       dailyTrend, | 
					
						
							|  |  |  |  | 		"monthly_trend":     monthlyTrend, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return stats, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // getAdminSystemStats 获取管理员系统统计 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) getAdminSystemStats(ctx context.Context, period string, startTime, endTime time.Time) (map[string]interface{}, error) { | 
					
						
							|  |  |  |  | 	// 获取用户统计 | 
					
						
							|  |  |  |  | 	userStats, err := s.getUserStats(ctx, period, startTime, endTime) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取用户统计失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取认证统计 | 
					
						
							|  |  |  |  | 	certificationStats, err := s.getCertificationStats(ctx, period, startTime, endTime) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取认证统计失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取API调用统计 | 
					
						
							|  |  |  |  | 	apiCallStats, err := s.getSystemApiCallStats(ctx, period, startTime, endTime) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取API调用统计失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取财务统计 | 
					
						
							|  |  |  |  | 	financeStats, err := s.getSystemFinanceStats(ctx, period, startTime, endTime) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取财务统计失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	stats := map[string]interface{}{ | 
					
						
							|  |  |  |  | 		"users":         userStats, | 
					
						
							|  |  |  |  | 		"certification": certificationStats, | 
					
						
							|  |  |  |  | 		"api_calls":     apiCallStats, | 
					
						
							|  |  |  |  | 		"finance":       financeStats, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return stats, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // AdminGetUserStatistics 管理员获取单个用户统计 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) AdminGetUserStatistics(ctx context.Context, userID string) (*QueryResponse, error) { | 
					
						
							|  |  |  |  | 	// 验证用户ID | 
					
						
							|  |  |  |  | 	if userID == "" { | 
					
						
							|  |  |  |  | 		return &QueryResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "用户ID不能为空", | 
					
						
							|  |  |  |  | 			Error:   "用户ID不能为空", | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取用户API调用统计 | 
					
						
							|  |  |  |  | 	apiCalls, err := s.getUserApiCallsStats(ctx, userID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取用户API调用统计失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &QueryResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "获取API调用统计失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取用户消费统计 | 
					
						
							|  |  |  |  | 	consumption, err := s.getUserConsumptionStats(ctx, userID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取用户消费统计失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &QueryResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "获取消费统计失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取用户充值统计 | 
					
						
							|  |  |  |  | 	recharge, err := s.getUserRechargeStats(ctx, userID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取用户充值统计失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return &QueryResponse{ | 
					
						
							|  |  |  |  | 			Success: false, | 
					
						
							|  |  |  |  | 			Message: "获取充值统计失败", | 
					
						
							|  |  |  |  | 			Error:   err.Error(), | 
					
						
							|  |  |  |  | 		}, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 组装用户统计数据 | 
					
						
							|  |  |  |  | 	userStats := map[string]interface{}{ | 
					
						
							|  |  |  |  | 		"user_id":     userID, | 
					
						
							|  |  |  |  | 		"api_calls":   apiCalls, | 
					
						
							|  |  |  |  | 		"consumption": consumption, | 
					
						
							|  |  |  |  | 		"recharge":    recharge, | 
					
						
							|  |  |  |  | 		"summary": map[string]interface{}{ | 
					
						
							|  |  |  |  | 			"total_calls":     apiCalls["total_calls"], | 
					
						
							|  |  |  |  | 			"total_consumed":  consumption["total_amount"], | 
					
						
							|  |  |  |  | 			"total_recharged": recharge["total_amount"], | 
					
						
							|  |  |  |  | 			"balance":         recharge["total_amount"].(float64) - consumption["total_amount"].(float64), | 
					
						
							|  |  |  |  | 		}, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	s.logger.Info("管理员获取用户统计", zap.String("user_id", userID)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &QueryResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "获取用户统计成功", | 
					
						
							|  |  |  |  | 		Data:    userStats, | 
					
						
							|  |  |  |  | 		Meta: map[string]interface{}{ | 
					
						
							|  |  |  |  | 			"generated_at": time.Now(), | 
					
						
							|  |  |  |  | 			"user_id":      userID, | 
					
						
							|  |  |  |  | 		}, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ================ 统计查询辅助方法 ================ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // getApiCallsCountByDateRange 获取指定日期范围内的API调用次数 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) getApiCallsCountByDateRange(ctx context.Context, userID string, startDate, endDate time.Time) (int64, error) { | 
					
						
							|  |  |  |  | 	return s.apiCallRepo.CountByUserIdAndDateRange(ctx, userID, startDate, endDate) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // getApiCallsDailyTrend 获取API调用每日趋势 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) getApiCallsDailyTrend(ctx context.Context, userID string, startDate, endDate time.Time) ([]map[string]interface{}, error) { | 
					
						
							|  |  |  |  | 	return s.apiCallRepo.GetDailyStatsByUserId(ctx, userID, startDate, endDate) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // getApiCallsMonthlyTrend 获取API调用每月趋势 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) getApiCallsMonthlyTrend(ctx context.Context, userID string, startDate, endDate time.Time) ([]map[string]interface{}, error) { | 
					
						
							|  |  |  |  | 	return s.apiCallRepo.GetMonthlyStatsByUserId(ctx, userID, startDate, endDate) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ================ 更多统计查询辅助方法 ================ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // getTotalWalletTransactionAmount 获取用户总钱包交易金额 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) getTotalWalletTransactionAmount(ctx context.Context, userID string) (float64, error) { | 
					
						
							|  |  |  |  | 	return s.walletTransactionRepo.GetTotalAmountByUserId(ctx, userID) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // getTotalRechargeAmount 获取用户总充值金额 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) getTotalRechargeAmount(ctx context.Context, userID string) (float64, error) { | 
					
						
							|  |  |  |  | 	return s.rechargeRecordRepo.GetTotalAmountByUserId(ctx, userID) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // getConsumptionDailyTrend 获取消费每日趋势 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) getConsumptionDailyTrend(ctx context.Context, userID string, startDate, endDate time.Time) ([]map[string]interface{}, error) { | 
					
						
							|  |  |  |  | 	return s.walletTransactionRepo.GetDailyStatsByUserId(ctx, userID, startDate, endDate) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // getConsumptionMonthlyTrend 获取消费每月趋势 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) getConsumptionMonthlyTrend(ctx context.Context, userID string, startDate, endDate time.Time) ([]map[string]interface{}, error) { | 
					
						
							|  |  |  |  | 	return s.walletTransactionRepo.GetMonthlyStatsByUserId(ctx, userID, startDate, endDate) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // getRechargeDailyTrend 获取充值每日趋势 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) getRechargeDailyTrend(ctx context.Context, userID string, startDate, endDate time.Time) ([]map[string]interface{}, error) { | 
					
						
							|  |  |  |  | 	return s.rechargeRecordRepo.GetDailyStatsByUserId(ctx, userID, startDate, endDate) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // getRechargeMonthlyTrend 获取充值每月趋势 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) getRechargeMonthlyTrend(ctx context.Context, userID string, startDate, endDate time.Time) ([]map[string]interface{}, error) { | 
					
						
							|  |  |  |  | 	return s.rechargeRecordRepo.GetMonthlyStatsByUserId(ctx, userID, startDate, endDate) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // getUserStats 获取用户统计 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) getUserStats(ctx context.Context, period string, startTime, endTime time.Time) (map[string]interface{}, error) { | 
					
						
							|  |  |  |  | 	// 获取系统用户统计信息 | 
					
						
							|  |  |  |  | 	userStats, err := s.userRepo.GetSystemUserStats(ctx) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取用户统计失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 根据时间范围获取趋势数据 | 
					
						
							|  |  |  |  | 	var trendData []map[string]interface{} | 
					
						
							|  |  |  |  | 	if !startTime.IsZero() && !endTime.IsZero() { | 
					
						
							|  |  |  |  | 		if period == "day" { | 
					
						
							|  |  |  |  | 			trendData, err = s.userRepo.GetSystemDailyUserStats(ctx, startTime, endTime) | 
					
						
							|  |  |  |  | 		} else if period == "month" { | 
					
						
							|  |  |  |  | 			trendData, err = s.userRepo.GetSystemMonthlyUserStats(ctx, startTime, endTime) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("获取用户趋势数据失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return nil, err | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		// 默认获取最近7天的数据 | 
					
						
							|  |  |  |  | 		endDate := time.Now() | 
					
						
							|  |  |  |  | 		startDate := endDate.AddDate(0, 0, -7) | 
					
						
							|  |  |  |  | 		trendData, err = s.userRepo.GetSystemDailyUserStats(ctx, startDate, endDate) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("获取用户每日趋势失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return nil, err | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 计算时间范围内的新增用户数 | 
					
						
							|  |  |  |  | 	var newInRange int64 | 
					
						
							|  |  |  |  | 	if !startTime.IsZero() && !endTime.IsZero() { | 
					
						
							|  |  |  |  | 		rangeStats, err := s.userRepo.GetSystemUserStatsByDateRange(ctx, startTime, endTime) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("获取时间范围内用户统计失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return nil, err | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		newInRange = rangeStats.TodayRegistrations | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	stats := map[string]interface{}{ | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 		"total_users":  userStats.TotalUsers, | 
					
						
							|  |  |  |  | 		"new_today":    userStats.TodayRegistrations, | 
					
						
							|  |  |  |  | 		"new_in_range": newInRange, | 
					
						
							|  |  |  |  | 		"daily_trend":  trendData, | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return stats, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // getCertificationStats 获取认证统计 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) getCertificationStats(ctx context.Context, period string, startTime, endTime time.Time) (map[string]interface{}, error) { | 
					
						
							|  |  |  |  | 	// 获取系统用户统计信息 | 
					
						
							|  |  |  |  | 	userStats, err := s.userRepo.GetSystemUserStats(ctx) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取用户统计失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 计算认证成功率 | 
					
						
							|  |  |  |  | 	var successRate float64 | 
					
						
							|  |  |  |  | 	if userStats.TotalUsers > 0 { | 
					
						
							|  |  |  |  | 		successRate = float64(userStats.CertifiedUsers) / float64(userStats.TotalUsers) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 根据时间范围获取趋势数据 | 
					
						
							|  |  |  |  | 	var trendData []map[string]interface{} | 
					
						
							|  |  |  |  | 	if !startTime.IsZero() && !endTime.IsZero() { | 
					
						
							|  |  |  |  | 		if period == "day" { | 
					
						
							|  |  |  |  | 			trendData, err = s.userRepo.GetSystemDailyUserStats(ctx, startTime, endTime) | 
					
						
							|  |  |  |  | 		} else if period == "month" { | 
					
						
							|  |  |  |  | 			trendData, err = s.userRepo.GetSystemMonthlyUserStats(ctx, startTime, endTime) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("获取认证趋势数据失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return nil, err | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		// 默认获取最近7天的数据 | 
					
						
							|  |  |  |  | 		endDate := time.Now() | 
					
						
							|  |  |  |  | 		startDate := endDate.AddDate(0, 0, -7) | 
					
						
							|  |  |  |  | 		trendData, err = s.userRepo.GetSystemDailyUserStats(ctx, startDate, endDate) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("获取认证每日趋势失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return nil, err | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	stats := map[string]interface{}{ | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 		"total_certified": userStats.CertifiedUsers, | 
					
						
							|  |  |  |  | 		"certified_today": userStats.TodayRegistrations, // 今日注册的用户 | 
					
						
							|  |  |  |  | 		"success_rate":    successRate, | 
					
						
							|  |  |  |  | 		"daily_trend":     trendData, | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return stats, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // getSystemApiCallStats 获取系统API调用统计 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) getSystemApiCallStats(ctx context.Context, period string, startTime, endTime time.Time) (map[string]interface{}, error) { | 
					
						
							|  |  |  |  | 	// 获取系统总API调用次数 | 
					
						
							|  |  |  |  | 	totalCalls, err := s.apiCallRepo.GetSystemTotalCalls(ctx) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取系统总API调用次数失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取今日API调用次数 | 
					
						
							|  |  |  |  | 	today := time.Now().Truncate(24 * time.Hour) | 
					
						
							|  |  |  |  | 	tomorrow := today.Add(24 * time.Hour) | 
					
						
							|  |  |  |  | 	todayCalls, err := s.apiCallRepo.GetSystemCallsByDateRange(ctx, today, tomorrow) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取今日API调用次数失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 根据时间范围获取趋势数据 | 
					
						
							|  |  |  |  | 	var trendData []map[string]interface{} | 
					
						
							|  |  |  |  | 	if !startTime.IsZero() && !endTime.IsZero() { | 
					
						
							|  |  |  |  | 		if period == "day" { | 
					
						
							|  |  |  |  | 			trendData, err = s.apiCallRepo.GetSystemDailyStats(ctx, startTime, endTime) | 
					
						
							|  |  |  |  | 		} else if period == "month" { | 
					
						
							|  |  |  |  | 			trendData, err = s.apiCallRepo.GetSystemMonthlyStats(ctx, startTime, endTime) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("获取API调用趋势数据失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return nil, err | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		// 默认获取最近7天的数据 | 
					
						
							|  |  |  |  | 		endDate := time.Now() | 
					
						
							|  |  |  |  | 		startDate := endDate.AddDate(0, 0, -7) | 
					
						
							|  |  |  |  | 		trendData, err = s.apiCallRepo.GetSystemDailyStats(ctx, startDate, endDate) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("获取API调用每日趋势失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return nil, err | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	stats := map[string]interface{}{ | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 		"total_calls": totalCalls, | 
					
						
							|  |  |  |  | 		"calls_today": todayCalls, | 
					
						
							|  |  |  |  | 		"daily_trend": trendData, | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return stats, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // getSystemFinanceStats 获取系统财务统计 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) getSystemFinanceStats(ctx context.Context, period string, startTime, endTime time.Time) (map[string]interface{}, error) { | 
					
						
							|  |  |  |  | 	// 获取系统总消费金额 | 
					
						
							|  |  |  |  | 	totalConsumption, err := s.walletTransactionRepo.GetSystemTotalAmount(ctx) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取系统总消费金额失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取系统总充值金额 | 
					
						
							|  |  |  |  | 	totalRecharge, err := s.rechargeRecordRepo.GetSystemTotalAmount(ctx) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取系统总充值金额失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取今日消费金额 | 
					
						
							|  |  |  |  | 	today := time.Now().Truncate(24 * time.Hour) | 
					
						
							|  |  |  |  | 	tomorrow := today.Add(24 * time.Hour) | 
					
						
							|  |  |  |  | 	todayConsumption, err := s.walletTransactionRepo.GetSystemAmountByDateRange(ctx, today, tomorrow) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取今日消费金额失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取今日充值金额 | 
					
						
							|  |  |  |  | 	todayRecharge, err := s.rechargeRecordRepo.GetSystemAmountByDateRange(ctx, today, tomorrow) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取今日充值金额失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 根据时间范围获取趋势数据 | 
					
						
							|  |  |  |  | 	var trendData []map[string]interface{} | 
					
						
							|  |  |  |  | 	if !startTime.IsZero() && !endTime.IsZero() { | 
					
						
							|  |  |  |  | 		if period == "day" { | 
					
						
							|  |  |  |  | 			// 获取消费趋势 | 
					
						
							|  |  |  |  | 			consumptionTrend, err := s.walletTransactionRepo.GetSystemDailyStats(ctx, startTime, endTime) | 
					
						
							|  |  |  |  | 			if err != nil { | 
					
						
							|  |  |  |  | 				s.logger.Error("获取消费趋势数据失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 				return nil, err | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			// 获取充值趋势 | 
					
						
							|  |  |  |  | 			rechargeTrend, err := s.rechargeRecordRepo.GetSystemDailyStats(ctx, startTime, endTime) | 
					
						
							|  |  |  |  | 			if err != nil { | 
					
						
							|  |  |  |  | 				s.logger.Error("获取充值趋势数据失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 				return nil, err | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			// 合并趋势数据 | 
					
						
							|  |  |  |  | 			trendData = s.mergeFinanceTrends(consumptionTrend, rechargeTrend, "day") | 
					
						
							|  |  |  |  | 		} else if period == "month" { | 
					
						
							|  |  |  |  | 			// 获取消费趋势 | 
					
						
							|  |  |  |  | 			consumptionTrend, err := s.walletTransactionRepo.GetSystemMonthlyStats(ctx, startTime, endTime) | 
					
						
							|  |  |  |  | 			if err != nil { | 
					
						
							|  |  |  |  | 				s.logger.Error("获取消费趋势数据失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 				return nil, err | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			// 获取充值趋势 | 
					
						
							|  |  |  |  | 			rechargeTrend, err := s.rechargeRecordRepo.GetSystemMonthlyStats(ctx, startTime, endTime) | 
					
						
							|  |  |  |  | 			if err != nil { | 
					
						
							|  |  |  |  | 				s.logger.Error("获取充值趋势数据失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 				return nil, err | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			// 合并趋势数据 | 
					
						
							|  |  |  |  | 			trendData = s.mergeFinanceTrends(consumptionTrend, rechargeTrend, "month") | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		// 默认获取最近7天的数据 | 
					
						
							|  |  |  |  | 		endDate := time.Now() | 
					
						
							|  |  |  |  | 		startDate := endDate.AddDate(0, 0, -7) | 
					
						
							|  |  |  |  | 		consumptionTrend, err := s.walletTransactionRepo.GetSystemDailyStats(ctx, startDate, endDate) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("获取消费每日趋势失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return nil, err | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		rechargeTrend, err := s.rechargeRecordRepo.GetSystemDailyStats(ctx, startDate, endDate) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("获取充值每日趋势失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return nil, err | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		trendData = s.mergeFinanceTrends(consumptionTrend, rechargeTrend, "day") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	stats := map[string]interface{}{ | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 		"total_deduct":   totalConsumption, | 
					
						
							|  |  |  |  | 		"deduct_today":   todayConsumption, | 
					
						
							|  |  |  |  | 		"total_recharge": totalRecharge, | 
					
						
							|  |  |  |  | 		"recharge_today": todayRecharge, | 
					
						
							|  |  |  |  | 		"daily_trend":    trendData, | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return stats, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // mergeFinanceTrends 合并财务趋势数据 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) mergeFinanceTrends(consumptionTrend, rechargeTrend []map[string]interface{}, period string) []map[string]interface{} { | 
					
						
							|  |  |  |  | 	// 创建日期到数据的映射 | 
					
						
							|  |  |  |  | 	consumptionMap := make(map[string]float64) | 
					
						
							|  |  |  |  | 	rechargeMap := make(map[string]float64) | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	// 处理消费数据 | 
					
						
							|  |  |  |  | 	for _, item := range consumptionTrend { | 
					
						
							|  |  |  |  | 		var dateKey string | 
					
						
							|  |  |  |  | 		var amount float64 | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 		if period == "day" { | 
					
						
							|  |  |  |  | 			if date, ok := item["date"].(string); ok { | 
					
						
							|  |  |  |  | 				dateKey = date | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			if amt, ok := item["amount"].(float64); ok { | 
					
						
							|  |  |  |  | 				amount = amt | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} else if period == "month" { | 
					
						
							|  |  |  |  | 			if month, ok := item["month"].(string); ok { | 
					
						
							|  |  |  |  | 				dateKey = month | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			if amt, ok := item["amount"].(float64); ok { | 
					
						
							|  |  |  |  | 				amount = amt | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 		if dateKey != "" { | 
					
						
							|  |  |  |  | 			consumptionMap[dateKey] = amount | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	// 处理充值数据 | 
					
						
							|  |  |  |  | 	for _, item := range rechargeTrend { | 
					
						
							|  |  |  |  | 		var dateKey string | 
					
						
							|  |  |  |  | 		var amount float64 | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 		if period == "day" { | 
					
						
							|  |  |  |  | 			if date, ok := item["date"].(string); ok { | 
					
						
							|  |  |  |  | 				dateKey = date | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			if amt, ok := item["amount"].(float64); ok { | 
					
						
							|  |  |  |  | 				amount = amt | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} else if period == "month" { | 
					
						
							|  |  |  |  | 			if month, ok := item["month"].(string); ok { | 
					
						
							|  |  |  |  | 				dateKey = month | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			if amt, ok := item["amount"].(float64); ok { | 
					
						
							|  |  |  |  | 				amount = amt | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 		if dateKey != "" { | 
					
						
							|  |  |  |  | 			rechargeMap[dateKey] = amount | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	// 合并数据 | 
					
						
							|  |  |  |  | 	var mergedTrend []map[string]interface{} | 
					
						
							|  |  |  |  | 	allDates := make(map[string]bool) | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	// 收集所有日期 | 
					
						
							|  |  |  |  | 	for date := range consumptionMap { | 
					
						
							|  |  |  |  | 		allDates[date] = true | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	for date := range rechargeMap { | 
					
						
							|  |  |  |  | 		allDates[date] = true | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	// 按日期排序并合并 | 
					
						
							|  |  |  |  | 	for date := range allDates { | 
					
						
							|  |  |  |  | 		consumption := consumptionMap[date] | 
					
						
							|  |  |  |  | 		recharge := rechargeMap[date] | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 		item := map[string]interface{}{ | 
					
						
							|  |  |  |  | 			"date":     date, | 
					
						
							|  |  |  |  | 			"deduct":   consumption, | 
					
						
							|  |  |  |  | 			"recharge": recharge, | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		mergedTrend = append(mergedTrend, item) | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	// 简单排序(按日期字符串) | 
					
						
							|  |  |  |  | 	for i := 0; i < len(mergedTrend)-1; i++ { | 
					
						
							|  |  |  |  | 		for j := i + 1; j < len(mergedTrend); j++ { | 
					
						
							|  |  |  |  | 			if mergedTrend[i]["date"].(string) > mergedTrend[j]["date"].(string) { | 
					
						
							|  |  |  |  | 				mergedTrend[i], mergedTrend[j] = mergedTrend[j], mergedTrend[i] | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	return mergedTrend | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // getUserDailyTrend 获取用户每日趋势 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) getUserDailyTrend(ctx context.Context, days int) ([]map[string]interface{}, error) { | 
					
						
							|  |  |  |  | 	// 生成最近N天的日期列表 | 
					
						
							|  |  |  |  | 	var trend []map[string]interface{} | 
					
						
							|  |  |  |  | 	now := time.Now() | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	for i := days - 1; i >= 0; i-- { | 
					
						
							|  |  |  |  | 		date := now.AddDate(0, 0, -i).Truncate(24 * time.Hour) | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 		// 这里需要实现按日期查询用户注册数的逻辑 | 
					
						
							|  |  |  |  | 		// 暂时使用模拟数据 | 
					
						
							|  |  |  |  | 		count := int64(10 + i*2) // 模拟数据 | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 		trend = append(trend, map[string]interface{}{ | 
					
						
							|  |  |  |  | 			"date":  date.Format("2006-01-02"), | 
					
						
							|  |  |  |  | 			"count": count, | 
					
						
							|  |  |  |  | 		}) | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	return trend, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // getCertificationDailyTrend 获取认证每日趋势 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) getCertificationDailyTrend(ctx context.Context, days int) ([]map[string]interface{}, error) { | 
					
						
							|  |  |  |  | 	// 生成最近N天的日期列表 | 
					
						
							|  |  |  |  | 	var trend []map[string]interface{} | 
					
						
							|  |  |  |  | 	now := time.Now() | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	for i := days - 1; i >= 0; i-- { | 
					
						
							|  |  |  |  | 		date := now.AddDate(0, 0, -i).Truncate(24 * time.Hour) | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 		// 这里需要实现按日期查询认证数的逻辑 | 
					
						
							|  |  |  |  | 		// 暂时使用模拟数据 | 
					
						
							|  |  |  |  | 		count := int64(5 + i) // 模拟数据 | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 		trend = append(trend, map[string]interface{}{ | 
					
						
							|  |  |  |  | 			"date":  date.Format("2006-01-02"), | 
					
						
							|  |  |  |  | 			"count": count, | 
					
						
							|  |  |  |  | 		}) | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	return trend, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // getWalletTransactionsByDateRange 获取指定日期范围内的钱包交易金额 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) getWalletTransactionsByDateRange(ctx context.Context, userID string, startDate, endDate time.Time) (float64, error) { | 
					
						
							|  |  |  |  | 	// 这里需要实现按日期范围查询钱包交易金额的逻辑 | 
					
						
							|  |  |  |  | 	// 暂时返回0,实际实现需要扩展仓储接口或使用原生SQL查询 | 
					
						
							|  |  |  |  | 	return 0.0, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-15 21:15:23 +08:00
										 |  |  |  | // getRechargeRecordsByDateRange 获取指定日期范围内的充值金额(排除赠送) | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | func (s *StatisticsApplicationServiceImpl) getRechargeRecordsByDateRange(ctx context.Context, userID string, startDate, endDate time.Time) (float64, error) { | 
					
						
							| 
									
										
										
										
											2025-09-15 21:15:23 +08:00
										 |  |  |  | 	return s.rechargeRecordRepo.GetTotalAmountByUserIdAndDateRange(ctx, userID, startDate, endDate) | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ================ 独立统计接口实现 ================ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // GetApiCallsStatistics 获取API调用统计 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) GetApiCallsStatistics(ctx context.Context, userID string, startDate, endDate time.Time, unit string) (*QueryResponse, error) { | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 	s.logger.Info("获取API调用统计", | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 		zap.String("user_id", userID), | 
					
						
							|  |  |  |  | 		zap.Time("start_date", startDate), | 
					
						
							|  |  |  |  | 		zap.Time("end_date", endDate), | 
					
						
							|  |  |  |  | 		zap.String("unit", unit)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取总调用次数 | 
					
						
							|  |  |  |  | 	totalCalls, err := s.apiCallRepo.CountByUserId(ctx, userID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取API调用总数失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取指定时间范围内的调用次数 | 
					
						
							|  |  |  |  | 	rangeCalls, err := s.apiCallRepo.CountByUserIdAndDateRange(ctx, userID, startDate, endDate) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取API调用范围统计失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	var trendData []map[string]interface{} | 
					
						
							|  |  |  |  | 	if unit == "day" { | 
					
						
							|  |  |  |  | 		trendData, err = s.apiCallRepo.GetDailyStatsByUserId(ctx, userID, startDate, endDate) | 
					
						
							|  |  |  |  | 	} else if unit == "month" { | 
					
						
							|  |  |  |  | 		trendData, err = s.apiCallRepo.GetMonthlyStatsByUserId(ctx, userID, startDate, endDate) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取API调用趋势数据失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	result := map[string]interface{}{ | 
					
						
							|  |  |  |  | 		"total_calls": totalCalls, | 
					
						
							|  |  |  |  | 		"range_calls": rangeCalls, | 
					
						
							|  |  |  |  | 		"trend_data":  trendData, | 
					
						
							|  |  |  |  | 		"unit":        unit, | 
					
						
							|  |  |  |  | 		"start_date":  startDate.Format("2006-01-02"), | 
					
						
							|  |  |  |  | 		"end_date":    endDate.Format("2006-01-02"), | 
					
						
							|  |  |  |  | 		"user_id":     userID, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &QueryResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "获取API调用统计成功", | 
					
						
							|  |  |  |  | 		Data:    result, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // GetConsumptionStatistics 获取消费统计 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) GetConsumptionStatistics(ctx context.Context, userID string, startDate, endDate time.Time, unit string) (*QueryResponse, error) { | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 	s.logger.Info("获取消费统计", | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 		zap.String("user_id", userID), | 
					
						
							|  |  |  |  | 		zap.Time("start_date", startDate), | 
					
						
							|  |  |  |  | 		zap.Time("end_date", endDate), | 
					
						
							|  |  |  |  | 		zap.String("unit", unit)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取总消费金额 | 
					
						
							|  |  |  |  | 	totalAmount, err := s.walletTransactionRepo.GetTotalAmountByUserId(ctx, userID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取消费总金额失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取指定时间范围内的消费金额 | 
					
						
							|  |  |  |  | 	rangeAmount, err := s.walletTransactionRepo.GetTotalAmountByUserIdAndDateRange(ctx, userID, startDate, endDate) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取消费范围统计失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	var trendData []map[string]interface{} | 
					
						
							|  |  |  |  | 	if unit == "day" { | 
					
						
							|  |  |  |  | 		trendData, err = s.walletTransactionRepo.GetDailyStatsByUserId(ctx, userID, startDate, endDate) | 
					
						
							|  |  |  |  | 	} else if unit == "month" { | 
					
						
							|  |  |  |  | 		trendData, err = s.walletTransactionRepo.GetMonthlyStatsByUserId(ctx, userID, startDate, endDate) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取消费趋势数据失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	result := map[string]interface{}{ | 
					
						
							|  |  |  |  | 		"total_amount": totalAmount, | 
					
						
							|  |  |  |  | 		"range_amount": rangeAmount, | 
					
						
							|  |  |  |  | 		"trend_data":   trendData, | 
					
						
							|  |  |  |  | 		"unit":         unit, | 
					
						
							|  |  |  |  | 		"start_date":   startDate.Format("2006-01-02"), | 
					
						
							|  |  |  |  | 		"end_date":     endDate.Format("2006-01-02"), | 
					
						
							|  |  |  |  | 		"user_id":      userID, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &QueryResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "获取消费统计成功", | 
					
						
							|  |  |  |  | 		Data:    result, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // GetRechargeStatistics 获取充值统计 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) GetRechargeStatistics(ctx context.Context, userID string, startDate, endDate time.Time, unit string) (*QueryResponse, error) { | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 	s.logger.Info("获取充值统计", | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 		zap.String("user_id", userID), | 
					
						
							|  |  |  |  | 		zap.Time("start_date", startDate), | 
					
						
							|  |  |  |  | 		zap.Time("end_date", endDate), | 
					
						
							|  |  |  |  | 		zap.String("unit", unit)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取总充值金额 | 
					
						
							|  |  |  |  | 	totalAmount, err := s.rechargeRecordRepo.GetTotalAmountByUserId(ctx, userID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取充值总金额失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取指定时间范围内的充值金额 | 
					
						
							|  |  |  |  | 	rangeAmount, err := s.rechargeRecordRepo.GetTotalAmountByUserIdAndDateRange(ctx, userID, startDate, endDate) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取充值范围统计失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	var trendData []map[string]interface{} | 
					
						
							|  |  |  |  | 	if unit == "day" { | 
					
						
							|  |  |  |  | 		trendData, err = s.rechargeRecordRepo.GetDailyStatsByUserId(ctx, userID, startDate, endDate) | 
					
						
							|  |  |  |  | 	} else if unit == "month" { | 
					
						
							|  |  |  |  | 		trendData, err = s.rechargeRecordRepo.GetMonthlyStatsByUserId(ctx, userID, startDate, endDate) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取充值趋势数据失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	result := map[string]interface{}{ | 
					
						
							|  |  |  |  | 		"total_amount": totalAmount, | 
					
						
							|  |  |  |  | 		"range_amount": rangeAmount, | 
					
						
							|  |  |  |  | 		"trend_data":   trendData, | 
					
						
							|  |  |  |  | 		"unit":         unit, | 
					
						
							|  |  |  |  | 		"start_date":   startDate.Format("2006-01-02"), | 
					
						
							|  |  |  |  | 		"end_date":     endDate.Format("2006-01-02"), | 
					
						
							|  |  |  |  | 		"user_id":      userID, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &QueryResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "获取充值统计成功", | 
					
						
							|  |  |  |  | 		Data:    result, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // GetLatestProducts 获取最新产品推荐 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) GetLatestProducts(ctx context.Context, limit int) (*QueryResponse, error) { | 
					
						
							|  |  |  |  | 	s.logger.Info("获取最新产品推荐", zap.Int("limit", limit)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取最新的产品 | 
					
						
							|  |  |  |  | 	query := &productQueries.ListProductsQuery{ | 
					
						
							|  |  |  |  | 		Page:      1, | 
					
						
							|  |  |  |  | 		PageSize:  limit, | 
					
						
							|  |  |  |  | 		IsVisible: &[]bool{true}[0], | 
					
						
							|  |  |  |  | 		IsEnabled: &[]bool{true}[0], | 
					
						
							|  |  |  |  | 		SortBy:    "created_at", | 
					
						
							|  |  |  |  | 		SortOrder: "desc", | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	productsList, _, err := s.productRepo.ListProducts(ctx, query) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取最新产品失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	var products []map[string]interface{} | 
					
						
							|  |  |  |  | 	for _, product := range productsList { | 
					
						
							|  |  |  |  | 		products = append(products, map[string]interface{}{ | 
					
						
							|  |  |  |  | 			"id":          product.ID, | 
					
						
							|  |  |  |  | 			"name":        product.Name, | 
					
						
							|  |  |  |  | 			"description": product.Description, | 
					
						
							|  |  |  |  | 			"code":        product.Code, | 
					
						
							|  |  |  |  | 			"price":       product.Price, | 
					
						
							|  |  |  |  | 			"category_id": product.CategoryID, | 
					
						
							|  |  |  |  | 			"created_at":  product.CreatedAt, | 
					
						
							|  |  |  |  | 			"is_new":      true, // 暂时都标记为新产品 | 
					
						
							|  |  |  |  | 		}) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	result := map[string]interface{}{ | 
					
						
							|  |  |  |  | 		"products": products, | 
					
						
							|  |  |  |  | 		"count":    len(products), | 
					
						
							|  |  |  |  | 		"limit":    limit, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &QueryResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "获取最新产品推荐成功", | 
					
						
							|  |  |  |  | 		Data:    result, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ================ 管理员独立域统计接口 ================ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // AdminGetUserDomainStatistics 管理员获取用户域统计 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) AdminGetUserDomainStatistics(ctx context.Context, period, startDate, endDate string) (*QueryResponse, error) { | 
					
						
							|  |  |  |  | 	s.logger.Info("管理员获取用户域统计", zap.String("period", period), zap.String("startDate", startDate), zap.String("endDate", endDate)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 解析日期 | 
					
						
							|  |  |  |  | 	var startTime, endTime time.Time | 
					
						
							|  |  |  |  | 	var err error | 
					
						
							|  |  |  |  | 	if startDate != "" { | 
					
						
							|  |  |  |  | 		startTime, err = time.Parse("2006-01-02", startDate) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("解析开始日期失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return nil, err | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if endDate != "" { | 
					
						
							|  |  |  |  | 		endTime, err = time.Parse("2006-01-02", endDate) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("解析结束日期失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return nil, err | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取用户统计数据 | 
					
						
							|  |  |  |  | 	userStats, err := s.getUserStats(ctx, period, startTime, endTime) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取用户统计数据失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取认证统计数据 | 
					
						
							|  |  |  |  | 	certificationStats, err := s.getCertificationStats(ctx, period, startTime, endTime) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取认证统计数据失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	result := map[string]interface{}{ | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 		"user_stats":          userStats, | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 		"certification_stats": certificationStats, | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 		"period":              period, | 
					
						
							|  |  |  |  | 		"start_date":          startDate, | 
					
						
							|  |  |  |  | 		"end_date":            endDate, | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &QueryResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "获取用户域统计成功", | 
					
						
							|  |  |  |  | 		Data:    result, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // AdminGetApiDomainStatistics 管理员获取API域统计 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) AdminGetApiDomainStatistics(ctx context.Context, period, startDate, endDate string) (*QueryResponse, error) { | 
					
						
							|  |  |  |  | 	s.logger.Info("管理员获取API域统计", zap.String("period", period), zap.String("startDate", startDate), zap.String("endDate", endDate)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 解析日期 | 
					
						
							|  |  |  |  | 	var startTime, endTime time.Time | 
					
						
							|  |  |  |  | 	var err error | 
					
						
							|  |  |  |  | 	if startDate != "" { | 
					
						
							|  |  |  |  | 		startTime, err = time.Parse("2006-01-02", startDate) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("解析开始日期失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return nil, err | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if endDate != "" { | 
					
						
							|  |  |  |  | 		endTime, err = time.Parse("2006-01-02", endDate) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("解析结束日期失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return nil, err | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取API调用统计数据 | 
					
						
							|  |  |  |  | 	apiCallStats, err := s.getSystemApiCallStats(ctx, period, startTime, endTime) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取API调用统计数据失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	result := map[string]interface{}{ | 
					
						
							|  |  |  |  | 		"api_call_stats": apiCallStats, | 
					
						
							|  |  |  |  | 		"period":         period, | 
					
						
							|  |  |  |  | 		"start_date":     startDate, | 
					
						
							|  |  |  |  | 		"end_date":       endDate, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &QueryResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "获取API域统计成功", | 
					
						
							|  |  |  |  | 		Data:    result, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // AdminGetConsumptionDomainStatistics 管理员获取消费域统计 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) AdminGetConsumptionDomainStatistics(ctx context.Context, period, startDate, endDate string) (*QueryResponse, error) { | 
					
						
							|  |  |  |  | 	s.logger.Info("管理员获取消费域统计", zap.String("period", period), zap.String("startDate", startDate), zap.String("endDate", endDate)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 解析日期 | 
					
						
							|  |  |  |  | 	var startTime, endTime time.Time | 
					
						
							|  |  |  |  | 	var err error | 
					
						
							|  |  |  |  | 	if startDate != "" { | 
					
						
							|  |  |  |  | 		startTime, err = time.Parse("2006-01-02", startDate) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("解析开始日期失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return nil, err | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if endDate != "" { | 
					
						
							|  |  |  |  | 		endTime, err = time.Parse("2006-01-02", endDate) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("解析结束日期失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return nil, err | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取消费统计数据 | 
					
						
							|  |  |  |  | 	totalConsumption, err := s.walletTransactionRepo.GetSystemTotalAmount(ctx) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取系统总消费金额失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 	// 获取今日消费金额 | 
					
						
							|  |  |  |  | 	today := time.Now().Truncate(24 * time.Hour) | 
					
						
							|  |  |  |  | 	tomorrow := today.Add(24 * time.Hour) | 
					
						
							|  |  |  |  | 	todayConsumption, err := s.walletTransactionRepo.GetSystemAmountByDateRange(ctx, today, tomorrow) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取今日消费金额失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取指定时间范围内的消费金额 | 
					
						
							|  |  |  |  | 	rangeConsumption := float64(0) | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	if !startTime.IsZero() && !endTime.IsZero() { | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 		rangeConsumption, err = s.walletTransactionRepo.GetSystemAmountByDateRange(ctx, startTime, endTime) | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("获取指定时间范围消费金额失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return nil, err | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	var consumptionTrend []map[string]interface{} | 
					
						
							| 
									
										
										
										
											2025-09-12 13:29:03 +08:00
										 |  |  |  | 	if !startTime.IsZero() && !endTime.IsZero() { | 
					
						
							|  |  |  |  | 		if period == "day" { | 
					
						
							|  |  |  |  | 			consumptionTrend, err = s.walletTransactionRepo.GetSystemDailyStats(ctx, startTime, endTime) | 
					
						
							|  |  |  |  | 		} else if period == "month" { | 
					
						
							|  |  |  |  | 			consumptionTrend, err = s.walletTransactionRepo.GetSystemMonthlyStats(ctx, startTime, endTime) | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 13:29:03 +08:00
										 |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("获取消费趋势数据失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return nil, err | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		// 如果没有指定时间范围,获取最近7天的数据 | 
					
						
							|  |  |  |  | 		defaultEndDate := time.Now() | 
					
						
							|  |  |  |  | 		defaultStartDate := defaultEndDate.AddDate(0, 0, -7) | 
					
						
							|  |  |  |  | 		consumptionTrend, err = s.walletTransactionRepo.GetSystemDailyStats(ctx, defaultStartDate, defaultEndDate) | 
					
						
							| 
									
										
										
										
											2025-09-14 16:34:55 +08:00
										 |  |  |  | 		if err != nil {   | 
					
						
							| 
									
										
										
										
											2025-09-12 13:29:03 +08:00
										 |  |  |  | 			s.logger.Error("获取消费每日趋势失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return nil, err | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	result := map[string]interface{}{ | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 		"total_consumption": totalConsumption, | 
					
						
							|  |  |  |  | 		"today_consumption": todayConsumption, | 
					
						
							|  |  |  |  | 		"range_consumption": rangeConsumption, | 
					
						
							|  |  |  |  | 		"consumption_trend": consumptionTrend, | 
					
						
							|  |  |  |  | 		"period":            period, | 
					
						
							|  |  |  |  | 		"start_date":        startDate, | 
					
						
							|  |  |  |  | 		"end_date":          endDate, | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &QueryResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "获取消费域统计成功", | 
					
						
							|  |  |  |  | 		Data:    result, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // AdminGetRechargeDomainStatistics 管理员获取充值域统计 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) AdminGetRechargeDomainStatistics(ctx context.Context, period, startDate, endDate string) (*QueryResponse, error) { | 
					
						
							|  |  |  |  | 	s.logger.Info("管理员获取充值域统计", zap.String("period", period), zap.String("startDate", startDate), zap.String("endDate", endDate)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 解析日期 | 
					
						
							|  |  |  |  | 	var startTime, endTime time.Time | 
					
						
							|  |  |  |  | 	var err error | 
					
						
							|  |  |  |  | 	if startDate != "" { | 
					
						
							|  |  |  |  | 		startTime, err = time.Parse("2006-01-02", startDate) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("解析开始日期失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return nil, err | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if endDate != "" { | 
					
						
							|  |  |  |  | 		endTime, err = time.Parse("2006-01-02", endDate) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("解析结束日期失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return nil, err | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取充值统计数据 | 
					
						
							|  |  |  |  | 	totalRecharge, err := s.rechargeRecordRepo.GetSystemTotalAmount(ctx) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取系统总充值金额失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 	// 获取今日充值金额 | 
					
						
							|  |  |  |  | 	today := time.Now().Truncate(24 * time.Hour) | 
					
						
							|  |  |  |  | 	tomorrow := today.Add(24 * time.Hour) | 
					
						
							|  |  |  |  | 	todayRecharge, err := s.rechargeRecordRepo.GetSystemAmountByDateRange(ctx, today, tomorrow) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取今日充值金额失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取指定时间范围内的充值金额 | 
					
						
							|  |  |  |  | 	rangeRecharge := float64(0) | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	if !startTime.IsZero() && !endTime.IsZero() { | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 		rangeRecharge, err = s.rechargeRecordRepo.GetSystemAmountByDateRange(ctx, startTime, endTime) | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("获取指定时间范围充值金额失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return nil, err | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	var rechargeTrend []map[string]interface{} | 
					
						
							| 
									
										
										
										
											2025-09-12 13:29:03 +08:00
										 |  |  |  | 	if !startTime.IsZero() && !endTime.IsZero() { | 
					
						
							|  |  |  |  | 		if period == "day" { | 
					
						
							|  |  |  |  | 			rechargeTrend, err = s.rechargeRecordRepo.GetSystemDailyStats(ctx, startTime, endTime) | 
					
						
							|  |  |  |  | 		} else if period == "month" { | 
					
						
							|  |  |  |  | 			rechargeTrend, err = s.rechargeRecordRepo.GetSystemMonthlyStats(ctx, startTime, endTime) | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 13:29:03 +08:00
										 |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("获取充值趋势数据失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return nil, err | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		// 如果没有指定时间范围,获取最近7天的数据 | 
					
						
							|  |  |  |  | 		defaultEndDate := time.Now() | 
					
						
							|  |  |  |  | 		defaultStartDate := defaultEndDate.AddDate(0, 0, -7) | 
					
						
							|  |  |  |  | 		rechargeTrend, err = s.rechargeRecordRepo.GetSystemDailyStats(ctx, defaultStartDate, defaultEndDate) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("获取充值每日趋势失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return nil, err | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	result := map[string]interface{}{ | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 		"total_recharge": totalRecharge, | 
					
						
							|  |  |  |  | 		"today_recharge": todayRecharge, | 
					
						
							|  |  |  |  | 		"range_recharge": rangeRecharge, | 
					
						
							|  |  |  |  | 		"recharge_trend": rechargeTrend, | 
					
						
							|  |  |  |  | 		"period":         period, | 
					
						
							|  |  |  |  | 		"start_date":     startDate, | 
					
						
							|  |  |  |  | 		"end_date":       endDate, | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &QueryResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "获取充值域统计成功", | 
					
						
							|  |  |  |  | 		Data:    result, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // AdminGetUserCallRanking 获取用户调用排行榜 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) AdminGetUserCallRanking(ctx context.Context, rankingType, period string, limit int) (*QueryResponse, error) { | 
					
						
							|  |  |  |  | 	s.logger.Info("获取用户调用排行榜", zap.String("type", rankingType), zap.String("period", period), zap.Int("limit", limit)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	var rankings []map[string]interface{} | 
					
						
							|  |  |  |  | 	var err error | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	switch rankingType { | 
					
						
							|  |  |  |  | 	case "calls": | 
					
						
							|  |  |  |  | 		// 按调用次数排行 | 
					
						
							|  |  |  |  | 		switch period { | 
					
						
							|  |  |  |  | 		case "today": | 
					
						
							|  |  |  |  | 			rankings, err = s.getUserCallRankingByCalls(ctx, "today", limit) | 
					
						
							|  |  |  |  | 		case "month": | 
					
						
							|  |  |  |  | 			rankings, err = s.getUserCallRankingByCalls(ctx, "month", limit) | 
					
						
							|  |  |  |  | 		case "total": | 
					
						
							|  |  |  |  | 			rankings, err = s.getUserCallRankingByCalls(ctx, "total", limit) | 
					
						
							|  |  |  |  | 		default: | 
					
						
							|  |  |  |  | 			return nil, fmt.Errorf("不支持的时间周期: %s", period) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	case "consumption": | 
					
						
							|  |  |  |  | 		// 按消费金额排行 | 
					
						
							|  |  |  |  | 		switch period { | 
					
						
							|  |  |  |  | 		case "today": | 
					
						
							|  |  |  |  | 			rankings, err = s.getUserCallRankingByConsumption(ctx, "today", limit) | 
					
						
							|  |  |  |  | 		case "month": | 
					
						
							|  |  |  |  | 			rankings, err = s.getUserCallRankingByConsumption(ctx, "month", limit) | 
					
						
							|  |  |  |  | 		case "total": | 
					
						
							|  |  |  |  | 			rankings, err = s.getUserCallRankingByConsumption(ctx, "total", limit) | 
					
						
							|  |  |  |  | 		default: | 
					
						
							|  |  |  |  | 			return nil, fmt.Errorf("不支持的时间周期: %s", period) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	default: | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("不支持的排行类型: %s", rankingType) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取用户调用排行榜失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	result := map[string]interface{}{ | 
					
						
							|  |  |  |  | 		"ranking_type": rankingType, | 
					
						
							|  |  |  |  | 		"period":       period, | 
					
						
							|  |  |  |  | 		"limit":        limit, | 
					
						
							|  |  |  |  | 		"rankings":     rankings, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &QueryResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "获取用户调用排行榜成功", | 
					
						
							|  |  |  |  | 		Data:    result, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // AdminGetRechargeRanking 获取充值排行榜 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) AdminGetRechargeRanking(ctx context.Context, period string, limit int) (*QueryResponse, error) { | 
					
						
							|  |  |  |  | 	s.logger.Info("获取充值排行榜", zap.String("period", period), zap.Int("limit", limit)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	var rankings []map[string]interface{} | 
					
						
							|  |  |  |  | 	var err error | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	switch period { | 
					
						
							|  |  |  |  | 	case "today": | 
					
						
							|  |  |  |  | 		rankings, err = s.getRechargeRanking(ctx, "today", limit) | 
					
						
							|  |  |  |  | 	case "month": | 
					
						
							|  |  |  |  | 		rankings, err = s.getRechargeRanking(ctx, "month", limit) | 
					
						
							|  |  |  |  | 	case "total": | 
					
						
							|  |  |  |  | 		rankings, err = s.getRechargeRanking(ctx, "total", limit) | 
					
						
							|  |  |  |  | 	default: | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("不支持的时间周期: %s", period) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取充值排行榜失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	result := map[string]interface{}{ | 
					
						
							|  |  |  |  | 		"period":   period, | 
					
						
							|  |  |  |  | 		"limit":    limit, | 
					
						
							|  |  |  |  | 		"rankings": rankings, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &QueryResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "获取充值排行榜成功", | 
					
						
							|  |  |  |  | 		Data:    result, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // getUserCallRankingByCalls 按调用次数获取用户排行 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) getUserCallRankingByCalls(ctx context.Context, period string, limit int) ([]map[string]interface{}, error) { | 
					
						
							|  |  |  |  | 	// 调用用户仓储获取真实数据 | 
					
						
							|  |  |  |  | 	rankings, err := s.userRepo.GetUserCallRankingByCalls(ctx, period, limit) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取用户调用次数排行失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	// 添加排名信息 | 
					
						
							|  |  |  |  | 	for i, ranking := range rankings { | 
					
						
							|  |  |  |  | 		ranking["rank"] = i + 1 | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	return rankings, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // getUserCallRankingByConsumption 按消费金额获取用户排行 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) getUserCallRankingByConsumption(ctx context.Context, period string, limit int) ([]map[string]interface{}, error) { | 
					
						
							|  |  |  |  | 	// 调用用户仓储获取真实数据 | 
					
						
							|  |  |  |  | 	rankings, err := s.userRepo.GetUserCallRankingByConsumption(ctx, period, limit) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取用户消费金额排行失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	// 添加排名信息 | 
					
						
							|  |  |  |  | 	for i, ranking := range rankings { | 
					
						
							|  |  |  |  | 		ranking["rank"] = i + 1 | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	return rankings, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // getRechargeRanking 获取充值排行 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) getRechargeRanking(ctx context.Context, period string, limit int) ([]map[string]interface{}, error) { | 
					
						
							|  |  |  |  | 	// 调用用户仓储获取真实数据 | 
					
						
							|  |  |  |  | 	rankings, err := s.userRepo.GetRechargeRanking(ctx, period, limit) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取充值排行失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	// 添加排名信息 | 
					
						
							|  |  |  |  | 	for i, ranking := range rankings { | 
					
						
							|  |  |  |  | 		ranking["rank"] = i + 1 | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	return rankings, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // AdminGetApiPopularityRanking 获取API受欢迎程度排行榜 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) AdminGetApiPopularityRanking(ctx context.Context, period string, limit int) (*QueryResponse, error) { | 
					
						
							|  |  |  |  | 	s.logger.Info("获取API受欢迎程度排行榜", zap.String("period", period), zap.Int("limit", limit)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 调用API调用仓储获取真实数据 | 
					
						
							|  |  |  |  | 	rankings, err := s.apiCallRepo.GetApiPopularityRanking(ctx, period, limit) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取API受欢迎程度排行榜失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	// 添加排名信息 | 
					
						
							|  |  |  |  | 	for i, ranking := range rankings { | 
					
						
							|  |  |  |  | 		ranking["rank"] = i + 1 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	result := map[string]interface{}{ | 
					
						
							|  |  |  |  | 		"period":   period, | 
					
						
							|  |  |  |  | 		"limit":    limit, | 
					
						
							|  |  |  |  | 		"rankings": rankings, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &QueryResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "获取API受欢迎程度排行榜成功", | 
					
						
							|  |  |  |  | 		Data:    result, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // AdminGetTodayCertifiedEnterprises 获取今日认证企业列表 | 
					
						
							|  |  |  |  | func (s *StatisticsApplicationServiceImpl) AdminGetTodayCertifiedEnterprises(ctx context.Context, limit int) (*QueryResponse, error) { | 
					
						
							|  |  |  |  | 	// 获取今日开始和结束时间 | 
					
						
							|  |  |  |  | 	now := time.Now() | 
					
						
							|  |  |  |  | 	todayStart := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()) | 
					
						
							|  |  |  |  | 	todayEnd := todayStart.Add(24 * time.Hour) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 查询所有已完成的认证,然后过滤今日完成的 | 
					
						
							|  |  |  |  | 	query := &certificationQueries.ListCertificationsQuery{ | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 		Page:      1, | 
					
						
							|  |  |  |  | 		PageSize:  1000, // 设置较大的页面大小以获取所有数据 | 
					
						
							|  |  |  |  | 		SortBy:    "updated_at", | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 		SortOrder: "desc", | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 		Status:    certificationEnums.StatusCompleted, | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	certifications, _, err := s.certificationRepo.List(ctx, query) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取今日认证企业失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("获取今日认证企业失败: %w", err) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 过滤出今日完成的认证(基于completed_at字段) | 
					
						
							|  |  |  |  | 	var completedCertifications []*certificationEntities.Certification | 
					
						
							|  |  |  |  | 	for _, cert := range certifications { | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 		if cert.CompletedAt != nil && | 
					
						
							|  |  |  |  | 			cert.CompletedAt.After(todayStart) && | 
					
						
							|  |  |  |  | 			cert.CompletedAt.Before(todayEnd) { | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 			completedCertifications = append(completedCertifications, cert) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 按完成时间排序(最新的在前) | 
					
						
							|  |  |  |  | 	for i := 0; i < len(completedCertifications)-1; i++ { | 
					
						
							|  |  |  |  | 		for j := i + 1; j < len(completedCertifications); j++ { | 
					
						
							|  |  |  |  | 			if completedCertifications[i].CompletedAt.Before(*completedCertifications[j].CompletedAt) { | 
					
						
							|  |  |  |  | 				completedCertifications[i], completedCertifications[j] = completedCertifications[j], completedCertifications[i] | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 限制返回数量 | 
					
						
							|  |  |  |  | 	if limit > 0 && len(completedCertifications) > limit { | 
					
						
							|  |  |  |  | 		completedCertifications = completedCertifications[:limit] | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 	// 直接从企业信息表获取数据 | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	var enterprises []map[string]interface{} | 
					
						
							|  |  |  |  | 	for _, cert := range completedCertifications { | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 		// 获取企业信息 | 
					
						
							|  |  |  |  | 		enterpriseInfo, err := s.enterpriseInfoRepo.GetByUserID(ctx, cert.UserID) | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 			s.logger.Warn("获取企业信息失败", zap.String("user_id", cert.UserID), zap.Error(err)) | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 			continue | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 		// 获取用户基本信息(仅需要用户名) | 
					
						
							|  |  |  |  | 		user, err := s.userRepo.GetByID(ctx, cert.UserID) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Warn("获取用户信息失败", zap.String("user_id", cert.UserID), zap.Error(err)) | 
					
						
							|  |  |  |  | 			continue | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		enterprise := map[string]interface{}{ | 
					
						
							| 
									
										
										
										
											2025-09-12 13:20:08 +08:00
										 |  |  |  | 			"id":                    cert.ID, | 
					
						
							|  |  |  |  | 			"user_id":              cert.UserID, | 
					
						
							|  |  |  |  | 			"username":             user.Username, | 
					
						
							|  |  |  |  | 			"enterprise_name":      enterpriseInfo.CompanyName, | 
					
						
							|  |  |  |  | 			"legal_person_name":    enterpriseInfo.LegalPersonName, | 
					
						
							|  |  |  |  | 			"legal_person_phone":   enterpriseInfo.LegalPersonPhone, | 
					
						
							|  |  |  |  | 			"unified_social_code":  enterpriseInfo.UnifiedSocialCode, | 
					
						
							|  |  |  |  | 			"enterprise_address":   enterpriseInfo.EnterpriseAddress, | 
					
						
							|  |  |  |  | 			"certified_at":         cert.CompletedAt.Format(time.RFC3339), | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 		enterprises = append(enterprises, enterprise) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	result := map[string]interface{}{ | 
					
						
							|  |  |  |  | 		"enterprises": enterprises, | 
					
						
							|  |  |  |  | 		"total":       len(enterprises), | 
					
						
							|  |  |  |  | 		"date":        todayStart.Format("2006-01-02"), | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &QueryResponse{ | 
					
						
							|  |  |  |  | 		Success: true, | 
					
						
							|  |  |  |  | 		Message: "获取今日认证企业列表成功", | 
					
						
							|  |  |  |  | 		Data:    result, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } |