update
This commit is contained in:
@ -58,8 +58,12 @@ func (q ArticleQuery) Offset() int { return (q.Page - 1) * q.Size }
|
|||||||
|
|
||||||
// ---------- 响应 ----------
|
// ---------- 响应 ----------
|
||||||
|
|
||||||
// PublicArticleImage 对外展示用的图片结构(仅 url + 名称)。
|
// PublicArticleImage 对外展示用的图片结构。
|
||||||
|
//
|
||||||
|
// ID 是图片自身的编码 id(hashid,i=走秀单图 / j=街拍单图),供「单图收藏」定位到具体某一张;
|
||||||
|
// 此前只有 image + name,前端无法稳定标识单张图片,故补充该字段。
|
||||||
type PublicArticleImage struct {
|
type PublicArticleImage struct {
|
||||||
|
ID string `json:"id"`
|
||||||
Image string `json:"image"`
|
Image string `json:"image"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,16 @@ package dto
|
|||||||
|
|
||||||
// ---------- 收藏 ----------
|
// ---------- 收藏 ----------
|
||||||
|
|
||||||
|
// 收藏粒度:与 model.Favorite.Kind 对应。
|
||||||
|
const (
|
||||||
|
FavoriteKindGallery = "gallery" // 整篇图集(runway / street)
|
||||||
|
FavoriteKindImage = "image" // 单张图片(runway_image / snap_image)
|
||||||
|
)
|
||||||
|
|
||||||
// FavoriteItem 对外返回的收藏项:id 即 target_uid,便于前端直接比对卡片 id。
|
// FavoriteItem 对外返回的收藏项:id 即 target_uid,便于前端直接比对卡片 id。
|
||||||
|
//
|
||||||
|
// kind=image 时 image_url 是这一张图、parent_uid 是所属图集,前端用这两项渲染与回跳;
|
||||||
|
// kind=gallery 时沿用 cover / title / brand 快照。
|
||||||
type FavoriteItem struct {
|
type FavoriteItem struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
@ -10,15 +19,23 @@ type FavoriteItem struct {
|
|||||||
Cover string `json:"cover"`
|
Cover string `json:"cover"`
|
||||||
Brand string `json:"brand"`
|
Brand string `json:"brand"`
|
||||||
AddedAt uint32 `json:"added_at"`
|
AddedAt uint32 `json:"added_at"`
|
||||||
|
Kind string `json:"kind"`
|
||||||
|
ImageURL string `json:"image_url"`
|
||||||
|
ParentUID string `json:"parent_uid"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// FavoriteAdd 添加收藏请求体。target_uid 为前端卡片的 it.id(编码串)。
|
// FavoriteAdd 添加收藏请求体。target_uid 为前端卡片的 id(图集或图片的编码串)。
|
||||||
type FavoriteAdd struct {
|
type FavoriteAdd struct {
|
||||||
TargetType string `json:"target_type" binding:"required"` // runway | street
|
TargetType string `json:"target_type" binding:"required"` // runway | street | runway_image | snap_image
|
||||||
TargetUID string `json:"target_uid" binding:"required"`
|
TargetUID string `json:"target_uid" binding:"required"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Cover string `json:"cover"`
|
Cover string `json:"cover"`
|
||||||
Brand string `json:"brand"`
|
Brand string `json:"brand"`
|
||||||
|
|
||||||
|
// 图片收藏可选字段。kind 留空时由 target_type 推断(*_image → image,否则 gallery)。
|
||||||
|
Kind string `json:"kind"`
|
||||||
|
ImageURL string `json:"image_url"`
|
||||||
|
ParentUID string `json:"parent_uid"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// FavoriteCheck 批量查询哪些 target_uid 已收藏(列表页打勾用,与收藏总量解耦)。
|
// FavoriteCheck 批量查询哪些 target_uid 已收藏(列表页打勾用,与收藏总量解耦)。
|
||||||
|
|||||||
@ -24,7 +24,8 @@ func NewFavoriteHandler(favs service.FavoriteService) *FavoriteHandler {
|
|||||||
|
|
||||||
// List 当前用户收藏(服务端分页)。
|
// List 当前用户收藏(服务端分页)。
|
||||||
//
|
//
|
||||||
// GET /api/v1/auth/favorites?page=1&per_page=24(per_page 上限 100)
|
// GET /api/v1/auth/favorites?page=1&per_page=24&kind=(per_page 上限 100)
|
||||||
|
// kind 留空=不限粒度;gallery=只要图集收藏;image=只要单图收藏。
|
||||||
// 成功:200 { data: { items:[...], total, last_page } }
|
// 成功:200 { data: { items:[...], total, last_page } }
|
||||||
func (h *FavoriteHandler) List(c *gin.Context) {
|
func (h *FavoriteHandler) List(c *gin.Context) {
|
||||||
userID, ok := middleware.UserIDFrom(c)
|
userID, ok := middleware.UserIDFrom(c)
|
||||||
@ -40,7 +41,12 @@ func (h *FavoriteHandler) List(c *gin.Context) {
|
|||||||
if perPage < 1 || perPage > 100 {
|
if perPage < 1 || perPage > 100 {
|
||||||
perPage = 24
|
perPage = 24
|
||||||
}
|
}
|
||||||
items, total, err := h.favs.ListPaged(c.Request.Context(), userID, page, perPage)
|
kind := c.Query("kind")
|
||||||
|
if kind != "" && kind != dto.FavoriteKindGallery && kind != dto.FavoriteKindImage {
|
||||||
|
response.Error(c, http.StatusBadRequest, "invalid kind")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
items, total, err := h.favs.ListPaged(c.Request.Context(), userID, page, perPage, kind)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fail(c, err)
|
fail(c, err)
|
||||||
return
|
return
|
||||||
|
|||||||
@ -2,18 +2,28 @@ package model
|
|||||||
|
|
||||||
// Favorite 用户收藏(服务端持久化,按用户隔离)。
|
// Favorite 用户收藏(服务端持久化,按用户隔离)。
|
||||||
//
|
//
|
||||||
// 存储「对外编码 uid」(如 runway 的 r= 前缀串、street 的 s= 前缀串)而非数字主键,
|
// 存储「对外编码 uid」而非数字主键,这样无需 decode 即可与前端卡片的 id 直接对齐,
|
||||||
// 这样无需 decode 即可与前端卡片的 it.id 直接对齐,取消收藏时也只靠该串匹配。
|
// 取消收藏时也只靠该串匹配。两种粒度共用一张表,由 kind 区分:
|
||||||
// title / cover / brand 为收藏时的快照,供个人中心直接渲染,不必回查原表。
|
// - kind=gallery(默认):收藏整篇图集,target_uid 是图集 uid(r/s 前缀),
|
||||||
|
// title / cover / brand 为收藏时的快照,供个人中心直接渲染,不必回查原表;
|
||||||
|
// - kind=image:收藏单张图片,target_uid 是图片自身的编码 id(i/j 前缀),
|
||||||
|
// image_url 存这张图,parent_uid 指向所属图集(用于从收藏回跳原图集)。
|
||||||
|
//
|
||||||
|
// 两种粒度的 uid 前缀互不冲突(图集 r/s,图片 i/j),因此唯一键 (user_id, target_uid)
|
||||||
|
// 无需调整即可同时约束两种收藏。
|
||||||
type Favorite struct {
|
type Favorite struct {
|
||||||
ID uint32 `gorm:"primaryKey;column:id" json:"id"`
|
ID uint32 `gorm:"primaryKey;column:id" json:"id"`
|
||||||
CreatedAt uint32 `gorm:"column:created_at" json:"created_at"`
|
CreatedAt uint32 `gorm:"column:created_at" json:"created_at"`
|
||||||
UserID uint32 `gorm:"column:user_id;index:idx_user;not null" json:"user_id"`
|
UserID uint32 `gorm:"column:user_id;index:idx_user;not null" json:"user_id"`
|
||||||
TargetType string `gorm:"column:target_type;size:16;not null" json:"target_type"` // runway | street
|
TargetType string `gorm:"column:target_type;size:16;not null" json:"target_type"` // runway | street | runway_image | snap_image
|
||||||
TargetUID string `gorm:"column:target_uid;size:64;not null;uniqueIndex:uniq_user_target" json:"target_uid"`
|
TargetUID string `gorm:"column:target_uid;size:64;not null;uniqueIndex:uniq_user_target" json:"target_uid"`
|
||||||
Title string `gorm:"column:title;size:255" json:"title"`
|
Title string `gorm:"column:title;size:255" json:"title"`
|
||||||
Cover string `gorm:"column:cover;size:512" json:"cover"`
|
Cover string `gorm:"column:cover;size:512" json:"cover"`
|
||||||
Brand string `gorm:"column:brand;size:255" json:"brand"`
|
Brand string `gorm:"column:brand;size:255" json:"brand"`
|
||||||
|
|
||||||
|
Kind string `gorm:"column:kind;size:16;not null;default:gallery" json:"kind"` // gallery | image
|
||||||
|
ImageURL string `gorm:"column:image_url;size:512" json:"image_url"` // kind=image 时:这一张图
|
||||||
|
ParentUID string `gorm:"column:parent_uid;size:64" json:"parent_uid"` // kind=image 时:所属图集 uid
|
||||||
}
|
}
|
||||||
|
|
||||||
// TableName 指定表名。
|
// TableName 指定表名。
|
||||||
|
|||||||
@ -130,6 +130,12 @@ func Decode(s string) (uint32, error) {
|
|||||||
const (
|
const (
|
||||||
TypeRunway = 'r' // 走秀 / 文章 lookbook(brand_runway 表)
|
TypeRunway = 'r' // 走秀 / 文章 lookbook(brand_runway 表)
|
||||||
TypeSnap = 's' // 街拍(street_snap 表)
|
TypeSnap = 's' // 街拍(street_snap 表)
|
||||||
|
|
||||||
|
// 图片级前缀:单张图片也要有对外标识(图片收藏用)。
|
||||||
|
// 与图集前缀(r/s)互不冲突,因此同一数字主键在图集与图片下得到不同编码串,
|
||||||
|
// 收藏表可用 target_uid 同时容纳两种粒度而不撞车;后续也能凭前缀反查所属表。
|
||||||
|
TypeRunwayImage = 'i' // 走秀单图(brand_runway_images 表)
|
||||||
|
TypeSnapImage = 'j' // 街拍单图(street_snap_images 表)
|
||||||
)
|
)
|
||||||
|
|
||||||
// EncodeTyped 在编码串前拼一个类型字符前缀(如 "r"+base62 串)。前缀字符取自 base62 字母表,
|
// EncodeTyped 在编码串前拼一个类型字符前缀(如 "r"+base62 串)。前缀字符取自 base62 字母表,
|
||||||
|
|||||||
@ -10,11 +10,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// FavoriteRepository 收藏数据访问接口。
|
// FavoriteRepository 收藏数据访问接口。
|
||||||
|
//
|
||||||
|
// kind 用于区分收藏粒度(gallery=整篇图集 / image=单张图片);传空表示不限粒度。
|
||||||
type FavoriteRepository interface {
|
type FavoriteRepository interface {
|
||||||
// ListPaged 分页取某用户收藏,按收藏时间倒序。
|
// ListPaged 分页取某用户收藏,按收藏时间倒序。
|
||||||
ListPaged(ctx context.Context, userID uint32, page, perPage int) ([]model.Favorite, error)
|
ListPaged(ctx context.Context, userID uint32, page, perPage int, kind string) ([]model.Favorite, error)
|
||||||
// CountByUser 取某用户收藏总数(分页用)。
|
// CountByUser 取某用户收藏总数(分页用)。
|
||||||
CountByUser(ctx context.Context, userID uint32) (int64, error)
|
CountByUser(ctx context.Context, userID uint32, kind string) (int64, error)
|
||||||
// Add 新增收藏;同用户同 target 已存在时幂等忽略(ON DUPLICATE KEY DO NOTHING)。
|
// Add 新增收藏;同用户同 target 已存在时幂等忽略(ON DUPLICATE KEY DO NOTHING)。
|
||||||
Add(ctx context.Context, f *model.Favorite) error
|
Add(ctx context.Context, f *model.Favorite) error
|
||||||
// Remove 删除某用户对某个 target 的收藏。
|
// Remove 删除某用户对某个 target 的收藏。
|
||||||
@ -32,14 +34,17 @@ func NewFavoriteRepository(db *gorm.DB) FavoriteRepository {
|
|||||||
return &favoriteRepository{db: db}
|
return &favoriteRepository{db: db}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *favoriteRepository) ListPaged(ctx context.Context, userID uint32, page, perPage int) ([]model.Favorite, error) {
|
func (r *favoriteRepository) ListPaged(ctx context.Context, userID uint32, page, perPage int, kind string) ([]model.Favorite, error) {
|
||||||
var rows []model.Favorite
|
var rows []model.Favorite
|
||||||
offset := (page - 1) * perPage
|
offset := (page - 1) * perPage
|
||||||
if offset < 0 {
|
if offset < 0 {
|
||||||
offset = 0
|
offset = 0
|
||||||
}
|
}
|
||||||
err := r.db.WithContext(ctx).
|
q := r.db.WithContext(ctx).Where("user_id = ?", userID)
|
||||||
Where("user_id = ?", userID).
|
if kind != "" {
|
||||||
|
q = q.Where("kind = ?", kind)
|
||||||
|
}
|
||||||
|
err := q.
|
||||||
Order("created_at DESC").
|
Order("created_at DESC").
|
||||||
Offset(offset).
|
Offset(offset).
|
||||||
Limit(perPage).
|
Limit(perPage).
|
||||||
@ -47,12 +52,15 @@ func (r *favoriteRepository) ListPaged(ctx context.Context, userID uint32, page,
|
|||||||
return rows, err
|
return rows, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *favoriteRepository) CountByUser(ctx context.Context, userID uint32) (int64, error) {
|
func (r *favoriteRepository) CountByUser(ctx context.Context, userID uint32, kind string) (int64, error) {
|
||||||
var n int64
|
var n int64
|
||||||
err := r.db.WithContext(ctx).
|
q := r.db.WithContext(ctx).
|
||||||
Model(&model.Favorite{}).
|
Model(&model.Favorite{}).
|
||||||
Where("user_id = ?", userID).
|
Where("user_id = ?", userID)
|
||||||
Count(&n).Error
|
if kind != "" {
|
||||||
|
q = q.Where("kind = ?", kind)
|
||||||
|
}
|
||||||
|
err := q.Count(&n).Error
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -122,14 +122,19 @@ func (s *articleService) Detail(ctx context.Context, id string, locale string) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IDs 返回全部文章的编码 uid(供 SSG 枚举详情页路径使用,对外暴露的即编码串)。
|
// IDs 返回全部文章的编码 uid(供 SSG 枚举详情页路径使用,对外暴露的即编码串)。
|
||||||
// toPublicImages 把图片实体映射为对外结构(只保留 url 与名称)。
|
// toPublicImages 把图片实体映射为对外结构(url + 名称 + 图片自身的编码 id)。
|
||||||
|
// ID 用 TypeRunwayImage 前缀编码,与文章 uid(r 前缀)区分开,供单图收藏定位。
|
||||||
func toPublicImages(imgs []model.BrandRunwayImage) []dto.PublicArticleImage {
|
func toPublicImages(imgs []model.BrandRunwayImage) []dto.PublicArticleImage {
|
||||||
if len(imgs) == 0 {
|
if len(imgs) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
out := make([]dto.PublicArticleImage, 0, len(imgs))
|
out := make([]dto.PublicArticleImage, 0, len(imgs))
|
||||||
for _, im := range imgs {
|
for _, im := range imgs {
|
||||||
out = append(out, dto.PublicArticleImage{Image: im.Image, Name: im.Name})
|
out = append(out, dto.PublicArticleImage{
|
||||||
|
ID: hashid.EncodeTyped(hashid.TypeRunwayImage, im.ID),
|
||||||
|
Image: im.Image,
|
||||||
|
Name: im.Name,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"fashionapi/internal/dto"
|
"fashionapi/internal/dto"
|
||||||
@ -12,7 +13,8 @@ import (
|
|||||||
// FavoriteService 收藏业务接口。所有方法均要求调用方已通过中间件解析出 userID。
|
// FavoriteService 收藏业务接口。所有方法均要求调用方已通过中间件解析出 userID。
|
||||||
type FavoriteService interface {
|
type FavoriteService interface {
|
||||||
// ListPaged 分页取当前用户收藏(服务端分页,与收藏总量解耦)。
|
// ListPaged 分页取当前用户收藏(服务端分页,与收藏总量解耦)。
|
||||||
ListPaged(ctx context.Context, userID uint32, page, perPage int) ([]dto.FavoriteItem, int64, error)
|
// kind 传空表示不限粒度;传 gallery / image 只取对应粒度。
|
||||||
|
ListPaged(ctx context.Context, userID uint32, page, perPage int, kind string) ([]dto.FavoriteItem, int64, error)
|
||||||
// Add 新增收藏(幂等)。
|
// Add 新增收藏(幂等)。
|
||||||
Add(ctx context.Context, userID uint32, req dto.FavoriteAdd) (*dto.FavoriteItem, error)
|
Add(ctx context.Context, userID uint32, req dto.FavoriteAdd) (*dto.FavoriteItem, error)
|
||||||
// Remove 删除收藏。
|
// Remove 删除收藏。
|
||||||
@ -30,12 +32,12 @@ func NewFavoriteService(favs repository.FavoriteRepository) FavoriteService {
|
|||||||
return &favoriteService{favs: favs}
|
return &favoriteService{favs: favs}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *favoriteService) ListPaged(ctx context.Context, userID uint32, page, perPage int) ([]dto.FavoriteItem, int64, error) {
|
func (s *favoriteService) ListPaged(ctx context.Context, userID uint32, page, perPage int, kind string) ([]dto.FavoriteItem, int64, error) {
|
||||||
rows, err := s.favs.ListPaged(ctx, userID, page, perPage)
|
rows, err := s.favs.ListPaged(ctx, userID, page, perPage, kind)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, internalErr(err.Error())
|
return nil, 0, internalErr(err.Error())
|
||||||
}
|
}
|
||||||
total, err := s.favs.CountByUser(ctx, userID)
|
total, err := s.favs.CountByUser(ctx, userID, kind)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, internalErr(err.Error())
|
return nil, 0, internalErr(err.Error())
|
||||||
}
|
}
|
||||||
@ -47,12 +49,26 @@ func (s *favoriteService) ListPaged(ctx context.Context, userID uint32, page, pe
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *favoriteService) Add(ctx context.Context, userID uint32, req dto.FavoriteAdd) (*dto.FavoriteItem, error) {
|
func (s *favoriteService) Add(ctx context.Context, userID uint32, req dto.FavoriteAdd) (*dto.FavoriteItem, error) {
|
||||||
if req.TargetType != "runway" && req.TargetType != "street" {
|
if !validTargetType(req.TargetType) {
|
||||||
return nil, badRequest("invalid target_type")
|
return nil, badRequest("invalid target_type")
|
||||||
}
|
}
|
||||||
if req.TargetUID == "" {
|
if req.TargetUID == "" {
|
||||||
return nil, badRequest("target_uid required")
|
return nil, badRequest("target_uid required")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 粒度:请求未显式指定时按 target_type 推断(*_image 即图片收藏)。
|
||||||
|
kind := req.Kind
|
||||||
|
if kind == "" {
|
||||||
|
kind = inferKind(req.TargetType)
|
||||||
|
}
|
||||||
|
if kind != dto.FavoriteKindGallery && kind != dto.FavoriteKindImage {
|
||||||
|
return nil, badRequest("invalid kind")
|
||||||
|
}
|
||||||
|
// 图片收藏必须带上图片地址,否则个人中心无从渲染。
|
||||||
|
if kind == dto.FavoriteKindImage && req.ImageURL == "" {
|
||||||
|
return nil, badRequest("image_url required for image favorite")
|
||||||
|
}
|
||||||
|
|
||||||
row := &model.Favorite{
|
row := &model.Favorite{
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
TargetType: req.TargetType,
|
TargetType: req.TargetType,
|
||||||
@ -60,6 +76,9 @@ func (s *favoriteService) Add(ctx context.Context, userID uint32, req dto.Favori
|
|||||||
Title: req.Title,
|
Title: req.Title,
|
||||||
Cover: req.Cover,
|
Cover: req.Cover,
|
||||||
Brand: req.Brand,
|
Brand: req.Brand,
|
||||||
|
Kind: kind,
|
||||||
|
ImageURL: req.ImageURL,
|
||||||
|
ParentUID: req.ParentUID,
|
||||||
CreatedAt: uint32(time.Now().Unix()),
|
CreatedAt: uint32(time.Now().Unix()),
|
||||||
}
|
}
|
||||||
if err := s.favs.Add(ctx, row); err != nil {
|
if err := s.favs.Add(ctx, row); err != nil {
|
||||||
@ -90,7 +109,28 @@ func (s *favoriteService) Check(ctx context.Context, userID uint32, ids []string
|
|||||||
return got, nil
|
return got, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validTargetType 允许的收藏目标类型:图集两种 + 单图两种。
|
||||||
|
func validTargetType(t string) bool {
|
||||||
|
switch t {
|
||||||
|
case "runway", "street", "runway_image", "snap_image":
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// inferKind 由 target_type 推断收藏粒度。
|
||||||
|
func inferKind(targetType string) string {
|
||||||
|
if strings.HasSuffix(targetType, "_image") {
|
||||||
|
return dto.FavoriteKindImage
|
||||||
|
}
|
||||||
|
return dto.FavoriteKindGallery
|
||||||
|
}
|
||||||
|
|
||||||
func toFavoriteItem(r model.Favorite) dto.FavoriteItem {
|
func toFavoriteItem(r model.Favorite) dto.FavoriteItem {
|
||||||
|
kind := r.Kind
|
||||||
|
if kind == "" {
|
||||||
|
kind = dto.FavoriteKindGallery // 历史数据无 kind 列值,一律视为图集
|
||||||
|
}
|
||||||
return dto.FavoriteItem{
|
return dto.FavoriteItem{
|
||||||
ID: r.TargetUID,
|
ID: r.TargetUID,
|
||||||
Type: r.TargetType,
|
Type: r.TargetType,
|
||||||
@ -98,5 +138,8 @@ func toFavoriteItem(r model.Favorite) dto.FavoriteItem {
|
|||||||
Cover: r.Cover,
|
Cover: r.Cover,
|
||||||
Brand: r.Brand,
|
Brand: r.Brand,
|
||||||
AddedAt: r.CreatedAt,
|
AddedAt: r.CreatedAt,
|
||||||
|
Kind: kind,
|
||||||
|
ImageURL: r.ImageURL,
|
||||||
|
ParentUID: r.ParentUID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -137,14 +137,19 @@ func (s *streetSnapService) Popular(ctx context.Context, limit int) ([]dto.Publi
|
|||||||
return list, nil
|
return list, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// toPublicSnapImages 把图片实体映射为对外结构(只保留 url 与名称)。
|
// toPublicSnapImages 把图片实体映射为对外结构(url + 名称 + 图片自身的编码 id)。
|
||||||
|
// ID 用 TypeSnapImage 前缀编码,与街拍 uid(s 前缀)区分开,供单图收藏定位。
|
||||||
func toPublicSnapImages(imgs []model.StreetSnapImage) []dto.PublicArticleImage {
|
func toPublicSnapImages(imgs []model.StreetSnapImage) []dto.PublicArticleImage {
|
||||||
if len(imgs) == 0 {
|
if len(imgs) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
out := make([]dto.PublicArticleImage, 0, len(imgs))
|
out := make([]dto.PublicArticleImage, 0, len(imgs))
|
||||||
for _, im := range imgs {
|
for _, im := range imgs {
|
||||||
out = append(out, dto.PublicArticleImage{Image: im.Image, Name: im.Name})
|
out = append(out, dto.PublicArticleImage{
|
||||||
|
ID: hashid.EncodeTyped(hashid.TypeSnapImage, im.ID),
|
||||||
|
Image: im.Image,
|
||||||
|
Name: im.Name,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user