refactor:优化了like和unlike功能

This commit is contained in:
Leon
2025-12-23 02:20:08 +08:00
parent de732abeb1
commit b0a7c85a8d
3 changed files with 38 additions and 84 deletions

View File

@@ -89,21 +89,3 @@ func (lh *LikeHandler) IsLiked(c *gin.Context) {
}
c.JSON(200, gin.H{"is_liked": isLiked})
}
func (lh *LikeHandler) GetLikesCount(c *gin.Context) {
var req LikeRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
if req.VideoID <= 0 {
c.JSON(400, gin.H{"error": "video_id is required"})
return
}
likesCount, err := lh.service.GetLikesCount(c.Request.Context(), req.VideoID)
if err != nil {
c.JSON(500, gin.H{"error": err.Error()})
return
}
c.JSON(200, gin.H{"likes_count": likesCount})
}

View File

@@ -34,14 +34,3 @@ func (r *LikeRepository) IsLiked(ctx context.Context, videoID, accountID uint) (
}
return count > 0, nil
}
func (r *LikeRepository) GetLikesCount(ctx context.Context, videoID uint) (int64, error) {
var count int64
err := r.db.WithContext(ctx).Model(&Like{}).
Where("video_id = ?", videoID).
Count(&count).Error
if err != nil {
return 0, err
}
return count, nil
}

View File

@@ -4,6 +4,9 @@ import (
"context"
"errors"
"time"
"github.com/go-sql-driver/mysql"
"gorm.io/gorm"
)
type LikeService struct {
@@ -15,69 +18,49 @@ func NewLikeService(repo *LikeRepository, videoRepo *VideoRepository) *LikeServi
return &LikeService{repo: repo, VideoRepo: videoRepo}
}
func (s *LikeService) Like(ctx context.Context, like *Like) error {
exists, err := s.VideoRepo.IsExist(ctx, like.VideoID)
if err != nil {
return err
}
if !exists {
return errors.New("video not found")
}
func isDupKey(err error) bool {
var me *mysql.MySQLError
return errors.As(err, &me) && me.Number == 1062
}
isLiked, err := s.IsLiked(ctx, like.VideoID, like.AccountID)
if err != nil {
return err
}
if isLiked {
return errors.New("user has liked this video")
}
func (s *LikeService) Like(ctx context.Context, like *Like) error {
like.CreatedAt = time.Now()
if err := s.repo.Like(ctx, like); err != nil {
return err
}
likesCount, err := s.GetLikesCount(ctx, like.VideoID)
if err != nil {
return err
}
if err := s.VideoRepo.UpdateLikesCount(ctx, like.VideoID, likesCount); err != nil {
return err
}
return nil
return s.repo.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
if err := tx.Select("id").First(&Video{}, like.VideoID).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return errors.New("video not found")
}
return err
}
if err := tx.Create(like).Error; err != nil {
if isDupKey(err) {
return errors.New("user has liked this video")
}
return err
}
if err := tx.Model(&Video{}).Where("id = ?", like.VideoID).
UpdateColumn("likes_count", gorm.Expr("likes_count + 1")).Error; err != nil {
return err
}
return nil
})
}
func (s *LikeService) Unlike(ctx context.Context, like *Like) error {
exists, err := s.VideoRepo.IsExist(ctx, like.VideoID)
if err != nil {
return err
}
if !exists {
return errors.New("video not found")
}
return s.repo.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
del := tx.Where("video_id = ? AND account_id = ?", like.VideoID, like.AccountID).Delete(&Like{})
if del.Error != nil {
return del.Error
}
if del.RowsAffected == 0 {
return errors.New("user has not liked this video")
}
isLiked, err := s.IsLiked(ctx, like.VideoID, like.AccountID)
if err != nil {
return err
}
if !isLiked {
return errors.New("user has not liked this video")
}
if err := s.repo.Unlike(ctx, like); err != nil {
return err
}
likesCount, err := s.GetLikesCount(ctx, like.VideoID)
if err != nil {
return err
}
if err := s.VideoRepo.UpdateLikesCount(ctx, like.VideoID, likesCount); err != nil {
return err
}
return nil
return tx.Model(&Video{}).Where("id = ?", like.VideoID).
UpdateColumn("likes_count", gorm.Expr("GREATEST(likes_count - 1, 0)")).Error
})
}
func (s *LikeService) IsLiked(ctx context.Context, videoID, accountID uint) (bool, error) {
return s.repo.IsLiked(ctx, videoID, accountID)
}
func (s *LikeService) GetLikesCount(ctx context.Context, videoID uint) (int64, error) {
return s.repo.GetLikesCount(ctx, videoID)
}