createpostlogic.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. package logic
  2. import (
  3. "context"
  4. "slowwild/internal/svc"
  5. "strings"
  6. "git.banshen.xyz/huangguangrong/slow_wild_protobuff/slowwild/slowwildserver"
  7. "slowwild/internal/errorx"
  8. "slowwild/internal/model"
  9. "time"
  10. "slowwild/internal/utils"
  11. "github.com/spf13/cast"
  12. "github.com/zeromicro/go-zero/core/logx"
  13. "gorm.io/gorm"
  14. )
  15. type CreatePostLogic struct {
  16. ctx context.Context
  17. svcCtx *svc.ServiceContext
  18. logx.Logger
  19. }
  20. func NewCreatePostLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreatePostLogic {
  21. return &CreatePostLogic{
  22. ctx: ctx,
  23. svcCtx: svcCtx,
  24. Logger: logx.WithContext(ctx),
  25. }
  26. }
  27. // 发布帖子
  28. func (l *CreatePostLogic) CreatePost(in *slowwildserver.CreatePostReq) (*slowwildserver.CreatePostRsp, error) {
  29. if in.UserId <= 0 || in.Content == "" {
  30. return nil, errorx.ErrInvalidParam
  31. }
  32. // 检查帖子类型是否合法
  33. if in.Type != 0 && in.Type != 1 {
  34. return nil, errorx.NewCodeError(20001, "帖子类型不合法")
  35. }
  36. // 开启事务
  37. err := l.svcCtx.UserModel.Transaction(l.ctx, func(tx *gorm.DB) error {
  38. postModel := model.NewPostModel(tx, l.svcCtx.Redis)
  39. postContentModel := model.NewPostContentModel(tx)
  40. userModel := model.NewUserModel(tx)
  41. tagModel := model.NewTagModel(tx, l.svcCtx.Redis)
  42. messageModel := model.NewMessageModel(tx)
  43. // 提取话题名称
  44. var tagNames []string
  45. for _, tag := range in.Tags {
  46. tagNames = append(tagNames, tag.Name)
  47. }
  48. // 检查话题是否存在
  49. existingTags, err := tagModel.FindByNames(l.ctx, tagNames)
  50. if err != nil {
  51. return err
  52. }
  53. // 找出不存在的话题名称
  54. existingTagMap := make(map[string]bool)
  55. for _, tag := range existingTags {
  56. existingTagMap[tag.Name] = true
  57. }
  58. // 需要新建的话题
  59. var newTags []*model.Tag
  60. for _, tag := range in.Tags {
  61. if !existingTagMap[tag.Name] {
  62. newTags = append(newTags, &model.Tag{
  63. Model: &model.Model{
  64. CreatedOn: time.Now().Unix(),
  65. ModifiedOn: time.Now().Unix(),
  66. },
  67. UserId: in.UserId,
  68. Name: tag.Name,
  69. HotNum: 0,
  70. })
  71. }
  72. }
  73. // 创建新话题
  74. if len(newTags) > 0 {
  75. if err = tagModel.BatchCreate(l.ctx, newTags); err != nil {
  76. return err
  77. }
  78. }
  79. // 获取所有话题的ID
  80. var tagIds []int64
  81. for _, tag := range existingTags {
  82. tagIds = append(tagIds, tag.ID)
  83. }
  84. for _, tag := range newTags {
  85. tagIds = append(tagIds, tag.ID)
  86. }
  87. // 判断@用户是否重复,重复只发一次
  88. existUserMap := make(map[string]bool)
  89. if len(in.AtUserIds) > 0 {
  90. for _, id := range in.AtUserIds {
  91. existUserMap[cast.ToString(id)] = true
  92. }
  93. }
  94. atUserIds := make([]string, 0, len(existUserMap))
  95. if len(existUserMap) > 0 {
  96. for id := range existUserMap {
  97. atUserIds = append(atUserIds, id)
  98. }
  99. }
  100. // 创建帖子
  101. post := &model.Post{
  102. Model: &model.Model{
  103. CreatedOn: time.Now().Unix(),
  104. ModifiedOn: time.Now().Unix(),
  105. },
  106. UserId: in.UserId,
  107. PostType: in.Type,
  108. Visibility: int8(in.Visibility),
  109. Tags: strings.Join(tagNames, ","),
  110. Ip: in.Ip,
  111. IpLoc: in.IpLoc,
  112. WithUserIds: strings.Join(atUserIds, ","),
  113. CommentCount: 0,
  114. CollectionCount: 0,
  115. UpvoteCount: 0,
  116. ShareCount: 0,
  117. IsTop: 0,
  118. IsEssence: 0,
  119. HotNum: 0,
  120. }
  121. // 创建帖子基本信息
  122. if err := postModel.Create(l.ctx, post); err != nil {
  123. return err
  124. }
  125. // 处理内容,生成摘要
  126. plainContent := utils.StripHTML(in.Content)
  127. contentSummary := utils.TruncateText(plainContent, 1000)
  128. // 创建帖子内容
  129. postContent := &model.PostContent{
  130. Model: &model.Model{
  131. CreatedOn: time.Now().Unix(),
  132. ModifiedOn: time.Now().Unix(),
  133. },
  134. PostId: post.ID,
  135. UserId: in.UserId,
  136. Title: in.Title,
  137. Content: in.Content, // 保存原始内容
  138. ContentSummary: contentSummary, // 保存处理后的摘要
  139. PostVideoCover: in.VideoCover,
  140. PostCovers: strings.Join(in.Images, ","),
  141. PostVideoUrl: in.VideoUrl,
  142. Sort: 0,
  143. }
  144. if err := postContentModel.Create(l.ctx, postContent); err != nil {
  145. return err
  146. }
  147. // 创建帖子和话题的关联关系
  148. if err := tagModel.CreateTagWithPost(l.ctx, post.ID, tagIds); err != nil {
  149. return err
  150. }
  151. // 检查被艾特的用户是否存在
  152. if len(atUserIds) > 0 {
  153. atUsers, err := userModel.FindByIds(l.ctx, in.AtUserIds)
  154. if err != nil {
  155. return err
  156. }
  157. // 发送站内信给被艾特的用户
  158. for _, user := range atUsers {
  159. err = messageModel.SendNotification(l.ctx, in.UserId, user.ID, 1, "你被艾特了", "你被艾特在一条动态中", post.ID, 0, 0)
  160. if err != nil {
  161. return err
  162. }
  163. }
  164. }
  165. // 增加用户的帖子数
  166. if err := userModel.IncrementTweetCount(l.ctx, in.UserId); err != nil {
  167. return err
  168. }
  169. // 删除缓存
  170. postModel.ClearListCache(l.ctx)
  171. return nil
  172. })
  173. if err != nil {
  174. l.Logger.Errorf("发布帖子失败: %v", err)
  175. return nil, errorx.NewCodeError(20002, "发布帖子失败")
  176. }
  177. return &slowwildserver.CreatePostRsp{}, nil
  178. }