Files
backend_v2/internal/handler/article_handler.go
toom1996 a325e438be update
2026-08-31 00:44:23 +08:00

99 lines
3.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package handler
import (
"net/http"
"strconv"
"strings"
"fashionapi/internal/dto"
"fashionapi/internal/pkg/hashid"
"fashionapi/internal/pkg/response"
"fashionapi/internal/service"
"github.com/gin-gonic/gin"
)
// ArticleHandler 对外公开的文章接口。
type ArticleHandler struct {
articles service.ArticleService
}
// NewArticleHandler 创建文章 handler。
func NewArticleHandler(articles service.ArticleService) *ArticleHandler {
return &ArticleHandler{articles: articles}
}
// List 走秀列表(分页 + 单值筛选 + 排序)。
//
// GET /api/v1/public/runway-looks
//
// 查询参数(均为单值,size / images 由服务端固定,前端不传):
// - page 页码,默认 1(服务端固定每页 ArticleFixedSize=24 条)
// - collection rtw / menswear / couture / resort / pre_fall
// - season spring / fall
// - year 年份(整数),0 表示不过滤
// - sort newest(默认)/ year_desc / year_asc / image_count
// - brand_id hashid 编码串;传入则只返回该品牌走秀(查询参数,取代原嵌套路由 /brands/:brandId/runway-looks)
// - locale cn / en
//
// 每篇附带前 ArticleFixedImages=6 张缩略图(服务端固定,不进参数)。
func (h *ArticleHandler) List(c *gin.Context) {
h.respondRunways(c, h.parseListQuery(c))
}
// parseListQuery 从 query string 解析走秀列表的筛选条件。
// brand_id 为 hashid 编码串;非法串忽略(当作不过滤,返回空结果集而非 404)。
func (h *ArticleHandler) parseListQuery(c *gin.Context) dto.ArticleQuery {
q := dto.ArticleQuery{
Page: queryInt(c, "page", 1),
Size: dto.ArticleFixedSize, // 服务端固定,前端不传
Collection: c.Query("collection"),
Season: c.Query("season"),
Year: queryInt(c, "year", 0),
Sort: c.DefaultQuery("sort", "newest"),
Images: dto.ArticleFixedImages, // 服务端固定,前端不传
Locale: parseLocale(c),
}
if raw := strings.TrimSpace(c.Query("brand_id")); raw != "" {
if n, err := hashid.Decode(raw); err == nil {
q.BrandIDs = []uint32{n}
}
}
return q
}
// respondRunways 统一执行列表查询并回包(分页)。
func (h *ArticleHandler) respondRunways(c *gin.Context, q dto.ArticleQuery) {
q.Normalize()
list, total, err := h.articles.List(c.Request.Context(), q)
if err != nil {
fail(c, err)
return
}
response.Page(c, http.StatusOK, list, total, q.Size)
}
// Detail 走秀详情(含完整图片集)。
//
// GET /api/public/runways/:id
// :id 是对外编码串(无序),需先解码为数字主键再查库;非法串视为不存在。
func (h *ArticleHandler) Detail(c *gin.Context) {
raw := strings.TrimSpace(c.Param("id"))
if raw == "" {
response.Error(c, http.StatusBadRequest, "缺少文章 id")
return
}
_, numeric, err := hashid.DecodeTyped(raw)
if err != nil {
response.Error(c, http.StatusNotFound, "文章不存在")
return
}
detail, err := h.articles.Detail(c.Request.Context(), strconv.FormatUint(uint64(numeric), 10), parseLocale(c))
if err != nil {
fail(c, err)
return
}
response.Data(c, http.StatusOK, detail)
}