qoder生成项目
This commit is contained in:
274
handlers/post.go
Normal file
274
handlers/post.go
Normal file
@@ -0,0 +1,274 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"goblog/database"
|
||||
"goblog/models"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// 文章列表请求参数
|
||||
type PostListQuery struct {
|
||||
Page int `form:"page,default=1"`
|
||||
PageSize int `form:"page_size,default=10"`
|
||||
CategoryID uint `form:"category_id"`
|
||||
TagID uint `form:"tag_id"`
|
||||
Status string `form:"status"`
|
||||
Keyword string `form:"keyword"`
|
||||
}
|
||||
|
||||
// 创建文章请求
|
||||
type CreatePostRequest struct {
|
||||
Title string `json:"title" binding:"required"`
|
||||
Content string `json:"content" binding:"required"`
|
||||
Summary string `json:"summary"`
|
||||
Cover string `json:"cover"`
|
||||
CategoryID uint `json:"category_id" binding:"required"`
|
||||
Tags []string `json:"tags"`
|
||||
Status string `json:"status"`
|
||||
IsTop bool `json:"is_top"`
|
||||
}
|
||||
|
||||
// 更新文章请求
|
||||
type UpdatePostRequest struct {
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
Summary string `json:"summary"`
|
||||
Cover string `json:"cover"`
|
||||
CategoryID uint `json:"category_id"`
|
||||
Tags []string `json:"tags"`
|
||||
Status string `json:"status"`
|
||||
IsTop bool `json:"is_top"`
|
||||
}
|
||||
|
||||
// 生成 slug
|
||||
func generateSlug(title string) string {
|
||||
slug := strings.ToLower(title)
|
||||
slug = strings.ReplaceAll(slug, " ", "-")
|
||||
slug = strings.ReplaceAll(slug, "_", "-")
|
||||
// 简化处理,实际项目中可能需要更完善的 slug 生成
|
||||
return slug
|
||||
}
|
||||
|
||||
// 获取文章列表
|
||||
func GetPosts(c *gin.Context) {
|
||||
var query PostListQuery
|
||||
if err := c.ShouldBindQuery(&query); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
db := database.DB.Model(&models.Post{}).Preload("Category").Preload("Tags").Preload("Author")
|
||||
|
||||
// 前端只显示已发布的文章
|
||||
if !isAdmin(c) {
|
||||
db = db.Where("status = ?", "published")
|
||||
} else if query.Status != "" {
|
||||
db = db.Where("status = ?", query.Status)
|
||||
}
|
||||
|
||||
if query.CategoryID > 0 {
|
||||
db = db.Where("category_id = ?", query.CategoryID)
|
||||
}
|
||||
|
||||
if query.TagID > 0 {
|
||||
db = db.Joins("JOIN post_tags ON post_tags.post_id = posts.id").
|
||||
Where("post_tags.tag_id = ?", query.TagID)
|
||||
}
|
||||
|
||||
if query.Keyword != "" {
|
||||
db = db.Where("title LIKE ? OR content LIKE ?", "%"+query.Keyword+"%", "%"+query.Keyword+"%")
|
||||
}
|
||||
|
||||
var total int64
|
||||
db.Count(&total)
|
||||
|
||||
var posts []models.Post
|
||||
offset := (query.Page - 1) * query.PageSize
|
||||
db.Order("is_top DESC, published_at DESC, created_at DESC").
|
||||
Offset(offset).Limit(query.PageSize).Find(&posts)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"data": posts,
|
||||
"total": total,
|
||||
"page": query.Page,
|
||||
"size": query.PageSize,
|
||||
})
|
||||
}
|
||||
|
||||
// 获取单篇文章
|
||||
func GetPost(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
|
||||
var post models.Post
|
||||
query := database.DB.Preload("Category").Preload("Tags").Preload("Author").Preload("Comments", func(db *gorm.DB) *gorm.DB {
|
||||
return db.Where("status = ? AND parent_id IS NULL", "approved").Preload("Children", func(db *gorm.DB) *gorm.DB {
|
||||
return db.Where("status = ?", "approved")
|
||||
})
|
||||
})
|
||||
|
||||
// 尝试按 ID 或 slug 查找
|
||||
if _, err := strconv.Atoi(id); err == nil {
|
||||
query = query.Where("id = ?", id)
|
||||
} else {
|
||||
query = query.Where("slug = ?", id)
|
||||
}
|
||||
|
||||
// 非管理员只能查看已发布文章
|
||||
if !isAdmin(c) {
|
||||
query = query.Where("status = ?", "published")
|
||||
}
|
||||
|
||||
if err := query.First(&post).Error; err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "文章不存在"})
|
||||
return
|
||||
}
|
||||
|
||||
// 增加浏览量
|
||||
database.DB.Model(&post).UpdateColumn("views", gorm.Expr("views + 1"))
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"data": post})
|
||||
}
|
||||
|
||||
// 创建文章
|
||||
func CreatePost(c *gin.Context) {
|
||||
var req CreatePostRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
userID, _ := c.Get("userID")
|
||||
|
||||
post := models.Post{
|
||||
Title: req.Title,
|
||||
Slug: generateSlug(req.Title),
|
||||
Content: req.Content,
|
||||
Summary: req.Summary,
|
||||
Cover: req.Cover,
|
||||
AuthorID: userID.(uint),
|
||||
CategoryID: req.CategoryID,
|
||||
Status: req.Status,
|
||||
IsTop: req.IsTop,
|
||||
}
|
||||
|
||||
if req.Status == "published" {
|
||||
now := time.Now()
|
||||
post.PublishedAt = &now
|
||||
}
|
||||
|
||||
// 处理标签
|
||||
if len(req.Tags) > 0 {
|
||||
var tags []models.Tag
|
||||
for _, tagName := range req.Tags {
|
||||
var tag models.Tag
|
||||
database.DB.FirstOrCreate(&tag, models.Tag{
|
||||
Name: tagName,
|
||||
Slug: generateSlug(tagName),
|
||||
})
|
||||
tags = append(tags, tag)
|
||||
}
|
||||
post.Tags = tags
|
||||
}
|
||||
|
||||
if err := database.DB.Create(&post).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "创建文章失败"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusCreated, gin.H{"data": post})
|
||||
}
|
||||
|
||||
// 更新文章
|
||||
func UpdatePost(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
|
||||
var post models.Post
|
||||
if err := database.DB.First(&post, id).Error; err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "文章不存在"})
|
||||
return
|
||||
}
|
||||
|
||||
var req UpdatePostRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
updates := map[string]interface{}{}
|
||||
if req.Title != "" {
|
||||
updates["title"] = req.Title
|
||||
updates["slug"] = generateSlug(req.Title)
|
||||
}
|
||||
if req.Content != "" {
|
||||
updates["content"] = req.Content
|
||||
}
|
||||
if req.Summary != "" {
|
||||
updates["summary"] = req.Summary
|
||||
}
|
||||
if req.Cover != "" {
|
||||
updates["cover"] = req.Cover
|
||||
}
|
||||
if req.CategoryID > 0 {
|
||||
updates["category_id"] = req.CategoryID
|
||||
}
|
||||
if req.Status != "" {
|
||||
updates["status"] = req.Status
|
||||
if req.Status == "published" && post.Status != "published" {
|
||||
now := time.Now()
|
||||
updates["published_at"] = &now
|
||||
}
|
||||
}
|
||||
updates["is_top"] = req.IsTop
|
||||
|
||||
// 处理标签
|
||||
if len(req.Tags) > 0 {
|
||||
var tags []models.Tag
|
||||
for _, tagName := range req.Tags {
|
||||
var tag models.Tag
|
||||
database.DB.FirstOrCreate(&tag, models.Tag{
|
||||
Name: tagName,
|
||||
Slug: generateSlug(tagName),
|
||||
})
|
||||
tags = append(tags, tag)
|
||||
}
|
||||
database.DB.Model(&post).Association("Tags").Replace(tags)
|
||||
}
|
||||
|
||||
if err := database.DB.Model(&post).Updates(updates).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "更新文章失败"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"data": post})
|
||||
}
|
||||
|
||||
// 删除文章
|
||||
func DeletePost(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
|
||||
var post models.Post
|
||||
if err := database.DB.First(&post, id).Error; err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "文章不存在"})
|
||||
return
|
||||
}
|
||||
|
||||
if err := database.DB.Delete(&post).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "删除文章失败"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "删除成功"})
|
||||
}
|
||||
|
||||
// 判断是否为管理员
|
||||
func isAdmin(c *gin.Context) bool {
|
||||
role, exists := c.Get("role")
|
||||
return exists && role == "admin"
|
||||
}
|
||||
Reference in New Issue
Block a user