bugfix
This commit is contained in:
@@ -22,6 +22,9 @@ type OutfitService struct {
|
||||
outfitItemDao *mysqldao.OutfitItemDao
|
||||
clothesDao *mysqldao.ClothesDao
|
||||
auditLogDao *mysqldao.OutfitAuditLogDao
|
||||
userDao *mysqldao.UserDao
|
||||
likeDao *mysqldao.LikeDao
|
||||
collectDao *mysqldao.CollectDao
|
||||
}
|
||||
|
||||
// NewOutfitService 创建穿搭服务。
|
||||
@@ -31,6 +34,9 @@ func NewOutfitService() *OutfitService {
|
||||
outfitItemDao: mysqldao.NewOutfitItemDao(),
|
||||
clothesDao: mysqldao.NewClothesDao(),
|
||||
auditLogDao: mysqldao.NewOutfitAuditLogDao(),
|
||||
userDao: mysqldao.NewUserDao(),
|
||||
likeDao: mysqldao.NewLikeDao(),
|
||||
collectDao: mysqldao.NewCollectDao(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,6 +181,30 @@ func (s *OutfitService) List(ctx context.Context, userID int64, request *dto.Out
|
||||
}, nil
|
||||
}
|
||||
|
||||
// CommunityList 分页查询社区穿搭:其他用户「公开 + 审核通过 + 状态正常」的穿搭,
|
||||
// 聚合作者信息与点赞/收藏计数后一次性下发(批量查询,避免 N+1)。
|
||||
func (s *OutfitService) CommunityList(ctx context.Context, userID int64, request *dto.OutfitCommunityListRequest) (*dto.OutfitCommunityListResponse, *errcode.Error) {
|
||||
ctx, span := global.Tracer.Start(ctx, "svc.OutfitCommunityList")
|
||||
defer span.End()
|
||||
|
||||
page, pageSize := normalizePage(request.Page, request.PageSize)
|
||||
|
||||
list, total, err := s.outfitDao.OutfitListCommunity(ctx, userID, page, pageSize)
|
||||
if err != nil {
|
||||
return nil, errcode.DatabaseError
|
||||
}
|
||||
|
||||
items, berr := s.buildCommunityItems(ctx, list)
|
||||
if berr != nil {
|
||||
return nil, errcode.DatabaseError
|
||||
}
|
||||
|
||||
return &dto.OutfitCommunityListResponse{
|
||||
PageResponse: dto.PageResponse{Total: total, Page: page, PageSize: pageSize},
|
||||
List: items,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Delete 删除穿搭(软删除穿搭 + 清理明细)。
|
||||
func (s *OutfitService) Delete(ctx context.Context, userID int64, request *dto.OutfitDeleteRequest) (*dto.OutfitDeleteResponse, *errcode.Error) {
|
||||
ctx, span := global.Tracer.Start(ctx, "svc.OutfitDelete")
|
||||
@@ -414,6 +444,93 @@ func (s *OutfitService) buildOutfitListResponses(ctx context.Context, list []mys
|
||||
return resps, nil
|
||||
}
|
||||
|
||||
// buildCommunityItems 批量组装社区穿搭列表项(明细/衣物/作者/互动计数均批量查询,避免 N+1)。
|
||||
func (s *OutfitService) buildCommunityItems(ctx context.Context, list []mysqlmodel.Outfit) ([]dto.OutfitCommunityItem, error) {
|
||||
items := make([]dto.OutfitCommunityItem, 0, len(list))
|
||||
if len(list) == 0 {
|
||||
return items, nil
|
||||
}
|
||||
|
||||
outfitIDs := make([]int64, 0, len(list))
|
||||
ownerIDs := make([]int64, 0, len(list))
|
||||
for _, o := range list {
|
||||
outfitIDs = append(outfitIDs, o.ID)
|
||||
ownerIDs = append(ownerIDs, o.UserID)
|
||||
}
|
||||
|
||||
// 1. 穿搭明细 + 衣物(批量)。
|
||||
allItems, err := s.outfitItemDao.OutfitItemListByOutfitIDs(ctx, outfitIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
itemsByOutfit := make(map[int64][]int64, len(list))
|
||||
clothesIDSet := make(map[int64]struct{}, len(allItems))
|
||||
for _, it := range allItems {
|
||||
itemsByOutfit[it.OutfitID] = append(itemsByOutfit[it.OutfitID], it.ClothesID)
|
||||
clothesIDSet[it.ClothesID] = struct{}{}
|
||||
}
|
||||
clothesIDs := make([]int64, 0, len(clothesIDSet))
|
||||
for id := range clothesIDSet {
|
||||
clothesIDs = append(clothesIDs, id)
|
||||
}
|
||||
clothesByID := make(map[int64]mysqlmodel.Clothes, len(clothesIDs))
|
||||
if len(clothesIDs) > 0 {
|
||||
clothesList, cerr := s.clothesDao.ClothesGetByIDs(ctx, clothesIDs)
|
||||
if cerr != nil {
|
||||
return nil, cerr
|
||||
}
|
||||
for i := range clothesList {
|
||||
clothesByID[clothesList[i].ID] = clothesList[i]
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 作者信息(批量;头像 COS key 统一转可访问 URL)。
|
||||
ownerByID := make(map[int64]mysqlmodel.User, len(ownerIDs))
|
||||
if owners, uerr := s.userDao.UserGetByIDs(ctx, ownerIDs); uerr == nil {
|
||||
for i := range owners {
|
||||
ownerByID[owners[i].ID] = owners[i]
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 点赞 / 收藏计数(批量)。
|
||||
likeCounts, lerr := s.likeDao.LikeCountByTargets(ctx, LikeTypeOutfit, outfitIDs)
|
||||
if lerr != nil {
|
||||
return nil, lerr
|
||||
}
|
||||
collectCounts, cerr := s.collectDao.CollectCountByTargets(ctx, CollectTypeOutfit, outfitIDs)
|
||||
if cerr != nil {
|
||||
return nil, cerr
|
||||
}
|
||||
|
||||
for i := range list {
|
||||
o := &list[i]
|
||||
oItems := make([]dto.OutfitItemResponse, 0, len(itemsByOutfit[o.ID]))
|
||||
for _, cid := range itemsByOutfit[o.ID] {
|
||||
if c, ok := clothesByID[cid]; ok {
|
||||
oItems = append(oItems, buildOutfitItemResponse(&c))
|
||||
}
|
||||
}
|
||||
|
||||
item := dto.OutfitCommunityItem{
|
||||
OutfitUUID: o.OutfitUUID,
|
||||
OutfitName: o.OutfitName,
|
||||
OutfitDesc: o.OutfitDesc,
|
||||
Scene: o.Scene,
|
||||
Source: o.Source,
|
||||
CreatedAt: o.CreatedAt,
|
||||
Items: oItems,
|
||||
LikeCount: likeCounts[o.ID],
|
||||
CollectCount: collectCounts[o.ID],
|
||||
}
|
||||
if owner, ok := ownerByID[o.UserID]; ok {
|
||||
item.OwnerName = owner.Username
|
||||
item.OwnerAvatar = upload.AvatarURL(owner.Avatar)
|
||||
}
|
||||
items = append(items, item)
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
// buildOutfitItemResponse 组装穿搭明细(processed_image 转为可访问 URL)。
|
||||
func buildOutfitItemResponse(c *mysqlmodel.Clothes) dto.OutfitItemResponse {
|
||||
return dto.OutfitItemResponse{ClothesUUID: c.ClothesUUID, ProcessedImage: clothesImageURL(c.ProcessedImage)}
|
||||
|
||||
Reference in New Issue
Block a user