119 lines
3.8 KiB
Go
119 lines
3.8 KiB
Go
|
|
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,
|
|||
|
|
})
|
|||
|
|
}
|