feat(moderation): add manual content review system with three-tier AI moderation
All checks were successful
Build Backend / build (push) Successful in 2m43s
Build Backend / build-docker (push) Successful in 1m22s

Add admin comment moderation endpoints (single and batch) and introduce a three-tier moderation system (pass/review/block) for content flagged by AI. Content with unclear violations is now held for manual review instead of being auto-rejected. Deleted the legacy audit_service.go in favor of the unified hook-based moderation system.
This commit is contained in:
lafay
2026-04-11 04:23:24 +08:00
parent 6af6aaa9d0
commit 1bb82e1e2b
17 changed files with 432 additions and 732 deletions

View File

@@ -121,6 +121,58 @@ func (h *AdminCommentHandler) BatchDeleteComments(c *gin.Context) {
response.Success(c, result)
}
func (h *AdminCommentHandler) ModerateComment(c *gin.Context) {
commentID := c.Param("id")
if commentID == "" {
response.BadRequest(c, "comment id is required")
return
}
var req dto.AdminModerateCommentRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "invalid request body: "+err.Error())
return
}
if req.Status != string(model.CommentStatusPublished) && req.Status != string(model.CommentStatusRejected) {
response.BadRequest(c, "invalid status value, must be 'published' or 'rejected'")
return
}
reviewedBy := c.GetString("user_id")
commentDetail, err := h.adminCommentService.ModerateComment(c.Request.Context(), commentID, model.CommentStatus(req.Status), req.Reason, reviewedBy)
if err != nil {
response.HandleError(c, err, "failed to moderate comment")
return
}
response.Success(c, commentDetail)
}
func (h *AdminCommentHandler) BatchModerateComments(c *gin.Context) {
var req dto.AdminBatchModerateCommentsRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "invalid request body: "+err.Error())
return
}
if req.Status != string(model.CommentStatusPublished) && req.Status != string(model.CommentStatusRejected) {
response.BadRequest(c, "invalid status value, must be 'published' or 'rejected'")
return
}
reviewedBy := c.GetString("user_id")
result, err := h.adminCommentService.BatchModerateComments(c.Request.Context(), req.IDs, model.CommentStatus(req.Status), reviewedBy)
if err != nil {
response.InternalServerError(c, "failed to batch moderate comments")
return
}
response.Success(c, result)
}
// GetPostComments 获取帖子的评论列表
// GET /api/v1/admin/posts/:postId/comments
func (h *AdminCommentHandler) GetPostComments(c *gin.Context) {

View File

@@ -2,7 +2,6 @@ package handler
import (
"encoding/json"
"errors"
"strconv"
"github.com/gin-gonic/gin"
@@ -61,11 +60,6 @@ func (h *CommentHandler) Create(c *gin.Context) {
comment, err := h.commentService.Create(c.Request.Context(), req.PostID, userID, req.Content, req.ParentID, imagesJSON, req.Images)
if err != nil {
var moderationErr *service.CommentModerationRejectedError
if errors.As(err, &moderationErr) {
response.BadRequest(c, moderationErr.UserMessage())
return
}
response.InternalServerError(c, "failed to create comment")
return
}