This commit is contained in:
toom1996
2026-08-30 10:45:34 +08:00
parent a6724265ad
commit 9c3403a903
23 changed files with 284 additions and 508 deletions

View File

@ -8,19 +8,13 @@ import (
"fashionapi/internal/dto"
"fashionapi/internal/model"
"fashionapi/internal/pkg/hashid"
"fashionapi/internal/pkg/textutil"
"fashionapi/internal/repository"
)
// summaryLength 对外摘要的截断长度(rune 数),与原项目一致。
const summaryLength = 140
// ArticleService 文章业务接口。
type ArticleService interface {
List(ctx context.Context, q dto.ArticleQuery) ([]dto.PublicArticle, int64, error)
Detail(ctx context.Context, id string, locale string) (*dto.PublicArticleDetail, error)
// IDs 返回全部文章的编码 uid,供 SSG 路径枚举(getStaticPaths)。
IDs(ctx context.Context) ([]string, error)
}
type articleService struct {
@ -46,25 +40,17 @@ func (s *articleService) List(ctx context.Context, q dto.ArticleQuery) ([]dto.Pu
for _, r := range rows {
ids = append(ids, r.ID)
list = append(list, dto.PublicArticle{
UID: hashid.Encode(r.ID),
BrandUID: hashid.Encode(r.BrandID),
Title: pickLocale(r.TitleEn, r.TitleCn, q.Locale),
Summary: textutil.Summarize(pickLocale(r.DescriptionEn, r.DescriptionCn, q.Locale), summaryLength),
Cover: r.Cover,
// 品牌名强制优先英文("en"),仅在英文缺失时回落中文,避免留空;
// 与 title/description 不同,品牌名不随 locale 切换,保持英文观感。
BrandName: pickLocale(r.BrandNameEn, r.BrandNameCn, "en"),
Year: r.Year,
ImageCount: r.ImageCount,
CollectionType: r.CollectionType,
Season: r.Season,
SeasonCode: r.SeasonCode,
PublishedAt: r.CreatedAt,
UID: hashid.Encode(r.ID),
BrandUID: hashid.Encode(r.BrandID),
Title: pickLocale(r.TitleEn, r.TitleCn, q.Locale),
Cover: r.Cover,
BrandName: pickLocale(r.BrandNameEn, r.BrandNameCn, "en"), // 品牌名强制优先英文,保持英文观感
ImageCount: r.ImageCount,
})
}
if q.WithImages > 0 && len(list) > 0 {
if err := s.attachImages(ctx, list, ids, q.WithImages); err != nil {
if q.Images > 0 && len(list) > 0 {
if err := s.attachImages(ctx, list, ids, q.Images); err != nil {
return nil, 0, internalErr(err.Error())
}
}
@ -110,32 +96,15 @@ func (s *articleService) Detail(ctx context.Context, id string, locale string) (
UID: hashid.Encode(row.ID),
BrandUID: hashid.Encode(row.BrandID),
Title: pickLocale(row.TitleEn, row.TitleCn, locale),
Summary: textutil.Summarize(pickLocale(row.DescriptionEn, row.DescriptionCn, locale), summaryLength),
Description: pickLocale(row.DescriptionEn, row.DescriptionCn, locale),
Cover: row.Cover,
// 品牌名强制优先英文("en"),不随 locale 切换,保持英文观感。
BrandName: pickLocale(row.BrandNameEn, row.BrandNameCn, "en"),
Year: row.Year,
ImageCount: row.ImageCount,
SourceURL: row.SourceURL,
PublishedAt: row.CreatedAt,
Images: toPublicImages(imgs),
BrandName: pickLocale(row.BrandNameEn, row.BrandNameCn, "en"),
Images: toPublicImages(imgs),
}, nil
}
// IDs 返回全部文章的编码 uid(供 SSG 枚举详情页路径使用,对外暴露的即编码串)。
func (s *articleService) IDs(ctx context.Context) ([]string, error) {
ids, err := s.articles.IDs(ctx)
if err != nil {
return nil, internalErr(err.Error())
}
out := make([]string, 0, len(ids))
for _, id := range ids {
out = append(out, hashid.Encode(id))
}
return out, nil
}
// toPublicImages 把图片实体映射为对外结构(只保留 url 与名称)。
func toPublicImages(imgs []model.BrandRunwayImage) []dto.PublicArticleImage {
if len(imgs) == 0 {