package configser import ( "strconv" "strings" ) // AppConfigVM 注入全站页面的公共配置(字段名与接口 newAddressInfo / seoInfo 对齐)。 type AppConfigVM struct { ForeverURLAddr string `json:"foreverUrlAddr"` NewURLAddr string `json:"newUrlAddr"` NewURLAddr1 string `json:"newUrlAddr1"` NewURLAddr2 string `json:"newUrlAddr2"` GmailAddr string `json:"gmailAddr"` QQ string `json:"qq"` TGGroup string `json:"tgGroup"` Telegram string `json:"telegram"` PotaoGroup string `json:"potaoGroup"` CustomerServiceHost string `json:"customerServiceHost"` AppAddr string `json:"appAddr"` OfficialAppAddr string `json:"officialAppAddr"` PDFAddr string `json:"pdfAddr"` TwitterAddr string `json:"twitterAddr"` SeoInfo SeoInfo `json:"seoInfo,omitempty"` SeoNavInfo SeoNavInfo `json:"seoNavInfo,omitempty"` NavPageList []NavPageItem `json:"navPageList,omitempty"` Advitise AdvitiseData `json:"advitise"` // 网页只用后台「站点」的 5 个广告位: // 弹窗 / 9宫格(弹窗广告后弹出)/ 详情横幅 / 播放页小图标 / 首页小图标 DialogList []Advertisement `json:"dialogList,omitempty"` NineGridList []Advertisement `json:"nineGridList,omitempty"` DetailBannerList []Advertisement `json:"detailbannerList,omitempty"` AList []Advertisement `json:"AList,omitempty"` BList []Advertisement `json:"BList,omitempty"` } // BuildAppConfigVM 从上游配置组装前端可用字段。 func BuildAppConfigVM(info *ConfigInfoResp) AppConfigVM { if info == nil { return AppConfigVM{} } addr := info.NewAddressInfo return AppConfigVM{ ForeverURLAddr: sanitizeURL(addr.ForeverURLAddr), NewURLAddr: sanitizeURL(addr.NewURLAddr), NewURLAddr1: sanitizeURL(addr.NewURLAddr1), NewURLAddr2: sanitizeURL(addr.NewURLAddr2), GmailAddr: strings.TrimSpace(addr.GmailAddr), QQ: strings.TrimSpace(addr.QQ), TGGroup: sanitizeURL(addr.TGGroup), Telegram: sanitizeURL(addr.Telegram), PotaoGroup: sanitizeURL(firstNonEmptyURL(info.Config.PotaoGroup, addr.PotaoGroup)), CustomerServiceHost: sanitizeURL(addr.CustomerServiceHost), AppAddr: sanitizeURL(addr.AppAddr), OfficialAppAddr: sanitizeURL(addr.OfficialAppAddr), PDFAddr: sanitizeURL(addr.PDFAddr), TwitterAddr: sanitizeURL(addr.TwitterAddr), NavPageList: buildNavPageList(info.NavPageList), Advitise: info.Advitise, DialogList: buildAdvertisementList(info.Advitise.DialogList), NineGridList: buildAdvertisementList(info.Advitise.NineGridList), // 本站后台用 videoTopList / appInfoAList / appInfoBList;兼容 detailbannerList / AList / BList 命名 DetailBannerList: firstAdvertisementList(info.Advitise.VideoTopList, info.Advitise.DetailBannerList), AList: firstAdvertisementList(info.Advitise.AppInfoAList, info.Advitise.AList), BList: firstAdvertisementList(info.Advitise.AppInfoBList, info.Advitise.BList), SeoInfo: SeoInfo{ Title: strings.TrimSpace(info.SeoInfo.Title), Description: strings.TrimSpace(info.SeoInfo.Description), Keywords: info.SeoInfo.Keywords, CanonicalURL: strings.TrimSpace(info.SeoInfo.CanonicalURL), WebSiteName: strings.TrimSpace(info.SeoInfo.WebSiteName), }, SeoNavInfo: SeoNavInfo{ DhTitle: strings.TrimSpace(info.SeoNavInfo.DhTitle), DhDescription: strings.TrimSpace(info.SeoNavInfo.DhDescription), DhKeyworld: info.SeoNavInfo.DhKeyworld, DhSiteName: strings.TrimSpace(info.SeoNavInfo.DhSiteName), }, } } func buildAdvertisementList(list []Advertisement) []Advertisement { if len(list) == 0 { return nil } out := make([]Advertisement, 0, len(list)) for _, item := range list { item.ID = strings.TrimSpace(item.ID) item.Images = sanitizeURL(item.Images) item.Link = sanitizeURL(item.Link) item.Title = strings.TrimSpace(item.Title) if item.Images == "" { continue } out = append(out, item) } return out } // ClickID 广告点击上报用的数字 ID(上游下发为数字字符串);非正整数时返回 0。 func (a Advertisement) ClickID() int64 { id, err := strconv.ParseInt(strings.TrimSpace(a.ID), 10, 64) if err != nil || id <= 0 { return 0 } return id } // ClickTrackable 广告 ID 与广告位均有效时才输出点击上报数据(data-ads-id / data-ads-location)。 func (a Advertisement) ClickTrackable() bool { return a.ClickID() > 0 && a.Location > 0 } // firstAdvertisementList 返回第一个有可用广告的列表(按字段优先级)。 func firstAdvertisementList(lists ...[]Advertisement) []Advertisement { for _, list := range lists { if built := buildAdvertisementList(list); len(built) > 0 { return built } } return nil } // QRText 下载弹窗二维码、跳转及复制链接内容:仅使用应用下载地址 appAddr。 func (c AppConfigVM) QRText() string { return strings.TrimSpace(c.AppAddr) } func buildNavPageList(list []NavPageItem) []NavPageItem { if len(list) == 0 { return nil } out := make([]NavPageItem, 0, len(list)) for _, item := range list { u := sanitizeURL(item.URL) if u == "" { continue } out = append(out, NavPageItem{Line: item.Line, URL: u}) } return out } func (n NavPageItem) Label() string { digits := []string{"", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十"} if n.Line >= 1 && n.Line <= 10 { return "线路" + digits[n.Line] } if n.Line > 0 { return "线路" + strconv.Itoa(n.Line) } return "线路" } func sanitizeURL(v string) string { v = strings.TrimSpace(v) v = strings.TrimRight(v, "\\") return strings.TrimSpace(v) } func firstNonEmptyURL(values ...string) string { for _, v := range values { if sanitizeURL(v) != "" { return v } } return "" }