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, }) }