From 7aae53e533bc529faad5c62883654d1aaae9b685 Mon Sep 17 00:00:00 2001 From: landaiqing <3517283258@qq.com> Date: Mon, 23 Sep 2024 00:53:43 +0800 Subject: [PATCH] :sparkles: improve the functions related to commenting on images --- api/client_api/client_api.go | 12 +- api/comment_api/comment.go | 25 +- api/comment_api/comment_api.go | 223 +++++++++++++++++- api/comment_api/dto/request_dto.go | 17 ++ api/oauth_api/wechat_api.go | 2 +- api/user_api/user_api.go | 2 +- common/enum/comment_type.go | 6 + common/enum/topic_type.go | 5 + common/randomname/actsomething.go | 8 + common/randomname/adjective.go | 31 +++ common/randomname/person.go | 11 + common/randomname/randomname.go | 20 ++ common/randomname/randomtype.go | 8 + common/result/result.go | 4 +- config/conf_mongodb.go | 18 ++ config/config.go | 1 + core/gorm.go | 3 + core/mongodb.go | 40 ++++ docs/docs.go | 168 ++++++++++++- docs/swagger.json | 168 ++++++++++++- docs/swagger.yaml | 111 ++++++++- global/global.go | 2 + go.mod | 32 ++- go.sum | 64 +++-- i18n/language/en.toml | 7 +- i18n/language/zh.toml | 7 +- main.go | 1 + model/sca_comment_likes.go | 3 +- model/sca_comment_reply.go | 11 +- router/modules/comment_router.go | 2 + .../comment_reply_service.go | 26 ++ utils/paginator.go | 52 ++++ 32 files changed, 1004 insertions(+), 86 deletions(-) create mode 100644 common/enum/comment_type.go create mode 100644 common/enum/topic_type.go create mode 100644 common/randomname/actsomething.go create mode 100644 common/randomname/adjective.go create mode 100644 common/randomname/person.go create mode 100644 common/randomname/randomname.go create mode 100644 common/randomname/randomtype.go create mode 100644 config/conf_mongodb.go create mode 100644 core/mongodb.go create mode 100644 utils/paginator.go diff --git a/api/client_api/client_api.go b/api/client_api/client_api.go index 8c5e6e6..cdc6762 100644 --- a/api/client_api/client_api.go +++ b/api/client_api/client_api.go @@ -2,7 +2,7 @@ package client_api import ( "github.com/gin-gonic/gin" - uuid "github.com/satori/go.uuid" + "github.com/google/uuid" "schisandra-cloud-album/common/constant" "schisandra-cloud-album/common/redis" "schisandra-cloud-album/common/result" @@ -31,12 +31,16 @@ func (ClientAPI) GenerateClientId(c *gin.Context) { return } // 生成新的客户端ID - v1 := uuid.NewV1() - err := redis.Set(constant.UserLoginClientRedisKey+ip, v1.String(), time.Hour*24*7).Err() + uid, err := uuid.NewUUID() if err != nil { global.LOG.Error(err) return } - result.OkWithData(v1.String(), c) + err = redis.Set(constant.UserLoginClientRedisKey+ip, uid, time.Hour*24*7).Err() + if err != nil { + global.LOG.Error(err) + return + } + result.OkWithData(uid, c) return } diff --git a/api/comment_api/comment.go b/api/comment_api/comment.go index 3d9afa4..8b4f8fa 100644 --- a/api/comment_api/comment.go +++ b/api/comment_api/comment.go @@ -1,7 +1,30 @@ package comment_api -import "schisandra-cloud-album/service" +import ( + "schisandra-cloud-album/model" + "schisandra-cloud-album/service" +) type CommentAPI struct{} var commentReplyService = service.Service.CommentReplyService + +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"` + CreatedAt string `json:"created_at" bson:"created_at" required:"true"` +} + +type CommentData struct { + Comment model.ScaCommentReply `json:"comment"` + Images []string `json:"images,omitempty"` +} + +type CommentResponse struct { + Size int `json:"size"` + Total int64 `json:"total"` + Current int `json:"current"` + Comments []CommentData `json:"comments"` +} diff --git a/api/comment_api/comment_api.go b/api/comment_api/comment_api.go index cad31e9..0c642ed 100644 --- a/api/comment_api/comment_api.go +++ b/api/comment_api/comment_api.go @@ -1,28 +1,235 @@ package comment_api import ( + "context" + "errors" + "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" "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" + "time" ) // CommentSubmit 提交评论 +// @Summary 提交评论 +// @Description 提交评论 +// @Tags 评论 +// @Accept json +// @Produce json +// @Param comment_request body dto.CommentRequest true "评论请求" +// @Router /auth/comment/submit [post] func (CommentAPI) CommentSubmit(c *gin.Context) { commentRequest := dto.CommentRequest{} - err := c.ShouldBindJSON(&commentRequest) + if err := c.ShouldBindJSON(&commentRequest); err != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) + return + } + + if commentRequest.Content == "" || commentRequest.UserID == "" || commentRequest.TopicId == "" { + result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) + return + } + if len(commentRequest.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 commentRequest.UserID == commentRequest.Author { + isAuthor = 1 + } + commentReply := model.ScaCommentReply{ + Content: commentRequest.Content, + UserId: commentRequest.UserID, + TopicId: commentRequest.TopicId, + TopicType: enum.CommentTopicType, + CommentType: enum.COMMENT, + Author: isAuthor, + CommentIp: ip, + Location: location, + Browser: browser, + OperatingSystem: operatingSystem, + } + + if err = commentReplyService.CreateCommentReply(&commentReply); err != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "CommentSubmitFailed"), c) + return + } + + if len(commentRequest.Images) > 0 { + commentImages := CommentImages{ + TopicId: commentRequest.TopicId, + CommentId: commentReply.Id, + UserId: commentRequest.UserID, + Images: commentRequest.Images, + 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) + return + } + } + result.OkWithMessage(ginI18n.MustGetMessage(c, "CommentSubmitSuccess"), c) + return +} + +// ReplySubmit 提交回复 +// @Summary 提交回复 +// @Description 提交回复 +// @Tags 评论 +// @Accept json +// @Produce json +// @Param reply_comment_request body dto.ReplyCommentRequest true "回复评论请求" +// @Router /auth/reply/submit [post] +func (CommentAPI) ReplySubmit(c *gin.Context) { + replyCommentRequest := dto.ReplyCommentRequest{} + if err := c.ShouldBindJSON(&replyCommentRequest); err != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) + return + } + + if replyCommentRequest.Content == "" || + replyCommentRequest.UserID == "" || + replyCommentRequest.TopicId == "" || + replyCommentRequest.ReplyId == "" || + replyCommentRequest.ReplyUser == "" { + result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) + return + } + if len(replyCommentRequest.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 replyCommentRequest.UserID == replyCommentRequest.Author { + isAuthor = 1 + } + commentReply := model.ScaCommentReply{ + Content: replyCommentRequest.Content, + UserId: replyCommentRequest.UserID, + TopicId: replyCommentRequest.TopicId, + TopicType: enum.CommentTopicType, + CommentType: enum.REPLY, + ReplyId: replyCommentRequest.ReplyId, + ReplyUser: replyCommentRequest.ReplyUser, + Author: isAuthor, + CommentIp: ip, + Location: location, + Browser: browser, + OperatingSystem: operatingSystem, + } + + if err = commentReplyService.CreateCommentReply(&commentReply); err != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "CommentSubmitFailed"), c) + return + } + + if len(replyCommentRequest.Images) > 0 { + commentImages := CommentImages{ + TopicId: replyCommentRequest.TopicId, + CommentId: commentReply.Id, + UserId: replyCommentRequest.UserID, + Images: replyCommentRequest.Images, + 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) + return + } + } + result.OkWithMessage(ginI18n.MustGetMessage(c, "CommentSubmitSuccess"), c) + return +} + +// CommentList 获取评论列表 +// @Summary 获取评论列表 +// @Description 获取评论列表 +// @Tags 评论 +// @Accept json +// @Produce json +// @Param comment_list_request body dto.CommentListRequest true "评论列表请求" +// @Router /auth/comment/list [post] +func (CommentAPI) CommentList(c *gin.Context) { + commentListRequest := dto.CommentListRequest{} + err := c.ShouldBindJSON(&commentListRequest) if err != nil { result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) return } - content := commentRequest.Content - images := commentRequest.Images - if content == "" { - result.FailWithMessage(ginI18n.MustGetMessage(c, "RequestParamsNotEmpty"), c) + if commentListRequest.TopicId == "" { + result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) return } - if len(images) > 5 { - result.FailWithMessage(ginI18n.MustGetMessage(c, "TooManyImages"), c) - return + query, u := gplus.NewQuery[model.ScaCommentReply]() + page := gplus.NewPage[model.ScaCommentReply](commentListRequest.Page, commentListRequest.Size) + query.Eq(&u.TopicId, commentListRequest.TopicId).OrderByDesc(&u.Likes) + page, _ = gplus.SelectPage(page, query) + + var commentsWithImages []CommentData + + for _, user := 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) + if wrong != nil && !errors.Is(wrong, mongo.ErrNoDocuments) { + global.LOG.Errorln(wrong) + } + commentsWithImages = append(commentsWithImages, CommentData{ + Comment: *user, + Images: commentImages.Images, + }) } + response := CommentResponse{ + Comments: commentsWithImages, + Size: page.Size, + Current: page.Current, + Total: page.Total, + } + result.OkWithData(response, c) + return } diff --git a/api/comment_api/dto/request_dto.go b/api/comment_api/dto/request_dto.go index ff8aded..80d2ac8 100644 --- a/api/comment_api/dto/request_dto.go +++ b/api/comment_api/dto/request_dto.go @@ -3,4 +3,21 @@ package dto type CommentRequest struct { Content string `json:"content"` Images []string `json:"images"` + UserID string `json:"user_id"` + TopicId string `json:"topic_id"` + Author string `json:"author"` +} +type ReplyCommentRequest struct { + Content string `json:"content"` + Images []string `json:"images"` + UserID string `json:"user_id"` + TopicId string `json:"topic_id"` + ReplyId string `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"` } diff --git a/api/oauth_api/wechat_api.go b/api/oauth_api/wechat_api.go index 9259e74..b0c9f49 100644 --- a/api/oauth_api/wechat_api.go +++ b/api/oauth_api/wechat_api.go @@ -9,7 +9,6 @@ import ( "github.com/ArtisanCloud/PowerWeChat/v3/src/kernel/messages" models2 "github.com/ArtisanCloud/PowerWeChat/v3/src/kernel/models" "github.com/ArtisanCloud/PowerWeChat/v3/src/officialAccount/server/handlers/models" - "github.com/DanPlayer/randomname" ginI18n "github.com/gin-contrib/i18n" "github.com/gin-gonic/gin" "github.com/yitter/idgenerator-go/idgen" @@ -18,6 +17,7 @@ import ( "schisandra-cloud-album/api/websocket_api" "schisandra-cloud-album/common/constant" "schisandra-cloud-album/common/enum" + "schisandra-cloud-album/common/randomname" "schisandra-cloud-album/common/redis" "schisandra-cloud-album/common/result" "schisandra-cloud-album/global" diff --git a/api/user_api/user_api.go b/api/user_api/user_api.go index 92c9308..6492848 100644 --- a/api/user_api/user_api.go +++ b/api/user_api/user_api.go @@ -2,7 +2,6 @@ package user_api import ( "errors" - "github.com/DanPlayer/randomname" ginI18n "github.com/gin-contrib/i18n" "github.com/gin-gonic/gin" "github.com/mssola/useragent" @@ -12,6 +11,7 @@ import ( "schisandra-cloud-album/api/user_api/dto" "schisandra-cloud-album/common/constant" "schisandra-cloud-album/common/enum" + "schisandra-cloud-album/common/randomname" "schisandra-cloud-album/common/redis" "schisandra-cloud-album/common/result" "schisandra-cloud-album/global" diff --git a/common/enum/comment_type.go b/common/enum/comment_type.go new file mode 100644 index 0000000..afae415 --- /dev/null +++ b/common/enum/comment_type.go @@ -0,0 +1,6 @@ +package enum + +var ( + COMMENT = 0 + REPLY = 1 +) diff --git a/common/enum/topic_type.go b/common/enum/topic_type.go new file mode 100644 index 0000000..c07d367 --- /dev/null +++ b/common/enum/topic_type.go @@ -0,0 +1,5 @@ +package enum + +var ( + CommentTopicType = 0 +) diff --git a/common/randomname/actsomething.go b/common/randomname/actsomething.go new file mode 100644 index 0000000..4471fe3 --- /dev/null +++ b/common/randomname/actsomething.go @@ -0,0 +1,8 @@ +package randomname + +// ActSomethingSlice 做什么事情 +var ActSomethingSlice = []string{ + "打豆豆", "吃爆米花", "走向人生巅峰", "大力出奇迹", "得到了金球奖", "爆射世界杯", "有亿点点忧伤", "完成了梅开二度", "完成了帽子戏法", "完成了大四喜", "完成了五子登科", + "望穿秋水", "掐指一算", "横扫千军", "一眼定情", "会发财", "求而不得", "舞力四射", "横扫六合", "救了一个美女", "使出了佛怒火莲", "在巴黎徒步", "心花怒放", "在武汉看电影", +} +var ActSomethingSliceCount = len(ActSomethingSlice) diff --git a/common/randomname/adjective.go b/common/randomname/adjective.go new file mode 100644 index 0000000..8a43ee7 --- /dev/null +++ b/common/randomname/adjective.go @@ -0,0 +1,31 @@ +package randomname + +// AdjectiveSlice 形容词 +var AdjectiveSlice = []string{ + "帅气的", "迷人的", "大汗淋漓的", "朝气蓬勃的", "隐身的", "天神下凡的", "快乐的", "冷静的", "醉熏的", "潇洒的", "糊涂的", "积极的", + "冷酷的", "深情的", "粗暴的", "温柔的", "可爱的", "愉快的", "义气的", "认真的", "威武的", "传统的", "潇洒的", "漂亮的", "自然的", + "专一的", "听话的", "昏睡的", "狂野的", "等待的", "搞怪的", "幽默的", "魁梧的", "活泼的", "开心的", "高兴的", "超帅的", "留胡子的", + "坦率的", "直率的", "轻松的", "痴情的", "完美的", "精明的", "无聊的", "有魅力的", "丰富的", "高挑的", "傻傻的", "冷艳的", "爱听歌的", + "繁荣的", "饱满的", "炙热的", "暴躁的", "碧蓝的", "俊逸的", "英勇的", "健忘的", "故意的", "无心的", "土豪的", "朴实的", "兴奋的", + "幸福的", "淡定的", "不安的", "阔达的", "孤独的", "独特的", "疯狂的", "时尚的", "落后的", "风趣的", "忧伤的", "大胆的", "爱笑的", "矮小的", + "健康的", "合适的", "玩命的", "沉默的", "斯文的", "香蕉的", "苹果的", "鲤鱼的", "鳗鱼的", "任性的", "细心的", "粗心的", "大意的", "甜甜的", + "酷酷的", "健壮的", "英俊的", "霸气的", "阳光的", "默默的", "大力的", "孝顺的", "忧虑的", "着急的", "紧张的", "善良的", "凶狠的", "害怕的", + "重要的", "危机的", "欢喜的", "欣慰的", "满意的", "跳跃的", "诚心的", "称心的", "如意的", "怡然的", "娇气的", "无奈的", "无语的", "激动的", + "愤怒的", "美好的", "感动的", "激情的", "激昂的", "震动的", "虚拟的", "超级的", "寒冷的", "精明的", "明理的", "犹豫的", "忧郁的", "寂寞的", + "奋斗的", "勤奋的", "现代的", "过时的", "稳重的", "热情的", "含蓄的", "开放的", "无辜的", "多情的", "纯真的", "拉长的", "热心的", "从容的", + "体贴的", "风中的", "曾经的", "追寻的", "儒雅的", "优雅的", "开朗的", "外向的", "内向的", "清爽的", "文艺的", "长情的", "平常的", "单身的", + "伶俐的", "高大的", "懦弱的", "柔弱的", "爱笑的", "乐观的", "耍酷的", "酷炫的", "神勇的", "年轻的", "唠叨的", "瘦瘦的", "无情的", "包容的", + "顺心的", "畅快的", "舒适的", "靓丽的", "负责的", "背后的", "简单的", "谦让的", "彩色的", "缥缈的", "欢呼的", "生动的", "复杂的", "慈祥的", + "仁爱的", "魔幻的", "虚幻的", "淡然的", "受伤的", "雪白的", "高高的", "糟糕的", "顺利的", "闪闪的", "羞涩的", "缓慢的", "迅速的", "优秀的", + "聪明的", "含糊的", "俏皮的", "淡淡的", "坚强的", "平淡的", "欣喜的", "能干的", "灵巧的", "友好的", "机智的", "机灵的", "正直的", "谨慎的", + "俭朴的", "殷勤的", "虚心的", "辛勤的", "自觉的", "无私的", "无限的", "踏实的", "老实的", "现实的", "可靠的", "务实的", "拼搏的", "个性的", + "粗犷的", "活力的", "成就的", "勤劳的", "单纯的", "落寞的", "朴素的", "悲凉的", "忧心的", "洁净的", "清秀的", "自由的", "小巧的", "单薄的", + "贪玩的", "刻苦的", "干净的", "壮观的", "和谐的", "文静的", "调皮的", "害羞的", "安详的", "自信的", "端庄的", "坚定的", "美满的", "舒心的", + "温暖的", "专注的", "勤恳的", "美丽的", "腼腆的", "优美的", "甜美的", "甜蜜的", "整齐的", "动人的", "典雅的", "尊敬的", "舒服的", "妩媚的", + "秀丽的", "喜悦的", "甜美的", "彪壮的", "强健的", "大方的", "俊秀的", "聪慧的", "陶醉的", "悦耳的", "动听的", "明亮的", "结实的", "魁梧的", + "标致的", "清脆的", "敏感的", "光亮的", "大气的", "老迟到的", "知性的", "冷傲的", "呆萌的", "野性的", "隐形的", "笑点低的", "微笑的", "笨笨的", + "难过的", "沉静的", "火星上的", "失眠的", "安静的", "纯情的", "要减肥的", "迷路的", "烂漫的", "哭泣的", "贤惠的", "苗条的", "温婉的", "发嗲的", + "会撒娇的", "贪玩的", "执着的", "眯眯眼的", "花痴的", "想人陪的", "眼睛大的", "高贵的", "傲娇的", "心灵美的", "爱撒娇的", "细腻的", "天真的", + "怕黑的", "感性的", "飘逸的", "怕孤独的", "忐忑的", "还单身的", "怕孤单的", "懵懂的", +} +var AdjectiveSliceCount = len(AdjectiveSlice) diff --git a/common/randomname/person.go b/common/randomname/person.go new file mode 100644 index 0000000..66f0836 --- /dev/null +++ b/common/randomname/person.go @@ -0,0 +1,11 @@ +package randomname + +// PersonSlice 人物 +var PersonSlice = []string{ + "梅西", "罗纳尔多", "内马尔", "贝克汉姆", "姆巴佩", "苏牙", "小罗", "大罗", "鲁尼", "本泽马", "贝利", "约翰", "柯南", "米老鼠", + "弗朗茨", "普拉蒂尼", "迪斯蒂法诺", "普斯卡什", "乔治·贝斯特", "范巴斯滕", "尤西比奥", "列夫·雅辛", "博比", "博比·摩尔", "盖德·穆勒", + "巴乔", "斯坦利", "济科", "弗兰科", "加林查", "保罗", "肯尼", "巴蒂斯图塔", "坎通纳", "哈吉", "罗马里奥", + "齐达內", "古利特", "约翰·查尔斯", "卡卡", "哈维", "伊布", "莫德里奇", "欧文", "巴乔", "萧炎", "鸣人", "佐助", "盖茨比", "乔布斯", "索尔", + "宙斯", "雅典娜", "星矢", "托尼", "科比", "乔丹", "西瓜太郎", "一休", "莫甘娜", "永恩", "爱因斯坦", "肖申克", "摩尔", +} +var PersonSliceCount = len(PersonSlice) diff --git a/common/randomname/randomname.go b/common/randomname/randomname.go new file mode 100644 index 0000000..a1e3dbb --- /dev/null +++ b/common/randomname/randomname.go @@ -0,0 +1,20 @@ +package randomname + +import ( + "math/rand" + "time" +) + +// GenerateName 生成随机昵称 +func GenerateName() string { + var name string + rand.New(rand.NewSource(time.Now().UnixNano())) + selectedType := RandomType(rand.Intn(2)) + switch selectedType { + case AdjectiveAndPerson: + name = AdjectiveSlice[rand.Intn(AdjectiveSliceCount)] + PersonSlice[rand.Intn(PersonSliceCount)] + case PersonActSomething: + name = PersonSlice[rand.Intn(PersonSliceCount)] + ActSomethingSlice[rand.Intn(ActSomethingSliceCount)] + } + return name +} diff --git a/common/randomname/randomtype.go b/common/randomname/randomtype.go new file mode 100644 index 0000000..85294e8 --- /dev/null +++ b/common/randomname/randomtype.go @@ -0,0 +1,8 @@ +package randomname + +type RandomType int + +const ( + AdjectiveAndPerson RandomType = iota // 形容词+人物 例如:帅气的罗纳尔多 + PersonActSomething // 人物+做事情 例如:梅西吃爆米花 +) diff --git a/common/result/result.go b/common/result/result.go index 191f512..218960f 100644 --- a/common/result/result.go +++ b/common/result/result.go @@ -13,8 +13,8 @@ type Response struct { } const ( - SUCCESS = 0 - FAIL = -1 + SUCCESS = 200 + FAIL = 500 ) func Result(code int, msg string, data any, success bool, c *gin.Context) { diff --git a/config/conf_mongodb.go b/config/conf_mongodb.go new file mode 100644 index 0000000..800907b --- /dev/null +++ b/config/conf_mongodb.go @@ -0,0 +1,18 @@ +package config + +import "strconv" + +type MongoDB struct { + Host string `yaml:"host"` + Port int `yaml:"port"` + AuthSource string `yaml:"auth-source"` + DB string `yaml:"db"` + User string `yaml:"user"` + Password string `yaml:"password"` + MaxOpenConn int `yaml:"max-open-conn"` + MaxIdleConn int `yaml:"max-idle-conn"` +} + +func (m *MongoDB) MongoDsn() string { + return "mongodb://" + m.Host + ":" + strconv.Itoa(m.Port) +} diff --git a/config/config.go b/config/config.go index 06c0eea..6f526d2 100644 --- a/config/config.go +++ b/config/config.go @@ -12,4 +12,5 @@ type Config struct { OAuth OAuth `yaml:"oauth"` Swagger Swagger `yaml:"swagger"` Casbin Casbin `yaml:"casbin"` + MongoDB MongoDB `yaml:"mongodb"` } diff --git a/core/gorm.go b/core/gorm.go index 7b6e806..eabe7fd 100644 --- a/core/gorm.go +++ b/core/gorm.go @@ -2,6 +2,7 @@ package core import ( "fmt" + "github.com/acmestack/gorm-plus/gplus" "gorm.io/driver/mysql" "gorm.io/gorm" "gorm.io/gorm/logger" @@ -61,5 +62,7 @@ func MySQlConnect() *gorm.DB { sqlDB.SetMaxIdleConns(global.CONFIG.MySQL.MaxIdleConnes) sqlDB.SetMaxOpenConns(global.CONFIG.MySQL.MaxOpenConnes) sqlDB.SetConnMaxLifetime(time.Hour * 4) //连接最大复用时间 + // 初始化gplus + gplus.Init(db) return db } diff --git a/core/mongodb.go b/core/mongodb.go new file mode 100644 index 0000000..25b164f --- /dev/null +++ b/core/mongodb.go @@ -0,0 +1,40 @@ +package core + +import ( + "context" + "fmt" + "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/mongo/options" + "schisandra-cloud-album/global" + "time" +) + +// InitMongoDB initializes the MongoDB connection +func InitMongoDB() { + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + clientOptions := options.Client().ApplyURI(global.CONFIG.MongoDB.MongoDsn()) + clientOptions.SetAuth(options.Credential{ + AuthMechanism: "SCRAM-SHA-256", + AuthMechanismProperties: nil, + AuthSource: global.CONFIG.MongoDB.AuthSource, + Username: global.CONFIG.MongoDB.User, + Password: global.CONFIG.MongoDB.Password, + PasswordSet: true, + }) + connect, err := mongo.Connect(ctx, clientOptions) + if err != nil { + global.LOG.Fatalf(err.Error()) + return + } + // Check the connection + err = connect.Ping(context.TODO(), nil) + if err != nil { + global.LOG.Fatalf(err.Error()) + return + } + global.MongoDB = connect + fmt.Println("Connected to MongoDB!") +} diff --git a/docs/docs.go b/docs/docs.go index f7c6b54..1f4ce99 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -42,6 +42,33 @@ const docTemplate = `{ "responses": {} } }, + "/api/auth/permission/assign": { + "post": { + "description": "给指定角色分配权限", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "权限管理" + ], + "summary": "给指定角色分配权限", + "parameters": [ + { + "description": "权限列表", + "name": "permissions", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.AddPermissionToRoleRequestDto" + } + } + ], + "responses": {} + } + }, "/api/auth/role/add_role_to_user": { "post": { "description": "给指定用户添加角色", @@ -137,6 +164,22 @@ const docTemplate = `{ } } }, + "/api/auth/user/logout": { + "post": { + "tags": [ + "用户模块" + ], + "summary": "退出登录", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, "/api/auth/user/query_by_phone": { "get": { "tags": [ @@ -405,6 +448,60 @@ const docTemplate = `{ } } }, + "/api/comment/reply": { + "post": { + "description": "提交回复", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "评论" + ], + "summary": "提交回复", + "parameters": [ + { + "description": "回复评论请求", + "name": "reply_comment_request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.ReplyCommentRequest" + } + } + ], + "responses": {} + } + }, + "/api/comment/submit": { + "post": { + "description": "提交评论", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "评论" + ], + "summary": "提交评论", + "parameters": [ + { + "description": "评论请求", + "name": "comment_request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.CommentRequest" + } + } + ], + "responses": {} + } + }, "/api/oauth/callback_notify": { "post": { "description": "微信回调", @@ -762,16 +859,6 @@ const docTemplate = `{ "summary": "创建websocket服务", "responses": {} } - }, - "/api/ws/socket": { - "get": { - "description": "创建websocket服务", - "tags": [ - "websocket" - ], - "summary": "创建websocket服务(gorilla)", - "responses": {} - } } }, "definitions": { @@ -800,6 +887,20 @@ const docTemplate = `{ } } }, + "dto.AddPermissionToRoleRequestDto": { + "type": "object", + "properties": { + "method": { + "type": "string" + }, + "permission": { + "type": "string" + }, + "role_key": { + "type": "string" + } + } + }, "dto.AddRoleToUserRequestDto": { "type": "object", "properties": { @@ -811,6 +912,26 @@ const docTemplate = `{ } } }, + "dto.CommentRequest": { + "type": "object", + "properties": { + "content": { + "type": "string" + }, + "images": { + "type": "array", + "items": { + "type": "string" + } + }, + "topic_id": { + "type": "string" + }, + "user_id": { + "type": "string" + } + } + }, "dto.PhoneLoginRequest": { "type": "object", "properties": { @@ -825,6 +946,32 @@ const docTemplate = `{ } } }, + "dto.ReplyCommentRequest": { + "type": "object", + "properties": { + "content": { + "type": "string" + }, + "images": { + "type": "array", + "items": { + "type": "string" + } + }, + "reply_id": { + "type": "string" + }, + "reply_user": { + "type": "string" + }, + "topic_id": { + "type": "string" + }, + "user_id": { + "type": "string" + } + } + }, "dto.ResetPasswordRequest": { "type": "object", "properties": { @@ -913,7 +1060,6 @@ const docTemplate = `{ "type": "integer" }, "update_by": { - "description": "更新人", "type": "string" }, "update_time": { diff --git a/docs/swagger.json b/docs/swagger.json index 3bdf03e..1e315bb 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -31,6 +31,33 @@ "responses": {} } }, + "/api/auth/permission/assign": { + "post": { + "description": "给指定角色分配权限", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "权限管理" + ], + "summary": "给指定角色分配权限", + "parameters": [ + { + "description": "权限列表", + "name": "permissions", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.AddPermissionToRoleRequestDto" + } + } + ], + "responses": {} + } + }, "/api/auth/role/add_role_to_user": { "post": { "description": "给指定用户添加角色", @@ -126,6 +153,22 @@ } } }, + "/api/auth/user/logout": { + "post": { + "tags": [ + "用户模块" + ], + "summary": "退出登录", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, "/api/auth/user/query_by_phone": { "get": { "tags": [ @@ -394,6 +437,60 @@ } } }, + "/api/comment/reply": { + "post": { + "description": "提交回复", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "评论" + ], + "summary": "提交回复", + "parameters": [ + { + "description": "回复评论请求", + "name": "reply_comment_request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.ReplyCommentRequest" + } + } + ], + "responses": {} + } + }, + "/api/comment/submit": { + "post": { + "description": "提交评论", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "评论" + ], + "summary": "提交评论", + "parameters": [ + { + "description": "评论请求", + "name": "comment_request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.CommentRequest" + } + } + ], + "responses": {} + } + }, "/api/oauth/callback_notify": { "post": { "description": "微信回调", @@ -751,16 +848,6 @@ "summary": "创建websocket服务", "responses": {} } - }, - "/api/ws/socket": { - "get": { - "description": "创建websocket服务", - "tags": [ - "websocket" - ], - "summary": "创建websocket服务(gorilla)", - "responses": {} - } } }, "definitions": { @@ -789,6 +876,20 @@ } } }, + "dto.AddPermissionToRoleRequestDto": { + "type": "object", + "properties": { + "method": { + "type": "string" + }, + "permission": { + "type": "string" + }, + "role_key": { + "type": "string" + } + } + }, "dto.AddRoleToUserRequestDto": { "type": "object", "properties": { @@ -800,6 +901,26 @@ } } }, + "dto.CommentRequest": { + "type": "object", + "properties": { + "content": { + "type": "string" + }, + "images": { + "type": "array", + "items": { + "type": "string" + } + }, + "topic_id": { + "type": "string" + }, + "user_id": { + "type": "string" + } + } + }, "dto.PhoneLoginRequest": { "type": "object", "properties": { @@ -814,6 +935,32 @@ } } }, + "dto.ReplyCommentRequest": { + "type": "object", + "properties": { + "content": { + "type": "string" + }, + "images": { + "type": "array", + "items": { + "type": "string" + } + }, + "reply_id": { + "type": "string" + }, + "reply_user": { + "type": "string" + }, + "topic_id": { + "type": "string" + }, + "user_id": { + "type": "string" + } + } + }, "dto.ResetPasswordRequest": { "type": "object", "properties": { @@ -902,7 +1049,6 @@ "type": "integer" }, "update_by": { - "description": "更新人", "type": "string" }, "update_time": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index e390756..5c113c5 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -15,6 +15,15 @@ definitions: $ref: '#/definitions/model.ScaAuthPermission' type: array type: object + dto.AddPermissionToRoleRequestDto: + properties: + method: + type: string + permission: + type: string + role_key: + type: string + type: object dto.AddRoleToUserRequestDto: properties: role_key: @@ -22,6 +31,19 @@ definitions: uid: type: string type: object + dto.CommentRequest: + properties: + content: + type: string + images: + items: + type: string + type: array + topic_id: + type: string + user_id: + type: string + type: object dto.PhoneLoginRequest: properties: auto_login: @@ -31,6 +53,23 @@ definitions: phone: type: string type: object + dto.ReplyCommentRequest: + properties: + content: + type: string + images: + items: + type: string + type: array + reply_id: + type: string + reply_user: + type: string + topic_id: + type: string + user_id: + type: string + type: object dto.ResetPasswordRequest: properties: captcha: @@ -94,7 +133,6 @@ definitions: description: 类型 0 菜单 1 目录 2 按钮 -1其他 type: integer update_by: - description: 更新人 type: string update_time: description: 更新时间 @@ -121,6 +159,24 @@ paths: summary: 批量添加权限 tags: - 权限管理 + /api/auth/permission/assign: + post: + consumes: + - application/json + description: 给指定角色分配权限 + parameters: + - description: 权限列表 + in: body + name: permissions + required: true + schema: + $ref: '#/definitions/dto.AddPermissionToRoleRequestDto' + produces: + - application/json + responses: {} + summary: 给指定角色分配权限 + tags: + - 权限管理 /api/auth/role/add_role_to_user: post: consumes: @@ -183,6 +239,16 @@ paths: summary: 删除用户 tags: - 用户模块 + /api/auth/user/logout: + post: + responses: + "200": + description: OK + schema: + type: string + summary: 退出登录 + tags: + - 用户模块 /api/auth/user/query_by_phone: get: parameters: @@ -358,6 +424,42 @@ paths: summary: 生成基础文字验证码 tags: - 基础文字验证码 + /api/comment/reply: + post: + consumes: + - application/json + description: 提交回复 + parameters: + - description: 回复评论请求 + in: body + name: reply_comment_request + required: true + schema: + $ref: '#/definitions/dto.ReplyCommentRequest' + produces: + - application/json + responses: {} + summary: 提交回复 + tags: + - 评论 + /api/comment/submit: + post: + consumes: + - application/json + description: 提交评论 + parameters: + - description: 评论请求 + in: body + name: comment_request + required: true + schema: + $ref: '#/definitions/dto.CommentRequest' + produces: + - application/json + responses: {} + summary: 提交评论 + tags: + - 评论 /api/oauth/callback_notify: post: description: 微信回调 @@ -595,11 +697,4 @@ paths: summary: 创建websocket服务 tags: - websocket - /api/ws/socket: - get: - description: 创建websocket服务 - responses: {} - summary: 创建websocket服务(gorilla) - tags: - - websocket swagger: "2.0" diff --git a/global/global.go b/global/global.go index 078b00f..8c74d1b 100644 --- a/global/global.go +++ b/global/global.go @@ -9,6 +9,7 @@ import ( "github.com/wenlng/go-captcha/v2/click" "github.com/wenlng/go-captcha/v2/rotate" "github.com/wenlng/go-captcha/v2/slide" + "go.mongodb.org/mongo-driver/mongo" "gorm.io/gorm" "schisandra-cloud-album/config" ) @@ -28,4 +29,5 @@ var ( Wechat *officialAccount.OfficialAccount // 微信公众号 Casbin *casbin.CachedEnforcer // casbin权限管理器 IP2Location *xdb.Searcher // IP地址定位 + MongoDB *mongo.Client ) diff --git a/go.mod b/go.mod index 699e06e..48df6f3 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,13 @@ module schisandra-cloud-album -go 1.22.5 +go 1.23 + +toolchain go1.23.1 require ( - github.com/ArtisanCloud/PowerLibs/v3 v3.2.5 + github.com/ArtisanCloud/PowerLibs/v3 v3.2.6 github.com/ArtisanCloud/PowerWeChat/v3 v3.2.38 - github.com/BurntSushi/toml v1.3.2 + github.com/BurntSushi/toml v1.4.0 github.com/casbin/casbin/v2 v2.98.0 github.com/casbin/gorm-adapter/v3 v3.28.0 github.com/gin-contrib/cors v1.7.2 @@ -13,13 +15,13 @@ require ( github.com/gin-gonic/gin v1.10.0 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 + github.com/google/uuid v1.6.0 github.com/juju/ratelimit v1.0.2 github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20240510055607-89e20ab7b6c6 github.com/lxzan/gws v1.8.5 github.com/mssola/useragent v1.0.0 github.com/pkg6/go-sms v0.1.2 github.com/redis/go-redis/v9 v9.6.1 - github.com/satori/go.uuid v1.2.0 github.com/sirupsen/logrus v1.9.3 github.com/swaggo/files v1.0.1 github.com/swaggo/gin-swagger v1.6.0 @@ -28,8 +30,9 @@ require ( github.com/wenlng/go-captcha/v2 v2.0.0 github.com/wumansgy/goEncrypt v1.1.0 github.com/yitter/idgenerator-go v1.3.3 - golang.org/x/crypto v0.25.0 - golang.org/x/text v0.16.0 + go.mongodb.org/mongo-driver v1.17.0 + golang.org/x/crypto v0.27.0 + golang.org/x/text v0.18.0 gopkg.in/yaml.v3 v3.0.1 gorm.io/driver/mysql v1.5.7 gorm.io/gen v0.3.26 @@ -39,8 +42,8 @@ require ( require ( filippo.io/edwards25519 v1.1.0 // indirect github.com/ArtisanCloud/PowerSocialite/v3 v3.0.7 // indirect - github.com/DanPlayer/randomname v1.0.1 // indirect github.com/KyleBanks/depth v1.2.1 // indirect + github.com/acmestack/gorm-plus v0.1.5 // indirect github.com/bytedance/sonic v1.12.0 // indirect github.com/bytedance/sonic/loader v0.2.0 // indirect github.com/casbin/govaluate v1.2.0 // indirect @@ -66,7 +69,7 @@ require ( github.com/goccy/go-json v0.10.3 // indirect github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect github.com/golang-sql/sqlexp v0.1.0 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/golang/snappy v0.0.4 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect github.com/jackc/pgx/v5 v5.5.5 // indirect @@ -75,7 +78,7 @@ require ( github.com/jinzhu/now v1.1.5 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.17.5 // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/klauspost/cpuid/v2 v2.2.8 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect @@ -83,6 +86,7 @@ require ( github.com/microsoft/go-mssqldb v1.6.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/montanaflynn/stats v0.7.1 // indirect github.com/nicksnyder/go-i18n/v2 v2.4.0 // indirect github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect @@ -91,14 +95,20 @@ require ( github.com/remyoudompheng/bigfft v0.0.0-20230126093431-47fa9a501578 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect + github.com/xdg-go/pbkdf2 v1.0.0 // indirect + github.com/xdg-go/scram v1.1.2 // indirect + github.com/xdg-go/stringprep v1.0.4 // indirect + github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect + go.opentelemetry.io/otel v1.4.0 // indirect + go.opentelemetry.io/otel/trace v1.4.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/arch v0.8.0 // indirect golang.org/x/image v0.18.0 // indirect golang.org/x/mod v0.19.0 // indirect golang.org/x/net v0.27.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.22.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.25.0 // indirect golang.org/x/tools v0.23.0 // indirect google.golang.org/protobuf v1.34.2 // indirect gorm.io/datatypes v1.2.1 // indirect diff --git a/go.sum b/go.sum index de6ff1b..3a628b3 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= -github.com/ArtisanCloud/PowerLibs/v3 v3.2.5 h1:W3NKBTnh4d5RBzondNo++QdZ99HPYs5TQKMH2gngKvk= -github.com/ArtisanCloud/PowerLibs/v3 v3.2.5/go.mod h1:XFRnJA+D0b0IoeSk2ceZzBp9qxatMHOGtWdZCa/r/3U= +github.com/ArtisanCloud/PowerLibs/v3 v3.2.6 h1:xNDXBJ1VNYAEgs4UG/lSygzU66/XG3mTA7mm/qE//NY= +github.com/ArtisanCloud/PowerLibs/v3 v3.2.6/go.mod h1:xFGsskCnzAu+6rFEJbGVAlwhrwZPXAny6m7j71S/B5k= github.com/ArtisanCloud/PowerSocialite/v3 v3.0.7 h1:P+erNlErr+X2v7Et+yTWaTfIRhw+HfpAPdvNIEwk9Gw= github.com/ArtisanCloud/PowerSocialite/v3 v3.0.7/go.mod h1:VZQNCvcK/rldF3QaExiSl1gJEAkyc5/I8RLOd3WFZq4= github.com/ArtisanCloud/PowerWeChat/v3 v3.2.38 h1:f2gDqq4s3FR3wEdaMJM/Cr3gRhSG3usjQhhbM3Tj+eU= @@ -24,12 +24,12 @@ github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0/go.mod h github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= github.com/AzureAD/microsoft-authentication-library-for-go v1.1.0 h1:HCc0+LpPfpCKs6LGGLAhwBARt9632unrVcI6i8s/8os= github.com/AzureAD/microsoft-authentication-library-for-go v1.1.0/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/DanPlayer/randomname v1.0.1 h1:BY7WkgB0gsjESNsqG7NADD5KSlWYAglCiRDKMJ9Q1Zo= -github.com/DanPlayer/randomname v1.0.1/go.mod h1:3baqzjkyc22BGUIAGK+maXF8I6vTcO+XF/tvXaZAU3E= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= +github.com/acmestack/gorm-plus v0.1.5 h1:8FhGeZ1fQpebtT8vgL0Gkt2sJkGjDFitYWnU/Ym2Xwo= +github.com/acmestack/gorm-plus v0.1.5/go.mod h1:qGJTQQkQ7ttaov5lIKLshyGaPdtVvJab0Td8iI08XLA= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= @@ -81,6 +81,10 @@ github.com/glebarez/go-sqlite v1.20.3/go.mod h1:u3N6D/wftiAzIOJtZl6BmedqxmmkDfH3 github.com/glebarez/sqlite v1.7.0 h1:A7Xj/KN2Lvie4Z4rrgQHY8MsbebX3NyWsL3n2i82MVI= github.com/glebarez/sqlite v1.7.0/go.mod h1:PkeevrRlF/1BhQBCnzcMWzgrIk7IOop+qS2jUYLfHhk= github.com/go-bindata/go-bindata v3.1.2+incompatible/go.mod h1:xK8Dsgwmeed+BBsSy2XTopBn/8uK2HWuGSnA11C3Joo= +github.com/go-logr/logr v1.2.2 h1:ahHml/yUpnlb96Rp8HCvtYVPY8ZYpxq3g7UYchIYwbs= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= @@ -115,13 +119,17 @@ github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF0 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= @@ -150,8 +158,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/juju/ratelimit v1.0.2 h1:sRxmtRiajbvrcLQT7S+JbqU0ntsb9W2yhSdNN8tWfaI= github.com/juju/ratelimit v1.0.2/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk= -github.com/klauspost/compress v1.17.5 h1:d4vBd+7CHydUqpFBgUEKkSdtSugf9YFmSkvUYPquI5E= -github.com/klauspost/compress v1.17.5/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= @@ -186,6 +194,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= +github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/mssola/useragent v1.0.0 h1:WRlDpXyxHDNfvZaPEut5Biveq86Ze4o4EMffyMxmH5o= github.com/mssola/useragent v1.0.0/go.mod h1:hz9Cqz4RXusgg1EdI4Al0INR62kP7aPSRNHnpU+b85Y= github.com/nicksnyder/go-i18n/v2 v2.4.0 h1:3IcvPOAvnCKwNm0TB0dLDTuawWEj+ax/RERNC+diLMM= @@ -211,8 +221,6 @@ github.com/remyoudompheng/bigfft v0.0.0-20230126093431-47fa9a501578 h1:VstopitMQ github.com/remyoudompheng/bigfft v0.0.0-20230126093431-47fa9a501578/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= @@ -247,9 +255,25 @@ github.com/wenlng/go-captcha/v2 v2.0.0 h1:7Z4Zy09SIHgvj9e8ZxP4VhYOwg7IHt8kGlVrE5 github.com/wenlng/go-captcha/v2 v2.0.0/go.mod h1:5hac1em3uXoyC5ipZ0xFv9umNM/waQvYAQdr0cx/h34= github.com/wumansgy/goEncrypt v1.1.0 h1:Krr2FJL4GEsMTBvLfsnoTmgWb7rkGnL4siJ9K2cxMs0= github.com/wumansgy/goEncrypt v1.1.0/go.mod h1:dWgF7mi5Ujmt8V5EoyRqjH6XtZ8wmNQyT4u2uvH8Pyg= +github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY= +github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= +github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8= +github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= github.com/yitter/idgenerator-go v1.3.3 h1:i6rzmpbCL0vlmr/tuW5+lSQzNuDG9vYBjIYRvnRcHE8= github.com/yitter/idgenerator-go v1.3.3/go.mod h1:VVjbqFjGUsIkaXVkXEdmx1LiXUL3K1NvyxWPJBPbBpE= +github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM= +github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.mongodb.org/mongo-driver v1.17.0 h1:Hp4q2MCjvY19ViwimTs00wHi7G4yzxh4/2+nTx8r40k= +go.mongodb.org/mongo-driver v1.17.0/go.mod h1:wwWm/+BuOddhcq3n68LKRmgk2wXzmF6s0SFOa0GINL4= +go.opentelemetry.io/otel v1.4.0 h1:7ESuKPq6zpjRaY5nvVDGiuwK7VAJ8MwkKnmNJ9whNZ4= +go.opentelemetry.io/otel v1.4.0/go.mod h1:jeAqMFKy2uLIxCtKxoFj0FAL5zAPKQagc3+GtBWakzk= +go.opentelemetry.io/otel/sdk v1.4.0 h1:LJE4SW3jd4lQTESnlpQZcBhQ3oci0U2MLR5uhicfTHQ= +go.opentelemetry.io/otel/sdk v1.4.0/go.mod h1:71GJPNJh4Qju6zJuYl1CrYtXbrgfau/M9UAggqiy1UE= +go.opentelemetry.io/otel/trace v1.4.0 h1:4OOUrPZdVFQkbzl/JSdvGCWIdw5ONXXxzHlaLlWppmo= +go.opentelemetry.io/otel/trace v1.4.0/go.mod h1:uc3eRsqDfWs9R7b92xbQbU42/eTNz4N+gLP8qJCi4aE= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -265,8 +289,8 @@ golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58 golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= -golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/image v0.16.0/go.mod h1:ugSZItdV4nOxyqp56HmXwH0Ry0nBCpjnZdpDaIHdoPs= golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ= golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E= @@ -291,8 +315,8 @@ golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -307,8 +331,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -318,13 +342,14 @@ golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -333,6 +358,7 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/i18n/language/en.toml b/i18n/language/en.toml index aecaf3f..06108ce 100644 --- a/i18n/language/en.toml +++ b/i18n/language/en.toml @@ -64,4 +64,9 @@ RequestLimit = "request limit!" PermissionVerifyFailed = "permission verify failed!" IllegalRequests = "illegal requests!" RequestParamsNotEmpty = "request params can not be empty!" -TooManyImages = "too many images!" \ No newline at end of file +TooManyImages = "too many images!" +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 diff --git a/i18n/language/zh.toml b/i18n/language/zh.toml index fca3c2a..122ff16 100644 --- a/i18n/language/zh.toml +++ b/i18n/language/zh.toml @@ -64,4 +64,9 @@ RequestLimit = "请求频率过高!" PermissionVerifyFailed = "权限验证失败!" IllegalRequests = "非法请求!" RequestParamsNotEmpty = "请求参数不能为空!" -TooManyImages = "最多只能上传5张图片!" \ No newline at end of file +TooManyImages = "最多只能上传3张图片!" +CommentSubmitFailed = "评论提交失败!" +CommentSubmitSuccess = "评论提交成功!" +ImageStorageError = "图片存储错误!" +ImageDecodeError = "图片解码错误!" +ImageSaveError = "图片保存错误!" \ No newline at end of file diff --git a/main.go b/main.go index 2f7200c..2d08971 100644 --- a/main.go +++ b/main.go @@ -13,6 +13,7 @@ func main() { core.InitConfig() // 读取配置文件 core.InitLogger() // 初始化日志 core.InitGorm() // 初始化数据库 + core.InitMongoDB() // 初始化MongoDB core.InitRedis() // 初始化redis core.InitCaptcha() // 初始化验证码 core.InitIDGenerator() // 初始化ID生成器 diff --git a/model/sca_comment_likes.go b/model/sca_comment_likes.go index 8c5c65f..60bf8e6 100644 --- a/model/sca_comment_likes.go +++ b/model/sca_comment_likes.go @@ -6,7 +6,8 @@ const ScaCommentLikesTableName = "sca_comment_likes" type ScaCommentLikes struct { Id int64 `gorm:"column:id;type:bigint(20);primary_key" json:"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" json:"comment_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 06fb586..9adebfe 100644 --- a/model/sca_comment_reply.go +++ b/model/sca_comment_reply.go @@ -17,21 +17,20 @@ type ScaCommentReply struct { 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"` - Author int `gorm:"column:author;type:int(11);comment:评论回复是否作者 0否 1是" json:"author"` - Likes int64 `gorm:"column:likes;type:bigint(20);comment:点赞数" json:"likes"` - ReplyCount int64 `gorm:"column:reply_count;type:bigint(20);comment:回复数量" json:"reply_count"` - PicUrls string `gorm:"column:pic_urls;type:longtext;comment:图片链接" json:"pic_urls"` + 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"` - Dislikes int64 `gorm:"column:dislikes;type:bigint(20);comment:踩数" json:"dislikes"` + 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"` 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"` - Order int64 `gorm:"column:order;type:bigint(20);comment:评论排序" json:"order"` + CommentOrder int64 `gorm:"column:comment_order;type:bigint(20);default:0;comment:评论排序" json:"comment_order"` } func (comment *ScaCommentReply) TableName() string { diff --git a/router/modules/comment_router.go b/router/modules/comment_router.go index d448257..63aff60 100644 --- a/router/modules/comment_router.go +++ b/router/modules/comment_router.go @@ -9,4 +9,6 @@ var commonApi = api.Api.CommonApi 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) } diff --git a/service/comment_reply_service/comment_reply_service.go b/service/comment_reply_service/comment_reply_service.go index f317cef..c4623cb 100644 --- a/service/comment_reply_service/comment_reply_service.go +++ b/service/comment_reply_service/comment_reply_service.go @@ -12,3 +12,29 @@ func (CommentReplyService) CreateCommentReply(comment *model.ScaCommentReply) er } return nil } + +// GetCommentListOrderByCreatedTimeDesc 通过topic_id获取评论列表 +func (CommentReplyService) GetCommentListOrderByCreatedTimeDesc(topicID uint, page, pageSize int) ([]model.ScaCommentReply, error) { + var comments []model.ScaCommentReply + // 计算偏移量 + offset := (page - 1) * pageSize + + if err := global.DB.Where("topic_id =? and deleted = 0", topicID).Order("created_time desc"). + Offset(offset).Limit(pageSize).Find(&comments).Error; err != nil { + return nil, err + } + return comments, nil +} + +// GetCommentListOrderByLikesDesc 通过topic_id获取评论列表 +func (CommentReplyService) GetCommentListOrderByLikesDesc(topicID uint, page, pageSize int) ([]model.ScaCommentReply, error) { + var comments []model.ScaCommentReply + // 计算偏移量 + offset := (page - 1) * pageSize + + if err := global.DB.Where("topic_id =? and deleted = 0", topicID).Order("likes desc"). + Offset(offset).Limit(pageSize).Find(&comments).Error; err != nil { + return nil, err + } + return comments, nil +} diff --git a/utils/paginator.go b/utils/paginator.go new file mode 100644 index 0000000..7a3d94b --- /dev/null +++ b/utils/paginator.go @@ -0,0 +1,52 @@ +package utils + +import ( + "gorm.io/gorm" +) + +// 标准分页结构体,接收最原始的DO +// 建议在外部再建一个字段一样的结构体,用以将DO转换成DTO或VO +type Page[T any] struct { + CurrentPage int64 `json:"currentPage"` + PageSize int64 `json:"pageSize"` + Total int64 `json:"total"` + Pages int64 `json:"pages"` + Data []T `json:"data"` +} + +// 各种查询条件先在query设置好后再放进来 +func (page *Page[T]) SelectPages(query *gorm.DB) (e error) { + var model T + query.Model(&model).Count(&page.Total) + if page.Total == 0 { + page.Data = []T{} + return + } + e = query.Model(&model).Scopes(Paginate(page)).Find(&page.Data).Error + return +} + +func Paginate[T any](page *Page[T]) func(db *gorm.DB) *gorm.DB { + return func(db *gorm.DB) *gorm.DB { + if page.CurrentPage <= 0 { + page.CurrentPage = 1 + } + switch { + case page.PageSize > 10000: + page.PageSize = 10000 // 限制一下分页大小 + case page.PageSize <= 0: + page.PageSize = 10 + } + page.Pages = page.Total / page.PageSize + if page.Total%page.PageSize != 0 { + page.Pages++ + } + p := page.CurrentPage + if page.CurrentPage > page.Pages { + p = page.Pages + } + size := page.PageSize + offset := int((p - 1) * size) + return db.Offset(offset).Limit(int(size)) + } +}