191 lines
4.8 KiB
Go
191 lines
4.8 KiB
Go
package handlers
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"goblog/database"
|
|
"goblog/models"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// 创建评论请求
|
|
type CreateCommentRequest struct {
|
|
PostID uint `json:"post_id" binding:"required"`
|
|
ParentID *uint `json:"parent_id"`
|
|
Author string `json:"author" binding:"required"`
|
|
Email string `json:"email" binding:"required,email"`
|
|
Website string `json:"website"`
|
|
Content string `json:"content" binding:"required"`
|
|
}
|
|
|
|
// 获取评论列表
|
|
func GetComments(c *gin.Context) {
|
|
postID := c.Query("post_id")
|
|
status := c.Query("status")
|
|
|
|
db := database.DB.Model(&models.Comment{}).Preload("User").
|
|
Preload("Post", func(db *gorm.DB) *gorm.DB {
|
|
return db.Select("id", "title", "slug")
|
|
})
|
|
|
|
// 非管理员只能查看自己文章上的评论
|
|
if !isAdmin(c) {
|
|
if userID, exists := c.Get("userID"); exists {
|
|
db = db.Where("post_id IN (?)",
|
|
database.DB.Model(&models.Post{}).Select("id").Where("author_id = ?", userID))
|
|
}
|
|
}
|
|
|
|
if postID != "" {
|
|
db = db.Where("post_id = ?", postID)
|
|
}
|
|
if status != "" {
|
|
db = db.Where("status = ?", status)
|
|
}
|
|
|
|
var comments []models.Comment
|
|
db.Order("created_at DESC").Find(&comments)
|
|
|
|
// Comment.Post 在 JSON 中被隐藏,额外附加文章标题和别名供前端展示
|
|
type commentWithPost struct {
|
|
models.Comment
|
|
PostTitle string `json:"post_title"`
|
|
PostSlug string `json:"post_slug"`
|
|
}
|
|
list := make([]commentWithPost, 0, len(comments))
|
|
for _, cm := range comments {
|
|
list = append(list, commentWithPost{cm, cm.Post.Title, cm.Post.Slug})
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"data": list})
|
|
}
|
|
|
|
// 创建评论
|
|
func CreateComment(c *gin.Context) {
|
|
var req CreateCommentRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
// 检查文章是否存在
|
|
var post models.Post
|
|
if err := database.DB.First(&post, req.PostID).Error; err != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "文章不存在"})
|
|
return
|
|
}
|
|
|
|
comment := models.Comment{
|
|
PostID: req.PostID,
|
|
ParentID: req.ParentID,
|
|
Author: req.Author,
|
|
Email: req.Email,
|
|
Website: req.Website,
|
|
Content: req.Content,
|
|
IP: c.ClientIP(),
|
|
Status: "pending", // 默认待审核
|
|
}
|
|
|
|
// 如果用户已登录
|
|
if userID, exists := c.Get("userID"); exists {
|
|
uid := userID.(uint)
|
|
comment.UserID = &uid
|
|
comment.Status = "approved" // 登录用户评论自动通过
|
|
}
|
|
|
|
if err := database.DB.Create(&comment).Error; err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "发表评论失败"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusCreated, gin.H{"data": comment})
|
|
}
|
|
|
|
// canManageComment 检查当前用户是否有权管理该评论(管理员始终可以,普通用户只能管理自己文章上的评论)
|
|
func canManageComment(c *gin.Context, comment *models.Comment) bool {
|
|
if isAdmin(c) {
|
|
return true
|
|
}
|
|
if userID, exists := c.Get("userID"); exists {
|
|
var post models.Post
|
|
if err := database.DB.Select("author_id").First(&post, comment.PostID).Error; err != nil {
|
|
return false
|
|
}
|
|
return post.AuthorID == userID.(uint)
|
|
}
|
|
return false
|
|
}
|
|
|
|
// 审核评论
|
|
func ApproveComment(c *gin.Context) {
|
|
id := c.Param("id")
|
|
|
|
var comment models.Comment
|
|
if err := database.DB.First(&comment, id).Error; err != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "评论不存在"})
|
|
return
|
|
}
|
|
|
|
if !canManageComment(c, &comment) {
|
|
c.JSON(http.StatusForbidden, gin.H{"error": "无权管理该评论"})
|
|
return
|
|
}
|
|
|
|
comment.Status = "approved"
|
|
if err := database.DB.Save(&comment).Error; err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "审核失败"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "审核通过"})
|
|
}
|
|
|
|
// 标记为垃圾评论
|
|
func MarkSpamComment(c *gin.Context) {
|
|
id := c.Param("id")
|
|
|
|
var comment models.Comment
|
|
if err := database.DB.First(&comment, id).Error; err != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "评论不存在"})
|
|
return
|
|
}
|
|
|
|
if !canManageComment(c, &comment) {
|
|
c.JSON(http.StatusForbidden, gin.H{"error": "无权管理该评论"})
|
|
return
|
|
}
|
|
|
|
comment.Status = "spam"
|
|
if err := database.DB.Save(&comment).Error; err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "操作失败"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "已标记为垃圾评论"})
|
|
}
|
|
|
|
// 删除评论
|
|
func DeleteComment(c *gin.Context) {
|
|
id := c.Param("id")
|
|
|
|
var comment models.Comment
|
|
if err := database.DB.First(&comment, id).Error; err != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "评论不存在"})
|
|
return
|
|
}
|
|
|
|
if !canManageComment(c, &comment) {
|
|
c.JSON(http.StatusForbidden, gin.H{"error": "无权管理该评论"})
|
|
return
|
|
}
|
|
|
|
if err := database.DB.Delete(&comment).Error; err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "删除评论失败"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "删除成功"})
|
|
}
|