From 97175c3d6797ddd6f38ab21137036559c25e6a46 Mon Sep 17 00:00:00 2001 From: landaiqing <3517283258@qq.com> Date: Wed, 25 Sep 2024 11:46:49 +0800 Subject: [PATCH] :zap: optimize the list of comments --- api/comment_api/comment.go | 3 +- api/comment_api/comment_api.go | 376 +++++++++++++----- api/comment_api/dto/request_dto.go | 5 +- i18n/language/en.toml | 6 +- i18n/language/zh.toml | 6 +- model/sca_comment_likes.go | 1 - model/sca_comment_reply.go | 1 - router/modules/comment_router.go | 2 + .../comment_reply_service.go | 32 ++ 9 files changed, 333 insertions(+), 99 deletions(-) diff --git a/api/comment_api/comment.go b/api/comment_api/comment.go index 118464e..7091e48 100644 --- a/api/comment_api/comment.go +++ b/api/comment_api/comment.go @@ -14,6 +14,7 @@ import ( type CommentAPI struct{} var wg sync.WaitGroup +var mx sync.Mutex var commentReplyService = service.Service.CommentReplyService // CommentImages 评论图片 @@ -42,10 +43,10 @@ type CommentContent struct { Likes int64 `json:"likes"` ReplyCount int64 `json:"reply_count"` CreatedTime time.Time `json:"created_time"` - Dislikes int64 `json:"dislikes"` Location string `json:"location"` Browser string `json:"browser"` OperatingSystem string `json:"operating_system"` + IsLiked bool `json:"is_liked" default:"false"` Images []string `json:"images,omitempty"` } diff --git a/api/comment_api/comment_api.go b/api/comment_api/comment_api.go index ba2fa6c..17cc3e5 100644 --- a/api/comment_api/comment_api.go +++ b/api/comment_api/comment_api.go @@ -3,7 +3,6 @@ package comment_api import ( "context" "encoding/base64" - "errors" "fmt" "github.com/acmestack/gorm-plus/gplus" ginI18n "github.com/gin-contrib/i18n" @@ -392,63 +391,126 @@ func (CommentAPI) CommentList(c *gin.Context) { result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) return } + // 查询评论列表 query, u := gplus.NewQuery[model.ScaCommentReply]() page := gplus.NewPage[model.ScaCommentReply](commentListRequest.Page, commentListRequest.Size) - query.Eq(&u.TopicId, commentListRequest.TopicId).Eq(&u.CommentType, enum.COMMENT).OrderByDesc(&u.Likes) - page, _ = gplus.SelectPage(page, query) + query.Eq(&u.TopicId, commentListRequest.TopicId).Eq(&u.CommentType, enum.COMMENT).OrderByDesc(&u.CommentOrder).OrderByDesc(&u.Likes).OrderByDesc(&u.ReplyCount).OrderByDesc(&u.CreatedTime) + page, pageDB := gplus.SelectPage(page, query) + if pageDB.Error != nil { + global.LOG.Errorln(pageDB.Error) + return + } + if len(page.Records) == 0 { + result.OkWithData(CommentResponse{Comments: []CommentContent{}, Size: page.Size, Current: page.Current, Total: page.Total}, c) + return + } userIds := make([]string, 0, len(page.Records)) + commentIds := make([]int64, 0, len(page.Records)) for _, comment := range page.Records { userIds = append(userIds, comment.UserId) + commentIds = append(commentIds, comment.Id) } - queryUser, n := gplus.NewQuery[model.ScaAuthUser]() - queryUser.In(&n.UID, userIds) - userInfos, _ := gplus.SelectList(queryUser) + // 结果存储 + userInfoMap := make(map[string]model.ScaAuthUser) + likeMap := make(map[int64]bool) + commentImagesMap := make(map[int64]CommentImages) - userInfoMap := make(map[string]model.ScaAuthUser, len(userInfos)) - for _, userInfo := range userInfos { - userInfoMap[*userInfo.UID] = *userInfo - } + // 使用 WaitGroup 等待协程完成 + wg.Add(3) - commentChannel := make(chan CommentContent, len(page.Records)) - imagesBase64S := make([][]string, len(page.Records)) // 存储每条评论的图片 + // 查询评论用户信息 + go func() { + defer wg.Done() + queryUser, n := gplus.NewQuery[model.ScaAuthUser]() + queryUser.Select(&n.UID, &n.Avatar, &n.Nickname).In(&n.UID, userIds) + userInfos, userInfosDB := gplus.SelectList(queryUser) + if userInfosDB.Error != nil { + global.LOG.Errorln(userInfosDB.Error) + return + } + for _, userInfo := range userInfos { + userInfoMap[*userInfo.UID] = *userInfo + } + }() - for index, comment := range page.Records { - wg.Add(1) - go func(comment model.ScaCommentReply, index int) { - defer wg.Done() - - // 使用 context 设置超时时间 - ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) // 设置超时,2秒 - defer cancel() - - // 获取评论图片并处理 - commentImages := CommentImages{} - wrong := global.MongoDB.Database(global.CONFIG.MongoDB.DB).Collection("comment_images").FindOne(ctx, bson.M{"comment_id": comment.Id}).Decode(&commentImages) - if wrong != nil && !errors.Is(wrong, mongo.ErrNoDocuments) { - global.LOG.Errorf("Failed to get images for comment ID %s: %v", comment.Id, wrong) + // 查询评论点赞状态 + go func() { + defer wg.Done() + if len(page.Records) > 0 { + queryLike, l := gplus.NewQuery[model.ScaCommentLikes]() + queryLike.Eq(&l.TopicId, commentListRequest.TopicId).Eq(&l.UserId, commentListRequest.UserID).In(&l.CommentId, commentIds) + likes, likesDB := gplus.SelectList(queryLike) + if likesDB.Error != nil { + global.LOG.Errorln(likesDB.Error) return } + for _, like := range likes { + likeMap[like.CommentId] = true + } + } + }() + // 查询评论图片信息 + go func() { + defer wg.Done() + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) // 设置超时,2秒 + defer cancel() + + cursor, err := global.MongoDB.Database(global.CONFIG.MongoDB.DB).Collection("comment_images").Find(ctx, bson.M{"comment_id": bson.M{"$in": commentIds}}) + if err != nil { + global.LOG.Errorf("Failed to get images for comments: %v", err) + return + } + defer func(cursor *mongo.Cursor, ctx context.Context) { + err := cursor.Close(ctx) + if err != nil { + return + } + }(cursor, ctx) + + for cursor.Next(ctx) { + var commentImages CommentImages + if err = cursor.Decode(&commentImages); err != nil { + global.LOG.Errorf("Failed to decode comment images: %v", err) + continue + } + commentImagesMap[commentImages.CommentId] = commentImages + } + }() + + // 等待所有查询完成 + wg.Wait() + commentChannel := make(chan CommentContent, len(page.Records)) + + for _, comment := range page.Records { + wg.Add(1) + go func(comment model.ScaCommentReply) { + defer wg.Done() // 将图片转换为base64 var imagesBase64 []string - for _, img := range commentImages.Images { - mimeType := getMimeType(img) - base64Img := base64.StdEncoding.EncodeToString(img) - base64WithPrefix := fmt.Sprintf("data:%s;base64,%s", mimeType, base64Img) - imagesBase64 = append(imagesBase64, base64WithPrefix) + if imgData, ok := commentImagesMap[comment.Id]; ok { + // 将图片转换为base64 + for _, img := range imgData.Images { + mimeType := getMimeType(img) + base64Img := base64.StdEncoding.EncodeToString(img) + base64WithPrefix := fmt.Sprintf("data:%s;base64,%s", mimeType, base64Img) + imagesBase64 = append(imagesBase64, base64WithPrefix) + } } - imagesBase64S[index] = imagesBase64 // 保存到切片中 - userInfo := userInfoMap[comment.UserId] + userInfo, exist := userInfoMap[comment.UserId] + if !exist { + global.LOG.Errorf("Failed to get user info for comment: %s", comment.UserId) + return + } commentContent := CommentContent{ Avatar: *userInfo.Avatar, NickName: *userInfo.Nickname, Id: comment.Id, UserId: comment.UserId, TopicId: comment.TopicId, - Dislikes: comment.Dislikes, Content: comment.Content, ReplyCount: comment.ReplyCount, Likes: comment.Likes, @@ -458,9 +520,10 @@ func (CommentAPI) CommentList(c *gin.Context) { Browser: comment.Browser, OperatingSystem: comment.OperatingSystem, Images: imagesBase64, + IsLiked: likeMap[comment.Id], } commentChannel <- commentContent - }(*comment, index) + }(*comment) } go func() { @@ -500,81 +563,131 @@ func (CommentAPI) ReplyList(c *gin.Context) { } query, u := gplus.NewQuery[model.ScaCommentReply]() page := gplus.NewPage[model.ScaCommentReply](replyListRequest.Page, replyListRequest.Size) - query.Eq(&u.TopicId, replyListRequest.TopicId).Eq(&u.ReplyId, replyListRequest.CommentId).Eq(&u.CommentType, enum.REPLY).OrderByDesc(&u.Likes) - page, _ = gplus.SelectPage(page, query) + query.Eq(&u.TopicId, replyListRequest.TopicId).Eq(&u.ReplyId, replyListRequest.CommentId).Eq(&u.CommentType, enum.REPLY).OrderByDesc(&u.CommentOrder).OrderByDesc(&u.Likes).OrderByDesc(&u.CreatedTime) + page, pageDB := gplus.SelectPage(page, query) + if pageDB.Error != nil { + global.LOG.Errorln(pageDB.Error) + return + } + if len(page.Records) == 0 { + result.OkWithData(CommentResponse{Comments: []CommentContent{}, Size: page.Size, Current: page.Current, Total: page.Total}, c) + return + } - userIds := make([]string, 0, len(page.Records)) - replyUserIds := make([]string, 0, len(page.Records)) - - // 收集用户 ID 和回复用户 ID + userIdsSet := make(map[string]struct{}) // 使用集合去重用户 ID + commentIds := make([]int64, 0, len(page.Records)) + // 收集用户 ID 和评论 ID for _, comment := range page.Records { - userIds = append(userIds, comment.UserId) + userIdsSet[comment.UserId] = struct{}{} // 去重 + commentIds = append(commentIds, comment.Id) if comment.ReplyUser != "" { - replyUserIds = append(replyUserIds, comment.ReplyUser) + userIdsSet[comment.ReplyUser] = struct{}{} // 去重 } } - - // 查询评论用户信息 - queryUser, n := gplus.NewQuery[model.ScaAuthUser]() - queryUser.In(&n.UID, userIds) - userInfos, _ := gplus.SelectList(queryUser) - - userInfoMap := make(map[string]model.ScaAuthUser, len(userInfos)) - for _, userInfo := range userInfos { - userInfoMap[*userInfo.UID] = *userInfo + // 将用户 ID 转换为切片 + userIds := make([]string, 0, len(userIdsSet)) + for userId := range userIdsSet { + userIds = append(userIds, userId) } - // 查询回复用户信息 - replyUserInfoMap := make(map[string]model.ScaAuthUser) - if len(replyUserIds) > 0 { - queryReplyUser, m := gplus.NewQuery[model.ScaAuthUser]() - queryReplyUser.In(&m.UID, replyUserIds) - replyUserInfos, _ := gplus.SelectList(queryReplyUser) + likeMap := make(map[int64]bool, len(page.Records)) + commentImagesMap := make(map[int64]CommentImages) + userInfoMap := make(map[string]model.ScaAuthUser, len(userIds)) - for _, replyUserInfo := range replyUserInfos { - replyUserInfoMap[*replyUserInfo.UID] = *replyUserInfo + wg.Add(3) + go func() { + defer wg.Done() + // 查询评论用户信息 + queryUser, n := gplus.NewQuery[model.ScaAuthUser]() + queryUser.Select(&n.UID, &n.Avatar, &n.Nickname).In(&n.UID, userIds) + userInfos, userInfosDB := gplus.SelectList(queryUser) + if userInfosDB.Error != nil { + global.LOG.Errorln(userInfosDB.Error) + return } - } + for _, userInfo := range userInfos { + userInfoMap[*userInfo.UID] = *userInfo + } + }() - replyChannel := make(chan CommentContent, len(page.Records)) // 使用通道传递回复内容 - imagesBase64S := make([][]string, len(page.Records)) // 存储每条回复的图片 + go func() { + defer wg.Done() + // 查询评论点赞状态 - for index, reply := range page.Records { - wg.Add(1) - go func(reply model.ScaCommentReply, index int) { - defer wg.Done() - - // 使用 context 设置超时时间 - ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) // 设置超时,2秒 - defer cancel() - - // 获取回复图片并处理 - replyImages := CommentImages{} - wrong := global.MongoDB.Database(global.CONFIG.MongoDB.DB).Collection("comment_images").FindOne(ctx, bson.M{"comment_id": reply.Id}).Decode(&replyImages) - if wrong != nil && !errors.Is(wrong, mongo.ErrNoDocuments) { - global.LOG.Errorf("Failed to get images for reply ID %s: %v", reply.Id, wrong) + if len(page.Records) > 0 { + queryLike, l := gplus.NewQuery[model.ScaCommentLikes]() + queryLike.Eq(&l.TopicId, replyListRequest.TopicId).Eq(&l.UserId, replyListRequest.UserID).In(&l.CommentId, commentIds) + likes, likesDB := gplus.SelectList(queryLike) + if likesDB.Error != nil { + global.LOG.Errorln(likesDB.Error) return } - - // 将图片转换为base64 - var imagesBase64 []string - for _, img := range replyImages.Images { - mimeType := getMimeType(img) - base64Img := base64.StdEncoding.EncodeToString(img) - base64WithPrefix := fmt.Sprintf("data:%s;base64,%s", mimeType, base64Img) - imagesBase64 = append(imagesBase64, base64WithPrefix) + for _, like := range likes { + likeMap[like.CommentId] = true } - imagesBase64S[index] = imagesBase64 // 保存到切片中 + } + }() - userInfo := userInfoMap[reply.UserId] - replyUserInfo := replyUserInfoMap[reply.ReplyUser] + go func() { + defer wg.Done() + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) // 设置超时,2秒 + defer cancel() + cursor, err := global.MongoDB.Database(global.CONFIG.MongoDB.DB).Collection("comment_images").Find(ctx, bson.M{"comment_id": bson.M{"$in": commentIds}}) + if err != nil { + global.LOG.Errorf("Failed to get images for comments: %v", err) + return + } + defer func(cursor *mongo.Cursor, ctx context.Context) { + warn := cursor.Close(ctx) + if warn != nil { + return + } + }(cursor, ctx) + + for cursor.Next(ctx) { + var commentImages CommentImages + if e := cursor.Decode(&commentImages); e != nil { + global.LOG.Errorf("Failed to decode comment images: %v", e) + continue + } + commentImagesMap[commentImages.CommentId] = commentImages + } + }() + wg.Wait() + + replyChannel := make(chan CommentContent, len(page.Records)) // 使用通道传递回复内容 + + for _, reply := range page.Records { + wg.Add(1) + go func(reply model.ScaCommentReply) { + defer wg.Done() + + var imagesBase64 []string + if imgData, ok := commentImagesMap[reply.Id]; ok { + // 将图片转换为base64 + for _, img := range imgData.Images { + mimeType := getMimeType(img) + base64Img := base64.StdEncoding.EncodeToString(img) + base64WithPrefix := fmt.Sprintf("data:%s;base64,%s", mimeType, base64Img) + imagesBase64 = append(imagesBase64, base64WithPrefix) + } + } + userInfo, exist := userInfoMap[reply.UserId] + if !exist { + global.LOG.Errorf("Failed to get user info for comment: %s", reply.UserId) + return + } + replyUserInfo, e := userInfoMap[reply.ReplyUser] + if !e { + global.LOG.Errorf("Failed to get reply user info for comment: %s", reply.ReplyUser) + return + } commentContent := CommentContent{ Avatar: *userInfo.Avatar, NickName: *userInfo.Nickname, Id: reply.Id, UserId: reply.UserId, TopicId: reply.TopicId, - Dislikes: reply.Dislikes, Content: reply.Content, ReplyUsername: *replyUserInfo.Nickname, ReplyCount: reply.ReplyCount, @@ -588,9 +701,10 @@ func (CommentAPI) ReplyList(c *gin.Context) { Browser: reply.Browser, OperatingSystem: reply.OperatingSystem, Images: imagesBase64, + IsLiked: likeMap[reply.Id], } replyChannel <- commentContent // 发送到通道 - }(*reply, index) + }(*reply) } go func() { @@ -614,6 +728,13 @@ func (CommentAPI) ReplyList(c *gin.Context) { } // CommentLikes 点赞评论 +// @Summary 点赞评论 +// @Description 点赞评论 +// @Tags 评论 +// @Accept json +// @Produce json +// @Param comment_like_request body dto.CommentLikeRequest true "点赞请求" +// @Router /auth/comment/like [post] func (CommentAPI) CommentLikes(c *gin.Context) { likeRequest := dto.CommentLikeRequest{} err := c.ShouldBindJSON(&likeRequest) @@ -621,8 +742,79 @@ func (CommentAPI) CommentLikes(c *gin.Context) { result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) return } + mx.Lock() + defer mx.Unlock() + likes := model.ScaCommentLikes{ + CommentId: likeRequest.CommentId, + UserId: likeRequest.UserID, + TopicId: likeRequest.TopicId, + } + + tx := global.DB.Begin() + defer func() { + if r := recover(); r != nil { + tx.Rollback() + } + }() + res := gplus.Insert(&likes) + if res.Error != nil { + tx.Rollback() + global.LOG.Errorln(res.Error) + result.FailWithMessage(ginI18n.MustGetMessage(c, "CommentLikeFailed"), c) + return + } + // 更新点赞计数 + if err = commentReplyService.UpdateCommentLikesCount(likeRequest.CommentId, likeRequest.TopicId); err != nil { + tx.Rollback() + global.LOG.Errorln(err) + result.FailWithMessage(ginI18n.MustGetMessage(c, "CommentLikeFailed"), c) + return + } + tx.Commit() + result.OkWithMessage(ginI18n.MustGetMessage(c, "CommentLikeSuccess"), c) + return } -func (CommentAPI) CommentDislikes(c *gin.Context) { - +// CancelCommentLikes 取消点赞评论 +// @Summary 取消点赞评论 +// @Description 取消点赞评论 +// @Tags 评论 +// @Accept json +// @Produce json +// @Param comment_like_request body dto.CommentLikeRequest true "取消点赞请求" +// @Router /auth/comment/cancel_like [post] +func (CommentAPI) CancelCommentLikes(c *gin.Context) { + likeRequest := dto.CommentLikeRequest{} + err := c.ShouldBindJSON(&likeRequest) + if err != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) + return + } + mx.Lock() + defer mx.Unlock() + tx := global.DB.Begin() + defer func() { + if r := recover(); r != nil { + tx.Rollback() + } + }() + query, u := gplus.NewQuery[model.ScaCommentLikes]() + query.Eq(&u.CommentId, likeRequest.CommentId).Eq(&u.UserId, likeRequest.UserID).Eq(&u.TopicId, likeRequest.TopicId) + res := gplus.Delete[model.ScaCommentLikes](query) + if res.Error != nil { + tx.Rollback() + global.LOG.Errorln(res.Error) + result.FailWithMessage(ginI18n.MustGetMessage(c, "CommentLikeCancelFailed"), c) + return + } + err = commentReplyService.DecrementCommentLikesCount(likeRequest.CommentId, likeRequest.TopicId) + if err != nil { + tx.Rollback() + global.LOG.Errorln(err) + result.FailWithMessage(ginI18n.MustGetMessage(c, "CommentLikeCancelFailed"), c) + return + } + tx.Commit() + result.OkWithMessage(ginI18n.MustGetMessage(c, "CommentLikeCancelSuccess"), c) + return } diff --git a/api/comment_api/dto/request_dto.go b/api/comment_api/dto/request_dto.go index a0e536e..dba1bb7 100644 --- a/api/comment_api/dto/request_dto.go +++ b/api/comment_api/dto/request_dto.go @@ -25,15 +25,17 @@ type ReplyReplyRequest struct { ReplyTo int64 `json:"reply_to" binding:"required"` ReplyId int64 `json:"reply_id" binding:"required"` ReplyUser string `json:"reply_user" binding:"required"` - Author string `json:"author" binding:"required""` + Author string `json:"author" binding:"required"` } type CommentListRequest struct { + UserID string `json:"user_id" binding:"required"` TopicId string `json:"topic_id" binding:"required"` Page int `json:"page" default:"1"` Size int `json:"size" default:"5"` } type ReplyListRequest struct { + UserID string `json:"user_id" binding:"required"` TopicId string `json:"topic_id" binding:"required"` CommentId int64 `json:"comment_id" binding:"required"` Page int `json:"page" default:"1"` @@ -43,5 +45,4 @@ type CommentLikeRequest struct { TopicId string `json:"topic_id" binding:"required"` CommentId int64 `json:"comment_id" binding:"required"` UserID string `json:"user_id" binding:"required"` - Type int `json:"type" binding:"required"` } diff --git a/i18n/language/en.toml b/i18n/language/en.toml index 06108ce..007d2e2 100644 --- a/i18n/language/en.toml +++ b/i18n/language/en.toml @@ -69,4 +69,8 @@ CommentSubmitFailed = "comment submit failed!" CommentSubmitSuccess = "comment submit successfully!" ImageStorageError = "image storage error!" ImageDecodeError = "image decode error!" -ImageSaveError = "image save error!" \ No newline at end of file +ImageSaveError = "image save error!" +CommentLikeSuccess = "comment like success!" +CommentLikeFailed = "comment like failed!" +CommentDislikeSuccess = "comment dislike success!" +CommentDislikeFailed = "comment dislike failed!" \ No newline at end of file diff --git a/i18n/language/zh.toml b/i18n/language/zh.toml index 122ff16..dd5a0ae 100644 --- a/i18n/language/zh.toml +++ b/i18n/language/zh.toml @@ -69,4 +69,8 @@ CommentSubmitFailed = "评论提交失败!" CommentSubmitSuccess = "评论提交成功!" ImageStorageError = "图片存储错误!" ImageDecodeError = "图片解码错误!" -ImageSaveError = "图片保存错误!" \ No newline at end of file +ImageSaveError = "图片保存错误!" +CommentLikeSuccess = "评论点赞成功!" +CommentLikeFailed = "评论点赞失败!" +CommentDislikeSuccess = "评论取消点赞成功!" +CommentDislikeFailed = "评论取消点赞失败!" \ No newline at end of file diff --git a/model/sca_comment_likes.go b/model/sca_comment_likes.go index f060ca7..b48f93c 100644 --- a/model/sca_comment_likes.go +++ b/model/sca_comment_likes.go @@ -8,7 +8,6 @@ type ScaCommentLikes struct { TopicId string `gorm:"column:topic_id;type:varchar(20);NOT NULL;comment:主题ID" json:"topic_id"` UserId string `gorm:"column:user_id;type:varchar(20);comment:用户ID;NOT NULL" json:"user_id"` CommentId int64 `gorm:"column:comment_id;type:bigint(20);comment:评论ID;NOT NULL" json:"comment_id"` - Type int `gorm:"column:type;type:int(11);comment:类型,0 点赞 1 踩;NOT NULL" json:"type"` } func (like *ScaCommentLikes) TableName() string { diff --git a/model/sca_comment_reply.go b/model/sca_comment_reply.go index d4dd128..3beca6a 100644 --- a/model/sca_comment_reply.go +++ b/model/sca_comment_reply.go @@ -26,7 +26,6 @@ type ScaCommentReply struct { Deleted int `gorm:"column:deleted;type:int(11);default:0;comment:是否删除 0未删除 1 已删除" json:"-"` CreatedBy string `gorm:"column:created_by;type:varchar(32);comment:创建人" json:"-"` UpdateBy string `gorm:"column:update_by;type:varchar(32);comment:更新人" json:"-"` - Dislikes int64 `gorm:"column:dislikes;type:bigint(20);default:0;comment:踩数" json:"dislikes"` CommentIp string `gorm:"column:comment_ip;type:varchar(20);comment:评论ip" json:"-"` Location string `gorm:"column:location;type:varchar(20);comment:评论地址" json:"location"` Browser string `gorm:"column:browser;type:varchar(20);comment:评论浏览器" json:"browser"` diff --git a/router/modules/comment_router.go b/router/modules/comment_router.go index 0a97d3a..daff17f 100644 --- a/router/modules/comment_router.go +++ b/router/modules/comment_router.go @@ -13,4 +13,6 @@ func CommentRouter(router *gin.RouterGroup) { router.POST("/auth/comment/list", commonApi.CommentList) router.POST("/auth/reply/list", commonApi.ReplyList) router.POST("/auth/reply/reply/submit", commonApi.ReplyReplySubmit) + router.POST("/auth/comment/like", commonApi.CommentLikes) + router.POST("/auth/comment/cancel_like", commonApi.CancelCommentLikes) } diff --git a/service/comment_reply_service/comment_reply_service.go b/service/comment_reply_service/comment_reply_service.go index 3bc42aa..beafd0f 100644 --- a/service/comment_reply_service/comment_reply_service.go +++ b/service/comment_reply_service/comment_reply_service.go @@ -56,3 +56,35 @@ func (CommentReplyService) UpdateCommentReplyCount(commentID int64) error { }) return err } + +// UpdateCommentLikesCount 更新评论 likes 数量 +func (CommentReplyService) UpdateCommentLikesCount(commentID int64, topicID string) error { + // 使用事务处理错误 + err := global.DB.Transaction(func(tx *gorm.DB) error { + result := tx.Model(&model.ScaCommentReply{}).Where("id = ? and topic_id = ? and deleted = 0", commentID, topicID).Update("likes", gorm.Expr("likes + ?", 1)) + if result.Error != nil { + return result.Error // 返回更新错误 + } + if result.RowsAffected == 0 { + return fmt.Errorf("comment not found") // 处理评论不存在的情况 + } + return nil + }) + return err +} + +// DecrementCommentLikesCount 减少评论 likes 数量 +func (CommentReplyService) DecrementCommentLikesCount(commentID int64, topicID string) error { + // 使用事务处理错误 + err := global.DB.Transaction(func(tx *gorm.DB) error { + result := tx.Model(&model.ScaCommentReply{}).Where("id = ? and topic_id = ? and deleted = 0", commentID, topicID).Update("likes", gorm.Expr("likes - ?", 1)) + if result.Error != nil { + return result.Error // 返回更新错误 + } + if result.RowsAffected == 0 { + return fmt.Errorf("comment not found") // 处理评论不存在的情况 + } + return nil + }) + return err +}