Files
web_hgdjc_h5/public/scripts/site-runtime.js
T
2026-11-06 00:13:27 +07:00

121 lines
18 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Layout and player controls retained from the HTML reference. Business data is loaded by the Next.js application.
/* ---- unified-empty-states-script ---- */
const emptyStateImages={"write":"/assets/ce2f84f155d32b0b.png","planet":"/assets/a6ba4b9749786513.png","records":"/assets/51e809aac4f1e40a.png","error":"/assets/7c46ae4811eea7e9.png","purchased":"/assets/b57b58bd55aeee91.png","profile":"/assets/1f0d06c643b6660a.png","content":"/assets/2a5a7edaf95ff943.png","data":"/assets/77dd91d1ecd3d16c.png","search":"/assets/f2ef01f956fdcd80.png","network":"/assets/47632de987649cda.png","messages":"/assets/9bb14f2dd28ab426.png","calendar":"/assets/eb4bee364040817e.png"};
function emptyStateMarkup(kind,options={}){
const defaults={search:['搜索无结果','换个关键词试试,也许下一部好剧就在这里。','查看全部短剧'],data:['暂无数据','这里还没有记录,去发现一些喜欢的短剧吧。','去发现好剧'],error:['加载失败','内容暂时未能加载,请稍后重试。','重新加载'],content:['暂无内容','精彩内容正在准备中,先去看看其他好剧吧。','随便逛逛']};
const config=defaults[kind]||defaults.content,escape=value=>String(value).replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
const title=options.title||config[0],description=options.description||config[1],label=options.action===false?'':(options.label||config[2]);
const action=label?(kind==='error'?'<button type="button" class="ui-empty-action" data-media="retry">'+escape(label)+'</button>':'<a class="ui-empty-action" href="/shorts/">'+escape(label)+'</a>'):'';
return '<div class="ui-empty-state" role="status"><img src="'+(emptyStateImages[options.image||kind]||emptyStateImages.content)+'" alt="'+escape(title)+'" aria-hidden="true"><h3>'+escape(title)+'</h3><p>'+escape(description)+'</p>'+action+'</div>';
}
;
/* ---- sidebar-initial-state ---- */
try{if(localStorage.getItem('jgdj-sidebar-collapsed')==='true')document.documentElement.classList.add('sidebar-collapsed')}catch{}
;
/* ---- collapsible-sidebar-script ---- */
(() => {
const root=document.documentElement;
const toggle=document.getElementById('sidebar-toggle');
const key='jgdj-sidebar-collapsed';
function update(){const collapsed=root.classList.contains('sidebar-collapsed');toggle.setAttribute('aria-expanded',String(!collapsed));toggle.setAttribute('aria-label',collapsed?'展开侧边栏':'收起侧边栏');toggle.title=collapsed?'展开侧边栏':'收起侧边栏'}
const header=toggle.closest('.sidebar-header');
toggle.addEventListener('click',()=>{const collapsed=root.classList.toggle('sidebar-collapsed');header.classList.toggle('just-collapsed',collapsed);try{localStorage.setItem(key,String(collapsed))}catch{}update()});
header.addEventListener('mouseleave',()=>header.classList.remove('just-collapsed'));
header.addEventListener('focusout',()=>header.classList.remove('just-collapsed'));
toggle.addEventListener('keydown',()=>header.classList.remove('just-collapsed'));
update();
})();
;
/* ---- custom-player-controls-script ---- */
function installPlayerControls(screen,currentEpisode=1,actions={}){
const video=screen.querySelector('video'),bar=screen.querySelector('.play-screen-controls'),overlay=screen.querySelector('.play-screen-overlay'),status=screen.querySelector('.play-source-status');
const paths={play:'<path d="m8 5 11 7-11 7Z" fill="currentColor" stroke="none"/>',pause:'<path d="M8 5v14M16 5v14" stroke-width="4"/>',next:'<path d="m5 5 10 7-10 7Z" fill="currentColor" stroke="none"/><path d="M18 5v14"/>',volume:'<path d="M4 9h4l5-4v14l-5-4H4Z"/><path d="M16 8a6 6 0 0 1 0 8m3-11a10 10 0 0 1 0 14"/>',mute:'<path d="M4 9h4l5-4v14l-5-4H4Z"/><path d="m17 9 5 6m0-6-5 6"/>',full:'<path d="M8 3H3v5m13-5h5v5M3 16v5h5m8 0h5v-5"/>',exit:'<path d="M3 8h5V3m8 0v5h5M8 21v-5H3m18 0h-5v5"/>'};
Object.assign(paths,{"play": "<path d=\"M4 18.7591L4 6.62263C4 4.13699 6.70123 2.57713 8.85714 3.81995L14.1201 6.8509L19.3831 9.89455C21.539 11.1374 21.539 14.2444 19.3831 15.4872L14.1201 18.5309L8.85714 21.5618C6.70123 22.8047 4 21.2575 4 18.7591Z\" fill=\"currentColor\" stroke=\"none\"/>", "centerPlay": "<path d=\"M12 3C16.9706 3 21 7.02944 21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3ZM10.7646 8.53613C10.1184 8.15144 9.31065 8.63262 9.31055 9.40234V14.5996C9.31079 15.3692 10.1185 15.8504 10.7646 15.4658L15.1279 12.8672C15.774 12.4822 15.7739 11.5198 15.1279 11.1348L10.7646 8.53613Z\" fill=\"currentColor\" stroke=\"none\"/>", "previous": "<path d=\"M22.0001 6.81803V17.3711C22.0001 19.5325 19.6513 20.8888 17.7766 19.8082L13.2003 17.1726L8.624 14.5261C6.74936 13.4454 6.74936 10.7437 8.624 9.66307L13.2003 7.01652L17.7766 4.381C19.6513 3.30033 22.0001 4.64566 22.0001 6.81803Z\" fill=\"currentColor\" stroke=\"none\"/>\n<path d=\"M3.82705 19.7311C3.37493 19.7311 3 19.3561 3 18.904V5.27431C3 4.82219 3.37493 4.44727 3.82705 4.44727C4.27916 4.44727 4.65409 4.82219 4.65409 5.27431V18.904C4.65409 19.3561 4.27916 19.7311 3.82705 19.7311Z\" fill=\"currentColor\" stroke=\"none\"/>", "next": "<path d=\"M3 6.81803V17.3711C3 19.5325 5.34881 20.8888 7.22345 19.8082L11.7998 17.1726L16.3761 14.5261C18.2507 13.4454 18.2507 10.7437 16.3761 9.66307L11.7998 7.01652L7.22345 4.381C5.34881 3.30033 3 4.64566 3 6.81803Z\" fill=\"currentColor\" stroke=\"none\"/>\n<path d=\"M21.1729 19.7311C20.7208 19.7311 20.3459 19.3561 20.3459 18.904V5.27431C20.3459 4.82219 20.7208 4.44727 21.1729 4.44727C21.6251 4.44727 22 4.82219 22 5.27431V18.904C22 19.3561 21.6361 19.7311 21.1729 19.7311Z\" fill=\"currentColor\" stroke=\"none\"/>", "pause": "<rect x=\"4.79962\" y=\"3.59985\" width=\"4.8\" height=\"16.8\" rx=\"2.4\" fill=\"currentColor\" stroke=\"none\"/>\n<rect x=\"14.3996\" y=\"3.59985\" width=\"4.8\" height=\"16.8\" rx=\"2.4\" fill=\"currentColor\" stroke=\"none\"/>"});
const icon=name=>'<svg viewBox="0 0 24 24" aria-hidden="true">'+paths[name]+'</svg>';
const last=bar.querySelector('[data-play-action="next"]')?.disabled;
bar.innerHTML=`<input class="player-range player-seek" type="range" min="0" max="100" step="0.1" value="0" aria-label="播放进度" disabled><div class="player-control-row"><button type="button" data-play-action="previous" aria-label="上一集" title="上一集" ${currentEpisode<=1?'disabled':''}>${icon('previous')}</button><button type="button" data-media="toggle" aria-label="播放" title="播放 / 暂停(空格)">${icon('play')}</button><button type="button" data-play-action="next" aria-label="下一集" title="下一集" ${last?'disabled':''}>${icon('next')}</button><span class="player-time">00:00 / 00:00</span><div class="player-control-spacer"></div><div class="player-menu-wrap"><button type="button" data-menu="quality" aria-expanded="false">清晰度</button><div class="player-options" data-options="quality" hidden><button type="button" role="menuitemradio" aria-checked="true">自动</button><button type="button" disabled>1080P 超清</button><button type="button" disabled>720P 高清</button><button type="button" disabled>480P 标清</button><small>等待接入多清晰度片源</small></div></div><div class="player-menu-wrap"><button type="button" data-menu="speed" aria-expanded="false">倍速</button><div class="player-options" data-options="speed" hidden>${[.5,.75,1,1.25,1.5,2].map(n=>`<button type="button" data-speed="${n}" role="menuitemradio" aria-checked="${n===1}">${n}×</button>`).join('')}</div></div><div class="player-volume"><button type="button" data-media="mute" aria-label="静音" title="静音(M)">${icon('volume')}</button><input class="player-range" type="range" min="0" max="1" step="0.01" value="1" aria-label="音量"></div><button type="button" data-media="fullscreen" aria-label="进入全屏" title="全屏(F)">${icon('full')}</button></div>`;
screen.tabIndex=0;screen.setAttribute('aria-label','视频播放器');
const seek=bar.querySelector('.player-seek'),volume=bar.querySelector('.player-volume input'),toggle=bar.querySelector('[data-media="toggle"]'),mute=bar.querySelector('[data-media="mute"]'),full=bar.querySelector('[data-media="fullscreen"]');
const center=overlay.querySelector('button');center.innerHTML=icon('centerPlay');center.removeAttribute('data-play-action');center.dataset.media='toggle';
const time=t=>{t=Number.isFinite(t)?Math.max(0,Math.floor(t)):0;return (t>=3600?Math.floor(t/3600)+':':'')+String(Math.floor(t/60)%60).padStart(2,'0')+':'+String(t%60).padStart(2,'0')};
function sync(){const duration=Number.isFinite(video.duration)?video.duration:0;seek.disabled=!duration;seek.max=duration||100;seek.value=video.currentTime||0;seek.style.setProperty('--fill',(duration?video.currentTime/duration*100:0)+'%');seek.setAttribute('aria-valuetext',time(video.currentTime)+' / '+time(duration));bar.querySelector('.player-time').textContent=time(video.currentTime)+' / '+time(duration);toggle.innerHTML=icon(video.paused?'play':'pause');toggle.setAttribute('aria-label',video.paused?'播放':'暂停');overlay.hidden=!video.paused;volume.value=video.muted?0:video.volume;volume.style.setProperty('--fill',Number(volume.value)*100+'%');mute.innerHTML=icon(video.muted||!video.volume?'mute':'volume');mute.setAttribute('aria-label',video.muted||!video.volume?'取消静音':'静音')}
async function play(){if(actions.toggle){try{await actions.toggle()}catch{status.textContent='播放失败,请重试';overlay.hidden=false}return}if(!video.currentSrc&&!video.getAttribute('src')&&!video.querySelector('source[src]')){status.textContent='本剧尚未提供视频源,接入视频后即可播放';return}if(video.paused){try{await video.play()}catch{status.textContent='暂时无法播放,请检查视频源后重试';overlay.hidden=false}}else video.pause()}
async function retry(){overlay.querySelector('.ui-empty-state')?.remove();center.hidden=false;status.hidden=false;status.textContent='正在重新加载…';try{if(actions.retry)await actions.retry();else{video.load();await play()}}catch{status.textContent='视频加载失败,请重试';overlay.hidden=false}}
async function fullscreen(){try{if(document.fullscreenElement)await document.exitFullscreen();else if(screen.requestFullscreen)await screen.requestFullscreen();else if(video.webkitEnterFullscreen)video.webkitEnterFullscreen();else throw Error()}catch{status.textContent='当前浏览器暂不支持全屏';overlay.hidden=false}}
function closeMenus(){bar.querySelectorAll('[data-options]').forEach(e=>e.hidden=true);bar.querySelectorAll('[data-menu]').forEach(e=>e.setAttribute('aria-expanded','false'))}
screen.addEventListener('click',e=>{const b=e.target.closest('button');if(!b){if(e.target===video){closeMenus();play()}return}if(['previous','next'].includes(b.dataset.playAction)||b.hasAttribute('data-show-unlock'))return;e.stopPropagation();if(b.dataset.media==='retry')void retry();if(b.dataset.media==='toggle')play();if(b.dataset.media==='mute'){if(video.muted||!video.volume){video.muted=false;if(!video.volume)video.volume=.5}else video.muted=true;sync()}if(b.dataset.media==='fullscreen')fullscreen();if(b.dataset.menu){const menu=bar.querySelector('[data-options="'+b.dataset.menu+'"]'),open=menu.hidden;closeMenus();menu.hidden=!open;b.setAttribute('aria-expanded',String(open))}else if(b.dataset.speed){video.playbackRate=Number(b.dataset.speed);bar.querySelector('[data-menu="speed"]').textContent=b.dataset.speed==='1'?'倍速':b.dataset.speed+'×';bar.querySelectorAll('[data-speed]').forEach(e=>e.setAttribute('aria-checked',String(e===b)));closeMenus()}else closeMenus()});
seek.addEventListener('input',()=>{if(Number.isFinite(video.duration)&&video.duration>0){video.currentTime=Math.min(video.duration,Math.max(0,Number(seek.value)));sync()}});
volume.addEventListener('input',()=>{video.volume=Number(volume.value);video.muted=video.volume===0;sync()});
screen.addEventListener('keydown',e=>{if(e.target.matches('input,button'))return;if(e.code==='Space'){e.preventDefault();play()}else if(e.key.toLowerCase()==='m'){mute.click()}else if(e.key.toLowerCase()==='f')fullscreen();else if(['ArrowLeft','ArrowRight'].includes(e.key)&&Number.isFinite(video.duration)){e.preventDefault();video.currentTime=Math.min(video.duration,Math.max(0,video.currentTime+(e.key==='ArrowRight'?5:-5)));sync()}else if(e.key==='Escape')closeMenus()});
screen.addEventListener('focusout',e=>{if(!screen.contains(e.relatedTarget))closeMenus()});
screen.addEventListener('fullscreenchange',()=>{const active=document.fullscreenElement===screen;full.innerHTML=icon(active?'exit':'full');full.setAttribute('aria-label',active?'退出全屏':'进入全屏')});
['loadedmetadata','durationchange','timeupdate','play','pause','ended','volumechange','emptied'].forEach(event=>video.addEventListener(event,sync));function failed(event){if(event.type==='error')status.textContent='视频加载失败,请重试';overlay.querySelector('.ui-empty-state')?.remove();center.hidden=true;status.hidden=true;overlay.insertAdjacentHTML('beforeend',emptyStateMarkup('error',{description:status.textContent}));overlay.hidden=false}video.addEventListener('error',failed);screen.addEventListener('playback:error',failed);
screen._disposePlayer=()=>video.pause();sync();
}
;
/* ---- sticky-search-header-script ---- */
(()=>{
const siteHeader=document.getElementById('global-site-header');if(!siteHeader)return;
let scheduled=false;
function update(){siteHeader.classList.toggle('is-scrolled',window.scrollY>8);scheduled=false}
function measure(){document.documentElement.style.setProperty('--global-header-height',siteHeader.getBoundingClientRect().height+'px')}
new ResizeObserver(measure).observe(siteHeader);measure();
window.addEventListener('scroll',()=>{if(!scheduled){scheduled=true;requestAnimationFrame(update)}},{passive:true});
window.addEventListener('site:route',update);update();
})();
;
/* ---- mobile-slide-navigation-script ---- */
(()=>{
const header=document.querySelector('#global-site-header .top'),sidebar=document.getElementById('site-sidebar');if(!header||!sidebar)return;
const mobile=matchMedia('(max-width:760px)'),trigger=document.createElement('button');trigger.type='button';trigger.className='mobile-menu-trigger';trigger.setAttribute('aria-label','打开导航菜单');trigger.setAttribute('aria-controls','mobile-navigation-drawer');trigger.setAttribute('aria-expanded','false');trigger.innerHTML='<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 6h16M4 12h16M4 18h16"/></svg>';header.prepend(trigger);
const drawer=document.createElement('dialog');drawer.id='mobile-navigation-drawer';drawer.setAttribute('aria-label','网站导航');
drawer.innerHTML='<button type="button" class="mobile-drawer-close" aria-label="关闭导航菜单" autofocus><svg viewBox="0 0 24 24" aria-hidden="true"><path d="m5 5 14 14M19 5 5 19"/></svg></button><a class="mobile-drawer-brand" href="/" aria-label="黄果短剧首页"></a><nav class="mobile-drawer-links" aria-label="手机端主导航"></nav><div class="mobile-drawer-info"></div><div class="mobile-drawer-social" aria-label="官方社区"></div>';
const brand=sidebar.querySelector('.sidebar-brand').cloneNode(true);brand.removeAttribute('class');drawer.querySelector('.mobile-drawer-brand').append(brand);
const nav=drawer.querySelector('.mobile-drawer-links');
const sourceNavigation=sidebar.querySelector('[data-site-navigation="sidebar"]');
if(sourceNavigation)nav.innerHTML=sourceNavigation.innerHTML;
nav.querySelectorAll('a[data-page]').forEach(link=>{link.dataset.mobileRoute=link.dataset.page;link.dataset.siteNav='sidebar';});
const pcInfo=sidebar.querySelector('.side-info');if(pcInfo)drawer.querySelector('.mobile-drawer-info').innerHTML=pcInfo.innerHTML;
const footerLogo=drawer.querySelector('.mobile-drawer-info .side-info-wordmark');if(footerLogo){const brandText=document.createElement('span');brandText.className='mobile-drawer-brand-text';brandText.textContent='黄果短剧';footerLogo.replaceWith(brandText);}
sidebar.querySelectorAll('.sidebar-social a').forEach(link=>drawer.querySelector('.mobile-drawer-social').append(link.cloneNode(true)));
document.body.append(drawer);let timer=null,start=null;
function finishClose(){clearTimeout(timer);timer=null;drawer.classList.remove('is-closing');if(drawer.open)drawer.close();document.body.classList.remove('mobile-drawer-open');trigger.setAttribute('aria-expanded','false')}
function close(animated=true){if(!drawer.open)return;if(!animated||matchMedia('(prefers-reduced-motion:reduce)').matches){finishClose();return}if(timer)return;drawer.classList.add('is-closing');timer=setTimeout(finishClose,180)}
trigger.addEventListener('click',()=>{if(!mobile.matches)return;clearTimeout(timer);timer=null;drawer.classList.remove('is-closing');drawer.showModal();document.body.classList.add('mobile-drawer-open');trigger.setAttribute('aria-expanded','true')});
drawer.querySelector('.mobile-drawer-close').addEventListener('click',()=>close());
drawer.addEventListener('cancel',e=>{e.preventDefault();close()});drawer.addEventListener('close',finishClose);
drawer.addEventListener('click',e=>{if(e.target.closest('a')){close();return}if(e.target!==drawer)return;const r=drawer.getBoundingClientRect();if(e.clientX<r.left||e.clientX>r.right||e.clientY<r.top||e.clientY>r.bottom)close()});
drawer.addEventListener('touchstart',e=>{start=e.touches.length===1?{x:e.touches[0].clientX,y:e.touches[0].clientY}:null},{passive:true});
drawer.addEventListener('touchend',e=>{if(!start)return;const t=e.changedTouches[0],dx=t.clientX-start.x,dy=t.clientY-start.y;start=null;if(dx < -60&&Math.abs(dx)>Math.abs(dy)*1.5)close()},{passive:true});
drawer.addEventListener('touchcancel',()=>{start=null},{passive:true});
window.addEventListener('site:route',()=>close());mobile.addEventListener('change',()=>{if(!mobile.matches)close(false)});
})();
;