Files
urldb/handlers/report_handler.go

310 lines
9.3 KiB
Go
Raw Permalink Normal View History

2025-11-19 02:22:04 +08:00
package handlers
import (
"net/http"
"strconv"
"github.com/ctwj/urldb/db/converter"
"github.com/ctwj/urldb/db/dto"
"github.com/ctwj/urldb/db/entity"
"github.com/ctwj/urldb/db/repo"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
"gorm.io/gorm"
)
type ReportHandler struct {
2025-11-19 08:32:01 +08:00
reportRepo repo.ReportRepository
resourceRepo repo.ResourceRepository
validate *validator.Validate
2025-11-19 02:22:04 +08:00
}
2025-11-19 08:32:01 +08:00
func NewReportHandler(reportRepo repo.ReportRepository, resourceRepo repo.ResourceRepository) *ReportHandler {
2025-11-19 02:22:04 +08:00
return &ReportHandler{
2025-11-19 08:32:01 +08:00
reportRepo: reportRepo,
resourceRepo: resourceRepo,
validate: validator.New(),
2025-11-19 02:22:04 +08:00
}
}
// CreateReport 创建举报
// @Summary 创建举报
// @Description 提交资源举报
// @Tags Report
// @Accept json
// @Produce json
// @Param request body dto.ReportCreateRequest true "举报信息"
// @Success 200 {object} Response{data=dto.ReportResponse}
// @Failure 400 {object} Response
// @Failure 500 {object} Response
// @Router /reports [post]
func (h *ReportHandler) CreateReport(c *gin.Context) {
var req dto.ReportCreateRequest
if err := c.ShouldBindJSON(&req); err != nil {
ErrorResponse(c, "参数错误: "+err.Error(), http.StatusBadRequest)
return
}
// 验证参数
if err := h.validate.Struct(req); err != nil {
ErrorResponse(c, "参数验证失败: "+err.Error(), http.StatusBadRequest)
return
}
// 创建举报实体
report := &entity.Report{
ResourceKey: req.ResourceKey,
Reason: req.Reason,
Description: req.Description,
Contact: req.Contact,
UserAgent: req.UserAgent,
IPAddress: req.IPAddress,
Status: "pending", // 默认为待处理
}
// 保存到数据库
if err := h.reportRepo.Create(report); err != nil {
ErrorResponse(c, "创建举报失败: "+err.Error(), http.StatusInternalServerError)
return
}
// 返回响应
response := converter.ReportToResponse(report)
SuccessResponse(c, response)
}
// GetReport 获取举报详情
// @Summary 获取举报详情
// @Description 根据ID获取举报详情
// @Tags Report
// @Produce json
// @Param id path int true "举报ID"
// @Success 200 {object} Response{data=dto.ReportResponse}
// @Failure 400 {object} Response
// @Failure 404 {object} Response
// @Failure 500 {object} Response
// @Router /reports/{id} [get]
func (h *ReportHandler) GetReport(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil {
ErrorResponse(c, "无效的ID", http.StatusBadRequest)
return
}
report, err := h.reportRepo.GetByID(uint(id))
if err != nil {
if err == gorm.ErrRecordNotFound {
ErrorResponse(c, "举报不存在", http.StatusNotFound)
return
}
ErrorResponse(c, "获取举报失败: "+err.Error(), http.StatusInternalServerError)
return
}
response := converter.ReportToResponse(report)
SuccessResponse(c, response)
}
// ListReports 获取举报列表
// @Summary 获取举报列表
// @Description 获取举报列表(支持分页和状态筛选)
// @Tags Report
// @Produce json
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(10)
// @Param status query string false "处理状态"
// @Success 200 {object} Response{data=object{items=[]dto.ReportResponse,total=int}}
// @Failure 400 {object} Response
// @Failure 500 {object} Response
// @Router /reports [get]
func (h *ReportHandler) ListReports(c *gin.Context) {
var req dto.ReportListRequest
if err := c.ShouldBindQuery(&req); err != nil {
ErrorResponse(c, "参数错误: "+err.Error(), http.StatusBadRequest)
return
}
// 设置默认值
if req.Page == 0 {
req.Page = 1
}
if req.PageSize == 0 {
req.PageSize = 10
}
// 验证参数
if err := h.validate.Struct(req); err != nil {
ErrorResponse(c, "参数验证失败: "+err.Error(), http.StatusBadRequest)
return
}
reports, total, err := h.reportRepo.List(req.Status, req.Page, req.PageSize)
if err != nil {
ErrorResponse(c, "获取举报列表失败: "+err.Error(), http.StatusInternalServerError)
return
}
2025-11-19 08:32:01 +08:00
// 获取每个举报关联的资源
var reportResponses []*dto.ReportResponse
for _, report := range reports {
// 通过资源key查找关联的资源
resources, err := h.getResourcesByResourceKey(report.ResourceKey)
if err != nil {
// 如果获取资源失败,仍然返回基本的举报信息
reportResponses = append(reportResponses, converter.ReportToResponse(report))
} else {
// 使用包含资源详情的转换函数
response := converter.ReportToResponseWithResources(report, resources)
reportResponses = append(reportResponses, response)
}
}
PageResponse(c, reportResponses, total, req.Page, req.PageSize)
}
// getResourcesByResourceKey 根据资源key获取关联的资源列表
func (h *ReportHandler) getResourcesByResourceKey(resourceKey string) ([]*entity.Resource, error) {
// 从资源仓库获取与key关联的所有资源
resources, err := h.resourceRepo.FindByResourceKey(resourceKey)
if err != nil {
return nil, err
}
// 将 []entity.Resource 转换为 []*entity.Resource
var resourcePointers []*entity.Resource
for i := range resources {
resourcePointers = append(resourcePointers, &resources[i])
}
return resourcePointers, nil
2025-11-19 02:22:04 +08:00
}
// UpdateReport 更新举报状态
// @Summary 更新举报状态
// @Description 更新举报处理状态
// @Tags Report
// @Accept json
// @Produce json
// @Param id path int true "举报ID"
// @Param request body dto.ReportUpdateRequest true "更新信息"
// @Success 200 {object} Response{data=dto.ReportResponse}
// @Failure 400 {object} Response
// @Failure 404 {object} Response
// @Failure 500 {object} Response
// @Router /reports/{id} [put]
func (h *ReportHandler) UpdateReport(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil {
ErrorResponse(c, "无效的ID", http.StatusBadRequest)
return
}
var req dto.ReportUpdateRequest
if err := c.ShouldBindJSON(&req); err != nil {
ErrorResponse(c, "参数错误: "+err.Error(), http.StatusBadRequest)
return
}
// 验证参数
if err := h.validate.Struct(req); err != nil {
ErrorResponse(c, "参数验证失败: "+err.Error(), http.StatusBadRequest)
return
}
// 获取当前举报
_, err = h.reportRepo.GetByID(uint(id))
if err != nil {
if err == gorm.ErrRecordNotFound {
ErrorResponse(c, "举报不存在", http.StatusNotFound)
return
}
ErrorResponse(c, "获取举报失败: "+err.Error(), http.StatusInternalServerError)
return
}
// 更新状态
processedBy := uint(0) // 从上下文获取当前用户ID如果存在的话
if currentUser := c.GetUint("user_id"); currentUser > 0 {
processedBy = currentUser
}
if err := h.reportRepo.UpdateStatus(uint(id), req.Status, &processedBy, req.Note); err != nil {
ErrorResponse(c, "更新举报状态失败: "+err.Error(), http.StatusInternalServerError)
return
}
// 获取更新后的举报信息
updatedReport, err := h.reportRepo.GetByID(uint(id))
if err != nil {
ErrorResponse(c, "获取更新后举报信息失败: "+err.Error(), http.StatusInternalServerError)
return
}
SuccessResponse(c, converter.ReportToResponse(updatedReport))
}
// DeleteReport 删除举报
// @Summary 删除举报
// @Description 删除举报记录
// @Tags Report
// @Produce json
// @Param id path int true "举报ID"
// @Success 200 {object} Response
// @Failure 400 {object} Response
// @Failure 500 {object} Response
// @Router /reports/{id} [delete]
func (h *ReportHandler) DeleteReport(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil {
ErrorResponse(c, "无效的ID", http.StatusBadRequest)
return
}
if err := h.reportRepo.Delete(uint(id)); err != nil {
ErrorResponse(c, "删除举报失败: "+err.Error(), http.StatusInternalServerError)
return
}
SuccessResponse(c, nil)
}
// GetReportByResource 获取某个资源的举报列表
// @Summary 获取资源举报列表
// @Description 获取某个资源的所有举报记录
// @Tags Report
// @Produce json
// @Param resource_key path string true "资源Key"
// @Success 200 {object} Response{data=[]dto.ReportResponse}
// @Failure 400 {object} Response
// @Failure 500 {object} Response
// @Router /reports/resource/{resource_key} [get]
func (h *ReportHandler) GetReportByResource(c *gin.Context) {
resourceKey := c.Param("resource_key")
if resourceKey == "" {
ErrorResponse(c, "资源Key不能为空", http.StatusBadRequest)
return
}
reports, err := h.reportRepo.GetByResourceKey(resourceKey)
if err != nil {
ErrorResponse(c, "获取资源举报失败: "+err.Error(), http.StatusInternalServerError)
return
}
SuccessResponse(c, converter.ReportsToResponse(reports))
}
// RegisterReportRoutes 注册举报相关路由
2025-11-19 08:32:01 +08:00
func RegisterReportRoutes(router *gin.RouterGroup, reportRepo repo.ReportRepository, resourceRepo repo.ResourceRepository) {
handler := NewReportHandler(reportRepo, resourceRepo)
2025-11-19 02:22:04 +08:00
reports := router.Group("/reports")
{
reports.POST("", handler.CreateReport) // 创建举报
reports.GET("/:id", handler.GetReport) // 获取举报详情
reports.GET("", handler.ListReports) // 获取举报列表
reports.PUT("/:id", handler.UpdateReport) // 更新举报状态
reports.DELETE("/:id", handler.DeleteReport) // 删除举报
reports.GET("/resource/:resource_key", handler.GetReportByResource) // 获取资源举报列表
}
}