feat: 添加举报功能支持
- 新增 Report 数据模型、DTO、Repository、Service 层 - 实现用户端举报 API (POST /api/v1/reports) - 实现管理端举报管理 API (列表、详情、处理、批量处理) - 添加举报自动隐藏机制(达到阈值自动隐藏内容) - 集成系统通知(举报处理结果通知) - 更新路由和 Wire 依赖注入配置 Made-with: Cursor
This commit is contained in:
212
internal/repository/report_repo.go
Normal file
212
internal/repository/report_repo.go
Normal file
@@ -0,0 +1,212 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"carrot_bbs/internal/dto"
|
||||
"carrot_bbs/internal/model"
|
||||
"context"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// ReportRepository 举报仓储接口
|
||||
type ReportRepository interface {
|
||||
// Create 创建举报
|
||||
Create(report *model.Report) error
|
||||
// CreateWithContext 使用上下文创建举报(支持事务)
|
||||
CreateWithContext(ctx context.Context, report *model.Report) error
|
||||
// FindByID 根据ID查询举报
|
||||
FindByID(id string) (*model.Report, error)
|
||||
// FindByIDWithContext 使用上下文查询举报
|
||||
FindByIDWithContext(ctx context.Context, id string) (*model.Report, error)
|
||||
// List 查询举报列表
|
||||
List(query dto.AdminReportListQuery) ([]*model.Report, int64, error)
|
||||
// GetReportCount 获取内容的举报次数
|
||||
GetReportCount(targetType model.ReportTargetType, targetID string) (int64, error)
|
||||
// HasUserReported 检查用户是否已举报过该内容
|
||||
HasUserReported(reporterID string, targetType model.ReportTargetType, targetID string) (bool, error)
|
||||
// GetPendingReportsByTarget 获取目标内容的待处理举报
|
||||
GetPendingReportsByTarget(targetType model.ReportTargetType, targetID string) ([]*model.Report, error)
|
||||
// UpdateStatus 更新举报状态
|
||||
UpdateStatus(id string, status model.ReportStatus, handledBy string, result string) error
|
||||
// UpdateStatusWithContext 使用上下文更新举报状态
|
||||
UpdateStatusWithContext(ctx context.Context, id string, status model.ReportStatus, handledBy string, result string) error
|
||||
// BatchUpdateStatus 批量更新举报状态
|
||||
BatchUpdateStatus(ids []string, status model.ReportStatus, handledBy string, result string) (int64, error)
|
||||
// BatchUpdateStatusWithContext 使用上下文批量更新举报状态
|
||||
BatchUpdateStatusWithContext(ctx context.Context, ids []string, status model.ReportStatus, handledBy string, result string) (int64, error)
|
||||
// GetByIDsWithContext 使用上下文批量查询举报
|
||||
GetByIDsWithContext(ctx context.Context, ids []string) ([]*model.Report, error)
|
||||
}
|
||||
|
||||
// reportRepository 举报仓储实现
|
||||
type reportRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
// NewReportRepository 创建举报仓储
|
||||
func NewReportRepository(db *gorm.DB) ReportRepository {
|
||||
return &reportRepository{db: db}
|
||||
}
|
||||
|
||||
// getDB 获取数据库实例(支持事务)
|
||||
func (r *reportRepository) getDB(ctx context.Context) *gorm.DB {
|
||||
if tx := GetTxFromContext(ctx); tx != nil {
|
||||
return tx
|
||||
}
|
||||
return r.db
|
||||
}
|
||||
|
||||
// Create 创建举报
|
||||
func (r *reportRepository) Create(report *model.Report) error {
|
||||
return r.db.Create(report).Error
|
||||
}
|
||||
|
||||
// CreateWithContext 使用上下文创建举报
|
||||
func (r *reportRepository) CreateWithContext(ctx context.Context, report *model.Report) error {
|
||||
return r.getDB(ctx).Create(report).Error
|
||||
}
|
||||
|
||||
// FindByID 根据ID查询举报
|
||||
func (r *reportRepository) FindByID(id string) (*model.Report, error) {
|
||||
var report model.Report
|
||||
err := r.db.Where("id = ?", id).First(&report).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &report, nil
|
||||
}
|
||||
|
||||
// FindByIDWithContext 使用上下文查询举报
|
||||
func (r *reportRepository) FindByIDWithContext(ctx context.Context, id string) (*model.Report, error) {
|
||||
var report model.Report
|
||||
err := r.getDB(ctx).Where("id = ?", id).First(&report).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &report, nil
|
||||
}
|
||||
|
||||
// List 查询举报列表
|
||||
func (r *reportRepository) List(query dto.AdminReportListQuery) ([]*model.Report, int64, error) {
|
||||
var reports []*model.Report
|
||||
var total int64
|
||||
|
||||
db := r.db.Model(&model.Report{})
|
||||
|
||||
// 筛选条件
|
||||
if query.TargetType != "" {
|
||||
db = db.Where("target_type = ?", query.TargetType)
|
||||
}
|
||||
if query.Status != "" {
|
||||
db = db.Where("status = ?", query.Status)
|
||||
}
|
||||
if query.StartDate != "" {
|
||||
db = db.Where("created_at >= ?", query.StartDate)
|
||||
}
|
||||
if query.EndDate != "" {
|
||||
db = db.Where("created_at <= ?", query.EndDate+" 23:59:59")
|
||||
}
|
||||
if query.Keyword != "" {
|
||||
keyword := "%" + query.Keyword + "%"
|
||||
db = db.Where("description LIKE ? OR reason LIKE ?", keyword, keyword)
|
||||
}
|
||||
|
||||
// 获取总数
|
||||
if err := db.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// 分页查询
|
||||
offset := (query.Page - 1) * query.PageSize
|
||||
if query.PageSize <= 0 {
|
||||
query.PageSize = 20
|
||||
}
|
||||
if query.Page <= 0 {
|
||||
query.Page = 1
|
||||
}
|
||||
|
||||
err := db.Order("created_at DESC").
|
||||
Offset(offset).
|
||||
Limit(query.PageSize).
|
||||
Find(&reports).Error
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return reports, total, nil
|
||||
}
|
||||
|
||||
// GetReportCount 获取内容的举报次数
|
||||
func (r *reportRepository) GetReportCount(targetType model.ReportTargetType, targetID string) (int64, error) {
|
||||
var count int64
|
||||
err := r.db.Model(&model.Report{}).
|
||||
Where("target_type = ? AND target_id = ?", targetType, targetID).
|
||||
Count(&count).Error
|
||||
return count, err
|
||||
}
|
||||
|
||||
// HasUserReported 检查用户是否已举报过该内容
|
||||
func (r *reportRepository) HasUserReported(reporterID string, targetType model.ReportTargetType, targetID string) (bool, error) {
|
||||
var count int64
|
||||
err := r.db.Model(&model.Report{}).
|
||||
Where("reporter_id = ? AND target_type = ? AND target_id = ?", reporterID, targetType, targetID).
|
||||
Count(&count).Error
|
||||
return count > 0, err
|
||||
}
|
||||
|
||||
// GetPendingReportsByTarget 获取目标内容的待处理举报
|
||||
func (r *reportRepository) GetPendingReportsByTarget(targetType model.ReportTargetType, targetID string) ([]*model.Report, error) {
|
||||
var reports []*model.Report
|
||||
err := r.db.Where("target_type = ? AND target_id = ? AND status = ?", targetType, targetID, model.ReportStatusPending).
|
||||
Find(&reports).Error
|
||||
return reports, err
|
||||
}
|
||||
|
||||
// UpdateStatus 更新举报状态
|
||||
func (r *reportRepository) UpdateStatus(id string, status model.ReportStatus, handledBy string, result string) error {
|
||||
updates := map[string]interface{}{
|
||||
"status": status,
|
||||
"handled_by": handledBy,
|
||||
"result": result,
|
||||
}
|
||||
return r.db.Model(&model.Report{}).Where("id = ?", id).Updates(updates).Error
|
||||
}
|
||||
|
||||
// UpdateStatusWithContext 使用上下文更新举报状态
|
||||
func (r *reportRepository) UpdateStatusWithContext(ctx context.Context, id string, status model.ReportStatus, handledBy string, result string) error {
|
||||
updates := map[string]interface{}{
|
||||
"status": status,
|
||||
"handled_by": handledBy,
|
||||
"result": result,
|
||||
}
|
||||
return r.getDB(ctx).Model(&model.Report{}).Where("id = ?", id).Updates(updates).Error
|
||||
}
|
||||
|
||||
// BatchUpdateStatus 批量更新举报状态
|
||||
func (r *reportRepository) BatchUpdateStatus(ids []string, status model.ReportStatus, handledBy string, result string) (int64, error) {
|
||||
updates := map[string]interface{}{
|
||||
"status": status,
|
||||
"handled_by": handledBy,
|
||||
"result": result,
|
||||
}
|
||||
resultDB := r.db.Model(&model.Report{}).Where("id IN ?", ids).Updates(updates)
|
||||
return resultDB.RowsAffected, resultDB.Error
|
||||
}
|
||||
|
||||
// BatchUpdateStatusWithContext 使用上下文批量更新举报状态
|
||||
func (r *reportRepository) BatchUpdateStatusWithContext(ctx context.Context, ids []string, status model.ReportStatus, handledBy string, result string) (int64, error) {
|
||||
updates := map[string]interface{}{
|
||||
"status": status,
|
||||
"handled_by": handledBy,
|
||||
"result": result,
|
||||
}
|
||||
resultDB := r.getDB(ctx).Model(&model.Report{}).Where("id IN ?", ids).Updates(updates)
|
||||
return resultDB.RowsAffected, resultDB.Error
|
||||
}
|
||||
|
||||
// GetByIDsWithContext 使用上下文批量查询举报
|
||||
func (r *reportRepository) GetByIDsWithContext(ctx context.Context, ids []string) ([]*model.Report, error) {
|
||||
var reports []*model.Report
|
||||
err := r.getDB(ctx).Where("id IN ?", ids).Find(&reports).Error
|
||||
return reports, err
|
||||
}
|
||||
Reference in New Issue
Block a user