496 lines
14 KiB
Go
496 lines
14 KiB
Go
package handler
|
||
|
||
import (
|
||
"carrotskin/internal/container"
|
||
"carrotskin/internal/model"
|
||
"strconv"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
"go.uber.org/zap"
|
||
)
|
||
|
||
// ReportHandler 举报处理器
|
||
type ReportHandler struct {
|
||
container *container.Container
|
||
logger *zap.Logger
|
||
}
|
||
|
||
// NewReportHandler 创建ReportHandler实例
|
||
func NewReportHandler(c *container.Container) *ReportHandler {
|
||
return &ReportHandler{
|
||
container: c,
|
||
logger: c.Logger,
|
||
}
|
||
}
|
||
|
||
// CreateReportRequest 创建举报请求
|
||
type CreateReportRequest struct {
|
||
TargetType string `json:"target_type" binding:"required"` // "texture" 或 "user"
|
||
TargetID int64 `json:"target_id" binding:"required"`
|
||
Reason string `json:"reason" binding:"required"`
|
||
}
|
||
|
||
// CreateReport 创建举报
|
||
// @Summary 创建举报
|
||
// @Description 用户举报皮肤或其他用户
|
||
// @Tags report
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Security Bearer
|
||
// @Param request body CreateReportRequest true "举报信息"
|
||
// @Success 200 {object} model.Response{data=model.Report} "创建成功"
|
||
// @Failure 400 {object} model.ErrorResponse "参数错误"
|
||
// @Failure 401 {object} model.ErrorResponse "未授权"
|
||
// @Router /api/v1/report [post]
|
||
func (h *ReportHandler) CreateReport(c *gin.Context) {
|
||
userID, ok := GetUserIDFromContext(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
|
||
var req CreateReportRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
RespondBadRequest(c, "参数错误", err)
|
||
return
|
||
}
|
||
|
||
// 转换目标类型
|
||
var targetType model.ReportType
|
||
switch req.TargetType {
|
||
case "texture":
|
||
targetType = model.ReportTypeTexture
|
||
case "user":
|
||
targetType = model.ReportTypeUser
|
||
default:
|
||
RespondBadRequest(c, "无效的举报类型", nil)
|
||
return
|
||
}
|
||
|
||
report, err := h.container.ReportService.CreateReport(c.Request.Context(), userID, targetType, req.TargetID, req.Reason)
|
||
if err != nil {
|
||
RespondBadRequest(c, err.Error(), err)
|
||
return
|
||
}
|
||
|
||
RespondSuccess(c, report)
|
||
}
|
||
|
||
// GetByID 获取举报详情
|
||
// @Summary 获取举报详情
|
||
// @Description 获取指定ID的举报详细信息
|
||
// @Tags report
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Security Bearer
|
||
// @Param id path int true "举报ID"
|
||
// @Success 200 {object} model.Response{data=model.Report} "获取成功"
|
||
// @Failure 400 {object} model.ErrorResponse "参数错误"
|
||
// @Failure 404 {object} model.ErrorResponse "举报不存在"
|
||
// @Router /api/v1/report/{id} [get]
|
||
func (h *ReportHandler) GetByID(c *gin.Context) {
|
||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||
if err != nil {
|
||
RespondBadRequest(c, "无效的举报ID", err)
|
||
return
|
||
}
|
||
|
||
report, err := h.container.ReportService.GetByID(c.Request.Context(), id)
|
||
if err != nil {
|
||
RespondNotFound(c, err.Error())
|
||
return
|
||
}
|
||
|
||
RespondSuccess(c, report)
|
||
}
|
||
|
||
// GetByReporterID 获取举报人的举报记录
|
||
// @Summary 获取举报人的举报记录
|
||
// @Description 获取指定用户的举报记录列表
|
||
// @Tags report
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Security Bearer
|
||
// @Param reporter_id path int true "举报人ID"
|
||
// @Param page query int false "页码" default(1)
|
||
// @Param page_size query int false "每页数量" default(20)
|
||
// @Success 200 {object} model.Response{data=map[string]interface{}} "获取成功"
|
||
// @Failure 400 {object} model.ErrorResponse "参数错误"
|
||
// @Router /api/v1/report/reporter/{reporter_id} [get]
|
||
func (h *ReportHandler) GetByReporterID(c *gin.Context) {
|
||
userID, ok := GetUserIDFromContext(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
|
||
reporterID, err := strconv.ParseInt(c.Param("reporter_id"), 10, 64)
|
||
if err != nil {
|
||
RespondBadRequest(c, "无效的举报人ID", err)
|
||
return
|
||
}
|
||
|
||
page := parseIntWithDefault(c.DefaultQuery("page", "1"), 1)
|
||
pageSize := parseIntWithDefault(c.DefaultQuery("page_size", "20"), 20)
|
||
|
||
reports, total, err := h.container.ReportService.GetByReporterID(c.Request.Context(), reporterID, userID, page, pageSize)
|
||
if err != nil {
|
||
RespondBadRequest(c, err.Error(), err)
|
||
return
|
||
}
|
||
|
||
RespondSuccess(c, gin.H{
|
||
"list": reports,
|
||
"total": total,
|
||
"page": page,
|
||
"per_page": pageSize,
|
||
})
|
||
}
|
||
|
||
// GetByTarget 获取目标对象的举报记录
|
||
// @Summary 获取目标对象的举报记录
|
||
// @Description 获取指定目标对象的举报记录列表(仅管理员)
|
||
// @Tags report
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Security Bearer
|
||
// @Param target_type path string true "目标类型 (texture/user)"
|
||
// @Param target_id path int true "目标ID"
|
||
// @Param page query int false "页码" default(1)
|
||
// @Param page_size query int false "每页数量" default(20)
|
||
// @Success 200 {object} model.Response{data=map[string]interface{}} "获取成功"
|
||
// @Failure 400 {object} model.ErrorResponse "参数错误"
|
||
// @Failure 403 {object} model.ErrorResponse "无权访问"
|
||
// @Router /api/v1/report/target/{target_type}/{target_id} [get]
|
||
func (h *ReportHandler) GetByTarget(c *gin.Context) {
|
||
userID, ok := GetUserIDFromContext(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
|
||
targetTypeStr := c.Param("target_type")
|
||
targetID, err := strconv.ParseInt(c.Param("target_id"), 10, 64)
|
||
if err != nil {
|
||
RespondBadRequest(c, "无效的目标ID", err)
|
||
return
|
||
}
|
||
|
||
var targetType model.ReportType
|
||
switch targetTypeStr {
|
||
case "texture":
|
||
targetType = model.ReportTypeTexture
|
||
case "user":
|
||
targetType = model.ReportTypeUser
|
||
default:
|
||
RespondBadRequest(c, "无效的目标类型", nil)
|
||
return
|
||
}
|
||
|
||
page := parseIntWithDefault(c.DefaultQuery("page", "1"), 1)
|
||
pageSize := parseIntWithDefault(c.DefaultQuery("page_size", "20"), 20)
|
||
|
||
reports, total, err := h.container.ReportService.GetByTarget(c.Request.Context(), targetType, targetID, userID, page, pageSize)
|
||
if err != nil {
|
||
RespondBadRequest(c, err.Error(), err)
|
||
return
|
||
}
|
||
|
||
RespondSuccess(c, gin.H{
|
||
"list": reports,
|
||
"total": total,
|
||
"page": page,
|
||
"per_page": pageSize,
|
||
})
|
||
}
|
||
|
||
// GetByStatus 根据状态查询举报记录
|
||
// @Summary 根据状态查询举报记录
|
||
// @Description 根据状态查询举报记录列表(仅管理员)
|
||
// @Tags report
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Security Bearer
|
||
// @Param status path string true "状态 (pending/approved/rejected)"
|
||
// @Param page query int false "页码" default(1)
|
||
// @Param page_size query int false "每页数量" default(20)
|
||
// @Success 200 {object} model.Response{data=map[string]interface{}} "获取成功"
|
||
// @Failure 400 {object} model.ErrorResponse "参数错误"
|
||
// @Router /api/v1/report/status/{status} [get]
|
||
func (h *ReportHandler) GetByStatus(c *gin.Context) {
|
||
statusStr := c.Param("status")
|
||
|
||
var status model.ReportStatus
|
||
switch statusStr {
|
||
case "pending":
|
||
status = model.ReportStatusPending
|
||
case "approved":
|
||
status = model.ReportStatusApproved
|
||
case "rejected":
|
||
status = model.ReportStatusRejected
|
||
default:
|
||
RespondBadRequest(c, "无效的状态", nil)
|
||
return
|
||
}
|
||
|
||
page := parseIntWithDefault(c.DefaultQuery("page", "1"), 1)
|
||
pageSize := parseIntWithDefault(c.DefaultQuery("page_size", "20"), 20)
|
||
|
||
reports, total, err := h.container.ReportService.GetByStatus(c.Request.Context(), status, page, pageSize)
|
||
if err != nil {
|
||
RespondServerError(c, err.Error(), err)
|
||
return
|
||
}
|
||
|
||
RespondSuccess(c, gin.H{
|
||
"list": reports,
|
||
"total": total,
|
||
"page": page,
|
||
"per_page": pageSize,
|
||
})
|
||
}
|
||
|
||
// Search 搜索举报记录
|
||
// @Summary 搜索举报记录
|
||
// @Description 搜索举报记录(仅管理员)
|
||
// @Tags report
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Security Bearer
|
||
// @Param keyword query int false "关键词(举报人ID或目标ID)"
|
||
// @Param page query int false "页码" default(1)
|
||
// @Param page_size query int false "每页数量" default(20)
|
||
// @Success 200 {object} model.Response{data=map[string]interface{}} "获取成功"
|
||
// @Failure 400 {object} model.ErrorResponse "参数错误"
|
||
// @Failure 403 {object} model.ErrorResponse "无权访问"
|
||
// @Router /api/v1/report/search [get]
|
||
func (h *ReportHandler) Search(c *gin.Context) {
|
||
userID, ok := GetUserIDFromContext(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
|
||
keywordStr := c.Query("keyword")
|
||
keyword, err := strconv.ParseInt(keywordStr, 10, 64)
|
||
if err != nil {
|
||
RespondBadRequest(c, "无效的关键词", err)
|
||
return
|
||
}
|
||
|
||
page := parseIntWithDefault(c.DefaultQuery("page", "1"), 1)
|
||
pageSize := parseIntWithDefault(c.DefaultQuery("page_size", "20"), 20)
|
||
|
||
reports, total, err := h.container.ReportService.Search(c.Request.Context(), keyword, userID, page, pageSize)
|
||
if err != nil {
|
||
RespondBadRequest(c, err.Error(), err)
|
||
return
|
||
}
|
||
|
||
RespondSuccess(c, gin.H{
|
||
"list": reports,
|
||
"total": total,
|
||
"page": page,
|
||
"per_page": pageSize,
|
||
})
|
||
}
|
||
|
||
// ReviewRequest 处理举报请求
|
||
type ReviewRequest struct {
|
||
Status string `json:"status" binding:"required"` // "approved" 或 "rejected"
|
||
ReviewNote string `json:"review_note"`
|
||
}
|
||
|
||
// Review 处理举报记录
|
||
// @Summary 处理举报记录
|
||
// @Description 管理员处理举报记录
|
||
// @Tags report
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Security Bearer
|
||
// @Param id path int true "举报ID"
|
||
// @Param request body ReviewRequest true "处理信息"
|
||
// @Success 200 {object} model.Response{data=model.Report} "处理成功"
|
||
// @Failure 400 {object} model.ErrorResponse "参数错误"
|
||
// @Failure 403 {object} model.ErrorResponse "无权访问"
|
||
// @Router /api/v1/report/{id}/review [put]
|
||
func (h *ReportHandler) Review(c *gin.Context) {
|
||
userID, ok := GetUserIDFromContext(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
|
||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||
if err != nil {
|
||
RespondBadRequest(c, "无效的举报ID", err)
|
||
return
|
||
}
|
||
|
||
var req ReviewRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
RespondBadRequest(c, "参数错误", err)
|
||
return
|
||
}
|
||
|
||
// 转换状态
|
||
var status model.ReportStatus
|
||
switch req.Status {
|
||
case "approved":
|
||
status = model.ReportStatusApproved
|
||
case "rejected":
|
||
status = model.ReportStatusRejected
|
||
default:
|
||
RespondBadRequest(c, "无效的状态", nil)
|
||
return
|
||
}
|
||
|
||
report, err := h.container.ReportService.Review(c.Request.Context(), id, userID, status, req.ReviewNote)
|
||
if err != nil {
|
||
RespondBadRequest(c, err.Error(), err)
|
||
return
|
||
}
|
||
|
||
RespondSuccess(c, report)
|
||
}
|
||
|
||
// BatchReviewRequest 批量处理举报请求
|
||
type BatchReviewRequest struct {
|
||
IDs []int64 `json:"ids" binding:"required"`
|
||
Status string `json:"status" binding:"required"` // "approved" 或 "rejected"
|
||
ReviewNote string `json:"review_note"`
|
||
}
|
||
|
||
// BatchReview 批量处理举报记录
|
||
// @Summary 批量处理举报记录
|
||
// @Description 管理员批量处理举报记录
|
||
// @Tags report
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Security Bearer
|
||
// @Param request body BatchReviewRequest true "处理信息"
|
||
// @Success 200 {object} model.Response{data=map[string]interface{}} "处理成功"
|
||
// @Failure 400 {object} model.ErrorResponse "参数错误"
|
||
// @Failure 403 {object} model.ErrorResponse "无权访问"
|
||
// @Router /api/v1/report/batch-review [put]
|
||
func (h *ReportHandler) BatchReview(c *gin.Context) {
|
||
userID, ok := GetUserIDFromContext(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
|
||
var req BatchReviewRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
RespondBadRequest(c, "参数错误", err)
|
||
return
|
||
}
|
||
|
||
// 转换状态
|
||
var status model.ReportStatus
|
||
switch req.Status {
|
||
case "approved":
|
||
status = model.ReportStatusApproved
|
||
case "rejected":
|
||
status = model.ReportStatusRejected
|
||
default:
|
||
RespondBadRequest(c, "无效的状态", nil)
|
||
return
|
||
}
|
||
|
||
affected, err := h.container.ReportService.BatchReview(c.Request.Context(), req.IDs, userID, status, req.ReviewNote)
|
||
if err != nil {
|
||
RespondBadRequest(c, err.Error(), err)
|
||
return
|
||
}
|
||
|
||
RespondSuccess(c, gin.H{
|
||
"affected": affected,
|
||
})
|
||
}
|
||
|
||
// Delete 删除举报记录
|
||
// @Summary 删除举报记录
|
||
// @Description 删除指定的举报记录
|
||
// @Tags report
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Security Bearer
|
||
// @Param id path int true "举报ID"
|
||
// @Success 200 {object} model.Response "删除成功"
|
||
// @Failure 400 {object} model.ErrorResponse "参数错误"
|
||
// @Failure 403 {object} model.ErrorResponse "无权访问"
|
||
// @Router /api/v1/report/{id} [delete]
|
||
func (h *ReportHandler) Delete(c *gin.Context) {
|
||
userID, ok := GetUserIDFromContext(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
|
||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||
if err != nil {
|
||
RespondBadRequest(c, "无效的举报ID", err)
|
||
return
|
||
}
|
||
|
||
if err := h.container.ReportService.Delete(c.Request.Context(), id, userID); err != nil {
|
||
RespondBadRequest(c, err.Error(), err)
|
||
return
|
||
}
|
||
|
||
RespondSuccess(c, nil)
|
||
}
|
||
|
||
// BatchDeleteRequest 批量删除请求
|
||
type BatchDeleteRequest struct {
|
||
IDs []int64 `json:"ids" binding:"required"`
|
||
}
|
||
|
||
// BatchDelete 批量删除举报记录
|
||
// @Summary 批量删除举报记录
|
||
// @Description 管理员批量删除举报记录
|
||
// @Tags report
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Security Bearer
|
||
// @Param request body BatchDeleteRequest true "删除信息"
|
||
// @Success 200 {object} model.Response{data=map[string]interface{}} "删除成功"
|
||
// @Failure 400 {object} model.ErrorResponse "参数错误"
|
||
// @Failure 403 {object} model.ErrorResponse "无权访问"
|
||
// @Router /api/v1/report/batch-delete [delete]
|
||
func (h *ReportHandler) BatchDelete(c *gin.Context) {
|
||
userID, ok := GetUserIDFromContext(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
|
||
var req BatchDeleteRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
RespondBadRequest(c, "参数错误", err)
|
||
return
|
||
}
|
||
|
||
affected, err := h.container.ReportService.BatchDelete(c.Request.Context(), req.IDs, userID)
|
||
if err != nil {
|
||
RespondBadRequest(c, err.Error(), err)
|
||
return
|
||
}
|
||
|
||
RespondSuccess(c, gin.H{
|
||
"affected": affected,
|
||
})
|
||
}
|
||
|
||
// GetStats 获取举报统计信息
|
||
// @Summary 获取举报统计信息
|
||
// @Description 获取举报统计信息(仅管理员)
|
||
// @Tags report
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Security Bearer
|
||
// @Success 200 {object} model.Response{data=map[string]interface{}} "获取成功"
|
||
// @Router /api/v1/report/stats [get]
|
||
func (h *ReportHandler) GetStats(c *gin.Context) {
|
||
stats, err := h.container.ReportService.GetStats(c.Request.Context())
|
||
if err != nil {
|
||
RespondServerError(c, err.Error(), err)
|
||
return
|
||
}
|
||
|
||
RespondSuccess(c, stats)
|
||
}
|