package handler import ( "net/http" "fashionapi/internal/pkg/response" "fashionapi/internal/service" "github.com/gin-gonic/gin" ) // SSGHandler 承载「仅供构建期(astro build)使用的内部接口」。 // // 这些接口返回全量/全 ID 数据,理论上不应暴露给公网,因此: // - 它们只挂在独立的内部端口(默认 8091,见 router.NewSSG)上; // - 该端口由 docker-compose 绑定 127.0.0.1(回环),nginx 也绝不反代; // - 复用现有 service 层逻辑,与对外公开接口保持同一份数据源与映射规则, // 不会出现「构建接口与线上接口返回结构不一致」的坑。 type SSGHandler struct { brands service.BrandService index service.IndexService snaps service.StreetSnapService } // NewSSGHandler 创建 SSG handler。 func NewSSGHandler(brands service.BrandService, index service.IndexService, snaps service.StreetSnapService) *SSGHandler { return &SSGHandler{brands: brands, index: index, snaps: snaps} } // IndexRunway 首页(/index/)runway 区块数据。 // // GET /api/v1/ssg/index/runway // // 数据由各模块在服务端写死组合(不接收任何参数),当前仅有 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 } 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 } response.Data(c, http.StatusOK, list) } // StreetSnapPopular 首页热门街拍(按图片数前 N,返回完整对象含封面)。 // // GET /api/v1/ssg/street-snaps/popular func (h *SSGHandler) StreetSnapPopular(c *gin.Context) { const limit = 20 list, err := h.snaps.Popular(c.Request.Context(), limit) if err != nil { fail(c, err) return } response.Data(c, http.StatusOK, list) }