package playletser import ( "fmt" "sync" "time" "videoweb/app/service/upstream" "videoweb/pub/common/log" "github.com/gin-gonic/gin" ) const homePath = "/api/app/playlet/home" const homeCacheTTL = 30 * time.Second var ( homeMu sync.Mutex homeCache *HomePlayletResponse homeAt time.Time ) // FetchHome 拉取首页短剧聚合数据。 func FetchHome(c *gin.Context) (*HomePlayletResponse, error) { var env APIEnvelope[HomePlayletResponse] if err := upstream.GetPublicJSON(c, homePath, &env); err != nil { return nil, err } if env.Code != 200 { return nil, fmt.Errorf("playlet home code=%d msg=%s", env.Code, env.Msg) } return &env.Data, nil } // FetchHomeOrEmpty 带短缓存;失败时打日志并返回空结构,保证 SSR 页面可渲染。 func FetchHomeOrEmpty(c *gin.Context) *HomePlayletResponse { homeMu.Lock() defer homeMu.Unlock() if homeCache != nil && time.Since(homeAt) < homeCacheTTL { return cloneHome(homeCache) } data, err := FetchHome(c) if err != nil { log.Error("fetch playlet home failed", log.E(err)) if homeCache != nil { return cloneHome(homeCache) } return &HomePlayletResponse{} } if data == nil { if homeCache != nil { return cloneHome(homeCache) } return &HomePlayletResponse{} } data.SeoInfo.Normalize() homeCache = data homeAt = time.Now() return cloneHome(homeCache) } func cloneHome(src *HomePlayletResponse) *HomePlayletResponse { if src == nil { return &HomePlayletResponse{} } out := *src if src.Announcements != nil { out.Announcements = append([]AnnouncementItem(nil), src.Announcements...) } if src.HomeBannerData != nil { out.HomeBannerData = append([]HomeBannerData(nil), src.HomeBannerData...) } if src.HomeTodayUpdateData != nil { out.HomeTodayUpdateData = append([]CommonData(nil), src.HomeTodayUpdateData...) } if src.HomeCategoryData != nil { out.HomeCategoryData = make([]HomeCategoryData, len(src.HomeCategoryData)) for i, cat := range src.HomeCategoryData { out.HomeCategoryData[i] = cat if cat.List != nil { out.HomeCategoryData[i].List = append([]CommonData(nil), cat.List...) } } } if src.HomeRecommendThemes != nil { out.HomeRecommendThemes = append([]HomeRecommendTheme(nil), src.HomeRecommendThemes...) } if src.SeoInfo.Keywords != nil { out.SeoInfo.Keywords = append([]string(nil), src.SeoInfo.Keywords...) } return &out } // ActiveHomeBanners 过滤未启用项,保留接口返回顺序。 func ActiveHomeBanners(list []HomeBannerData) []HomeBannerData { if len(list) == 0 { return list } out := make([]HomeBannerData, 0, len(list)) for _, item := range list { if !item.Status { continue } out = append(out, item) } return out }