feat(post): implement share recording functionality
All checks were successful
Build Backend / build (push) Successful in 13m16s
Build Backend / build-docker (push) Successful in 1m4s

- 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.
This commit is contained in:
lafay
2026-03-24 05:21:36 +08:00
parent 176cd20847
commit 15f0f1605e
4 changed files with 79 additions and 0 deletions

View File

@@ -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) {
// 检查是否使用游标分页

View File

@@ -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

View File

@@ -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)

View File

@@ -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)