The Go module name has been changed from `carrot_bbs` to `with_you`, which requires all import paths to be updated throughout the codebase and by external consumers. BREAKING CHANGE: Module name changed from carrot_bbs to with_you. All imports and dependencies must be updated from carrot_bbs/* to with_you/*.
229 lines
6.0 KiB
Go
229 lines
6.0 KiB
Go
package handler
|
|
|
|
import (
|
|
"strconv"
|
|
|
|
"with_you/internal/dto"
|
|
"with_you/internal/model"
|
|
"with_you/internal/pkg/response"
|
|
"with_you/internal/service"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// AdminPostHandler 管理端帖子处理器
|
|
type AdminPostHandler struct {
|
|
adminPostService service.AdminPostService
|
|
}
|
|
|
|
// NewAdminPostHandler 创建管理端帖子处理器
|
|
func NewAdminPostHandler(adminPostService service.AdminPostService) *AdminPostHandler {
|
|
return &AdminPostHandler{
|
|
adminPostService: adminPostService,
|
|
}
|
|
}
|
|
|
|
// GetPostList 获取帖子列表
|
|
// GET /api/v1/admin/posts
|
|
func (h *AdminPostHandler) GetPostList(c *gin.Context) {
|
|
// 解析分页参数
|
|
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
|
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
|
|
|
|
if page <= 0 {
|
|
page = 1
|
|
}
|
|
if pageSize <= 0 || pageSize > 100 {
|
|
pageSize = 20
|
|
}
|
|
|
|
// 获取筛选参数
|
|
keyword := c.Query("keyword")
|
|
status := c.Query("status")
|
|
authorID := c.Query("author_id")
|
|
startDate := c.Query("start_date")
|
|
endDate := c.Query("end_date")
|
|
|
|
// 验证状态参数
|
|
if status != "" && status != string(model.PostStatusDraft) &&
|
|
status != string(model.PostStatusPending) &&
|
|
status != string(model.PostStatusPublished) &&
|
|
status != string(model.PostStatusRejected) {
|
|
response.BadRequest(c, "invalid status value")
|
|
return
|
|
}
|
|
|
|
posts, total, err := h.adminPostService.GetPostList(c.Request.Context(), page, pageSize, keyword, status, authorID, startDate, endDate)
|
|
if err != nil {
|
|
response.InternalServerError(c, "failed to get post list")
|
|
return
|
|
}
|
|
|
|
response.Paginated(c, posts, total, page, pageSize)
|
|
}
|
|
|
|
// GetPostDetail 获取帖子详情
|
|
// GET /api/v1/admin/posts/:id
|
|
func (h *AdminPostHandler) GetPostDetail(c *gin.Context) {
|
|
postID := c.Param("id")
|
|
if postID == "" {
|
|
response.BadRequest(c, "post id is required")
|
|
return
|
|
}
|
|
|
|
postDetail, err := h.adminPostService.GetPostDetail(c.Request.Context(), postID)
|
|
if err != nil {
|
|
response.NotFound(c, "post not found")
|
|
return
|
|
}
|
|
|
|
response.Success(c, postDetail)
|
|
}
|
|
|
|
// DeletePost 删除帖子
|
|
// DELETE /api/v1/admin/posts/:id
|
|
func (h *AdminPostHandler) DeletePost(c *gin.Context) {
|
|
postID := c.Param("id")
|
|
if postID == "" {
|
|
response.BadRequest(c, "post id is required")
|
|
return
|
|
}
|
|
|
|
err := h.adminPostService.DeletePost(c.Request.Context(), postID)
|
|
if err != nil {
|
|
response.HandleError(c, err, "failed to delete post")
|
|
return
|
|
}
|
|
|
|
response.Success(c, dto.SuccessResponse{
|
|
Success: true,
|
|
Message: "post deleted successfully",
|
|
})
|
|
}
|
|
|
|
// ModeratePost 审核帖子
|
|
// PUT /api/v1/admin/posts/:id/moderate
|
|
func (h *AdminPostHandler) ModeratePost(c *gin.Context) {
|
|
postID := c.Param("id")
|
|
if postID == "" {
|
|
response.BadRequest(c, "post id is required")
|
|
return
|
|
}
|
|
|
|
var req dto.AdminModeratePostRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "invalid request body: "+err.Error())
|
|
return
|
|
}
|
|
|
|
// 验证状态值
|
|
if req.Status != string(model.PostStatusPublished) && req.Status != string(model.PostStatusRejected) {
|
|
response.BadRequest(c, "invalid status value, must be 'published' or 'rejected'")
|
|
return
|
|
}
|
|
|
|
// 获取当前用户ID作为审核人
|
|
reviewedBy := c.GetString("user_id")
|
|
|
|
postDetail, err := h.adminPostService.ModeratePost(c.Request.Context(), postID, model.PostStatus(req.Status), req.Reason, reviewedBy)
|
|
if err != nil {
|
|
response.HandleError(c, err, "failed to moderate post")
|
|
return
|
|
}
|
|
|
|
response.Success(c, postDetail)
|
|
}
|
|
|
|
// BatchDeletePosts 批量删除帖子
|
|
// POST /api/v1/admin/posts/batch-delete
|
|
func (h *AdminPostHandler) BatchDeletePosts(c *gin.Context) {
|
|
var req dto.AdminBatchDeletePostsRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "invalid request body: "+err.Error())
|
|
return
|
|
}
|
|
|
|
result, err := h.adminPostService.BatchDeletePosts(c.Request.Context(), req.IDs)
|
|
if err != nil {
|
|
response.InternalServerError(c, "failed to batch delete posts")
|
|
return
|
|
}
|
|
|
|
response.Success(c, result)
|
|
}
|
|
|
|
// BatchModeratePosts 批量审核帖子
|
|
// POST /api/v1/admin/posts/batch-moderate
|
|
func (h *AdminPostHandler) BatchModeratePosts(c *gin.Context) {
|
|
var req dto.AdminBatchModeratePostsRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "invalid request body: "+err.Error())
|
|
return
|
|
}
|
|
|
|
// 验证状态值
|
|
if req.Status != string(model.PostStatusPublished) && req.Status != string(model.PostStatusRejected) {
|
|
response.BadRequest(c, "invalid status value, must be 'published' or 'rejected'")
|
|
return
|
|
}
|
|
|
|
// 获取当前用户ID作为审核人
|
|
reviewedBy := c.GetString("user_id")
|
|
|
|
result, err := h.adminPostService.BatchModeratePosts(c.Request.Context(), req.IDs, model.PostStatus(req.Status), reviewedBy)
|
|
if err != nil {
|
|
response.InternalServerError(c, "failed to batch moderate posts")
|
|
return
|
|
}
|
|
|
|
response.Success(c, result)
|
|
}
|
|
|
|
// SetPostPin 置顶/取消置顶帖子
|
|
// PUT /api/v1/admin/posts/:id/pin
|
|
func (h *AdminPostHandler) SetPostPin(c *gin.Context) {
|
|
postID := c.Param("id")
|
|
if postID == "" {
|
|
response.BadRequest(c, "post id is required")
|
|
return
|
|
}
|
|
|
|
var req dto.AdminSetPostPinRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "invalid request body: "+err.Error())
|
|
return
|
|
}
|
|
|
|
postDetail, err := h.adminPostService.SetPostPin(c.Request.Context(), postID, req.IsPinned)
|
|
if err != nil {
|
|
response.HandleError(c, err, "failed to set post pin status")
|
|
return
|
|
}
|
|
|
|
response.Success(c, postDetail)
|
|
}
|
|
|
|
// SetPostFeature 加精/取消加精帖子
|
|
// PUT /api/v1/admin/posts/:id/feature
|
|
func (h *AdminPostHandler) SetPostFeature(c *gin.Context) {
|
|
postID := c.Param("id")
|
|
if postID == "" {
|
|
response.BadRequest(c, "post id is required")
|
|
return
|
|
}
|
|
|
|
var req dto.AdminSetPostFeatureRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "invalid request body: "+err.Error())
|
|
return
|
|
}
|
|
|
|
postDetail, err := h.adminPostService.SetPostFeature(c.Request.Context(), postID, req.IsFeatured)
|
|
if err != nil {
|
|
response.HandleError(c, err, "failed to set post feature status")
|
|
return
|
|
}
|
|
|
|
response.Success(c, postDetail)
|
|
}
|