From 5d86914cb715bd8516801bc6c706877b7ea92a34 Mon Sep 17 00:00:00 2001 From: landaiqing <3517283258@qq.com> Date: Tue, 24 Sep 2024 01:15:21 +0800 Subject: [PATCH] :sparkles: update comment --- api/comment_api/comment.go | 36 +- api/comment_api/comment_api.go | 341 +++++++++++++++++- api/comment_api/dto/request_dto.go | 22 +- core/session.go | 6 +- model/sca_comment_reply.go | 22 +- router/modules/comment_router.go | 2 + .../comment_reply_service.go | 18 + utils/session.go | 44 ++- 8 files changed, 452 insertions(+), 39 deletions(-) diff --git a/api/comment_api/comment.go b/api/comment_api/comment.go index 8b4f8fa..b86bc19 100644 --- a/api/comment_api/comment.go +++ b/api/comment_api/comment.go @@ -1,8 +1,8 @@ package comment_api import ( - "schisandra-cloud-album/model" "schisandra-cloud-album/service" + "time" ) type CommentAPI struct{} @@ -13,18 +13,36 @@ type CommentImages struct { TopicId string `json:"topic_id" bson:"topic_id" required:"true"` CommentId int64 `json:"comment_id" bson:"comment_id" required:"true"` UserId string `json:"user_id" bson:"user_id" required:"true"` - Images []string `json:"image_url" bson:"images" required:"true"` + Images [][]byte `json:"images" bson:"images" required:"true"` CreatedAt string `json:"created_at" bson:"created_at" required:"true"` } -type CommentData struct { - Comment model.ScaCommentReply `json:"comment"` - Images []string `json:"images,omitempty"` +type CommentContent struct { + NickName string `json:"nickname"` + Avatar string `json:"avatar"` + Level int `json:"level,omitempty"` + Id int64 `json:"id"` + UserId string `json:"user_id"` + TopicId string `json:"topic_id"` + Content string `json:"content"` + ReplyTo int64 `json:"reply_to,omitempty"` + ReplyId int64 `json:"reply_id,omitempty"` + ReplyUser string `json:"reply_user,omitempty"` + ReplyUsername string `json:"reply_username,omitempty"` + Author int `json:"author"` + 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"` + Images []string `json:"images,omitempty"` } type CommentResponse struct { - Size int `json:"size"` - Total int64 `json:"total"` - Current int `json:"current"` - Comments []CommentData `json:"comments"` + Size int `json:"size"` + Total int64 `json:"total"` + Current int `json:"current"` + Comments []CommentContent `json:"comments"` } diff --git a/api/comment_api/comment_api.go b/api/comment_api/comment_api.go index 0c642ed..9b07f5d 100644 --- a/api/comment_api/comment_api.go +++ b/api/comment_api/comment_api.go @@ -2,19 +2,25 @@ package comment_api import ( "context" + "encoding/base64" "errors" + "fmt" "github.com/acmestack/gorm-plus/gplus" ginI18n "github.com/gin-contrib/i18n" "github.com/gin-gonic/gin" "github.com/mssola/useragent" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" + "io" + "regexp" "schisandra-cloud-album/api/comment_api/dto" "schisandra-cloud-album/common/enum" "schisandra-cloud-album/common/result" "schisandra-cloud-album/global" "schisandra-cloud-album/model" "schisandra-cloud-album/utils" + "strconv" + "strings" "time" ) @@ -63,6 +69,12 @@ func (CommentAPI) CommentSubmit(c *gin.Context) { if commentRequest.UserID == commentRequest.Author { isAuthor = 1 } + tx := global.DB.Begin() + defer func() { + if r := recover(); r != nil { + tx.Rollback() + } + }() commentReply := model.ScaCommentReply{ Content: commentRequest.Content, UserId: commentRequest.UserID, @@ -74,31 +86,59 @@ func (CommentAPI) CommentSubmit(c *gin.Context) { Location: location, Browser: browser, OperatingSystem: operatingSystem, + Agent: userAgent, } if err = commentReplyService.CreateCommentReply(&commentReply); err != nil { result.FailWithMessage(ginI18n.MustGetMessage(c, "CommentSubmitFailed"), c) + tx.Rollback() return } if len(commentRequest.Images) > 0 { + + var imagesData [][]byte + for _, img := range commentRequest.Images { + re := regexp.MustCompile(`^data:image/\w+;base64,`) + imgWithoutPrefix := re.ReplaceAllString(img, "") + data, err := base64ToBytes(imgWithoutPrefix) + if err != nil { + global.LOG.Errorln(err) + tx.Rollback() + return + } + imagesData = append(imagesData, data) + } + commentImages := CommentImages{ TopicId: commentRequest.TopicId, CommentId: commentReply.Id, UserId: commentRequest.UserID, - Images: commentRequest.Images, + Images: imagesData, CreatedAt: time.Now().Format("2006-01-02 15:04:05"), } if _, err = global.MongoDB.Database(global.CONFIG.MongoDB.DB).Collection("comment_images").InsertOne(context.Background(), commentImages); err != nil { global.LOG.Errorln(err) result.FailWithMessage(ginI18n.MustGetMessage(c, "CommentSubmitFailed"), c) + tx.Rollback() return } } + tx.Commit() result.OkWithMessage(ginI18n.MustGetMessage(c, "CommentSubmitSuccess"), c) return } +// base64ToBytes 将base64字符串转换为字节数组 +func base64ToBytes(base64Str string) ([]byte, error) { + reader := base64.NewDecoder(base64.StdEncoding, strings.NewReader(base64Str)) + data, err := io.ReadAll(reader) + if err != nil { + return nil, errors.New("failed to decode base64 string") + } + return data, nil +} + // ReplySubmit 提交回复 // @Summary 提交回复 // @Description 提交回复 @@ -117,7 +157,7 @@ func (CommentAPI) ReplySubmit(c *gin.Context) { if replyCommentRequest.Content == "" || replyCommentRequest.UserID == "" || replyCommentRequest.TopicId == "" || - replyCommentRequest.ReplyId == "" || + strconv.FormatInt(replyCommentRequest.ReplyId, 10) == "" || replyCommentRequest.ReplyUser == "" { result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) return @@ -148,6 +188,12 @@ func (CommentAPI) ReplySubmit(c *gin.Context) { if replyCommentRequest.UserID == replyCommentRequest.Author { isAuthor = 1 } + tx := global.DB.Begin() + defer func() { + if r := recover(); r != nil { + tx.Rollback() + } + }() commentReply := model.ScaCommentReply{ Content: replyCommentRequest.Content, UserId: replyCommentRequest.UserID, @@ -161,27 +207,168 @@ func (CommentAPI) ReplySubmit(c *gin.Context) { Location: location, Browser: browser, OperatingSystem: operatingSystem, + Agent: userAgent, } if err = commentReplyService.CreateCommentReply(&commentReply); err != nil { result.FailWithMessage(ginI18n.MustGetMessage(c, "CommentSubmitFailed"), c) + tx.Rollback() + return + } + err = commentReplyService.UpdateCommentReplyCount(replyCommentRequest.ReplyId) + if err != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "CommentSubmitFailed"), c) + tx.Rollback() return } if len(replyCommentRequest.Images) > 0 { + + var imagesData [][]byte + for _, img := range replyCommentRequest.Images { + re := regexp.MustCompile(`^data:image/\w+;base64,`) + imgWithoutPrefix := re.ReplaceAllString(img, "") + data, err := base64ToBytes(imgWithoutPrefix) + if err != nil { + global.LOG.Errorln(err) + tx.Rollback() + return + } + imagesData = append(imagesData, data) + } commentImages := CommentImages{ TopicId: replyCommentRequest.TopicId, CommentId: commentReply.Id, UserId: replyCommentRequest.UserID, - Images: replyCommentRequest.Images, + Images: imagesData, CreatedAt: time.Now().Format("2006-01-02 15:04:05"), } if _, err = global.MongoDB.Database(global.CONFIG.MongoDB.DB).Collection("comment_images").InsertOne(context.Background(), commentImages); err != nil { global.LOG.Errorln(err) result.FailWithMessage(ginI18n.MustGetMessage(c, "CommentSubmitFailed"), c) + tx.Rollback() return } } + tx.Commit() + result.OkWithMessage(ginI18n.MustGetMessage(c, "CommentSubmitSuccess"), c) + return +} + +// ReplyReplySubmit 提交回复的回复 +// @Summary 提交回复的回复 +// @Description 提交回复的回复 +// @Tags 评论 +// @Accept json +// @Produce json +// @Param reply_reply_request body dto.ReplyReplyRequest true "回复回复请求" +// @Router /auth/reply/reply/submit [post] +func (CommentAPI) ReplyReplySubmit(c *gin.Context) { + replyReplyRequest := dto.ReplyReplyRequest{} + if err := c.ShouldBindJSON(&replyReplyRequest); err != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) + return + } + + if replyReplyRequest.Content == "" || + replyReplyRequest.UserID == "" || + replyReplyRequest.TopicId == "" || + replyReplyRequest.ReplyTo == 0 || + replyReplyRequest.ReplyId == 0 || + replyReplyRequest.ReplyUser == "" { + result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) + return + } + if len(replyReplyRequest.Images) > 3 { + result.FailWithMessage(ginI18n.MustGetMessage(c, "TooManyImages"), c) + return + } + + userAgent := c.GetHeader("User-Agent") + if userAgent == "" { + global.LOG.Errorln("user-agent is empty") + return + } + ua := useragent.New(userAgent) + + ip := utils.GetClientIP(c) + location, err := global.IP2Location.SearchByStr(ip) + if err != nil { + global.LOG.Errorln(err) + return + } + location = utils.RemoveZeroAndAdjust(location) + + browser, _ := ua.Browser() + operatingSystem := ua.OS() + isAuthor := 0 + if replyReplyRequest.UserID == replyReplyRequest.Author { + isAuthor = 1 + } + tx := global.DB.Begin() + defer func() { + if r := recover(); r != nil { + tx.Rollback() + } + }() + commentReply := model.ScaCommentReply{ + Content: replyReplyRequest.Content, + UserId: replyReplyRequest.UserID, + TopicId: replyReplyRequest.TopicId, + TopicType: enum.CommentTopicType, + CommentType: enum.REPLY, + ReplyTo: replyReplyRequest.ReplyTo, + ReplyId: replyReplyRequest.ReplyId, + ReplyUser: replyReplyRequest.ReplyUser, + Author: isAuthor, + CommentIp: ip, + Location: location, + Browser: browser, + OperatingSystem: operatingSystem, + Agent: userAgent, + } + + if err = commentReplyService.CreateCommentReply(&commentReply); err != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "CommentSubmitFailed"), c) + tx.Rollback() + return + } + err = commentReplyService.UpdateCommentReplyCount(replyReplyRequest.ReplyId) + if err != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "CommentSubmitFailed"), c) + tx.Rollback() + return + } + + if len(replyReplyRequest.Images) > 0 { + + var imagesData [][]byte + for _, img := range replyReplyRequest.Images { + re := regexp.MustCompile(`^data:image/\w+;base64,`) + imgWithoutPrefix := re.ReplaceAllString(img, "") + data, err := base64ToBytes(imgWithoutPrefix) + if err != nil { + global.LOG.Errorln(err) + tx.Rollback() + return + } + imagesData = append(imagesData, data) + } + commentImages := CommentImages{ + TopicId: replyReplyRequest.TopicId, + CommentId: commentReply.Id, + UserId: replyReplyRequest.UserID, + Images: imagesData, + CreatedAt: time.Now().Format("2006-01-02 15:04:05"), + } + if _, err = global.MongoDB.Database(global.CONFIG.MongoDB.DB).Collection("comment_images").InsertOne(context.Background(), commentImages); err != nil { + global.LOG.Errorln(err) + result.FailWithMessage(ginI18n.MustGetMessage(c, "CommentSubmitFailed"), c) + tx.Rollback() + return + } + } + tx.Commit() result.OkWithMessage(ginI18n.MustGetMessage(c, "CommentSubmitSuccess"), c) return } @@ -207,22 +394,154 @@ func (CommentAPI) CommentList(c *gin.Context) { } query, u := gplus.NewQuery[model.ScaCommentReply]() page := gplus.NewPage[model.ScaCommentReply](commentListRequest.Page, commentListRequest.Size) - query.Eq(&u.TopicId, commentListRequest.TopicId).OrderByDesc(&u.Likes) + query.Eq(&u.TopicId, commentListRequest.TopicId).Eq(&u.CommentType, enum.COMMENT).OrderByDesc(&u.Likes) page, _ = gplus.SelectPage(page, query) - var commentsWithImages []CommentData + var commentsWithImages []CommentContent - for _, user := range page.Records { + for _, comment := range page.Records { // 获取评论图片 commentImages := CommentImages{} - wrong := global.MongoDB.Database(global.CONFIG.MongoDB.DB).Collection("comment_images").FindOne(context.Background(), bson.M{"comment_id": user.Id}).Decode(&commentImages) + wrong := global.MongoDB.Database(global.CONFIG.MongoDB.DB).Collection("comment_images").FindOne(context.Background(), bson.M{"comment_id": comment.Id}).Decode(&commentImages) if wrong != nil && !errors.Is(wrong, mongo.ErrNoDocuments) { global.LOG.Errorln(wrong) } - commentsWithImages = append(commentsWithImages, CommentData{ - Comment: *user, - Images: commentImages.Images, - }) + // 将图片转换为base64 + var imagesBase64 []string + for _, img := range commentImages.Images { + mimeType := getMimeType(img) // 动态获取 MIME 类型 + base64Img := base64.StdEncoding.EncodeToString(img) + base64WithPrefix := fmt.Sprintf("data:%s;base64,%s", mimeType, base64Img) + imagesBase64 = append(imagesBase64, base64WithPrefix) + } + // 组装评论数据 + queryUser, n := gplus.NewQuery[model.ScaAuthUser]() + queryUser.Eq(&n.UID, comment.UserId) + userInfo, _ := gplus.SelectOne(queryUser) + commentsWithImages = append(commentsWithImages, + 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, + CreatedTime: comment.CreatedTime, + Author: comment.Author, + Location: comment.Location, + Browser: comment.Browser, + OperatingSystem: comment.OperatingSystem, + Images: imagesBase64, + }) + } + response := CommentResponse{ + Comments: commentsWithImages, + Size: page.Size, + Current: page.Current, + Total: page.Total, + } + result.OkWithData(response, c) + return +} + +func getMimeType(data []byte) string { + if len(data) < 4 { + return "application/octet-stream" // 默认类型 + } + + // 判断 JPEG + if data[0] == 0xFF && data[1] == 0xD8 { + return "image/jpeg" + } + + // 判断 PNG + if len(data) >= 8 && data[0] == 0x89 && data[1] == 0x50 && data[2] == 0x4E && data[3] == 0x47 && + data[4] == 0x0D && data[5] == 0x0A && data[6] == 0x1A && data[7] == 0x0A { + return "image/png" + } + + // 判断 GIF + if len(data) >= 6 && data[0] == 'G' && data[1] == 'I' && data[2] == 'F' { + return "image/gif" + } + + return "application/octet-stream" // 默认类型 +} + +// ReplyList 获取回复列表 +// @Summary 获取回复列表 +// @Description 获取回复列表 +// @Tags 评论 +// @Accept json +// @Produce json +// @Param reply_list_request body dto.ReplyListRequest true "回复列表请求" +// @Router /auth/reply/list [post] +func (CommentAPI) ReplyList(c *gin.Context) { + replyListRequest := dto.ReplyListRequest{} + err := c.ShouldBindJSON(&replyListRequest) + if err != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) + return + } + if replyListRequest.TopicId == "" || strconv.FormatInt(replyListRequest.CommentId, 10) == "" { + result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) + return + } + 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) + + var commentsWithImages []CommentContent + + for _, comment := range page.Records { + // 获取评论图片 + commentImages := CommentImages{} + wrong := global.MongoDB.Database(global.CONFIG.MongoDB.DB).Collection("comment_images").FindOne(context.Background(), bson.M{"comment_id": comment.Id}).Decode(&commentImages) + if wrong != nil && !errors.Is(wrong, mongo.ErrNoDocuments) { + global.LOG.Errorln(wrong) + } + // 将图片转换为base64 + var imagesBase64 []string + for _, img := range commentImages.Images { + mimeType := getMimeType(img) // 动态获取 MIME 类型 + base64Img := base64.StdEncoding.EncodeToString(img) + base64WithPrefix := fmt.Sprintf("data:%s;base64,%s", mimeType, base64Img) + imagesBase64 = append(imagesBase64, base64WithPrefix) + } + // 查询评论用户信息 + queryUser, n := gplus.NewQuery[model.ScaAuthUser]() + queryUser.Eq(&n.UID, comment.UserId) + userInfo, _ := gplus.SelectOne(queryUser) + // 查询回复用户信息 + queryReplyUser, m := gplus.NewQuery[model.ScaAuthUser]() + queryReplyUser.Eq(&m.UID, comment.ReplyUser) + replyUserInfo, _ := gplus.SelectOne(queryReplyUser) + commentsWithImages = append(commentsWithImages, + CommentContent{ + Avatar: *userInfo.Avatar, + NickName: *userInfo.Nickname, + Id: comment.Id, + UserId: comment.UserId, + TopicId: comment.TopicId, + Dislikes: comment.Dislikes, + Content: comment.Content, + ReplyUsername: *replyUserInfo.Nickname, + ReplyCount: comment.ReplyCount, + Likes: comment.Likes, + CreatedTime: comment.CreatedTime, + ReplyUser: comment.ReplyUser, + ReplyId: comment.ReplyId, + ReplyTo: comment.ReplyTo, + Author: comment.Author, + Location: comment.Location, + Browser: comment.Browser, + OperatingSystem: comment.OperatingSystem, + Images: imagesBase64, + }) } response := CommentResponse{ Comments: commentsWithImages, diff --git a/api/comment_api/dto/request_dto.go b/api/comment_api/dto/request_dto.go index 80d2ac8..5edd603 100644 --- a/api/comment_api/dto/request_dto.go +++ b/api/comment_api/dto/request_dto.go @@ -12,12 +12,30 @@ type ReplyCommentRequest struct { Images []string `json:"images"` UserID string `json:"user_id"` TopicId string `json:"topic_id"` - ReplyId string `json:"reply_id"` + ReplyId int64 `json:"reply_id"` ReplyUser string `json:"reply_user"` Author string `json:"author"` } + +type ReplyReplyRequest struct { + Content string `json:"content"` + Images []string `json:"images"` + UserID string `json:"user_id"` + TopicId string `json:"topic_id"` + ReplyTo int64 `json:"reply_to"` + ReplyId int64 `json:"reply_id"` + ReplyUser string `json:"reply_user"` + Author string `json:"author"` +} + type CommentListRequest struct { TopicId string `json:"topic_id"` Page int `json:"page" default:"1"` - Size int `json:"size" default:"10"` + Size int `json:"size" default:"5"` +} +type ReplyListRequest struct { + TopicId string `json:"topic_id"` + CommentId int64 `json:"comment_id"` + Page int `json:"page" default:"1"` + Size int `json:"size" default:"5"` } diff --git a/core/session.go b/core/session.go index 81b7be9..4dc5682 100644 --- a/core/session.go +++ b/core/session.go @@ -5,6 +5,7 @@ import ( "github.com/gorilla/sessions" "github.com/rbcervilla/redisstore/v9" "github.com/redis/go-redis/v9" + "net/http" "schisandra-cloud-album/common/constant" "schisandra-cloud-album/global" ) @@ -20,7 +21,10 @@ func InitSession(client *redis.Client) { store.Options(sessions.Options{ Path: "/", //Domain: global.CONFIG.System.Web, - MaxAge: 86400 * 7, + MaxAge: 86400 * 7, + HttpOnly: true, + Secure: true, + SameSite: http.SameSiteLaxMode, }) global.Session = store } diff --git a/model/sca_comment_reply.go b/model/sca_comment_reply.go index 9adebfe..d4dd128 100644 --- a/model/sca_comment_reply.go +++ b/model/sca_comment_reply.go @@ -12,25 +12,27 @@ type ScaCommentReply struct { Id int64 `gorm:"column:id;type:bigint(20);primary_key;AUTO_INCREMENT;comment:主键id" json:"id"` UserId string `gorm:"column:user_id;type:varchar(20);comment:评论用户id" json:"user_id"` TopicId string `gorm:"column:topic_id;type:varchar(20);comment:评论话题id" json:"topic_id"` - TopicType int `gorm:"column:topic_type;type:int(11);comment:话题类型" json:"topic_type"` + TopicType int `gorm:"column:topic_type;type:int(11);comment:话题类型" json:"-"` Content string `gorm:"column:content;type:longtext;comment:评论内容" json:"content"` - CommentType int `gorm:"column:comment_type;type:int(11);comment:评论类型 0评论 1 回复" json:"comment_type"` - ReplyId string `gorm:"column:reply_id;type:varchar(20);comment:回复目标id" json:"reply_id"` - ReplyUser string `gorm:"column:reply_user;type:varchar(20);comment:回复人id" json:"reply_user"` + CommentType int `gorm:"column:comment_type;type:int(11);comment:评论类型 0评论 1 回复" json:"-"` + ReplyTo int64 `gorm:"column:reply_to;type:bigint(20);comment:回复子评论id" json:"reply_to"` + ReplyId int64 `gorm:"column:reply_id;type:varchar(20);comment:回复目标id" json:"reply_id,omitempty"` + ReplyUser string `gorm:"column:reply_user;type:varchar(20);comment:回复人id" json:"reply_user,omitempty"` Author int `gorm:"column:author;type:int(11);default:0;comment:评论回复是否作者 0否 1是" json:"author"` Likes int64 `gorm:"column:likes;type:bigint(20);default:0;comment:点赞数" json:"likes"` ReplyCount int64 `gorm:"column:reply_count;type:bigint(20);default:0;comment:回复数量" json:"reply_count"` CreatedTime time.Time `gorm:"column:created_time;type:datetime;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_time"` - UpdateTime time.Time `gorm:"column:update_time;type:datetime;default:CURRENT_TIMESTAMP;comment:更新时间" json:"update_time"` - Deleted int `gorm:"column:deleted;type:int(11);default:0;comment:是否删除 0未删除 1 已删除" json:"deleted"` - CreatedBy string `gorm:"column:created_by;type:varchar(32);comment:创建人" json:"created_by"` - UpdateBy string `gorm:"column:update_by;type:varchar(32);comment:更新人" json:"update_by"` + UpdateTime time.Time `gorm:"column:update_time;type:datetime;default:CURRENT_TIMESTAMP;comment:更新时间" json:"-"` + 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:"comment_ip"` + 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"` OperatingSystem string `gorm:"column:operating_system;type:varchar(20);comment:评论操作系统" json:"operating_system"` - CommentOrder int64 `gorm:"column:comment_order;type:bigint(20);default:0;comment:评论排序" json:"comment_order"` + CommentOrder int64 `gorm:"column:comment_order;type:bigint(20);default:0;comment:评论排序" json:"-"` + Agent string `gorm:"column:agent;type:varchar(255);comment:客户端设备信息" json:"agent"` } func (comment *ScaCommentReply) TableName() string { diff --git a/router/modules/comment_router.go b/router/modules/comment_router.go index 63aff60..0a97d3a 100644 --- a/router/modules/comment_router.go +++ b/router/modules/comment_router.go @@ -11,4 +11,6 @@ func CommentRouter(router *gin.RouterGroup) { router.POST("/auth/comment/submit", commonApi.CommentSubmit) router.POST("/auth/reply/submit", commonApi.ReplySubmit) router.POST("/auth/comment/list", commonApi.CommentList) + router.POST("/auth/reply/list", commonApi.ReplyList) + router.POST("/auth/reply/reply/submit", commonApi.ReplyReplySubmit) } diff --git a/service/comment_reply_service/comment_reply_service.go b/service/comment_reply_service/comment_reply_service.go index c4623cb..4cb623c 100644 --- a/service/comment_reply_service/comment_reply_service.go +++ b/service/comment_reply_service/comment_reply_service.go @@ -1,6 +1,8 @@ package comment_reply_service import ( + "fmt" + "gorm.io/gorm" "schisandra-cloud-album/global" "schisandra-cloud-album/model" ) @@ -38,3 +40,19 @@ func (CommentReplyService) GetCommentListOrderByLikesDesc(topicID uint, page, pa } return comments, nil } + +// UpdateCommentReplyCount 更新评论 +func (CommentReplyService) UpdateCommentReplyCount(commentID int64) error { + // 使用事务处理错误 + err := global.DB.Transaction(func(tx *gorm.DB) error { + result := tx.Model(&model.ScaCommentReply{}).Where("id = ?", commentID).Update("reply_count", gorm.Expr("reply_count + ?", 1)) + if result.Error != nil { + return result.Error // 返回更新错误 + } + if result.RowsAffected == 0 { + return fmt.Errorf("comment not found") // 处理评论不存在的情况 + } + return nil + }) + return err +} diff --git a/utils/session.go b/utils/session.go index 4b8caf0..dd967e7 100644 --- a/utils/session.go +++ b/utils/session.go @@ -1,6 +1,7 @@ package utils import ( + "encoding/gob" "encoding/json" "github.com/gin-gonic/gin" "schisandra-cloud-album/global" @@ -12,12 +13,8 @@ func SetSession(c *gin.Context, key string, data interface{}) error { global.LOG.Error("SetSession failed: ", err) return err } - jsonData, err := json.Marshal(data) - if err != nil { - global.LOG.Error("SetSession failed: ", err) - return err - } - session.Values[key] = jsonData + gob.Register(data) + session.Values[key] = data err = session.Save(c.Request, c.Writer) if err != nil { global.LOG.Error("SetSession failed: ", err) @@ -25,3 +22,38 @@ func SetSession(c *gin.Context, key string, data interface{}) error { } return nil } + +func GetSession(c *gin.Context, key string) interface{} { + session, err := global.Session.Get(c.Request, key) + if err != nil { + global.LOG.Error("GetSession failed: ", err) + return nil + } + jsonData, ok := session.Values[key] + if !ok { + global.LOG.Error("GetSession failed: ", "key not found") + return nil + } + var data interface{} + err = json.Unmarshal(jsonData.([]byte), &data) + if err != nil { + global.LOG.Error("GetSession failed: ", err) + return nil + } + return data +} + +func DelSession(c *gin.Context, key string) { + session, err := global.Session.Get(c.Request, key) + if err != nil { + global.LOG.Error("DelSession failed: ", err) + return + } + delete(session.Values, key) + err = session.Save(c.Request, c.Writer) + if err != nil { + global.LOG.Error("DelSession failed: ", err) + return + } + return +}