Files
mce/internal/controller/admin/admin_post_controller.go
Victor_Jay eabc1e7d3d feat: 已发布帖子编辑后进修订审核,通过前保持展示旧内容
- Post 模型新增 PendingTitle/PendingBody 字段,分离已发布内容与待审修订
- Update: approved 帖子编辑写入 Pending 字段,不覆盖正文,不改变发布状态
- Approve: 有 PendingBody 时复制到正式字段后清空,无 PendingBody 走首次审核
- Reject: 有 PendingBody 时仅清空待审修订(保持已发布),无 PendingBody 走普通退回
- 新增 ListPendingRevisions 查询,管理后台独立展示"修订待审核"区域
- 详情页展示"修订审核中"标识,编辑页加载待审内容
- 通过修订后直接覆盖,不保留历史版本
2026-05-30 20:24:43 +08:00

174 lines
4.6 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 admin
import (
"errors"
"net/http"
"strconv"
"metazone.cc/metalab/internal/common"
"metazone.cc/metalab/internal/model"
"github.com/gin-gonic/gin"
)
// AdminPostController 管理后台帖子控制器
type AdminPostController struct {
postService adminPostUseCase
}
// NewAdminPostController 构造函数
func NewAdminPostController(ps adminPostUseCase) *AdminPostController {
return &AdminPostController{postService: ps}
}
// PostsPage 管理后台帖子列表页
func (ctrl *AdminPostController) PostsPage(c *gin.Context) {
keyword := c.Query("keyword")
status := c.Query("status")
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
posts, total, err := ctrl.postService.ListAdmin(keyword, status, page, pageSize)
if err != nil {
c.HTML(http.StatusOK, "admin/posts/index.html", common.BuildAdminPageData(c, gin.H{
"Title": "内容管理",
"Error": "加载帖子列表失败",
}))
return
}
totalPages := common.PageCount(total, pageSize)
prevPage := page - 1
if prevPage < 1 {
prevPage = 1
}
nextPage := page + 1
if nextPage > totalPages {
nextPage = totalPages
}
// 查询待审修订approved 帖子有 PendingBody 的)
revisions, _, _ := ctrl.postService.ListPendingRevisions(keyword, 1, 100)
c.HTML(http.StatusOK, "admin/posts/index.html", common.BuildAdminPageData(c, gin.H{
"Title": "内容管理",
"Posts": posts,
"Total": total,
"Page": page,
"TotalPages": totalPages,
"PrevPage": prevPage,
"NextPage": nextPage,
"Keyword": keyword,
"Status": status,
"StatusNames": common.PostStatusDisplayNames,
"Revisions": revisions,
"ExtraCSS": "/admin/static/css/posts.css",
}))
}
// Approve 审核通过
func (ctrl *AdminPostController) Approve(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil {
common.Error(c, http.StatusBadRequest, "无效的帖子 ID")
return
}
if err := ctrl.postService.Approve(uint(id)); err != nil {
if errors.Is(err, common.ErrPostCannotApprove) || errors.Is(err, common.ErrPostNotFound) {
common.Error(c, http.StatusBadRequest, err.Error())
} else {
common.Error(c, http.StatusInternalServerError, "审核失败")
}
return
}
common.OkMessage(c, "审核通过")
}
// Reject 退回
func (ctrl *AdminPostController) Reject(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil {
common.Error(c, http.StatusBadRequest, "无效的帖子 ID")
return
}
var req model.PostRejectRequest
if err := c.ShouldBindJSON(&req); err != nil {
common.Error(c, http.StatusBadRequest, "请填写退回理由")
return
}
if err := ctrl.postService.Reject(uint(id), req.Reason); err != nil {
if errors.Is(err, common.ErrPostCannotReject) || errors.Is(err, common.ErrPostNotFound) {
common.Error(c, http.StatusBadRequest, err.Error())
} else {
common.Error(c, http.StatusInternalServerError, "退回失败")
}
return
}
common.OkMessage(c, "已退回")
}
// Lock 锁定
func (ctrl *AdminPostController) Lock(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil {
common.Error(c, http.StatusBadRequest, "无效的帖子 ID")
return
}
if err := ctrl.postService.Lock(uint(id)); err != nil {
if errors.Is(err, common.ErrPostNotFound) || errors.Is(err, common.ErrPostCannotLock) {
common.Error(c, http.StatusBadRequest, err.Error())
} else {
common.Error(c, http.StatusInternalServerError, "锁定失败")
}
return
}
common.OkMessage(c, "已锁定")
}
// Unlock 解锁
func (ctrl *AdminPostController) Unlock(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil {
common.Error(c, http.StatusBadRequest, "无效的帖子 ID")
return
}
if err := ctrl.postService.Unlock(uint(id)); err != nil {
if errors.Is(err, common.ErrPostCannotUnlock) || errors.Is(err, common.ErrPostNotFound) {
common.Error(c, http.StatusBadRequest, err.Error())
} else {
common.Error(c, http.StatusInternalServerError, "解锁失败")
}
return
}
common.OkMessage(c, "已解锁")
}
// Restore 恢复软删除
func (ctrl *AdminPostController) Restore(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil {
common.Error(c, http.StatusBadRequest, "无效的帖子 ID")
return
}
if err := ctrl.postService.Restore(uint(id)); err != nil {
if errors.Is(err, common.ErrPostNotFound) {
common.Error(c, http.StatusBadRequest, err.Error())
} else {
common.Error(c, http.StatusInternalServerError, "恢复失败")
}
return
}
common.OkMessage(c, "已恢复")
}