package service import ( "errors" "github.com/freefire/jiang13-bbs/model" "gorm.io/gorm" ) // FavoriteService 收藏服务:收藏公开可见,公开列表只出 published 帖 type FavoriteService struct { db *gorm.DB posts *PostService } func NewFavoriteService(db *gorm.DB) *FavoriteService { return &FavoriteService{db: db} } // WithPosts 注入帖子服务(列表复用 PostListItem 组装与最后回复填充) func (s *FavoriteService) WithPosts(p *PostService) *FavoriteService { s.posts = p return s } // Toggle 切换收藏状态:已收藏则取消,未收藏则收藏。返回 (favorited, error) func (s *FavoriteService) Toggle(postID, userID uint) (bool, error) { var post model.Post if err := s.db.First(&post, postID).Error; err != nil { return false, errors.New("帖子不存在") } var fav model.Favorite err := s.db.Where("post_id = ? AND user_id = ?", postID, userID).First(&fav).Error if err == nil { if err := s.db.Delete(&fav).Error; err != nil { return true, err } return false, nil } if !errors.Is(err, gorm.ErrRecordNotFound) { return false, err } if err := s.db.Create(&model.Favorite{PostID: postID, UserID: userID}).Error; err != nil { return false, err } return true, nil } // HasFavorited 判断用户是否已收藏某帖子 func (s *FavoriteService) HasFavorited(postID, userID uint) bool { var count int64 s.db.Model(&model.Favorite{}).Where("post_id = ? AND user_id = ?", postID, userID).Count(&count) return count > 0 } // BatchHasFavorited 批量查询用户对多个帖子的收藏状态,返回 postID -> bool func (s *FavoriteService) BatchHasFavorited(postIDs []uint, userID uint) map[uint]bool { result := make(map[uint]bool) if len(postIDs) == 0 || userID == 0 { return result } var favs []model.Favorite s.db.Where("post_id IN ? AND user_id = ?", postIDs, userID).Find(&favs) for _, f := range favs { result[f.PostID] = true } return result } // List 用户收藏的帖子列表(公开可见,仅 published;按收藏时间倒序) func (s *FavoriteService) List(userID uint, page, size int) ([]PostListItem, int64, error) { if page < 1 { page = 1 } if size < 1 || size > 50 { size = 20 } query := s.db.Model(&model.Post{}). Joins("JOIN favorites ON favorites.post_id = posts.id"). Where("favorites.user_id = ? AND posts.status = ?", userID, model.ContentStatusPublished) var total int64 if err := query.Count(&total).Error; err != nil { return nil, 0, err } var posts []model.Post offset := (page - 1) * size if err := query.Select("posts.*").Order("favorites.created_at DESC").Offset(offset).Limit(size). Preload("Board").Preload("User").Preload("User.Badges.Badge").Find(&posts).Error; err != nil { return nil, 0, err } items := toPostListItems(posts) if s.posts != nil { s.posts.fillLastReply(items) } return items, total, nil } // CountByUser 用户收藏数量 func (s *FavoriteService) CountByUser(userID uint) int64 { var count int64 s.db.Model(&model.Favorite{}).Where("user_id = ?", userID).Count(&count) return count }