Files
jiang13-bbs/backend/service/favorite.go
freefire d7c6b3a961 feat: 帖子收藏与用户关注
- 新增收藏功能:favorite 服务与 handler、FavoriteButton 组件
- 新增关注功能:follow 服务与 handler、FollowButton 组件
- 用户主页适配关注/粉丝与收藏展示
- flash 消息工具、广告与侧边栏组件微调
2026-09-26 03:02:40 +08:00

105 lines
3.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
}