This commit is contained in:
toom1996
2026-09-13 00:52:35 +08:00
parent 10d8a96e8c
commit dbee704c95
44 changed files with 755 additions and 1148 deletions

View File

@ -17,7 +17,7 @@ import (
// StreetSnapService 街拍业务接口。
type StreetSnapService interface {
List(ctx context.Context, q dto.StreetSnapQuery) ([]dto.PublicStreetSnap, int64, error)
Detail(ctx context.Context, id string, hd bool) (*dto.PublicStreetSnapDetail, error)
Detail(ctx context.Context, id string) (*dto.PublicStreetSnapDetail, error)
// Popular 返回热度前 N 个街拍(按图片数降序),供 SSG 首页热门街拍展示。
Popular(ctx context.Context, limit int) ([]dto.PublicStreetSnap, error)
// GetForEdit 取原始街拍记录与图片,供后台编辑表单预填。
@ -43,9 +43,9 @@ type streetSnapService struct {
}
// NewStreetSnapService 创建街拍服务。
// img 负责把库里存储的七牛 key 拼装为可访问 URL(按 tier 决定普通/高清);
// media + deleter 用于删除图集时清理七牛孤儿文件(引用计数归零才真删);
// cleaner 把「删七牛」动作异步入队(由入库 worker 处理),避免阻塞删除请求。
// img 负责把库里存储的 S4 key 拼装为可访问 URL(统一走展示样式,VIP 与免费同质量);
// media + deleter 用于删除图集时清理孤儿文件(引用计数归零才真删);
// cleaner 把「删存储」动作异步入队(由入库 worker 处理),避免阻塞删除请求。
func NewStreetSnapService(repo repository.StreetSnapRepository, media repository.MediaRepository, img *imgurl.Composer, deleter storage.Deleter, cleaner MediaCleanupEnqueuer) StreetSnapService {
return &streetSnapService{repo: repo, media: media, img: img, deleter: deleter, cleaner: cleaner}
}
@ -69,7 +69,7 @@ func (s *streetSnapService) List(ctx context.Context, q dto.StreetSnapQuery) ([]
list = append(list, dto.PublicStreetSnap{
UID: hashid.EncodeTyped(hashid.TypeSnap, r.ID),
Title: r.Title,
Cover: s.img.Compose(r.Cover, false), // 列表封面统一普通图
Cover: s.img.ComposeThumb(r.Cover), // 列表封面走缩略图样式(小尺寸省流量)
ImageCount: r.ImageCount,
})
}
@ -93,8 +93,9 @@ func (s *streetSnapService) attachImages(ctx context.Context, list []dto.PublicS
if !ok {
continue
}
// 列表缩略图统一普通图;再剔除与卡片主图(cover)同 URL 的首图,避免重复展示。
imgs := s.toPublicSnapImages(raw, false)
// 列表缩略图走缩略图样式(与卡片封面同样式,故去重比较仍成立);
// 再剔除与卡片主图(cover)同 URL 的首图,避免重复展示。
imgs := s.toThumbSnapImages(raw)
imgs = excludeCoverSnap(imgs, list[i].Cover)
if len(imgs) > limit {
imgs = imgs[:limit]
@ -118,9 +119,8 @@ func excludeCoverSnap(imgs []dto.PublicArticleImage, cover string) []dto.PublicA
return kept
}
// Detail 查询街拍详情,含完整图片集。
// hd=true 时返回高清原图(VIP),false 时所有图拼普通样式(免费/未登录)。
func (s *streetSnapService) Detail(ctx context.Context, id string, hd bool) (*dto.PublicStreetSnapDetail, error) {
// Detail 查询街拍详情,含完整图片集。图片统一走展示样式(VIP 与免费同质量)。
func (s *streetSnapService) Detail(ctx context.Context, id string) (*dto.PublicStreetSnapDetail, error) {
snap, err := s.repo.FindByID(ctx, id)
if err != nil {
if errors.Is(err, repository.ErrNotFound) {
@ -137,8 +137,8 @@ func (s *streetSnapService) Detail(ctx context.Context, id string, hd bool) (*dt
return &dto.PublicStreetSnapDetail{
UID: hashid.EncodeTyped(hashid.TypeSnap, snap.ID),
Title: snap.Title,
Cover: s.img.Compose(snap.Cover, hd),
Images: s.toPublicSnapImages(imgs, hd),
Cover: s.img.Compose(snap.Cover),
Images: s.toPublicSnapImages(imgs),
}, nil
}
@ -154,7 +154,7 @@ func (s *streetSnapService) Popular(ctx context.Context, limit int) ([]dto.Publi
list = append(list, dto.PublicStreetSnap{
UID: hashid.EncodeTyped(hashid.TypeSnap, r.ID),
Title: r.Title,
Cover: s.img.Compose(r.Cover, false), // 热门街拍封面统一普通图
Cover: s.img.Compose(r.Cover), // 首页热门街拍卡片为大图展示,用高清样式(high)
ImageCount: r.ImageCount,
})
}
@ -163,8 +163,9 @@ func (s *streetSnapService) Popular(ctx context.Context, limit int) ([]dto.Publi
// toPublicSnapImages 把图片实体映射为对外结构(url + 名称 + 图片自身的编码 id)。
// ID 用 TypeSnapImage 前缀编码,与街拍 uid(s 前缀)区分开,供单图收藏定位。
// hd=true 时返回高清原图(VIP),false 时拼普通样式(免费/未登录)。
func (s *streetSnapService) toPublicSnapImages(imgs []model.StreetSnapImage, hd bool) []dto.PublicArticleImage {
// Image 走展示样式(high);额外给出 Thumb(缩略图样式),供大图灯箱左栏缩略图条等
// 小尺寸场景使用(列表用的 toThumbSnapImages 不填 Thumb,其 Image 本身就是缩略图)。
func (s *streetSnapService) toPublicSnapImages(imgs []model.StreetSnapImage) []dto.PublicArticleImage {
if len(imgs) == 0 {
return nil
}
@ -172,7 +173,25 @@ func (s *streetSnapService) toPublicSnapImages(imgs []model.StreetSnapImage, hd
for _, im := range imgs {
out = append(out, dto.PublicArticleImage{
ID: hashid.EncodeTyped(hashid.TypeSnapImage, im.ID),
Image: s.img.Compose(im.Image, hd),
Image: s.img.Compose(im.Image),
Thumb: s.img.ComposeThumb(im.Image),
Name: im.Name,
})
}
return out
}
// toThumbSnapImages 与 toPublicSnapImages 同构,但图片地址走「列表缩略图」样式(ComposeThumb),
// 仅供列表卡片 / 图条等小尺寸场景使用;详情页与大图灯箱仍用 toPublicSnapImages(展示样式)。
func (s *streetSnapService) toThumbSnapImages(imgs []model.StreetSnapImage) []dto.PublicArticleImage {
if len(imgs) == 0 {
return nil
}
out := make([]dto.PublicArticleImage, 0, len(imgs))
for _, im := range imgs {
out = append(out, dto.PublicArticleImage{
ID: hashid.EncodeTyped(hashid.TypeSnapImage, im.ID),
Image: s.img.ComposeThumb(im.Image),
Name: im.Name,
})
}