update
This commit is contained in:
@ -80,10 +80,4 @@ func (h *AuthHandler) Me(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"user": user})
|
||||
}
|
||||
|
||||
// Logout 登出。
|
||||
//
|
||||
// POST /api/auth/logout
|
||||
// 无状态 JWT 服务端无需作废令牌,由客户端丢弃即可;保留接口以便将来扩展黑名单。
|
||||
func (h *AuthHandler) Logout(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"ok": true})
|
||||
}
|
||||
|
||||
|
||||
@ -2,9 +2,7 @@ package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"fashionapi/internal/dto"
|
||||
"fashionapi/internal/pkg/response"
|
||||
"fashionapi/internal/service"
|
||||
|
||||
@ -19,27 +17,40 @@ import (
|
||||
// - 复用现有 service 层逻辑,与对外公开接口保持同一份数据源与映射规则,
|
||||
// 不会出现「构建接口与线上接口返回结构不一致」的坑。
|
||||
type SSGHandler struct {
|
||||
brands service.BrandService
|
||||
articles service.ArticleService
|
||||
brands service.BrandService
|
||||
index service.IndexService
|
||||
}
|
||||
|
||||
// NewSSGHandler 创建 SSG handler。
|
||||
func NewSSGHandler(brands service.BrandService, articles service.ArticleService) *SSGHandler {
|
||||
return &SSGHandler{brands: brands, articles: articles}
|
||||
func NewSSGHandler(brands service.BrandService, index service.IndexService) *SSGHandler {
|
||||
return &SSGHandler{brands: brands, index: index}
|
||||
}
|
||||
|
||||
// Popular 首页「热门品牌」区块数据(SSG 内部版)。
|
||||
// IndexRunway 首页(/index/)runway 区块数据。
|
||||
//
|
||||
// GET /api/ssg/brands/popular?limit=20
|
||||
// GET /api/v1/ssg/index/runway
|
||||
//
|
||||
// 与公开版逻辑完全一致(复用 service.BrandService.Popular),只是挪到了内部端口,
|
||||
// 不再挂在对外公开的 /api/public 下。limit 默认 20、上限 100。
|
||||
func (h *SSGHandler) Popular(c *gin.Context) {
|
||||
limit := queryInt(c, "limit", 20)
|
||||
if limit < 1 || limit > 100 {
|
||||
limit = 20
|
||||
// 数据由各模块在服务端写死组合(不接收任何参数),当前仅有 hotBrand(热门品牌,固定 20 条)。
|
||||
// 拼装逻辑由 service.IndexService.Runway 负责,handler 只做转发。
|
||||
func (h *SSGHandler) IndexRunway(c *gin.Context) {
|
||||
data, err := h.index.Runway(c.Request.Context(), parseLocale(c))
|
||||
if err != nil {
|
||||
fail(c, err)
|
||||
return
|
||||
}
|
||||
list, err := h.brands.Popular(c.Request.Context(), limit, parseLocale(c))
|
||||
response.Data(c, http.StatusOK, data)
|
||||
}
|
||||
|
||||
// HotBrands 走秀页(RunwayLooks)品牌筛选的热门品牌数据。
|
||||
//
|
||||
// GET /api/v1/ssg/brands/hot
|
||||
//
|
||||
// 固定返回热度前 30 的品牌(按走秀图片总数排名,结果按热度顺序),不接收任何参数——
|
||||
// 前端侧栏 filter 展示前 10 个,品牌弹窗 HOT 标签展示全部 30 个。
|
||||
func (h *SSGHandler) HotBrands(c *gin.Context) {
|
||||
const hotBrandLimit = 30
|
||||
|
||||
list, err := h.brands.Hot(c.Request.Context(), hotBrandLimit, parseLocale(c))
|
||||
if err != nil {
|
||||
fail(c, err)
|
||||
return
|
||||
@ -47,44 +58,4 @@ func (h *SSGHandler) Popular(c *gin.Context) {
|
||||
response.Data(c, http.StatusOK, list)
|
||||
}
|
||||
|
||||
// Brands 品牌索引页(HBX 风格 A-Z)的 SSG 全量数据。
|
||||
//
|
||||
// GET /api/ssg/brands?size=300&only_with_articles=1&featured=1
|
||||
//
|
||||
// 直接复用 BrandQuery + service.BrandService.List,支持字母/搜索/精选/分页等全部参数,
|
||||
// 返回 {data:[...]} 与公开列表同构,前端 brands.astro 无需任何适配。
|
||||
func (h *SSGHandler) Brands(c *gin.Context) {
|
||||
q := dto.BrandQuery{
|
||||
Letter: strings.ToUpper(strings.TrimSpace(c.Query("letter"))),
|
||||
Keyword: strings.TrimSpace(c.Query("keyword")),
|
||||
Page: queryInt(c, "page", 1),
|
||||
Size: queryInt(c, "size", 200),
|
||||
OnlyWithArticles: queryBool(c, "only_with_articles", true),
|
||||
Featured: queryBool(c, "featured", false),
|
||||
Metric: strings.ToLower(strings.TrimSpace(c.Query("metric"))),
|
||||
Limit: queryInt(c, "limit", 200),
|
||||
Locale: parseLocale(c),
|
||||
}
|
||||
q.Normalize()
|
||||
|
||||
list, total, err := h.brands.List(c.Request.Context(), q)
|
||||
if err != nil {
|
||||
fail(c, err)
|
||||
return
|
||||
}
|
||||
response.Page(c, http.StatusOK, list, total, q.Page, q.Size)
|
||||
}
|
||||
|
||||
// ArticleIDs 供 SSG 的 getStaticPaths 枚举详情页路径用。
|
||||
//
|
||||
// GET /api/ssg/articles/ids
|
||||
//
|
||||
// 只回 [id,...](升序),不带回封面/描述等大字段,比拉 size=500 再 .map(id) 省带宽。
|
||||
func (h *SSGHandler) ArticleIDs(c *gin.Context) {
|
||||
ids, err := h.articles.IDs(c.Request.Context())
|
||||
if err != nil {
|
||||
fail(c, err)
|
||||
return
|
||||
}
|
||||
response.Data(c, http.StatusOK, ids)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user