update
This commit is contained in:
@ -2,32 +2,36 @@ package dto
|
||||
|
||||
// ---------- 请求 ----------
|
||||
|
||||
// ArticleQuery 文章列表查询条件。
|
||||
// ArticleQuery 走秀列表查询条件(GET /public/runways)。
|
||||
//
|
||||
// 全部筛选项均支持多值(HBX 风格复选框),由 handler 从 query string 解析后填充。
|
||||
// 设计原则:参数尽可能少、不复用。
|
||||
// - 所有筛选均为单值(前端已全改为单选),不再支持多选数组;
|
||||
// - 按品牌过滤走查询参数 brand_id(hashid 编码串),不再使用独立嵌套路由;
|
||||
// - 关键词搜索已移除(无前端调用);season_code 冗余(season+year 已覆盖)也已移除。
|
||||
// - 分页 size 与附图 images 由服务端固定(ArticleFixedSize / ArticleFixedImages),前端不传、不可调。
|
||||
type ArticleQuery struct {
|
||||
Page int
|
||||
Size int
|
||||
Keyword string // 标题模糊搜索
|
||||
BrandID string // 单个品牌 id
|
||||
BrandIDs []uint32 // 多个品牌 id(brand_ids 逗号分隔)
|
||||
CollectionTypes []string // rtw / menswear / couture / resort / pre_fall
|
||||
Seasons []string // spring / fall
|
||||
SeasonCode string // SS26 / FW25,精确匹配
|
||||
Years []int // 年份
|
||||
Sort string // newest / year_desc / year_asc / image_count
|
||||
WithImages int // 列表附带每篇前 N 张图,0 表示不带
|
||||
Page int
|
||||
Size int // 服务端固定为 ArticleFixedSize,不从 query 读取
|
||||
Collection string // 单值:rtw / menswear / couture / resort / pre_fall
|
||||
Season string // 单值:spring / fall
|
||||
Year int // 单值年份,0 表示不过滤
|
||||
Sort string // newest(默认)/ year_desc / year_asc
|
||||
Images int // 服务端固定为 ArticleFixedImages,不从 query 读取
|
||||
|
||||
// Locale 语言:cn | en。空时由 service 回落默认 en。
|
||||
// 决定 title / description / brand_name 出参选取 *_en 还是 *_cn。
|
||||
Locale string
|
||||
|
||||
// BrandIDs 由列表接口从查询参数 brand_id(hashid 编码串)解码注入;为空表示不过滤。
|
||||
BrandIDs []uint32
|
||||
}
|
||||
|
||||
// 列表分页与附图数量的边界,与原项目保持一致。
|
||||
// 列表分页与附图数量由服务端固定(前端无调整入口),不再从 query 读取。
|
||||
const (
|
||||
articleDefaultSize = 12
|
||||
ArticleFixedSize = 24 // 每页条数(runway-looks 分页固定值)
|
||||
articleMaxSize = 100
|
||||
withImagesMax = 12
|
||||
ArticleFixedImages = 6 // 列表每篇附带前 N 张缩略图
|
||||
imagesMax = 12
|
||||
)
|
||||
|
||||
// Normalize 校正分页与附图参数,防止非法值打穿数据库。
|
||||
@ -36,13 +40,13 @@ func (q *ArticleQuery) Normalize() {
|
||||
q.Page = 1
|
||||
}
|
||||
if q.Size < 1 || q.Size > articleMaxSize {
|
||||
q.Size = articleDefaultSize
|
||||
q.Size = ArticleFixedSize
|
||||
}
|
||||
if q.WithImages < 0 {
|
||||
q.WithImages = 0
|
||||
if q.Images < 0 {
|
||||
q.Images = 0
|
||||
}
|
||||
if q.WithImages > withImagesMax {
|
||||
q.WithImages = withImagesMax
|
||||
if q.Images > imagesMax {
|
||||
q.Images = imagesMax
|
||||
}
|
||||
if q.Sort == "" {
|
||||
q.Sort = "newest"
|
||||
@ -60,39 +64,31 @@ type PublicArticleImage struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// PublicArticle 对外展示用的精简文章结构。
|
||||
// PublicArticle 对外展示用的精简文章结构(走秀列表)。
|
||||
//
|
||||
// 刻意剔除后台管理字段(is_deleted / updated_at / description 全文)。
|
||||
// 对外只暴露编码后的 UID(非自增主键),防止爬虫顺序枚举;
|
||||
// 同时把 brand_id 也编码为 brand_uid,品牌跳转同样不可枚举。
|
||||
// 只返回前端真正渲染的字段:id / brand_id / title / cover / brand_name / image_count / images。
|
||||
// year / season / season_code / collection_type / published_at / summary 前端从不展示,
|
||||
// 且排序已由后端按真实走秀新旧(year + season 优先级)完成,故响应不再携带这些元数据。
|
||||
// 对外只暴露编码后的 UID(非自增主键),防止爬虫顺序枚举;brand_id 同样编码为 brand_uid。
|
||||
type PublicArticle struct {
|
||||
UID string `json:"id"` // 编码后的文章 id(无序串)
|
||||
BrandUID string `json:"brand_id"` // 编码后的品牌 id(无序串)
|
||||
Title string `json:"title"`
|
||||
Summary string `json:"summary"` // description 截断后的对外摘要
|
||||
Cover string `json:"cover"` // 封面相对路径,如 /uploads/xxx.jpg
|
||||
BrandName string `json:"brand_name"` // JOIN brand 得到
|
||||
Year uint16 `json:"year"`
|
||||
ImageCount uint16 `json:"image_count"`
|
||||
CollectionType string `json:"collection_type"` // rtw/menswear/couture/resort/pre_fall
|
||||
Season string `json:"season"` // spring/fall/空
|
||||
SeasonCode string `json:"season_code"` // SS26/FW25/RES26/PF25
|
||||
PublishedAt uint32 `json:"published_at"` // = created_at,Unix 秒
|
||||
Images []PublicArticleImage `json:"images"` // with_images 参数控制,未请求时为 null
|
||||
UID string `json:"id"` // 编码后的文章 id(无序串)
|
||||
BrandUID string `json:"brand_id"` // 编码后的品牌 id(无序串)
|
||||
Title string `json:"title"`
|
||||
Cover string `json:"cover"` // 封面相对路径,如 /uploads/xxx.jpg
|
||||
BrandName string `json:"brand_name"` // JOIN brand 得到
|
||||
ImageCount uint16 `json:"image_count"` // 该走秀图片总数(列表卡片 "N+" 角标用)
|
||||
Images []PublicArticleImage `json:"images"` // 列表附带的每篇前 N 张缩略图
|
||||
}
|
||||
|
||||
// PublicArticleDetail 对外只读文章详情:含正文与完整图片集,不暴露管理字段。
|
||||
//
|
||||
// 与列表一致,只返回前端渲染所需的字段;image_count / source_url / 各类时间季节元数据前端均不展示,已移除。
|
||||
type PublicArticleDetail struct {
|
||||
UID string `json:"id"` // 编码后的文章 id(无序串)
|
||||
BrandUID string `json:"brand_id"` // 编码后的品牌 id(无序串)
|
||||
Title string `json:"title"`
|
||||
Summary string `json:"summary"`
|
||||
Description string `json:"description"`
|
||||
Cover string `json:"cover"`
|
||||
BrandName string `json:"brand_name"`
|
||||
Year uint16 `json:"year"`
|
||||
ImageCount uint16 `json:"image_count"`
|
||||
SourceURL string `json:"source_url"`
|
||||
PublishedAt uint32 `json:"published_at"`
|
||||
Images []PublicArticleImage `json:"images"`
|
||||
}
|
||||
|
||||
@ -1,18 +1,5 @@
|
||||
package dto
|
||||
|
||||
// ---------- 请求 ----------
|
||||
|
||||
// AuthRequest 注册 / 登录的统一请求体。
|
||||
//
|
||||
// 沿用原项目的单结构设计:注册用 username + email + password,
|
||||
// 登录用 account(可填邮箱或用户名)+ password。
|
||||
type AuthRequest struct {
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
Account string `json:"account"`
|
||||
}
|
||||
|
||||
// ---------- 响应 ----------
|
||||
|
||||
// UserPayload 对外返回的用户信息,绝不包含密码哈希。
|
||||
@ -21,10 +8,3 @@ type UserPayload struct {
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
// AuthResult 注册 / 登录成功后的返回:令牌 + 用户信息。
|
||||
// 前端 src/lib/auth.ts 依赖 token 与 user 两个顶层字段。
|
||||
type AuthResult struct {
|
||||
Token string `json:"token"`
|
||||
User UserPayload `json:"user"`
|
||||
}
|
||||
|
||||
@ -7,11 +7,7 @@ type BrandQuery struct {
|
||||
Letter string // A-Z 字母索引;OTHER 表示中文分桶;空表示全部拉丁字母
|
||||
Keyword string
|
||||
Page int
|
||||
Size int
|
||||
|
||||
// OnlyWithArticles 只返回"拥有走秀档案"的品牌,默认 true。
|
||||
// 库中有 2 万+ 无档案的品牌,若不过滤会污染 A-Z 索引。
|
||||
OnlyWithArticles bool
|
||||
Size int // 每页条数,已写死 brandDefaultSize(30),前端不传
|
||||
|
||||
// Featured 仅保留"代表品牌"精选集合(按指标排名的前 N 个)。
|
||||
Featured bool
|
||||
@ -25,7 +21,7 @@ type BrandQuery struct {
|
||||
|
||||
// 品牌列表分页与精选集合的边界,与原项目保持一致。
|
||||
const (
|
||||
brandDefaultSize = 200
|
||||
brandDefaultSize = 30
|
||||
brandMaxSize = 500
|
||||
featuredDefaultLimit = 200
|
||||
featuredMaxLimit = 500
|
||||
@ -54,13 +50,12 @@ func (q BrandQuery) Offset() int { return (q.Page - 1) * q.Size }
|
||||
|
||||
// PublicBrand 对外展示用的精简品牌结构,剔除 created_at / updated_at / is_deleted。
|
||||
// 注意:对外只暴露编码后的 UID(非自增主键),防止顺序枚举。
|
||||
// article_count(各品牌档案数)前端从不展示,已移除,故不再额外查一次分组计数。
|
||||
type PublicBrand struct {
|
||||
UID string `json:"id"` // 编码后的品牌 id(无序串),对外唯一标识
|
||||
Name string `json:"name"` // 按 locale 选列(cn→name_cn,en→name_en)
|
||||
NameEn string `json:"name_en"` // 英文规范名(始终返回,供前端组合双语展示)
|
||||
NameCn string `json:"name_cn"` // 中文名(可能为空,供前端组合双语展示)
|
||||
ShowName string `json:"show_name"`
|
||||
ArticleCount int `json:"article_count"` // 该品牌下的走秀档案数,用于索引计数
|
||||
UID string `json:"id"` // 编码后的品牌 id(无序串),对外唯一标识
|
||||
Name string `json:"name"` // 按 locale 选列(cn→name_cn,en→name_en)
|
||||
NameEn string `json:"name_en"` // 英文规范名(始终返回,供前端组合双语展示)
|
||||
NameCn string `json:"name_cn"` // 中文名(可能为空,供前端组合双语展示)
|
||||
}
|
||||
|
||||
// PopularBrand 首页"热门品牌"区块所需结构。
|
||||
|
||||
Reference in New Issue
Block a user