Files
backend_v2/internal/service/favorite_service.go
toom1996 1fd9c48f58 update
2026-09-02 21:51:35 +08:00

103 lines
3.0 KiB
Go

package service
import (
"context"
"time"
"fashionapi/internal/dto"
"fashionapi/internal/model"
"fashionapi/internal/repository"
)
// FavoriteService 收藏业务接口。所有方法均要求调用方已通过中间件解析出 userID。
type FavoriteService interface {
// ListPaged 分页取当前用户收藏(服务端分页,与收藏总量解耦)。
ListPaged(ctx context.Context, userID uint32, page, perPage int) ([]dto.FavoriteItem, int64, error)
// Add 新增收藏(幂等)。
Add(ctx context.Context, userID uint32, req dto.FavoriteAdd) (*dto.FavoriteItem, error)
// Remove 删除收藏。
Remove(ctx context.Context, userID uint32, targetUID string) error
// Check 返回给定 ids 中已收藏的子集(列表页打勾用)。
Check(ctx context.Context, userID uint32, ids []string) ([]string, error)
}
type favoriteService struct {
favs repository.FavoriteRepository
}
// NewFavoriteService 创建收藏服务。
func NewFavoriteService(favs repository.FavoriteRepository) FavoriteService {
return &favoriteService{favs: favs}
}
func (s *favoriteService) ListPaged(ctx context.Context, userID uint32, page, perPage int) ([]dto.FavoriteItem, int64, error) {
rows, err := s.favs.ListPaged(ctx, userID, page, perPage)
if err != nil {
return nil, 0, internalErr(err.Error())
}
total, err := s.favs.CountByUser(ctx, userID)
if err != nil {
return nil, 0, internalErr(err.Error())
}
out := make([]dto.FavoriteItem, 0, len(rows))
for _, r := range rows {
out = append(out, toFavoriteItem(r))
}
return out, total, nil
}
func (s *favoriteService) Add(ctx context.Context, userID uint32, req dto.FavoriteAdd) (*dto.FavoriteItem, error) {
if req.TargetType != "runway" && req.TargetType != "street" {
return nil, badRequest("invalid target_type")
}
if req.TargetUID == "" {
return nil, badRequest("target_uid required")
}
row := &model.Favorite{
UserID: userID,
TargetType: req.TargetType,
TargetUID: req.TargetUID,
Title: req.Title,
Cover: req.Cover,
Brand: req.Brand,
CreatedAt: uint32(time.Now().Unix()),
}
if err := s.favs.Add(ctx, row); err != nil {
return nil, internalErr(err.Error())
}
item := toFavoriteItem(*row)
return &item, nil
}
func (s *favoriteService) Remove(ctx context.Context, userID uint32, targetUID string) error {
if targetUID == "" {
return badRequest("target_uid required")
}
if err := s.favs.Remove(ctx, userID, targetUID); err != nil {
return internalErr(err.Error())
}
return nil
}
func (s *favoriteService) Check(ctx context.Context, userID uint32, ids []string) ([]string, error) {
if len(ids) == 0 {
return []string{}, nil
}
got, err := s.favs.FilterExisting(ctx, userID, ids)
if err != nil {
return nil, internalErr(err.Error())
}
return got, nil
}
func toFavoriteItem(r model.Favorite) dto.FavoriteItem {
return dto.FavoriteItem{
ID: r.TargetUID,
Type: r.TargetType,
Title: r.Title,
Cover: r.Cover,
Brand: r.Brand,
AddedAt: r.CreatedAt,
}
}