Files
jiang13-bbs/backend/handler/moderation.go
freefire a7b6421840 feat: 实现完整的板块级RBAC内容审核系统
- 新增站长/超级管理员/管理员/板块管理员四级角色体系
- 实现实时权限快照加载与细粒度权限校验
- 新增内容审核队列与前后端页面
- 重构用户权限管理与站点管理逻辑
- 新增评论/帖子审核状态与通知推送
- 优化前端权限控制与角色徽章展示
- 修正数据库迁移与默认值问题
2026-09-15 04:47:34 +08:00

86 lines
2.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package handler
import (
"errors"
"net/http"
"strconv"
"github.com/freefire/jiang13-bbs/middleware"
"github.com/freefire/jiang13-bbs/service"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
// ===== 内容审核队列(RequireStaff 基础鉴权,板块范围由 service 按 Actor 隔离) =====
// AdminPendingPosts 待审核帖子分页
func (h *Handlers) AdminPendingPosts(c *gin.Context) {
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
posts, total, err := h.Moderation.PendingPosts(middleware.CurrentActor(c), page, 15)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取待审帖子失败"})
return
}
c.JSON(http.StatusOK, gin.H{"posts": posts, "total": total, "page": page})
}
// AdminPendingComments 待审核评论分页
func (h *Handlers) AdminPendingComments(c *gin.Context) {
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
comments, total, err := h.Moderation.PendingComments(middleware.CurrentActor(c), page, 15)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取待审评论失败"})
return
}
c.JSON(http.StatusOK, gin.H{"comments": comments, "total": total, "page": page})
}
// AdminPendingCounts 当前操作者可见的待审数量(导航角标)
func (h *Handlers) AdminPendingCounts(c *gin.Context) {
posts, comments := h.Moderation.PendingCounts(middleware.CurrentActor(c))
c.JSON(http.StatusOK, gin.H{"posts": posts, "comments": comments})
}
// AdminApprovePost 通过帖子
func (h *Handlers) AdminApprovePost(c *gin.Context) {
h.execModeration(c, h.Moderation.ApprovePost)
}
// AdminRejectPost 拒绝帖子
func (h *Handlers) AdminRejectPost(c *gin.Context) {
h.execModeration(c, h.Moderation.RejectPost)
}
// AdminApproveComment 通过评论
func (h *Handlers) AdminApproveComment(c *gin.Context) {
h.execModeration(c, h.Moderation.ApproveComment)
}
// AdminRejectComment 拒绝评论
func (h *Handlers) AdminRejectComment(c *gin.Context) {
h.execModeration(c, h.Moderation.RejectComment)
}
// execModeration 统一解析 :id 并映射审核业务错误
func (h *Handlers) execModeration(c *gin.Context, fn func(*service.Actor, uint) error) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil || id == 0 {
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的 ID"})
return
}
if err := fn(middleware.CurrentActor(c), uint(id)); err != nil {
switch {
case errors.Is(err, gorm.ErrRecordNotFound):
c.JSON(http.StatusNotFound, gin.H{"error": "内容不存在"})
case errors.Is(err, service.ErrModerationForbidden):
c.JSON(http.StatusForbidden, gin.H{"error": err.Error()})
case errors.Is(err, service.ErrNotPending):
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
default:
c.JSON(http.StatusInternalServerError, gin.H{"error": "操作失败"})
}
return
}
c.JSON(http.StatusOK, gin.H{"message": "操作成功"})
}