广告添加
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"videoweb/app/service/configser"
|
||||
"videoweb/pub/common/log"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type adsClickBody struct {
|
||||
AdsID int64 `json:"adsId"`
|
||||
Location int64 `json:"location"`
|
||||
}
|
||||
|
||||
// AdsClick 代理上游 POST /api/app/ads/click;appId 由服务端固定填写。
|
||||
func AdsClick(c *gin.Context) {
|
||||
var body adsClickBody
|
||||
if err := c.ShouldBindJSON(&body); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"code": 1001,
|
||||
"msg": "参数错误",
|
||||
"tip": "参数错误",
|
||||
"data": nil,
|
||||
})
|
||||
return
|
||||
}
|
||||
if body.AdsID <= 0 || body.Location <= 0 {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": 1001,
|
||||
"msg": "参数错误",
|
||||
"tip": "缺少 adsId 或 location",
|
||||
"data": nil,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
env, err := configser.AdsClick(c, configser.AdsClickReq{
|
||||
AdsID: body.AdsID,
|
||||
Location: body.Location,
|
||||
})
|
||||
if err != nil {
|
||||
log.Error("ads click upstream failed", log.E(err))
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": 500,
|
||||
"msg": "ads click failed",
|
||||
"tip": "上报失败",
|
||||
"data": nil,
|
||||
})
|
||||
return
|
||||
}
|
||||
if env == nil || env.Code != 200 {
|
||||
code := 500
|
||||
msg := ""
|
||||
if env != nil {
|
||||
code = env.Code
|
||||
msg = env.Msg
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": code,
|
||||
"msg": msg,
|
||||
"tip": firstNonEmpty(msg, "上报失败"),
|
||||
"data": nil,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": 200,
|
||||
"msg": env.Msg,
|
||||
"tip": firstNonEmpty(env.Msg, "success"),
|
||||
"data": nil,
|
||||
})
|
||||
}
|
||||
@@ -38,6 +38,8 @@ func DHInit() *gin.Engine {
|
||||
engine.StaticFile("/favicon.svg", "./static/favicon.svg")
|
||||
engine.StaticFile("/favicon.png", "./static/favicon.png")
|
||||
engine.GET("/ui/dialog/:name", web.DialogFragment)
|
||||
// 导航页同样展示弹窗 / 九宫格广告,需要点击上报接口。
|
||||
engine.POST("/api/app/ads/click", web.AdsClick)
|
||||
engine.GET("/", web.Nav)
|
||||
engine.GET("/nav/", web.Nav)
|
||||
engine.GET("/dh/", web.Nav)
|
||||
@@ -151,6 +153,7 @@ func registerRoutes(r *gin.Engine) {
|
||||
r.POST("/api/contactus/add", web.AddContactUs)
|
||||
r.GET("/api/comment/list", web.CommentList)
|
||||
r.POST("/api/playlet/forward/heat", web.PlayletForwardHeat)
|
||||
r.POST("/api/app/ads/click", web.AdsClick)
|
||||
r.GET("/api/playlet/chapter/detail", web.ChapterDetail)
|
||||
r.GET("/api/playlet/chapter/list", web.ChapterList)
|
||||
r.GET("/api/playlet/operate/list", web.OperateList)
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package configser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"videoweb/app/service/upstream"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
const (
|
||||
adsClickPath = "/api/app/ads/click"
|
||||
// AdsClickAppID 广告点击上报的应用 ID,由广告后台分配,固定为 12。
|
||||
AdsClickAppID int64 = 12
|
||||
)
|
||||
|
||||
// AdsClickReq 对应上游 POST /api/app/ads/click(appId / adsId / location 均必填)。
|
||||
type AdsClickReq struct {
|
||||
AppID int64 `json:"appId"`
|
||||
AdsID int64 `json:"adsId"`
|
||||
Location int64 `json:"location"`
|
||||
}
|
||||
|
||||
// AdsClick 上报一次广告点击。
|
||||
func AdsClick(c *gin.Context, req AdsClickReq) (*APIEnvelope[any], error) {
|
||||
if req.AdsID <= 0 || req.Location <= 0 {
|
||||
return nil, fmt.Errorf("ads click invalid adsId=%d location=%d", req.AdsID, req.Location)
|
||||
}
|
||||
req.AppID = AdsClickAppID
|
||||
var env APIEnvelope[any]
|
||||
if _, err := upstream.PostJSON(c, adsClickPath, req, &env); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &env, nil
|
||||
}
|
||||
@@ -87,6 +87,11 @@ type AdvitiseData struct {
|
||||
TitleList []Advertisement `json:"titleList"`
|
||||
PlayList []Advertisement `json:"playList"`
|
||||
PauseyList []Advertisement `json:"pauseyList"`
|
||||
// 本站后台(webhgdjapi)的字段名:横幅 / 播放页小图标 / 首页小图标
|
||||
VideoTopList []Advertisement `json:"videoTopList"`
|
||||
VideoDownList []Advertisement `json:"videoDownList"`
|
||||
AppInfoAList []Advertisement `json:"appInfoAList"`
|
||||
AppInfoBList []Advertisement `json:"appInfoBList"`
|
||||
}
|
||||
|
||||
// Advertisement 对应 swagger proxy.AdvitiseInfo。
|
||||
|
||||
@@ -7,29 +7,31 @@ import (
|
||||
|
||||
// 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"`
|
||||
DetailTopList []Advertisement `json:"detailTopList,omitempty"`
|
||||
NineGridList []Advertisement `json:"nineGridList,omitempty"`
|
||||
DetailBannerList []Advertisement `json:"detailbannerList,omitempty"`
|
||||
BottomBanner []Advertisement `json:"bottomBanner,omitempty"`
|
||||
DialogList []Advertisement `json:"dialogList,omitempty"`
|
||||
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 从上游配置组装前端可用字段。
|
||||
@@ -55,11 +57,12 @@ func BuildAppConfigVM(info *ConfigInfoResp) AppConfigVM {
|
||||
TwitterAddr: sanitizeURL(addr.TwitterAddr),
|
||||
NavPageList: buildNavPageList(info.NavPageList),
|
||||
Advitise: info.Advitise,
|
||||
DetailTopList: buildAdvertisementList(info.Advitise.DetailTopList),
|
||||
NineGridList: buildAdvertisementList(info.Advitise.NineGridList),
|
||||
DetailBannerList: buildAdvertisementList(info.Advitise.DetailBannerList),
|
||||
BottomBanner: buildAdvertisementList(info.Advitise.BottomBanner),
|
||||
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),
|
||||
@@ -94,20 +97,28 @@ func buildAdvertisementList(list []Advertisement) []Advertisement {
|
||||
return out
|
||||
}
|
||||
|
||||
// NineGridRow 按首页设计每行返回两个 banner,超出当前行时返回空切片。
|
||||
func (c AppConfigVM) NineGridRow(row int) []Advertisement {
|
||||
if row < 0 {
|
||||
return nil
|
||||
// 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
|
||||
}
|
||||
start := row * 2
|
||||
if start >= len(c.NineGridList) {
|
||||
return nil
|
||||
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
|
||||
}
|
||||
}
|
||||
end := start + 2
|
||||
if end > len(c.NineGridList) {
|
||||
end = len(c.NineGridList)
|
||||
}
|
||||
return c.NineGridList[start:end]
|
||||
return nil
|
||||
}
|
||||
|
||||
// QRText 下载弹窗二维码、跳转及复制链接内容:仅使用应用下载地址 appAddr。
|
||||
|
||||
@@ -18,8 +18,7 @@ func TestBuildAppConfigVMIncludesValidAdvertisements(t *testing.T) {
|
||||
NewAddressInfo: NewAddressInfo{Telegram: " https://t.me/business ", QQ: " 2168045324 ", OfficialAppAddr: " https://app.example.com/download\\ "},
|
||||
Config: ConfigInfo{PotaoGroup: " https://potato.example.com/group\\ "},
|
||||
Advitise: AdvitiseData{
|
||||
HomeList: []Advertisement{{ID: "home", Images: "https://cdn.example.com/home.gif"}},
|
||||
DetailTopList: []Advertisement{{ID: "top", Images: " https://cdn.example.com/top.gif "}},
|
||||
HomeList: []Advertisement{{ID: "home", Images: "https://cdn.example.com/home.gif"}},
|
||||
NineGridList: []Advertisement{
|
||||
{ID: "banner-1", Images: "https://cdn.example.com/banner-1.gif"},
|
||||
{ID: "banner-empty", Images: " "},
|
||||
@@ -27,10 +26,13 @@ func TestBuildAppConfigVMIncludesValidAdvertisements(t *testing.T) {
|
||||
{ID: "banner-3", Images: "https://cdn.example.com/banner-3.gif"},
|
||||
},
|
||||
DetailBannerList: []Advertisement{{ID: "detail", Images: "https://cdn.example.com/detail.gif"}},
|
||||
BottomBanner: []Advertisement{
|
||||
{ID: " bottom ", Images: " https://cdn.example.com/bottom.gif ", Link: " https://example.com/bottom "},
|
||||
{ID: "bottom-empty", Images: " "},
|
||||
VideoTopList: []Advertisement{
|
||||
{ID: " video-top ", Images: " https://cdn.example.com/video-top.gif ", Link: " https://example.com/top "},
|
||||
{ID: "video-top-empty", Images: " "},
|
||||
},
|
||||
AList: []Advertisement{{ID: "a-legacy", Images: "https://cdn.example.com/a.gif"}},
|
||||
AppInfoAList: []Advertisement{{ID: "a", Images: "https://cdn.example.com/app-a.gif"}},
|
||||
BList: []Advertisement{{ID: "b", Images: "https://cdn.example.com/b.gif"}},
|
||||
DialogList: []Advertisement{
|
||||
{ID: " 1 ", Images: " https://cdn.example.com/ad.webp\\ ", Link: " https://example.com ", Title: " 广告一 "},
|
||||
{ID: "2", Images: " ", Title: "无图广告"},
|
||||
@@ -56,17 +58,19 @@ func TestBuildAppConfigVMIncludesValidAdvertisements(t *testing.T) {
|
||||
if len(vm.Advitise.NineGridList) != 4 {
|
||||
t.Fatalf("Advitise.NineGridList length = %d, want raw length 4", len(vm.Advitise.NineGridList))
|
||||
}
|
||||
if len(vm.DetailTopList) != 1 || vm.DetailTopList[0].ID != "top" {
|
||||
t.Fatalf("DetailTopList = %#v", vm.DetailTopList)
|
||||
}
|
||||
if len(vm.NineGridList) != 3 {
|
||||
t.Fatalf("NineGridList length = %d, want 3", len(vm.NineGridList))
|
||||
}
|
||||
if len(vm.DetailBannerList) != 1 || vm.DetailBannerList[0].ID != "detail" {
|
||||
// 详情横幅优先 videoTopList(本站后台字段),无效图片被过滤
|
||||
if len(vm.DetailBannerList) != 1 || vm.DetailBannerList[0].ID != "video-top" || vm.DetailBannerList[0].Images != "https://cdn.example.com/video-top.gif" {
|
||||
t.Fatalf("DetailBannerList = %#v", vm.DetailBannerList)
|
||||
}
|
||||
if len(vm.BottomBanner) != 1 || vm.BottomBanner[0].ID != "bottom" || vm.BottomBanner[0].Images != "https://cdn.example.com/bottom.gif" {
|
||||
t.Fatalf("BottomBanner = %#v", vm.BottomBanner)
|
||||
// 播放页小图标优先 appInfoAList;首页小图标无 appInfoBList 时回退 BList
|
||||
if len(vm.AList) != 1 || vm.AList[0].ID != "a" {
|
||||
t.Fatalf("AList = %#v", vm.AList)
|
||||
}
|
||||
if len(vm.BList) != 1 || vm.BList[0].ID != "b" {
|
||||
t.Fatalf("BList = %#v", vm.BList)
|
||||
}
|
||||
if len(vm.DialogList) != 1 {
|
||||
t.Fatalf("DialogList length = %d, want 1", len(vm.DialogList))
|
||||
@@ -77,15 +81,26 @@ func TestBuildAppConfigVMIncludesValidAdvertisements(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestNineGridRowReturnsTwoItemsPerRow(t *testing.T) {
|
||||
cfg := AppConfigVM{NineGridList: []Advertisement{{ID: "1"}, {ID: "2"}, {ID: "3"}}}
|
||||
if got := cfg.NineGridRow(0); len(got) != 2 || got[0].ID != "1" || got[1].ID != "2" {
|
||||
t.Fatalf("NineGridRow(0) = %#v", got)
|
||||
func TestAdvertisementClickTrackable(t *testing.T) {
|
||||
cases := []struct {
|
||||
ad Advertisement
|
||||
wantID int64
|
||||
trackable bool
|
||||
}{
|
||||
{Advertisement{ID: "1138200002", Location: 2}, 1138200002, true},
|
||||
{Advertisement{ID: " 1138200012 ", Location: 12}, 1138200012, true},
|
||||
{Advertisement{ID: "1138200003", Location: 0}, 1138200003, false},
|
||||
{Advertisement{ID: "", Location: 3}, 0, false},
|
||||
{Advertisement{ID: "0", Location: 3}, 0, false},
|
||||
{Advertisement{ID: "-5", Location: 3}, 0, false},
|
||||
{Advertisement{ID: "abc", Location: 3}, 0, false},
|
||||
}
|
||||
if got := cfg.NineGridRow(1); len(got) != 1 || got[0].ID != "3" {
|
||||
t.Fatalf("NineGridRow(1) = %#v", got)
|
||||
}
|
||||
if got := cfg.NineGridRow(2); len(got) != 0 {
|
||||
t.Fatalf("NineGridRow(2) = %#v, want empty", got)
|
||||
for _, tc := range cases {
|
||||
if got := tc.ad.ClickID(); got != tc.wantID {
|
||||
t.Fatalf("ClickID(%q) = %d, want %d", tc.ad.ID, got, tc.wantID)
|
||||
}
|
||||
if got := tc.ad.ClickTrackable(); got != tc.trackable {
|
||||
t.Fatalf("ClickTrackable(%q, %d) = %v, want %v", tc.ad.ID, tc.ad.Location, got, tc.trackable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -737,13 +737,13 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Figma: 1431×178 banner frame — stretch, 178px, radius 12, image cover-crop */
|
||||
/* 详情横幅:按素材 720×150 等比展示,避免裁切 */
|
||||
.content-ad-stack a {
|
||||
display: block;
|
||||
position: relative;
|
||||
align-self: stretch;
|
||||
width: 100%;
|
||||
height: 178px;
|
||||
aspect-ratio: 720 / 150;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
}
|
||||
@@ -865,7 +865,6 @@
|
||||
.content-ad-stack { gap: calc(12px * var(--detail-s)); }
|
||||
|
||||
.content-ad-stack a {
|
||||
height: calc(166px * var(--detail-s));
|
||||
border-radius: calc(12px * var(--detail-s));
|
||||
}
|
||||
|
||||
@@ -1001,9 +1000,11 @@
|
||||
.detail-h5-top-actions,
|
||||
.square-promo--pc-only,
|
||||
.content-official-info,
|
||||
.content-ad-stack,
|
||||
.content-column-divider { display: none !important; }
|
||||
|
||||
.content-ad-stack { gap: 10px; }
|
||||
.content-ad-stack a { border-radius: 8px; }
|
||||
|
||||
.detail-layout,
|
||||
.detail-main,
|
||||
.detail-sidebar { display: contents; }
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
/* Shared home banner ad row (PC 2-col flex / H5 stack). */
|
||||
|
||||
/* PC Figma: stretch row, 94px, gap 36, two equal flex slots */
|
||||
.home-ad-row {
|
||||
align-self: stretch;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
gap: 36px;
|
||||
width: 100%;
|
||||
flex-shrink: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.home-ad-row.home-ad-row--mobile {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.home-ad-row .home-ad-banner {
|
||||
position: relative;
|
||||
flex: 1 1 calc((100% - 36px) / 2);
|
||||
width: auto;
|
||||
min-width: 0;
|
||||
max-width: calc((100% - 36px) / 2);
|
||||
height: 94px;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.home-ad-row .home-ad-banner img {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.home-ad-row {
|
||||
gap: 36px;
|
||||
}
|
||||
|
||||
.home-ad-row .home-ad-banner {
|
||||
flex: 1 1 calc((100% - 36px) / 2);
|
||||
max-width: calc((100% - 36px) / 2);
|
||||
height: 94px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.home-ad-row .home-ad-banner img {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.home-ad-row,
|
||||
.home-ad-row.home-ad-row--mobile {
|
||||
height: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
align-self: stretch;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.home-ad-row.home-ad-row--desktop {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* H5 Figma: 343×43 banner — stretch, 43px, radius 6, image cover-crop */
|
||||
.home-ad-row .home-ad-banner {
|
||||
position: relative;
|
||||
align-self: stretch;
|
||||
flex: 0 0 43px;
|
||||
width: 100%;
|
||||
max-width: none;
|
||||
height: 43px;
|
||||
overflow: hidden;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.home-ad-row .home-ad-banner img {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
background: #464646;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/* 九宫格弹窗:深色模糊遮罩 + 4 列应用图标 + 底部关闭按钮(对齐 huangguocg.com) */
|
||||
.nine-grid-mask {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 1900;
|
||||
padding: 40px 24px;
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgba(0, 0, 0, 0.85);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
backdrop-filter: blur(12px);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.nine-grid-mask.is-open {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.nine-grid-panel {
|
||||
width: min(520px, 100%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.nine-grid-list {
|
||||
width: 100%;
|
||||
max-height: 70vh;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 28px 24px;
|
||||
overflow-y: auto;
|
||||
overscroll-behavior: contain;
|
||||
}
|
||||
|
||||
.nine-grid-item {
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.nine-grid-item[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nine-grid-icon {
|
||||
width: 100%;
|
||||
max-width: 80px;
|
||||
aspect-ratio: 1;
|
||||
display: block;
|
||||
object-fit: cover;
|
||||
border-radius: 18px;
|
||||
}
|
||||
|
||||
.nine-grid-name {
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.nine-grid-close {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.nine-grid-close img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.nine-grid-panel {
|
||||
width: min(360px, 100%);
|
||||
}
|
||||
|
||||
.nine-grid-list {
|
||||
gap: 20px 12px;
|
||||
}
|
||||
|
||||
.nine-grid-icon {
|
||||
max-width: 70px;
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.nine-grid-name {
|
||||
font-size: 13px;
|
||||
line-height: 18px;
|
||||
}
|
||||
}
|
||||
@@ -2784,7 +2784,6 @@ a.play-info-tag:focus-visible {
|
||||
|
||||
.square-promo--pc-only,
|
||||
.content-official-info,
|
||||
.content-ad-stack,
|
||||
.content-column-divider,
|
||||
.play-sidebar,
|
||||
.play-download-btn { display: none !important; }
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* 广告点击上报:POST /api/app/ads/click(本站 Go 服务代理到上游,appId 由服务端固定为 12)。
|
||||
* - 广告元素由服务端模板输出 data-ads-id / data-ads-location,ID 无效时不输出,即不上报
|
||||
* - document 捕获阶段监听 click 与 auxclick(中键),不阻止默认行为、不影响广告链接打开
|
||||
* - 不依赖 request.js(导航页未加载),失败静默
|
||||
*/
|
||||
(function () {
|
||||
if (window.__adClickBound) return;
|
||||
window.__adClickBound = true;
|
||||
|
||||
var ENDPOINT = "/api/app/ads/click";
|
||||
|
||||
function positiveInt(value) {
|
||||
var text = String(value == null ? "" : value).trim();
|
||||
if (!/^\d+$/.test(text)) return 0;
|
||||
var number = Number(text);
|
||||
return Number.isSafeInteger(number) && number > 0 ? number : 0;
|
||||
}
|
||||
|
||||
function payloadFrom(target) {
|
||||
if (!target || typeof target.closest !== "function") return null;
|
||||
var el = target.closest("[data-ads-id]");
|
||||
if (!el) return null;
|
||||
var adsId = positiveInt(el.getAttribute("data-ads-id"));
|
||||
var location = positiveInt(el.getAttribute("data-ads-location"));
|
||||
return adsId && location ? { adsId: adsId, location: location } : null;
|
||||
}
|
||||
|
||||
function report(payload) {
|
||||
try {
|
||||
fetch(ENDPOINT, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json", Accept: "application/json" },
|
||||
body: JSON.stringify(payload),
|
||||
credentials: "same-origin",
|
||||
keepalive: true,
|
||||
}).catch(function () {});
|
||||
} catch (error) {
|
||||
// 上报失败不影响广告跳转。
|
||||
}
|
||||
}
|
||||
|
||||
function onClick(event) {
|
||||
if (event.type === "auxclick" && event.button !== 1) return;
|
||||
var target = event.target;
|
||||
if (target && target.nodeType !== 1) target = target.parentElement;
|
||||
var payload = payloadFrom(target);
|
||||
if (payload) report(payload);
|
||||
}
|
||||
|
||||
document.addEventListener("click", onClick, true);
|
||||
document.addEventListener("auxclick", onClick, true);
|
||||
})();
|
||||
@@ -1,14 +1,21 @@
|
||||
(function () {
|
||||
// 弹窗广告队列结束(含没有 / 已关闭过)后通知九宫格弹窗:年龄确认 → 弹窗广告 → 九宫格
|
||||
function markDone() {
|
||||
if (window.__dialogAdDone) return;
|
||||
window.__dialogAdDone = true;
|
||||
document.dispatchEvent(new CustomEvent("dialogad:done"));
|
||||
}
|
||||
|
||||
var QUEUE_VERSION = "2";
|
||||
var DISMISSED_KEY = "dialogAdDismissed";
|
||||
var PROGRESS_KEY = "dialogAdProgress";
|
||||
var mask = document.querySelector("[data-dialog-ad]");
|
||||
var previousBodyOverflow = "";
|
||||
var hasDisplayedItem = false;
|
||||
if (!mask) return;
|
||||
if (!mask) return markDone();
|
||||
|
||||
var items = Array.prototype.slice.call(mask.querySelectorAll("[data-dialog-ad-item]"));
|
||||
if (!items.length) return;
|
||||
if (!items.length) return markDone();
|
||||
|
||||
var queueSignature =
|
||||
QUEUE_VERSION +
|
||||
@@ -111,7 +118,8 @@
|
||||
mask.classList.remove("is-open");
|
||||
mask.hidden = true;
|
||||
mask.setAttribute("hidden", "");
|
||||
document.body.style.overflow = previousBodyOverflow;
|
||||
document.body.style.overflow = previousBodyOverflow === "hidden" ? "" : previousBodyOverflow;
|
||||
markDone();
|
||||
}
|
||||
|
||||
function showWhenAgeGateAllows() {
|
||||
@@ -215,7 +223,7 @@
|
||||
}
|
||||
});
|
||||
|
||||
if (isDismissed()) return;
|
||||
if (isDismissed()) return markDone();
|
||||
if (currentIndex >= items.length) {
|
||||
finishQueue();
|
||||
return;
|
||||
|
||||
@@ -47,11 +47,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
var confirmBtn = mask.querySelector("[data-eight-pop-confirm]");
|
||||
// 确认按钮和右下角关闭按钮(X)都视为确认年龄并进入网站。
|
||||
var confirmBtns = mask.querySelectorAll("[data-eight-pop-confirm]");
|
||||
var exitBtns = mask.querySelectorAll("[data-eight-pop-exit]");
|
||||
if (confirmBtn) {
|
||||
confirmBtn.addEventListener("click", confirmAge);
|
||||
}
|
||||
confirmBtns.forEach(function (button) {
|
||||
button.addEventListener("click", confirmAge);
|
||||
});
|
||||
exitBtns.forEach(function (button) {
|
||||
button.addEventListener("click", exitSite);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
(function () {
|
||||
// 九宫格弹窗(对齐 huangguocg.com):年龄确认 → 弹窗广告 → 九宫格。
|
||||
// 点任一应用 / 关闭按钮 / 空白处 / Esc 即关闭;同一会话内容不变时不再弹出。
|
||||
var DISMISSED_KEY = "gridAdDismissed";
|
||||
var mask = document.querySelector("[data-nine-grid]");
|
||||
if (!mask) return;
|
||||
|
||||
var items = Array.prototype.slice.call(mask.querySelectorAll("[data-nine-grid-item]"));
|
||||
if (!items.length) return;
|
||||
|
||||
var signature = JSON.stringify(
|
||||
items.map(function (item) {
|
||||
var image = item.querySelector("[data-nine-grid-src]");
|
||||
return [
|
||||
item.getAttribute("data-creative-id") || "",
|
||||
image ? image.getAttribute("data-nine-grid-src") : "",
|
||||
item.getAttribute("href") || "",
|
||||
];
|
||||
}),
|
||||
);
|
||||
|
||||
function readSession(key) {
|
||||
try {
|
||||
return window.sessionStorage.getItem(key) || "";
|
||||
} catch (error) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
function writeSession(key, value) {
|
||||
try {
|
||||
window.sessionStorage.setItem(key, value);
|
||||
} catch (error) {
|
||||
// sessionStorage 不可用时仅本页关闭。
|
||||
}
|
||||
}
|
||||
|
||||
if (readSession(DISMISSED_KEY) === signature) return;
|
||||
|
||||
function waitForImage(image) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
if (image.complete && image.naturalWidth > 0 && image.src.indexOf("placeholder") === -1) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
var timeout = window.setTimeout(function () {
|
||||
cleanup();
|
||||
reject(new Error("image load timeout"));
|
||||
}, 12000);
|
||||
function cleanup() {
|
||||
window.clearTimeout(timeout);
|
||||
image.removeEventListener("load", handleLoad);
|
||||
image.removeEventListener("error", handleError);
|
||||
}
|
||||
function handleLoad() {
|
||||
cleanup();
|
||||
if (image.naturalWidth > 0) resolve();
|
||||
else reject(new Error("image decode failed"));
|
||||
}
|
||||
function handleError() {
|
||||
cleanup();
|
||||
reject(new Error("image load failed"));
|
||||
}
|
||||
image.addEventListener("load", handleLoad);
|
||||
image.addEventListener("error", handleError);
|
||||
});
|
||||
}
|
||||
|
||||
function loadIcon(image) {
|
||||
var source = image.getAttribute("data-nine-grid-src") || "";
|
||||
if (!source) return Promise.reject(new Error("image source is empty"));
|
||||
if (typeof window.processImage === "function") {
|
||||
return window.processImage(source, image).then(function (result) {
|
||||
if (!result) throw new Error("image decrypt failed");
|
||||
return waitForImage(image);
|
||||
});
|
||||
}
|
||||
image.src = source;
|
||||
return waitForImage(image);
|
||||
}
|
||||
|
||||
var opened = false;
|
||||
|
||||
function open() {
|
||||
if (opened) return;
|
||||
opened = true;
|
||||
mask.hidden = false;
|
||||
mask.removeAttribute("hidden");
|
||||
mask.classList.add("is-open");
|
||||
document.body.style.overflow = "hidden";
|
||||
}
|
||||
|
||||
function close() {
|
||||
if (!opened) return;
|
||||
opened = false;
|
||||
writeSession(DISMISSED_KEY, signature);
|
||||
mask.classList.remove("is-open");
|
||||
mask.hidden = true;
|
||||
mask.setAttribute("hidden", "");
|
||||
document.body.style.overflow = "";
|
||||
}
|
||||
|
||||
// 依次等待:年龄确认关闭 → 弹窗广告队列结束(没有弹窗广告时直接放行)
|
||||
function whenStartupReady(callback) {
|
||||
var ageGate = document.getElementById("eightPop");
|
||||
if (ageGate && ageGate.classList.contains("is-open")) {
|
||||
document.addEventListener(
|
||||
"eightpop:closed",
|
||||
function () {
|
||||
whenStartupReady(callback);
|
||||
},
|
||||
{ once: true },
|
||||
);
|
||||
return;
|
||||
}
|
||||
var hasDialogAd = !!document.querySelector("[data-dialog-ad]");
|
||||
if (hasDialogAd && !window.__dialogAdDone) {
|
||||
document.addEventListener("dialogad:done", callback, { once: true });
|
||||
return;
|
||||
}
|
||||
callback();
|
||||
}
|
||||
|
||||
// 只展示图标加载成功的应用;一个都没加载成功则不弹
|
||||
var ready = Promise.all(
|
||||
items.map(function (item) {
|
||||
var image = item.querySelector("[data-nine-grid-src]");
|
||||
if (!image) return Promise.resolve(false);
|
||||
return loadIcon(image)
|
||||
.then(function () {
|
||||
item.hidden = false;
|
||||
item.removeAttribute("hidden");
|
||||
return true;
|
||||
})
|
||||
.catch(function () {
|
||||
return false;
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
whenStartupReady(function () {
|
||||
ready.then(function (loaded) {
|
||||
if (loaded.some(Boolean)) open();
|
||||
});
|
||||
});
|
||||
|
||||
mask.addEventListener("click", function (event) {
|
||||
if (event.target === mask || event.target.closest("[data-nine-grid-close]") || event.target.closest("[data-nine-grid-item]")) {
|
||||
close();
|
||||
}
|
||||
});
|
||||
|
||||
mask.querySelector(".nine-grid-panel").addEventListener("click", function (event) {
|
||||
if (event.target === event.currentTarget) close();
|
||||
});
|
||||
|
||||
document.addEventListener("keydown", function (event) {
|
||||
if (event.key === "Escape" && opened) close();
|
||||
});
|
||||
})();
|
||||
@@ -1,5 +1,6 @@
|
||||
{{define "contentPromo"}}
|
||||
{{template "squarePromo" dict "Ads" .appConfig.DetailTopList "SlotKey" "detail_top" "SlotName" "详情顶部广告" "Label" "推广内容" "PCOnly" "1"}}
|
||||
{{/* 播放页小图标:后台位置 12(AList) */}}
|
||||
{{template "squarePromo" dict "Ads" .appConfig.AList "SlotKey" "play_icons" "SlotName" "播放页小图标" "Label" "推广"}}
|
||||
{{end}}
|
||||
|
||||
{{define "contentOfficialInfo"}}
|
||||
@@ -34,11 +35,12 @@
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{/* 详情横幅:后台位置 3(本站字段 videoTopList),素材 720×150 */}}
|
||||
{{define "contentAds"}}
|
||||
{{if .appConfig.DetailBannerList}}
|
||||
<div class="content-ad-stack" aria-label="广告">
|
||||
{{range $ad := .appConfig.DetailBannerList}}
|
||||
<a {{if $ad.Link}}href="{{$ad.Link}}" target="_blank" rel="sponsored nofollow noopener noreferrer"{{else}}aria-disabled="true"{{end}} data-creative-id="{{$ad.ID}}">
|
||||
<a {{if $ad.Link}}href="{{$ad.Link}}" target="_blank" rel="sponsored nofollow noopener noreferrer"{{else}}aria-disabled="true"{{end}} data-creative-id="{{$ad.ID}}"{{if $ad.ClickTrackable}} data-ads-id="{{$ad.ClickID}}" data-ads-location="{{$ad.Location}}"{{end}}>
|
||||
<img class="lazy" src="/static/images/placeholder.png?v=2" data-src="{{$ad.Images}}" alt="{{$ad.Title}}" title="{{$ad.Title}}" />
|
||||
</a>
|
||||
{{end}}
|
||||
|
||||
@@ -20,11 +20,11 @@
|
||||
hidden
|
||||
>
|
||||
{{if $dialog.Link}}
|
||||
<a class="dialog-ad-media" href="{{$dialog.Link}}" target="_blank" rel="sponsored nofollow noopener noreferrer" aria-label="{{if $dialog.Title}}{{$dialog.Title}}{{else}}查看广告{{end}}" data-creative-id="{{$dialog.ID}}">
|
||||
<a class="dialog-ad-media" href="{{$dialog.Link}}" target="_blank" rel="sponsored nofollow noopener noreferrer" aria-label="{{if $dialog.Title}}{{$dialog.Title}}{{else}}查看广告{{end}}" data-creative-id="{{$dialog.ID}}"{{if $dialog.ClickTrackable}} data-ads-id="{{$dialog.ClickID}}" data-ads-location="{{$dialog.Location}}"{{end}}>
|
||||
<img class="dialog-ad-image" src="/static/images/placeholder.png?v=2" data-dialog-ad-src="{{$dialog.Images}}" alt="{{$dialog.Title}}" title="{{$dialog.Title}}" decoding="async" />
|
||||
</a>
|
||||
{{else}}
|
||||
<div class="dialog-ad-media">
|
||||
<div class="dialog-ad-media"{{if $dialog.ClickTrackable}} data-ads-id="{{$dialog.ClickID}}" data-ads-location="{{$dialog.Location}}"{{end}}>
|
||||
<img class="dialog-ad-image" src="/static/images/placeholder.png?v=2" data-dialog-ad-src="{{$dialog.Images}}" alt="{{$dialog.Title}}" title="{{$dialog.Title}}" decoding="async" />
|
||||
</div>
|
||||
{{end}}
|
||||
@@ -34,6 +34,6 @@
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<script defer src="/static/js/pages/dialogAd.js?v=5"></script>
|
||||
<script defer src="/static/js/pages/dialogAd.js?v=6"></script>
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
<button class="eight-pop-btn eight-pop-btn--exit" type="button" data-eight-pop-exit>我未满18岁-退出</button>
|
||||
</div>
|
||||
</div>
|
||||
<button class="eight-pop-close" type="button" data-eight-pop-exit aria-label="关闭并退出访问">
|
||||
<button class="eight-pop-close" type="button" data-eight-pop-confirm aria-label="关闭并进入网站">
|
||||
<img src="/static/images/figma-age/close.svg" width="36" height="36" alt="" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/static/js/pages/eightPop.js?v=4"></script>
|
||||
<script src="/static/js/pages/eightPop.js?v=5"></script>
|
||||
{{end}}
|
||||
|
||||
@@ -166,7 +166,8 @@
|
||||
</div>
|
||||
|
||||
<script defer src="/static/js/common/request.js?v=3"></script>
|
||||
<script defer src="/static/js/common/adClick.js?v=1"></script>
|
||||
<script defer src="/static/common/imgDecypt.js?v=2"></script>
|
||||
<script defer src="/static/js/pages/header.js?v=10"></script>
|
||||
<script defer src="/static/js/pages/dialogLoader.js?v=7"></script>
|
||||
{{template "toast" .}} {{template "eightPop" .}} {{template "dialogAd" .}} {{end}}
|
||||
{{template "toast" .}} {{template "eightPop" .}} {{template "dialogAd" .}} {{template "nineGridDialog" .}} {{end}}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
{{define "homeAdRow"}}
|
||||
{{$ads := .Ads}}
|
||||
{{if $ads}}
|
||||
<link rel="stylesheet" href="/static/css/homeAdRow.css?v=3" />
|
||||
<div
|
||||
class="home-ad-row{{if .ExtraClass}} {{.ExtraClass}}{{end}}"
|
||||
aria-label="{{if .Label}}{{.Label}}{{else}}广告{{end}}"
|
||||
>
|
||||
{{range $ad := $ads}}
|
||||
<a
|
||||
class="home-ad-banner"
|
||||
{{if $ad.Link}}href="{{$ad.Link}}"
|
||||
target="_blank"
|
||||
rel="sponsored nofollow noopener noreferrer"
|
||||
{{else}}aria-disabled="true"
|
||||
{{end}}
|
||||
data-creative-id="{{$ad.ID}}"
|
||||
>
|
||||
<img
|
||||
class="lazy"
|
||||
src="/static/images/placeholder.png?v=2"
|
||||
data-src="{{$ad.Images}}"
|
||||
alt="{{$ad.Title}}"
|
||||
title="{{$ad.Title}}"
|
||||
/>
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
@@ -0,0 +1,29 @@
|
||||
{{define "nineGridDialog"}}
|
||||
{{/* 九宫格弹窗:后台位置 2(nineGridList),在年龄确认、弹窗广告之后弹出 */}}
|
||||
{{if .appConfig.NineGridList}}
|
||||
<link rel="stylesheet" href="/static/css/nineGridDialog.css?v=1" />
|
||||
<div class="nine-grid-mask" id="nineGridDialog" data-nine-grid hidden>
|
||||
<div class="nine-grid-panel" role="dialog" aria-modal="true" aria-label="推荐应用">
|
||||
<div class="nine-grid-list">
|
||||
{{range $ad := .appConfig.NineGridList}}
|
||||
<a
|
||||
class="nine-grid-item"
|
||||
{{if $ad.Link}}href="{{$ad.Link}}" target="_blank" rel="sponsored nofollow noopener noreferrer"{{else}}aria-disabled="true"{{end}}
|
||||
data-nine-grid-item
|
||||
data-creative-id="{{$ad.ID}}"
|
||||
{{if $ad.ClickTrackable}}data-ads-id="{{$ad.ClickID}}" data-ads-location="{{$ad.Location}}"{{end}}
|
||||
hidden
|
||||
>
|
||||
<img class="nine-grid-icon" src="/static/images/placeholder.png?v=2" data-nine-grid-src="{{$ad.Images}}" alt="{{$ad.Title}}" title="{{$ad.Title}}" decoding="async" />
|
||||
<span class="nine-grid-name">{{if $ad.Title}}{{$ad.Title}}{{else}}推荐应用{{end}}</span>
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
<button class="nine-grid-close" type="button" data-nine-grid-close aria-label="关闭">
|
||||
<img src="/static/images/figma-dialog-ad/close.svg" width="36" height="36" alt="" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<script defer src="/static/js/pages/nineGridDialog.js?v=1"></script>
|
||||
{{end}}
|
||||
{{end}}
|
||||
@@ -18,6 +18,7 @@
|
||||
{{else}}aria-disabled="true"
|
||||
{{end}}
|
||||
data-creative-id="{{$ad.ID}}"
|
||||
{{if $ad.ClickTrackable}}data-ads-id="{{$ad.ClickID}}" data-ads-location="{{$ad.Location}}"{{end}}
|
||||
>
|
||||
<span class="square-promo__cover">
|
||||
<img
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<script type="application/ld+json">{{.jsonLD}}</script>
|
||||
{{end}}
|
||||
<link rel="stylesheet" href="/static/css/index.css?v=27">
|
||||
<link rel="stylesheet" href="/static/css/detail.css?v=31">
|
||||
<link rel="stylesheet" href="/static/css/detail.css?v=32">
|
||||
<link rel="stylesheet" href="/static/css/detailHero.css?v=5">
|
||||
<link rel="stylesheet" href="/static/css/dramaTile.css?v=1" />
|
||||
|
||||
|
||||
@@ -92,7 +92,8 @@
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{template "squarePromo" dict "Ads" .appConfig.DetailTopList "SlotKey" "home_detail_top" "SlotName" "首页方块广告" "Label" "广告"}}
|
||||
{{/* 首页小图标:后台位置 13(BList) */}}
|
||||
{{template "squarePromo" dict "Ads" .appConfig.BList "SlotKey" "home_icons" "SlotName" "首页小图标" "Label" "推广"}}
|
||||
|
||||
{{range $catIndex, $category := .homeCategoryData}}
|
||||
{{if contains $category.Name "热榜"}}
|
||||
@@ -177,7 +178,6 @@
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{template "homeAdRow" dict "Ads" ($.appConfig.NineGridRow $catIndex) "SlotKey" "home_nine_grid" "SlotName" "首页横幅广告" "Label" "广告"}}
|
||||
{{end}}
|
||||
|
||||
{{if .homeRecommendThemes}}
|
||||
|
||||
@@ -61,16 +61,6 @@
|
||||
{{end}}
|
||||
</div>
|
||||
{{template "pagination" .}}
|
||||
{{template "homeAdRow" dict "Ads" .appConfig.NineGridList "SlotKey" "list_nine_grid" "SlotName" "片库横幅广告" "Label" "广告"}}
|
||||
{{if .appConfig.BottomBanner}}
|
||||
<div class="list-ad-list" aria-label="广告">
|
||||
{{range $ad := .appConfig.BottomBanner}}
|
||||
<a class="list-ad" {{if $ad.Link}}href="{{$ad.Link}}" target="_blank" rel="sponsored nofollow noopener noreferrer"{{else}}aria-disabled="true"{{end}} data-creative-id="{{$ad.ID}}">
|
||||
<img class="lazy" src="/static/images/placeholder.png?v=2" data-src="{{$ad.Images}}" alt="{{$ad.Title}}" title="{{$ad.Title}}" width="758" height="94">
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</main>
|
||||
{{template "footer" .}}
|
||||
|
||||
@@ -106,7 +106,9 @@
|
||||
{{template "pageConsole" .}}
|
||||
<noscript><div><img src="https://mc.yandex.ru/watch/113733101" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
|
||||
<script defer src="/static/common/imgDecypt.js?v=2"></script>
|
||||
<script defer src="/static/js/common/adClick.js?v=1"></script>
|
||||
{{template "dialogAd" .}}
|
||||
{{template "nineGridDialog" .}}
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
<script type="application/ld+json">{{.jsonLD}}</script>
|
||||
{{end}}
|
||||
<link rel="stylesheet" href="/static/css/index.css?v=27">
|
||||
<link rel="stylesheet" href="/static/css/detail.css?v=31">
|
||||
<link rel="stylesheet" href="/static/css/play.css?v=29">
|
||||
<link rel="stylesheet" href="/static/css/detail.css?v=32">
|
||||
<link rel="stylesheet" href="/static/css/play.css?v=30">
|
||||
<link rel="stylesheet" href="/static/css/dramaTile.css?v=1" />
|
||||
<link rel="stylesheet" href="/static/common/DPlayer.min.css">
|
||||
<script defer src="/static/common/hls.min.js"></script>
|
||||
|
||||
@@ -66,16 +66,6 @@
|
||||
{{end}}
|
||||
</div>
|
||||
{{template "pagination" .}}
|
||||
{{template "homeAdRow" dict "Ads" .appConfig.NineGridList "SlotKey" "rank_nine_grid" "SlotName" "排行榜横幅广告" "Label" "广告"}}
|
||||
{{if .appConfig.BottomBanner}}
|
||||
<div class="rank-ad-list" aria-label="广告">
|
||||
{{range $ad := .appConfig.BottomBanner}}
|
||||
<a class="rank-ad" {{if $ad.Link}}href="{{$ad.Link}}" target="_blank" rel="sponsored nofollow noopener noreferrer"{{else}}aria-disabled="true"{{end}} data-creative-id="{{$ad.ID}}">
|
||||
<img class="lazy" src="/static/images/placeholder.png?v=2" data-src="{{$ad.Images}}" alt="{{$ad.Title}}" title="{{$ad.Title}}" width="758" height="94">
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</main>
|
||||
{{template "footer" .}}
|
||||
|
||||
@@ -57,16 +57,6 @@
|
||||
{{end}}
|
||||
</div>
|
||||
{{template "pagination" .}}
|
||||
{{template "homeAdRow" dict "Ads" .appConfig.NineGridList "SlotKey" "series_nine_grid" "SlotName" "剧集横幅广告" "Label" "广告"}}
|
||||
{{if .appConfig.BottomBanner}}
|
||||
<div class="list-ad-list" aria-label="广告">
|
||||
{{range $ad := .appConfig.BottomBanner}}
|
||||
<a class="list-ad" {{if $ad.Link}}href="{{$ad.Link}}" target="_blank" rel="sponsored nofollow noopener noreferrer"{{else}}aria-disabled="true"{{end}} data-creative-id="{{$ad.ID}}">
|
||||
<img class="lazy" src="/static/images/placeholder.png?v=2" data-src="{{$ad.Images}}" alt="{{$ad.Title}}" title="{{$ad.Title}}" width="758" height="94">
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</main>
|
||||
{{template "footer" .}}
|
||||
|
||||
@@ -47,17 +47,7 @@
|
||||
|
||||
{{template "pagination" .}}
|
||||
|
||||
{{template "homeAdRow" dict "Ads" .appConfig.NineGridList "SlotKey" "topic_nine_grid" "SlotName" "专题横幅广告" "Label" "广告"}}
|
||||
|
||||
{{if .appConfig.BottomBanner}}
|
||||
<div class="theme-index-ads" aria-label="广告">
|
||||
{{range $ad := .appConfig.BottomBanner}}
|
||||
<a class="theme-index-ad" {{if $ad.Link}}href="{{$ad.Link}}" target="_blank" rel="sponsored nofollow noopener noreferrer"{{else}}aria-disabled="true"{{end}} data-creative-id="{{$ad.ID}}">
|
||||
<img class="lazy" src="/static/images/placeholder.png?v=2" data-src="{{$ad.Images}}" alt="{{$ad.Title}}" title="{{$ad.Title}}" width="758" height="94" />
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</main>
|
||||
{{template "footer" .}}
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user