| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- package model
- import (
- "context"
- "encoding/json"
- "fmt"
- "time"
- "github.com/go-redis/redis/v8"
- "gorm.io/gorm"
- )
- const (
- prefixCommentListKey = "comment:list:%d:%d:%d" // postId:page:pageSize
- prefixCommentKey = "comment:%d" // commentId
- prefixReplyListKey = "reply:list:%d" // commentId
- prefixCommentUpvoteKey = "comment:upvote:%d:%d" // userId:commentId
- )
- // PComment 评论
- type Comment struct {
- *Model
- PostId int64 `json:"post_id" gorm:"post_id"` // POST ID
- UserId int64 `json:"user_id" gorm:"user_id"` // 用户ID
- Ip string `json:"ip" gorm:"ip"` // IP地址
- IpLoc string `json:"ip_loc" gorm:"ip_loc"` // IP城市地址
- Content string `json:"content" gorm:"content"` // 评论内容
- Image string `json:"image" gorm:"image"` // 评论图片
- WithUserIds string `json:"with_user_ids" gorm:"with_user_ids"` // 被艾特的用户
- IsEssence int8 `json:"is_essence" gorm:"is_essence"` // 是否精选
- ReplyCount int64 `json:"reply_count" gorm:"reply_count"` // 回复数
- ThumbsUpCount int64 `json:"thumbs_up_count" gorm:"thumbs_up_count"` // 点赞数
- }
- // TableName 表名称
- func (*Comment) TableName() string {
- return "p_comment"
- }
- type CommentModel struct {
- conn *gorm.DB
- redis *redis.Client
- }
- func NewCommentModel(conn *gorm.DB, rdb *redis.Client) *CommentModel {
- return &CommentModel{
- conn: conn,
- redis: rdb,
- }
- }
- // GetCommentList 获取评论列表(带缓存)
- func (m *CommentModel) GetCommentList(ctx context.Context, postId int64, page, pageSize int) ([]*Comment, error) {
- // 尝试从缓存获取
- key := fmt.Sprintf(prefixCommentListKey, postId, page, pageSize)
- data, err := m.redis.Get(ctx, key).Bytes()
- if err == nil {
- var comments []*Comment
- if err := json.Unmarshal(data, &comments); err == nil {
- return comments, nil
- }
- }
- // 从数据库获取
- var comments []*Comment
- offset := (page - 1) * pageSize
- err = m.conn.WithContext(ctx).
- Where("post_id = ? AND parent_id = 0", postId).
- Order("created_on DESC").
- Offset(offset).
- Limit(pageSize).
- Find(&comments).Error
- if err != nil {
- return nil, err
- }
- // 写入缓存
- if data, err := json.Marshal(comments); err == nil {
- m.redis.Set(ctx, key, data, 5*time.Minute) // 评论列表缓存时间较短
- }
- return comments, nil
- }
- // GetLatestReplies 获取最新的N条回复(带缓存)
- func (m *CommentModel) GetLatestReplies(ctx context.Context, commentId int64, limit int) ([]*Comment, error) {
- // 尝试从缓存获取
- key := fmt.Sprintf(prefixReplyListKey, commentId)
- data, err := m.redis.Get(ctx, key).Bytes()
- if err == nil {
- var replies []*Comment
- if err := json.Unmarshal(data, &replies); err == nil {
- return replies, nil
- }
- }
- // 从数据库获取
- var replies []*Comment
- err = m.conn.WithContext(ctx).
- Where("parent_id = ?", commentId).
- Order("created_on DESC").
- Limit(limit).
- Find(&replies).Error
- if err != nil {
- return nil, err
- }
- // 写入缓存
- if data, err := json.Marshal(replies); err == nil {
- m.redis.Set(ctx, key, data, 5*time.Minute)
- }
- return replies, nil
- }
- // IsCommentUpvotedByUser 检查用户是否点赞了评论/回复(带缓存)
- func (m *CommentModel) IsCommentUpvotedByUser(ctx context.Context, userId, commentId int64) (bool, error) {
- // 尝试从缓存获取
- key := fmt.Sprintf(prefixCommentUpvoteKey, userId, commentId)
- exists, err := m.redis.Exists(ctx, key).Result()
- if err == nil && exists == 1 {
- return m.redis.Get(ctx, key).Bool()
- }
- // 从数据库获取
- var count int64
- err = m.conn.WithContext(ctx).Model(&CommentUpvote{}).
- Where("user_id = ? AND comment_id = ? AND is_del = 0", userId, commentId).
- Count(&count).Error
- if err != nil {
- return false, err
- }
- // 写入缓存
- isUpvoted := count > 0
- m.redis.Set(ctx, key, isUpvoted, cacheExpiry)
- return isUpvoted, nil
- }
- // GetReplyList 获取回复列表(带缓存)
- func (m *CommentModel) GetReplyList(ctx context.Context, commentId int64, page, pageSize int) ([]*Comment, error) {
- // 尝试从缓存获取
- key := fmt.Sprintf(prefixReplyListKey+":%d:%d", commentId, page, pageSize)
- data, err := m.redis.Get(ctx, key).Bytes()
- if err == nil {
- var replies []*Comment
- if err := json.Unmarshal(data, &replies); err == nil {
- return replies, nil
- }
- }
- // 从数据库获取
- var replies []*Comment
- offset := (page - 1) * pageSize
- err = m.conn.WithContext(ctx).
- Where("parent_id = ?", commentId).
- Order("created_on DESC").
- Offset(offset).
- Limit(pageSize).
- Find(&replies).Error
- if err != nil {
- return nil, err
- }
- // 写入缓存
- if data, err := json.Marshal(replies); err == nil {
- m.redis.Set(ctx, key, data, 5*time.Minute) // 回复列表缓存时间较短
- }
- return replies, nil
- }
- // Create 创建评论
- func (m *CommentModel) Create(ctx context.Context, comment *Comment) error {
- err := m.conn.WithContext(ctx).Create(comment).Error
- if err != nil {
- return err
- }
- // 删除相关缓存
- m.ClearCommentListCache(ctx, comment.PostId)
- return nil
- }
- // ClearCommentListCache 清除评论列表缓存
- func (m *CommentModel) ClearCommentListCache(ctx context.Context, postId int64) error {
- // 清除评论列表缓存
- pattern := fmt.Sprintf("comment:list:%d*", postId)
- keys, err := m.redis.Keys(ctx, pattern).Result()
- if err != nil {
- return err
- }
- if len(keys) > 0 {
- m.redis.Del(ctx, keys...)
- }
- // 清除回复列表缓存
- pattern = fmt.Sprintf(prefixReplyListKey+"*", postId)
- keys, err = m.redis.Keys(ctx, pattern).Result()
- if err != nil {
- return err
- }
- if len(keys) > 0 {
- m.redis.Del(ctx, keys...)
- }
- return nil
- }
- // IncrementUpvoteCount 增加点赞数
- func (m *CommentModel) IncrementUpvoteCount(ctx context.Context, commentId int64, increment int) error {
- err := m.conn.WithContext(ctx).Model(&Comment{}).
- Where("id = ?", commentId).
- UpdateColumn("thumbs_up_count", gorm.Expr("thumbs_up_count + ?", increment)).Error
- if err != nil {
- return err
- }
- // 删除评论缓存
- key := fmt.Sprintf(prefixCommentKey, commentId)
- m.redis.Del(ctx, key)
- return nil
- }
- // CreateCommentUpvote 创建评论点赞记录
- func (m *CommentModel) CreateCommentUpvote(ctx context.Context, upvote *CommentUpvote) error {
- err := m.conn.WithContext(ctx).Create(upvote).Error
- if err != nil {
- return err
- }
- // 删除点赞状态缓存
- key := fmt.Sprintf(prefixCommentUpvoteKey, upvote.UserId, upvote.CommentId)
- m.redis.Del(ctx, key)
- return nil
- }
- // DeleteCommentUpvote 删除评论点赞记录
- func (m *CommentModel) DeleteCommentUpvote(ctx context.Context, userId, commentId int64) error {
- err := m.conn.WithContext(ctx).Model(&CommentUpvote{}).
- Where("user_id = ? AND comment_id = ?", userId, commentId).
- Update("is_del", 1).Error
- if err != nil {
- return err
- }
- // 删除点赞状态缓存
- key := fmt.Sprintf(prefixCommentUpvoteKey, userId, commentId)
- m.redis.Del(ctx, key)
- return nil
- }
- // 获取评论
- func (m *CommentModel) GetComment(ctx context.Context, commentId int64) (*Comment, error) {
- var comment Comment
- err := m.conn.WithContext(ctx).Where("id = ?", commentId).First(&comment).Error
- if err != nil {
- return nil, err
- }
- return &comment, nil
- }
- // IncrementReplyCount 增加回复数
- func (m *CommentModel) IncrementReplyCount(ctx context.Context, commentId int64, increment int) error {
- err := m.conn.WithContext(ctx).Model(&Comment{}).
- Where("id = ?", commentId).
- UpdateColumn("reply_count", gorm.Expr("reply_count + ?", increment)).Error
- if err != nil {
- return err
- }
- // 删除评论缓存
- key := fmt.Sprintf(prefixCommentKey, commentId)
- m.redis.Del(ctx, key)
- return nil
- }
- // Delete 删除评论
- func (m *CommentModel) Delete(ctx context.Context, commentId int64) error {
- return m.conn.WithContext(ctx).Model(&Comment{}).
- Where("id = ?", commentId).
- Updates(map[string]interface{}{
- "is_del": 1,
- "deleted_on": time.Now().Unix(),
- "modified_on": time.Now().Unix(),
- }).Error
- }
|