package service import ( "context" "errors" "strconv" "time" apperrors "carrotskin/internal/errors" "carrotskin/internal/model" "carrotskin/internal/repository" "go.uber.org/zap" ) // reportService ReportService的实现 type reportService struct { reportRepo repository.ReportRepository userRepo repository.UserRepository logger *zap.Logger } // NewReportService 创建ReportService实例 func NewReportService( reportRepo repository.ReportRepository, userRepo repository.UserRepository, logger *zap.Logger, ) ReportService { return &reportService{ reportRepo: reportRepo, userRepo: userRepo, logger: logger, } } // CreateReport 创建举报 func (s *reportService) CreateReport(ctx context.Context, reporterID int64, targetType model.ReportType, targetID int64, reason string) (*model.Report, error) { // 验证举报人存在 reporter, err := s.userRepo.FindByID(ctx, reporterID) if err != nil { s.logger.Error("举报人不存在", zap.Int64("reporter_id", reporterID), zap.Error(err)) return nil, apperrors.ErrUserNotFound } if reporter == nil { return nil, apperrors.ErrUserNotFound } // 验证举报原因 if reason == "" { return nil, errors.New("举报原因不能为空") } if len(reason) > 500 { return nil, errors.New("举报原因不能超过500字符") } // 验证目标类型 if targetType != model.ReportTypeTexture && targetType != model.ReportTypeUser { return nil, errors.New("无效的举报类型") } // 检查是否重复举报 isDuplicate, err := s.reportRepo.CheckDuplicate(ctx, reporterID, targetType, targetID) if err != nil { s.logger.Error("检查重复举报失败", zap.Error(err)) return nil, err } if isDuplicate { return nil, errors.New("您已经举报过该对象,请勿重复举报") } // 创建举报记录 report := &model.Report{ ReporterID: reporterID, TargetType: targetType, TargetID: targetID, Reason: reason, Status: model.ReportStatusPending, CreatedAt: time.Now(), UpdatedAt: time.Now(), } if err := s.reportRepo.Create(ctx, report); err != nil { s.logger.Error("创建举报失败", zap.Error(err)) return nil, err } s.logger.Info("创建举报成功", zap.Int64("report_id", report.ID), zap.Int64("reporter_id", reporterID)) return report, nil } // GetByID 根据ID查询举报 func (s *reportService) GetByID(ctx context.Context, id int64) (*model.Report, error) { report, err := s.reportRepo.FindByID(ctx, id) if err != nil { s.logger.Error("查询举报失败", zap.Int64("report_id", id), zap.Error(err)) return nil, err } return report, nil } // GetByReporterID 根据举报人ID查询举报记录 func (s *reportService) GetByReporterID(ctx context.Context, reporterID, userID int64, page, pageSize int) ([]*model.Report, int64, error) { // 验证用户存在 user, err := s.userRepo.FindByID(ctx, userID) if err != nil { return nil, 0, err } if user == nil { return nil, 0, apperrors.ErrUserNotFound } // 只有本人或管理员可以查看自己的举报记录 if reporterID != userID && !(user.Role == "admin") { return nil, 0, errors.New("无权查看其他用户的举报记录") } reports, total, err := s.reportRepo.FindByReporterID(ctx, reporterID, page, pageSize) if err != nil { s.logger.Error("查询举报记录失败", zap.Error(err)) return nil, 0, err } return reports, total, nil } // GetByTarget 根据目标对象查询举报记录 func (s *reportService) GetByTarget(ctx context.Context, targetType model.ReportType, targetID, userID int64, page, pageSize int) ([]*model.Report, int64, error) { // 验证用户存在 user, err := s.userRepo.FindByID(ctx, userID) if err != nil { return nil, 0, err } if user == nil { return nil, 0, apperrors.ErrUserNotFound } // 只有管理员可以查看目标对象的举报记录 if !(user.Role == "admin") { return nil, 0, errors.New("无权查看举报记录") } reports, total, err := s.reportRepo.FindByTarget(ctx, targetType, targetID, page, pageSize) if err != nil { s.logger.Error("查询举报记录失败", zap.Error(err)) return nil, 0, err } return reports, total, nil } // GetByStatus 根据状态查询举报记录 func (s *reportService) GetByStatus(ctx context.Context, status model.ReportStatus, page, pageSize int) ([]*model.Report, int64, error) { reports, total, err := s.reportRepo.FindByStatus(ctx, status, page, pageSize) if err != nil { s.logger.Error("查询举报记录失败", zap.Error(err)) return nil, 0, err } return reports, total, nil } // Search 搜索举报记录 func (s *reportService) Search(ctx context.Context, keyword, userID int64, page, pageSize int) ([]*model.Report, int64, error) { // 验证用户存在 user, err := s.userRepo.FindByID(ctx, userID) if err != nil { return nil, 0, err } if user == nil { return nil, 0, apperrors.ErrUserNotFound } // 只有管理员可以搜索举报记录 if !(user.Role == "admin") { return nil, 0, errors.New("无权搜索举报记录") } reports, total, err := s.reportRepo.Search(ctx, strconv.FormatInt(keyword, 10), page, pageSize) if err != nil { s.logger.Error("搜索举报记录失败", zap.Error(err)) return nil, 0, err } return reports, total, nil } // Review 处理举报记录 func (s *reportService) Review(ctx context.Context, reportID, reviewerID int64, status model.ReportStatus, reviewNote string) (*model.Report, error) { // 验证处理人存在且是管理员 reviewer, err := s.userRepo.FindByID(ctx, reviewerID) if err != nil { s.logger.Error("处理人不存在", zap.Int64("reviewer_id", reviewerID), zap.Error(err)) return nil, apperrors.ErrUserNotFound } if reviewer == nil || !(reviewer.Role == "admin") { return nil, errors.New("只有管理员可以处理举报") } // 验证状态 if status != model.ReportStatusApproved && status != model.ReportStatusRejected { return nil, errors.New("无效的举报处理状态") } // 处理举报 if err := s.reportRepo.Review(ctx, reportID, status, reviewerID, reviewNote); err != nil { s.logger.Error("处理举报失败", zap.Int64("report_id", reportID), zap.Error(err)) return nil, err } // 返回更新后的举报记录 report, err := s.reportRepo.FindByID(ctx, reportID) if err != nil { s.logger.Error("查询举报记录失败", zap.Int64("report_id", reportID), zap.Error(err)) return nil, err } s.logger.Info("处理举报成功", zap.Int64("report_id", reportID), zap.Int64("reviewer_id", reviewerID), zap.String("status", string(status))) return report, nil } // BatchReview 批量处理举报记录 func (s *reportService) BatchReview(ctx context.Context, ids []int64, reviewerID int64, status model.ReportStatus, reviewNote string) (int64, error) { // 验证处理人存在且是管理员 reviewer, err := s.userRepo.FindByID(ctx, reviewerID) if err != nil { s.logger.Error("处理人不存在", zap.Int64("reviewer_id", reviewerID), zap.Error(err)) return 0, apperrors.ErrUserNotFound } if reviewer == nil || !(reviewer.Role == "admin") { return 0, errors.New("只有管理员可以处理举报") } // 验证状态 if status != model.ReportStatusApproved && status != model.ReportStatusRejected { return 0, errors.New("无效的举报处理状态") } // 批量处理举报 affected, err := s.reportRepo.BatchReview(ctx, ids, status, reviewerID, reviewNote) if err != nil { s.logger.Error("批量处理举报失败", zap.Error(err)) return 0, err } s.logger.Info("批量处理举报成功", zap.Int("count", int(affected)), zap.Int64("reviewer_id", reviewerID), zap.String("status", string(status))) return affected, nil } // Delete 删除举报记录 func (s *reportService) Delete(ctx context.Context, reportID, userID int64) error { // 验证用户存在 user, err := s.userRepo.FindByID(ctx, userID) if err != nil { return err } if user == nil { return apperrors.ErrUserNotFound } // 查询举报记录 report, err := s.reportRepo.FindByID(ctx, reportID) if err != nil { return err } if report == nil { return errors.New("举报记录不存在") } // 只有举报人、管理员或处理人可以删除举报记录 if report.ReporterID != userID && !(user.Role == "admin") && (report.ReviewerID == nil || *report.ReviewerID != userID) { return errors.New("无权删除此举报记录") } if err := s.reportRepo.Delete(ctx, reportID); err != nil { s.logger.Error("删除举报记录失败", zap.Int64("report_id", reportID), zap.Error(err)) return err } s.logger.Info("删除举报记录成功", zap.Int64("report_id", reportID)) return nil } // BatchDelete 批量删除举报记录 func (s *reportService) BatchDelete(ctx context.Context, ids []int64, userID int64) (int64, error) { // 验证用户存在 user, err := s.userRepo.FindByID(ctx, userID) if err != nil { return 0, err } if user == nil { return 0, apperrors.ErrUserNotFound } // 只有管理员可以批量删除 if !(user.Role == "admin") { return 0, errors.New("无权批量删除举报记录") } affected, err := s.reportRepo.BatchDelete(ctx, ids) if err != nil { s.logger.Error("批量删除举报记录失败", zap.Error(err)) return 0, err } s.logger.Info("批量删除举报记录成功", zap.Int("count", int(affected))) return affected, nil } // GetStats 获取举报统计信息 func (s *reportService) GetStats(ctx context.Context) (map[string]int64, error) { stats := make(map[string]int64) // 统计各状态的举报数量 pendingCount, err := s.reportRepo.CountByStatus(ctx, model.ReportStatusPending) if err != nil { return nil, err } stats["pending"] = pendingCount approvedCount, err := s.reportRepo.CountByStatus(ctx, model.ReportStatusApproved) if err != nil { return nil, err } stats["approved"] = approvedCount rejectedCount, err := s.reportRepo.CountByStatus(ctx, model.ReportStatusRejected) if err != nil { return nil, err } stats["rejected"] = rejectedCount stats["total"] = pendingCount + approvedCount + rejectedCount return stats, nil }