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.
This commit is contained in:
@@ -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) {
|
||||
// 检查是否使用游标分页
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user