package handler import ( "errors" "time" "github.com/gin-gonic/gin" "gorm.io/gorm" "git.sundynix.cn/Blizzard/sundynix-site/server/internal/model" "git.sundynix.cn/Blizzard/sundynix-site/server/internal/pkg/req" "git.sundynix.cn/Blizzard/sundynix-site/server/internal/pkg/resp" ) // AdminPostHandler 管理端文章 CRUD(含草稿)。 type AdminPostHandler struct { db *gorm.DB } func NewAdminPostHandler(db *gorm.DB) *AdminPostHandler { return &AdminPostHandler{db: db} } type postForm struct { Slug string `json:"slug" binding:"required"` Title string `json:"title" binding:"required"` Category string `json:"category"` Summary string `json:"summary"` Content string `json:"content"` Published bool `json:"published"` } // List GET /api/admin/posts — 分页 + 关键词,含草稿 func (h *AdminPostHandler) List(c *gin.Context) { var q req.PageQuery if err := c.ShouldBindQuery(&q); err != nil { resp.BadRequest(c, "分页参数不合法") return } q.Normalize() tx := h.db.Model(&model.Post{}) if q.Keyword != "" { kw := "%" + q.Keyword + "%" tx = tx.Where("title LIKE ? OR slug LIKE ? OR category LIKE ?", kw, kw, kw) } var total int64 if err := tx.Count(&total).Error; err != nil { resp.ServerError(c, "查询失败") return } var items []model.PostListItem err := tx.Order("created_at DESC"). Offset(q.Offset()).Limit(q.PageSize). Find(&items).Error if err != nil { resp.ServerError(c, "查询失败") return } resp.Page(c, items, total, q.Page, q.PageSize) } // Get GET /api/admin/posts/:id func (h *AdminPostHandler) Get(c *gin.Context) { var post model.Post err := h.db.First(&post, "id = ?", c.Param("id")).Error if errors.Is(err, gorm.ErrRecordNotFound) { resp.NotFound(c, "文章不存在") return } if err != nil { resp.ServerError(c, "查询失败") return } resp.OK(c, post) } // Create POST /api/admin/posts func (h *AdminPostHandler) Create(c *gin.Context) { var form postForm if err := c.ShouldBindJSON(&form); err != nil { resp.BadRequest(c, "slug 和标题不能为空") return } post := model.Post{ Slug: form.Slug, Title: form.Title, Category: form.Category, Summary: form.Summary, Content: form.Content, } if form.Published { now := time.Now() post.PublishedAt = &now } if err := h.db.Create(&post).Error; err != nil { if errors.Is(err, gorm.ErrDuplicatedKey) { resp.BadRequest(c, "slug 已存在") return } resp.ServerError(c, "创建失败:"+err.Error()) return } resp.OK(c, post) } // Update PUT /api/admin/posts/:id func (h *AdminPostHandler) Update(c *gin.Context) { var form postForm if err := c.ShouldBindJSON(&form); err != nil { resp.BadRequest(c, "slug 和标题不能为空") return } var post model.Post err := h.db.First(&post, "id = ?", c.Param("id")).Error if errors.Is(err, gorm.ErrRecordNotFound) { resp.NotFound(c, "文章不存在") return } if err != nil { resp.ServerError(c, "查询失败") return } post.Slug = form.Slug post.Title = form.Title post.Category = form.Category post.Summary = form.Summary post.Content = form.Content // 发布状态切换:首次发布记时间,撤回清空,重复发布保留原时间 if form.Published && post.PublishedAt == nil { now := time.Now() post.PublishedAt = &now } else if !form.Published { post.PublishedAt = nil } if err := h.db.Save(&post).Error; err != nil { resp.ServerError(c, "更新失败:"+err.Error()) return } resp.OK(c, post) } // Delete DELETE /api/admin/posts/:id func (h *AdminPostHandler) Delete(c *gin.Context) { res := h.db.Delete(&model.Post{}, "id = ?", c.Param("id")) if res.Error != nil { resp.ServerError(c, "删除失败") return } if res.RowsAffected == 0 { resp.NotFound(c, "文章不存在") return } resp.OK(c, nil) }