package configser import ( "fmt" "sync" "time" "videoweb/app/service/upstream" "videoweb/pub/common/log" "github.com/gin-gonic/gin" ) const footerPath = "/api/app/config/footer/info" const footerCacheTTL = 60 * time.Second var ( footerMu sync.Mutex footerCache *FooterInfo footerAt time.Time ) // FetchFooter 拉取底部配置,返回与 swagger proto.FooterInfo 一致的结构。 func FetchFooter(c *gin.Context) (*FooterInfo, error) { var env APIEnvelope[FooterInfoResp] if err := upstream.GetPublicJSON(c, footerPath, &env); err != nil { return nil, err } if env.Code != 200 { return nil, fmt.Errorf("footer info code=%d msg=%s", env.Code, env.Msg) } info := env.Data.FooterInfo return &info, nil } // FetchFooterOrEmpty 带短缓存;失败或空数据时返回空结构,不做写死兜底/字段映射。 func FetchFooterOrEmpty(c *gin.Context) FooterInfo { footerMu.Lock() defer footerMu.Unlock() if footerCache != nil && time.Since(footerAt) < footerCacheTTL { return *footerCache } info, err := FetchFooter(c) if err != nil { log.Error("fetch footer info failed", log.E(err)) return FooterInfo{} } footerCache = info footerAt = time.Now() return *info }