Files
toutoukan/controllers/comments/getcomments/getcomments.go
2025-09-25 18:17:41 +08:00

119 lines
3.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package getcomments
import (
"fmt"
"net/http"
"time"
"toutoukan/init/databaseInit"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
// ArticleReq 定义请求中文章ID的结构体
type ArticleReq struct {
ArticleID int64 `json:"articleId" binding:"required,min=1"`
}
// UserDetail 用户的关键信息,用于嵌入到评论响应中
type UserDetail struct {
UserID string `gorm:"column:user_id" json:"user_id"` // user_id 来自 comments 表
Username string `gorm:"column:username" json:"username"` // username 来自 user_info 表
AvatarURL string `gorm:"column:avatar_url" json:"avatar_url"` // avatar_url 来自 user_info 表
}
// CommentResponse 最终的评论响应结构体,包含了用户信息
type CommentResponse struct {
ID int64 `gorm:"column:id" json:"id"`
ArticleID int64 `gorm:"column:article_id" json:"article_id"`
ParentID int64 `gorm:"column:parent_id" json:"parent_id"`
Content string `gorm:"column:content" json:"content"`
LikesCount int `gorm:"column:likes_count" json:"likes_count"`
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
// 嵌入发布者的信息
Username string `gorm:"column:username" json:"username"` // 直接映射 user_info.username
AvatarURL string `gorm:"column:avatar_url" json:"avatar_url"` // 直接映射 user_info.avatar_url
Replies []*CommentResponse `gorm:"-" json:"replies,omitempty"` // 子评论列表忽略GORM
}
// TableName 为 Comment 结构体指定数据库表名 (仅供GORM模型参考实际查询使用原始表名)
func (CommentResponse) TableName() string {
return "article_comments"
}
// GetComments 获取特定文章的评论列表
func GetComments(c *gin.Context) {
var req ArticleReq
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "参数解析失败",
"detail": err.Error(),
})
return
}
// 1. 联表查询文章的所有评论及其发布者信息
// 注意:我们直接将结果映射到 CommentResponse 结构体
var allComments []*CommentResponse
// GORM 的 JOIN 查询
// SELECT 语句手动指定了字段,以避免字段名冲突 (如 user_id vs uid)
// 假设 user_info.uid 对应 article_comments.user_id
query := `
SELECT
c.id, c.articleId, c.user_id, c.parent_id, c.content, c.likes_count, c.created_time, c.update_time,
u.username, u.avatar_url
FROM article_comments c
JOIN user_info u ON c.user_id = u.uid
WHERE c.articleId = ?
ORDER BY c.created_time ASC
`
if err := databaseInit.UserDB.Raw(query, req.ArticleID).Scan(&allComments).Error; err != nil {
if err == gorm.ErrRecordNotFound {
// 如果没有找到评论,返回空列表
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "文章暂无评论",
"data": []CommentResponse{},
})
return
}
c.JSON(http.StatusInternalServerError, gin.H{
"error": fmt.Sprintf("查询评论失败: %s", err.Error()),
})
return
}
// 2. 构建评论树(父子关系)
commentMap := make(map[int64]*CommentResponse)
for _, comment := range allComments {
commentMap[comment.ID] = comment
}
var topLevelComments []*CommentResponse
for _, comment := range allComments {
// ParentID 默认为0表示顶级评论
if comment.ParentID == 0 {
topLevelComments = append(topLevelComments, comment)
} else {
// 找到父评论,并将其加入子评论列表
if parent, ok := commentMap[comment.ParentID]; ok {
parent.Replies = append(parent.Replies, comment)
}
// 如果找不到父评论,可能是脏数据,则忽略
}
}
// 3. 返回成功响应
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "获取评论成功",
"data": topLevelComments,
})
}