播放页引导下载添加
This commit is contained in:
@@ -3142,3 +3142,12 @@ html body .hg-footer-original .hg-footer-original-title .footer-brand-text{displ
|
||||
.hg-detail-actions .play-detail-actions{display:flex;flex-direction:row;flex-wrap:wrap;gap:8px}
|
||||
@media(max-width:760px){.hg-detail-actions .play-detail-actions{width:100%}.hg-detail-actions .play-detail-actions>button{flex:1 1 0;min-width:0}.hg-detail-actions .detail-play,.hg-detail-actions .series-download:not([hidden]){flex:1 1 auto;justify-content:center}}
|
||||
@media(max-width:760px){#drama-play-page .hg-detail-actions .play-detail-actions{flex-wrap:nowrap}#drama-play-page .hg-detail-actions .play-detail-actions>button{flex:1 1 0;width:auto;min-width:0;max-width:none;padding:9px 6px;justify-content:center}}
|
||||
.play-screen .hg-app-gate:not([hidden]){position:absolute;inset:0;z-index:6;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px;padding:24px;background:radial-gradient(circle at 50% 40%,#1d1e1ee6,#050505f2);text-align:center}
|
||||
.hg-app-gate-copy{display:flex;flex-direction:column;gap:6px}
|
||||
.hg-app-gate-copy strong{color:#fff;font-size:clamp(17px,2vw,22px);font-weight:700}
|
||||
.hg-app-gate-copy p,.hg-app-gate-fallback{margin:0;color:#c9c9c9;font-size:14px;line-height:1.7}
|
||||
.hg-app-gate-btn:not([hidden]){display:inline-flex;align-items:center;gap:8px;height:46px;padding:0 26px;border-radius:999px;font-size:15px;font-weight:700;text-decoration:none}
|
||||
.hg-app-gate-btn svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.8}
|
||||
.hg-app-gate:has(.hg-app-gate-btn:not([hidden])) .hg-app-gate-fallback{display:none}
|
||||
.hg-app-gate:has(.hg-app-gate-btn[hidden]) .hg-app-gate-copy{display:none}
|
||||
.play-screen:has(.hg-app-gate:not([hidden]))>:not(.hg-app-gate):not(video){visibility:hidden}
|
||||
|
||||
@@ -13,6 +13,11 @@ export function orderedChapters(value:unknown):Chapter[] {
|
||||
return recordList<Chapter>(value).filter(item=>Number.isSafeInteger(item.id)&&item.id>0).sort((a,b)=>(a.currentEpisode||0)-(b.currentEpisode||0));
|
||||
}
|
||||
|
||||
/** Shown in place of the player when this episode has no playable source: invites the visitor to the App. */
|
||||
export function appGate(heading:string,visible=false):string {
|
||||
return `<div class="hg-app-gate"${visible?'':' hidden'}><div class="hg-app-gate-copy"><strong>本集请在 黄果吃瓜 App 观看</strong><p>下载 App 即可继续观看《${escape(heading)}》及全部剧集</p></div><p class="hg-app-gate-fallback">本集视频暂未开放,请稍后再试</p><a class="primary hg-app-gate-btn" data-app-download data-app-download-entry target="_blank" rel="sponsored nofollow noopener noreferrer" hidden><svg viewBox="0 0 24 24" aria-hidden="true"><rect x="6" y="2" width="12" height="20" rx="3"/><path d="M10 5h4M11 19h2"/></svg><span>下载 App 继续观看</span></a></div>`;
|
||||
}
|
||||
|
||||
/** Recommended titles replace comments: crawlable internal links with full context for each title. */
|
||||
export function recommendationsMarkup(raw:DramaDetail):string {
|
||||
const related=recordList<Drama>(raw.relatedRecommendData).filter(item=>item.id!==raw.id).slice(0,12);
|
||||
@@ -25,11 +30,11 @@ export function playerMarkup(raw:DramaDetail,ordered:Chapter[],options:PlayerVie
|
||||
const displayTitle=title(raw),episodes=raw.totalEpisode||ordered.length,actionState=chapter||raw;
|
||||
const heading=chapter?`${displayTitle} 第${chapter.currentEpisode||1}集`:displayTitle;
|
||||
const access=isVideo?{allowed:!!playbackUrl(raw.video?.url),gate:playbackUrl(raw.video?.url)?'':'unavailable',source:playbackUrl(raw.video?.url)} as const:chapterAccess(chapter);
|
||||
const previewSource=isVideo?'':playbackUrl(raw.preview),mode=initialPlayMode(access,raw.preview);
|
||||
const previewSource=isVideo?'':playbackUrl(raw.preview),mode=initialPlayMode(access,raw.preview),blocked=!!chapter&&mode==='main'&&!access.allowed;
|
||||
const modeTabs=previewSource?`<div class="channel-tabs play-mode-tabs" role="group" aria-label="播放内容"><button type="button" data-play-mode="main" aria-pressed="${mode==='main'}">正片</button><button type="button" data-play-mode="preview" aria-pressed="${mode==='preview'}">免费预告</button></div>`:'';
|
||||
const initialEpisodePage=chapter?Math.floor(Math.max(0,ordered.findIndex(item=>item.id===chapter.id))/45):0;
|
||||
const actions=()=>`<div class="play-detail-actions"><button type="button" data-engage="like" aria-pressed="${actionState.isLike===1}">${detailActionIcon('like')}<span>${actionState.isLike===1?'已点赞':'点赞'}</span></button><button type="button" data-engage="collect" aria-pressed="${actionState.isCollect===1}">${detailActionIcon('save')}<span>${actionState.isCollect===1?'已收藏':'收藏'}</span></button><button type="button" data-share>${detailActionIcon('share')}<span>分享</span></button></div>`;
|
||||
const screen=()=>`${modeTabs}<div class="play-screen" data-play-mode="${mode}"><video ${INLINE_VIDEO_ATTRIBUTES} preload="metadata" ${imageAttributes(raw.cover||raw.coverImg,undefined,'poster')} aria-label="${escape(heading)}"></video><div class="play-screen-overlay"><button type="button" aria-label="播放">▶</button><p class="play-source-status" role="status">正在准备视频…</p></div><div class="play-screen-controls"><button data-play-action="next" ${!chapter||ordered.at(-1)?.id===chapter.id?'disabled':''}>下一集</button></div></div>`;
|
||||
const screen=()=>`${modeTabs}<div class="play-screen" data-play-mode="${mode}"><video ${INLINE_VIDEO_ATTRIBUTES} preload="metadata" ${imageAttributes(raw.cover||raw.coverImg,undefined,'poster')} aria-label="${escape(heading)}"></video><div class="play-screen-overlay"><button type="button" aria-label="播放"${blocked?' hidden':''}>▶</button><p class="play-source-status" role="status"${blocked?' hidden':''}>正在准备视频…</p></div>${appGate(heading,blocked)}<div class="play-screen-controls"><button data-play-action="next" ${!chapter||ordered.at(-1)?.id===chapter.id?'disabled':''}>下一集</button></div></div>`;
|
||||
const applicationAds=promotionRow(raw.advitise?.nineGridList||home.advitise?.nineGridList);
|
||||
const bannerAds=ads(raw.advitise?.detailbannerList,'play-banner-ad');
|
||||
const watchInfo=()=>`<section class="hg-watch-info">${chapter?`<span class="play-episode-caption">正在观看 第 ${chapter.currentEpisode||1} 集 / 共 ${episodes} 集</span>`:''}<h1 id="play-detail-title">${escape(heading)}</h1>${detailFacts(raw,episodes,actionState)}${actions()}</section>${synopsisMarkup(raw,`《${displayTitle}》剧情简介`)}`;
|
||||
|
||||
@@ -97,11 +97,12 @@ export async function renderPlayer(app:SiteContext,id:number,chapterId?:number,i
|
||||
page.querySelectorAll<HTMLButtonElement>('[data-play-mode]').forEach(button=>{if(button.tagName==='BUTTON')button.setAttribute('aria-pressed',String(button.dataset.playMode===mode));});
|
||||
const blocked=mode==='main'&&!access.allowed;
|
||||
box.querySelector('.ui-empty-state')?.remove();
|
||||
const center=box.querySelector<HTMLButtonElement>('[data-media="toggle"]');if(center)center.hidden=false;
|
||||
status.hidden=false;
|
||||
const center=box.querySelector<HTMLButtonElement>('[data-media="toggle"]');if(center)center.hidden=blocked;
|
||||
const gate=box.querySelector<HTMLElement>('.hg-app-gate');if(gate)gate.hidden=!blocked;
|
||||
status.hidden=blocked;
|
||||
void media!.setSource(mode==='preview'?previewSource:access.allowed?access.source:'');
|
||||
if(blocked)status.textContent='本集视频暂未开放,请稍后再试';
|
||||
else if(!(mode==='preview'?previewSource:access.source))status.textContent='该剧集暂未提供视频源';
|
||||
// A blocked main episode shows the App gate instead of a status line.
|
||||
if(!blocked&&!(mode==='preview'?previewSource:access.source))status.textContent='该剧集暂未提供视频源';
|
||||
else if(mode==='preview')status.textContent='免费预告 · 点击播放';
|
||||
}
|
||||
page.querySelectorAll<HTMLButtonElement>('button[data-play-mode]').forEach(button=>button.addEventListener('click',()=>{setMode(button.dataset.playMode as PlayMode);if(mode==='preview')void media!.toggle();},{signal}));
|
||||
|
||||
Reference in New Issue
Block a user