From 15f0f1605e41792dd71797220be59e2a25671b42 Mon Sep 17 00:00:00 2001 From: lafay <2021211506@stu.hit.edu.cn> Date: Tue, 24 Mar 2026 05:21:36 +0800 Subject: [PATCH] feat(post): implement share recording functionality - Added RecordShare method in PostHandler to handle sharing posts and increment share count. - Introduced IncrementShares method in PostRepository to update shares_count for published posts. - Updated PostService to include RecordShare, ensuring cache invalidation for post details and lists. - Integrated new share route in the router for handling share requests. --- internal/handler/post_handler.go | 36 ++++++++++++++++++++++++++++++++ internal/repository/post_repo.go | 26 +++++++++++++++++++++++ internal/router/router.go | 2 ++ internal/service/post_service.go | 15 +++++++++++++ 4 files changed, 79 insertions(+) diff --git a/internal/handler/post_handler.go b/internal/handler/post_handler.go index 4249e5b..470c482 100644 --- a/internal/handler/post_handler.go +++ b/internal/handler/post_handler.go @@ -6,6 +6,7 @@ import ( "strconv" "github.com/gin-gonic/gin" + "gorm.io/gorm" "carrot_bbs/internal/dto" "carrot_bbs/internal/model" @@ -145,6 +146,41 @@ func (h *PostHandler) RecordView(c *gin.Context) { response.Success(c, gin.H{"success": true}) } +// RecordShare 记录帖子分享(shares_count +1,仅已发布) +// 支持可选 JSON:{"channel":"wechat"|"qq"|"copy_link"|"system"|...},用于后续统计 +func (h *PostHandler) RecordShare(c *gin.Context) { + id := c.Param("id") + _ = c.GetString("user_id") // 预留:登录用户维度统计 + + type shareBody struct { + Channel string `json:"channel"` + } + var body shareBody + if c.Request.ContentLength > 0 { + if err := c.ShouldBindJSON(&body); err != nil { + response.BadRequest(c, "invalid json body") + return + } + } + + sharesCount, err := h.postService.RecordShare(c.Request.Context(), id, c.GetString("user_id")) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + response.NotFound(c, "post not found") + return + } + fmt.Printf("[ERROR] RecordShare post %s: %v\n", id, err) + response.InternalServerError(c, "failed to record share") + return + } + + data := gin.H{"success": true, "shares_count": sharesCount} + if body.Channel != "" { + data["channel"] = body.Channel + } + response.Success(c, data) +} + // List 获取帖子列表(支持游标分页和偏移分页) func (h *PostHandler) List(c *gin.Context) { // 检查是否使用游标分页 diff --git a/internal/repository/post_repo.go b/internal/repository/post_repo.go index 23743ec..d0d267a 100644 --- a/internal/repository/post_repo.go +++ b/internal/repository/post_repo.go @@ -413,6 +413,32 @@ func (r *PostRepository) IncrementViews(postID string) error { }).Error } +// IncrementShares 已发布帖子分享次数 +1,返回新的 shares_count;非已发布或不存在返回 gorm.ErrRecordNotFound +func (r *PostRepository) IncrementShares(postID string) (int, error) { + var newCount int + err := r.db.Transaction(func(tx *gorm.DB) error { + res := tx.Model(&model.Post{}). + Where("id = ? AND status = ?", postID, model.PostStatusPublished). + Updates(map[string]interface{}{ + "shares_count": gorm.Expr("shares_count + 1"), + "updated_at": gorm.Expr("updated_at"), + }) + if res.Error != nil { + return res.Error + } + if res.RowsAffected == 0 { + return gorm.ErrRecordNotFound + } + var p model.Post + if err := tx.Select("shares_count").Where("id = ?", postID).First(&p).Error; err != nil { + return err + } + newCount = p.SharesCount + return nil + }) + return newCount, err +} + // Search 搜索帖子 func (r *PostRepository) Search(keyword string, page, pageSize int) ([]*model.Post, int64, error) { var posts []*model.Post diff --git a/internal/router/router.go b/internal/router/router.go index 103a13c..17ef342 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -220,6 +220,8 @@ func (r *Router) setupRoutes() { // 浏览量记录(可选认证,允许游客浏览) posts.POST("/:id/view", middleware.OptionalAuth(r.jwtService), r.postHandler.RecordView) + // 分享计数(可选认证;仅已发布帖子生效) + posts.POST("/:id/share", middleware.OptionalAuth(r.jwtService), r.postHandler.RecordShare) // 点赞 posts.POST("/:id/like", authMiddleware, r.postHandler.Like) diff --git a/internal/service/post_service.go b/internal/service/post_service.go index ed81d10..be121f8 100644 --- a/internal/service/post_service.go +++ b/internal/service/post_service.go @@ -64,6 +64,8 @@ type PostService interface { // 其他 IncrementViews(ctx context.Context, postID, userID string) error + // RecordShare 记录分享(仅已发布帖子计数 +1),返回最新 shares_count + RecordShare(ctx context.Context, postID, userID string) (sharesCount int, err error) // 日志服务设置 SetLogService(logService *LogService) @@ -492,6 +494,19 @@ func (s *postServiceImpl) IncrementViews(ctx context.Context, postID, userID str return nil } +// RecordShare 记录分享:仅已发布帖子增加 shares_count,并失效帖子详情与列表缓存 +func (s *postServiceImpl) RecordShare(ctx context.Context, postID, userID string) (int, error) { + n, err := s.postRepo.IncrementShares(postID) + if err != nil { + return 0, err + } + if s.cache != nil { + cache.InvalidatePostDetail(s.cache, postID) + cache.InvalidatePostList(s.cache) + } + return n, nil +} + // GetFavorites 获取收藏列表 func (s *postServiceImpl) GetFavorites(ctx context.Context, userID string, page, pageSize int) ([]*model.Post, int64, error) { return s.postRepo.GetFavorites(userID, page, pageSize)