post_action_model.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. package model
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "strings"
  7. "time"
  8. "github.com/go-redis/redis/v8"
  9. "gorm.io/gorm"
  10. )
  11. // PPostAction 冒泡/文章动作
  12. type PostAction struct {
  13. *Model
  14. PostId int64 `json:"post_id" gorm:"post_id"` // POST ID
  15. UserId int64 `json:"user_id" gorm:"user_id"` // 用户ID
  16. ActionType int8 `json:"action_type" gorm:"action_type"` // 对帖子的动作0-点赞1-收藏2-分享
  17. }
  18. // TableName 表名称
  19. func (*PostAction) TableName() string {
  20. return "p_post_action"
  21. }
  22. // MessageModel 消息模型
  23. type PostActionModel struct {
  24. conn *gorm.DB
  25. redis *redis.Client
  26. }
  27. func NewPostActionModel(conn *gorm.DB, rConn *redis.Client) *PostActionModel {
  28. return &PostActionModel{
  29. conn: conn,
  30. redis: rConn,
  31. }
  32. }
  33. func (p *PostActionModel) CreatePostAction(c context.Context, data *PostAction) error {
  34. return p.conn.WithContext(c).Create(data).Error
  35. }
  36. func (p *PostActionModel) DeletePostAction(c context.Context, data *PostAction) error {
  37. return p.conn.WithContext(c).Updates(data).Error
  38. }
  39. // CheckPostAction 检查用户是否对帖子执行过某个动作
  40. func (p *PostActionModel) CheckPostAction(ctx context.Context, userId, postId int64, actionType int8) (bool, error) {
  41. var count int64
  42. err := p.conn.WithContext(ctx).Model(&PostAction{}).
  43. Where("user_id = ? AND post_id = ? AND action_type = ? AND is_del = 0", userId, postId, actionType).
  44. Count(&count).Error
  45. if err != nil {
  46. return false, err
  47. }
  48. return count > 0, nil
  49. }
  50. const (
  51. prefixUserCollectionKey = "user:collection:%d:%d:%d" // userId:page:pageSize
  52. )
  53. // GetUserCollectionPosts 获取用户收藏的帖子列表(带缓存)
  54. func (p *PostActionModel) GetUserCollectionPosts(ctx context.Context, userId int64, page, pageSize int) ([]*Post, int64, error) {
  55. // 尝试从缓存获取
  56. key := fmt.Sprintf(prefixUserCollectionKey, userId, page, pageSize)
  57. data, err := p.redis.Get(ctx, key).Bytes()
  58. if err == nil {
  59. var cacheData struct {
  60. Posts []*Post
  61. Total int64
  62. }
  63. if err := json.Unmarshal(data, &cacheData); err == nil {
  64. return cacheData.Posts, cacheData.Total, nil
  65. }
  66. }
  67. // 从数据库获取
  68. var posts []*Post
  69. var total int64
  70. // 获取收藏总数
  71. err = p.conn.Model(&PostAction{}).
  72. Where("user_id = ? AND action_type = ? AND is_del = 0", userId, 1). // 1表示收藏动作
  73. Count(&total).Error
  74. if err != nil {
  75. return nil, 0, err
  76. }
  77. // 获取收藏的帖子列表
  78. offset := (page - 1) * pageSize
  79. err = p.conn.Table("p_post_action pa").
  80. Select("p.*").
  81. Joins("LEFT JOIN p_post p ON p.id = pa.post_id").
  82. Where("pa.user_id = ? AND pa.action_type = ? AND pa.is_del = 0 AND p.is_del = 0", userId, 1).
  83. Order("pa.created_on DESC").
  84. Offset(offset).
  85. Limit(pageSize).
  86. Find(&posts).Error
  87. if err != nil {
  88. return nil, 0, err
  89. }
  90. // 写入缓存
  91. cacheData := struct {
  92. Posts []*Post
  93. Total int64
  94. }{
  95. Posts: posts,
  96. Total: total,
  97. }
  98. if data, err := json.Marshal(cacheData); err == nil {
  99. p.redis.Set(ctx, key, data, 5*time.Minute)
  100. }
  101. return posts, total, nil
  102. }
  103. // ClearUserCollectionCache 清除用户收藏列表缓存
  104. func (p *PostActionModel) ClearUserCollectionCache(ctx context.Context, userId int64) {
  105. pattern := fmt.Sprintf(prefixUserCollectionKey[:strings.LastIndex(prefixUserCollectionKey, ":")]+"*", userId)
  106. keys, err := p.redis.Keys(ctx, pattern).Result()
  107. if err != nil {
  108. return
  109. }
  110. if len(keys) > 0 {
  111. p.redis.Del(ctx, keys...)
  112. }
  113. }