Files
mce/internal/controller/admin/admin_post_controller.go
Victor_Jay 8a8d801187 fix: 修复帖子系统5项缺陷 + 代码块插入位置/language-class/分割线占位
- 作者显示 用户名(UID): 修正Post.AuthorName GORM标签从 -:all 改为 -:migration;<-:false;column:author_name
- 审核流程: 帖子详情页新增"提交审核"按钮(draft/rejected时作者可见)
- 图片上传: 新增 POST /api/posts/upload-image 端点,限制5MB/jpg/png/gif/webp
- 代码块语言标注: 工具栏插入代码块时弹出语言输入框,生成 language-xxx class
- 状态中文显示: 管理后台/帖子详情页状态改为 PostStatusDisplayNames 映射
- 修复代码块插入位置错误: init时调用switchMode同步DOM; 无选区时appendChild; 防<pre>嵌套
- 修复 bluemonday.UGCPolicy() 剥离 code/pre 的 class 属性,显式 AllowAttrs("class")
- 修复分割线工具栏插入多余text占位符: hr/link/image以外不强制填占位文本
2026-05-27 19:22:47 +08:00

151 lines
3.8 KiB
Go

package admin
import (
"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
}
if posts == nil {
posts = []model.Post{}
}
p := common.Pagination{Page: page, PageSize: pageSize}
p.DefaultPagination()
totalPages := int((total + int64(p.PageSize) - 1) / int64(p.PageSize))
prevPage := p.Page - 1
if prevPage < 1 { prevPage = 1 }
nextPage := p.Page + 1
if nextPage > totalPages { nextPage = totalPages }
c.HTML(http.StatusOK, "admin/posts/index.html", common.BuildAdminPageData(c, gin.H{
"Title": "内容管理",
"Posts": posts,
"Total": total,
"Page": p.Page,
"TotalPages": totalPages,
"PrevPage": prevPage,
"NextPage": nextPage,
"Keyword": keyword,
"Status": status,
"StatusNames": model.PostStatusDisplayNames,
"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 {
common.Error(c, http.StatusBadRequest, err.Error())
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 {
common.Error(c, http.StatusBadRequest, err.Error())
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 {
common.Error(c, http.StatusBadRequest, err.Error())
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 {
common.Error(c, http.StatusBadRequest, err.Error())
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 {
common.Error(c, http.StatusBadRequest, err.Error())
return
}
common.OkMessage(c, "已恢复")
}