<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>浮生之白蛇前缘 · 在线播放 (1080zyk)</title>
<script src="https://cdn.jsdelivr.net/npm/hls.js@1/dist/hls.min.js"></script>
<style>
:root{
--bg:#0d1017; --panel:#151a24; --panel2:#1b2230; --line:#26304200;
--txt:#e8edf5; --dim:#8b96ab; --acc:#ff5c7a; --acc2:#7aa2ff;
--ok:#3dd68c; --bad:#ff5c5c; --unk:#f0b34e;
}
*{box-sizing:border-box;margin:0;padding:0}
body{background:var(--bg);color:var(--txt);font-family:"Microsoft YaHei","PingFang SC",system-ui,sans-serif;font-size:14px}
a{color:var(--acc2);text-decoration:none}
.wrap{max-width:1280px;margin:0 auto;padding:16px}
header.hero{display:flex;flex-direction:column;align-items:center;text-align:center;background:linear-gradient(135deg,#1a2130,#12161f);border:1px solid #232c3d;border-radius:14px;padding:18px;margin-bottom:16px}
.hero h1{font-size:22px;display:flex;align-items:center;justify-content:center;gap:10px;flex-wrap:wrap}
.badge{font-size:12px;background:var(--acc);color:#fff;border-radius:6px;padding:2px 8px;font-weight:normal}
.badge.blue{background:var(--acc2)}
.meta{margin-top:8px;color:var(--dim);line-height:1.8;font-size:13px}
.meta b{color:var(--txt);font-weight:normal}
.layout{display:grid;grid-template-columns:minmax(0,1fr) 360px;gap:16px}
@media(max-width:960px){.layout{grid-template-columns:1fr}}
.card{background:var(--panel);border:1px solid #232c3d;border-radius:14px;overflow:hidden}
.player-box{position:relative;background:#000}
video{width:100%;aspect-ratio:16/9;display:block;background:#000}
.ctrlbar{display:flex;gap:8px;flex-wrap:wrap;align-items:center;padding:10px 12px;border-top:1px solid #232c3d;background:var(--panel)}
button{background:var(--panel2);color:var(--txt);border:1px solid #2b3547;border-radius:8px;padding:7px 14px;cursor:pointer;font-size:13px;transition:.15s}
button:hover{border-color:var(--acc2);color:#fff}
button.primary{background:var(--acc);border-color:var(--acc);color:#fff}
button.primary:hover{filter:brightness(1.1);color:#fff}
button:disabled{opacity:.45;cursor:not-allowed}
.spacer{flex:1}
.now{padding:10px 12px;color:var(--dim);font-size:13px;border-top:1px dashed #232c3d}
.now b{color:var(--acc2)}
.list-head{display:flex;flex-wrap:wrap;gap:8px;align-items:center;padding:12px;border-bottom:1px solid #232c3d}
.list-head h2{font-size:15px;margin-right:auto}
select,input[type=text]{background:var(--panel2);border:1px solid #2b3547;color:var(--txt);border-radius:8px;padding:6px 10px;font-size:13px}
.stats{padding:0 12px 10px;color:var(--dim);font-size:12px;display:flex;gap:12px;flex-wrap:wrap}
.dot{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:4px;vertical-align:middle}
.d-ok{background:var(--ok)} .d-bad{background:var(--bad)} .d-unk{background:var(--unk)} .d-none{background:#3a465c}
.eps{max-height:640px;overflow-y:auto;padding:10px;display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:8px}
.eps::-webkit-scrollbar{width:8px}.eps::-webkit-scrollbar-thumb{background:#2b3547;border-radius:8px}
.ep{position:relative;background:var(--panel2);border:1px solid #2b3547;border-radius:10px;padding:9px 10px;cursor:pointer;transition:.15s;overflow:hidden}
.ep:hover{border-color:var(--acc2)}
.ep.active{border-color:var(--acc);background:#2a1c26}
.ep .t{font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ep .s{font-size:11px;color:var(--dim);margin-top:4px;display:flex;align-items:center;gap:4px}
.ep .acts{position:absolute;top:6px;right:6px;display:flex;gap:4px;opacity:0;transition:.15s}
.ep:hover .acts{opacity:1}
.ep .acts button{padding:2px 7px;font-size:11px;border-radius:6px;line-height:1.5}
.prog{height:3px;background:#0d1017;border-radius:2px;margin-top:6px;overflow:hidden}
.prog i{display:block;height:100%;background:var(--acc2);width:0}
details.syn{margin-top:16px;background:var(--panel);border:1px solid #232c3d;border-radius:14px;padding:14px 18px}
details.syn summary{cursor:pointer;font-weight:bold}
details.syn p{margin-top:10px;color:#b9c2d4;line-height:1.9}
.toast{position:fixed;left:50%;bottom:28px;transform:translateX(-50%);background:#000c;color:#fff;padding:9px 18px;border-radius:20px;font-size:13px;z-index:99;display:none}
.overlay{position:absolute;inset:0;display:none;align-items:center;justify-content:center;flex-direction:column;gap:12px;background:#000a;z-index:5;text-align:center;padding:20px}
.overlay.show{display:flex}
label.chk{display:flex;align-items:center;gap:5px;cursor:pointer;user-select:none}
</style>
</head>
<body>
<div class="wrap">
<header class="hero">
<div style="flex:1;min-width:0">
<h1>浮生之白蛇前缘 <span class="badge">全24集</span> <span class="badge blue">1080zyk 源</span> <span class="badge" style="background:#3a465c">评分 6.7</span></h1>
<div class="meta">
别名:<b>白蛇前缘</b> | 类型:<b>国产剧·爱情·古装·奇幻</b> | 地区:<b>大陆</b> | 语言:<b>国语</b> | 年份:<b>2026</b><br>
导演:<b>郑智勇、张娜嘉</b><br>
主演:<b>赵娅婷、林亚冬、钟晨瑶、彭诗杰、白玉、童飞、李嘉铭、楼佳悦、媛梦、谭渤霖 等</b>
</div>
</div>
</header>
<div class="layout">
<section class="card">
<div class="player-box">
<video id="video" controls playsinline></video>
<div class="overlay" id="ovl">
<div id="ovlMsg" style="color:#ffd7de;font-size:15px"></div>
<div style="display:flex;gap:10px">
<button class="primary" onclick="retryCur()">重试本集</button>
<button onclick="playIdx(cur+1)">播放下一集</button>
</div>
</div>
</div>
<div class="ctrlbar">
<button class="primary" onclick="playIdx(cur-1)">◀ 上一集</button>
<button class="primary" onclick="playIdx(cur+1)">下一集 ▶</button>
<span id="epLabel" style="color:var(--dim)">未播放</span>
<div class="spacer"></div>
<label class="chk"><input type="checkbox" id="autoNext" checked>连播</label>
<label class="chk"><input type="checkbox" id="skipDead">优先可用</label>
<button onclick="copyUrl()">复制当前地址</button>
</div>
<div class="now">正在播放:<b id="nowTxt">-</b></div>
</section>
<aside class="card">
<div class="list-head">
<h2>剧集列表</h2>
<button class="primary" id="btnAll" onclick="checkAll()">一键检测全部</button>
<button onclick="clearChecks()">清除结果</button>
</div>
<div class="list-head" style="border-bottom:none;padding-bottom:0">
<select id="filter" onchange="renderList()">
<option value="all">全部集数</option>
<option value="ok">仅可用</option>
<option value="dead">仅失效</option>
<option value="unknown">仅异常</option>
<option value="none">仅未检测</option>
</select>
<input type="text" id="kw" placeholder="搜索集数…" style="width:110px" oninput="renderList()">
</div>
<div class="stats">
<span><i class="dot d-none"></i>未检 <b id="stNone">24</b></span>
<span><i class="dot d-ok"></i>可用 <b id="stOk">0</b></span>
<span><i class="dot d-bad"></i>失效 <b id="stBad">0</b></span>
<span><i class="dot d-unk"></i>异常 <b id="stUnk">0</b></span>
</div>
<div class="eps" id="eps"></div>
</aside>
</div>
<details class="syn">
<summary>剧情介绍</summary>
<p>修行五百年的白素贞本可飞升成仙,但因未了情劫遗失一段重要记忆,需遵上神之命下山寻找许仙报恩。白素贞与小青入世,结识身负灭门仇恨的捉妖师许仙和金山弟子法海,四人携手前行,展开一场宿命纠葛。</p>
</details>
</div>
<div class="toast" id="toast"></div>
<script>
const EPISODES=[
"https://player.yzzyvip-35.com/20260902/15503_d4f457bc/index.m3u8",
"https://player.yzzyvip-35.com/20260902/15504_cedb0f1d/index.m3u8",
"https://player.yzzyvip-35.com/20260902/15505_d92871c9/index.m3u8",
"https://player.yzzyvip-35.com/20260902/15506_26e0b344/index.m3u8",
"https://player.yzzyvip-35.com/20260902/15507_d63f5287/index.m3u8",
"https://player.yzzyvip-35.com/20260902/15508_58661be7/index.m3u8",
"https://cdn.vvvip-plays33.cc/20260903/19000_e9cf01c0/index.m3u8",
"https://cdn.vvvip-plays33.cc/20260903/19001_5f2150c4/index.m3u8",
"https://cdn.yzzy30-play.com/20260904/58743_ffc0e23e/index.m3u8",
"https://cdn.yzzy30-play.com/20260904/58744_33f6c40d/index.m3u8",
"https://cdn.yzzy30-play.com/20260905/58771_3f14abec/index.m3u8",
"https://cdn.yzzy30-play.com/20260905/58772_3bccf044/index.m3u8",
"https://cdn.yzzy31-play.com/20260906/25263_12b865d6/index.m3u8",
"https://cdn.yzzy30-play.com/20260907/58814_f4554276/index.m3u8",
"https://cdn.yzzy30-play.com/20260908/58838_9a047685/index.m3u8",
"https://player.yzzyvip-35.com/20260909/16311_a5a01195/index.m3u8",
"https://cdn.yzzy31-play.com/20260910/25560_ab8d6958/index.m3u8",
"https://cdn.vvvip-plays33.cc/20260910/19447_4332aede/index.m3u8",
"https://cdn.vvvip-plays33.cc/20260910/19448_17eb2eca/index.m3u8",
"https://cdn.vvvip-plays33.cc/20260910/19449_ada822e6/index.m3u8",
"https://cdn.vvvip-plays33.cc/20260910/19450_0d399929/index.m3u8",
"https://cdn.vvvip-plays33.cc/20260910/19451_ea9c07b5/index.m3u8",
"https://cdn.yzzy30-play.com/20260910/58908_b714cfe3/index.m3u8",
"https://cdn.yzzy30-play.com/20260910/58909_829553a5/index.m3u8"
].map((url,i)=>({n:i+1,url}));
const LS_STATUS='qdsbqy_status',LS_PROG='qdsbqy_prog',LS_LAST='qdsbqy_last';
let statuses={},progress={};
try{statuses=JSON.parse(localStorage.getItem(LS_STATUS))||{}}catch(e){}
try{progress=JSON.parse(localStorage.getItem(LS_PROG))||{}}catch(e){}
let cur=-1,hls=null,checking=false;
const $=id=>document.getElementById(id);
const video=$('video');
function toast(msg,ms=2200){const t=$('toast');t.textContent=msg;t.style.display='block';clearTimeout(t._tm);t._tm=setTimeout(()=>t.style.display='none',ms)}
function saveStatuses(){try{localStorage.setItem(LS_STATUS,JSON.stringify(statuses))}catch(e){}}
function saveProg(){try{localStorage.setItem(LS_PROG,JSON.stringify(progress))}catch(e){}}
function stOf(ep){return statuses[ep.url]&&statuses[ep.url].s||'none'}
function renderStats(){
let ok=0,bad=0,unk=0,none=0;
EPISODES.forEach(ep=>{const s=stOf(ep);if(s==='ok')ok++;else if(s==='dead')bad++;else if(s==='unknown')unk++;else none++});
$('stOk').textContent=ok;$('stBad').textContent=bad;$('stUnk').textContent=unk;$('stNone').textContent=none;
}
function renderList(){
const f=$('filter').value,kw=$('kw').value.trim();
const box=$('eps');box.innerHTML='';
EPISODES.forEach((ep,i)=>{
const s=stOf(ep);
if(f!=='all'&&f!==s)return;
if(kw&&!String(ep.n).includes(kw))return;
const cls=s==='ok'?'d-ok':s==='dead'?'d-bad':s==='unknown'?'d-unk':'d-none';
const label={ok:'可用',dead:'失效',unknown:'异常',none:'未检'}[s];
const p=Math.floor(progress[i]||0);
const el=document.createElement('div');
el.className='ep'+(i===cur?' active':'');
el.innerHTML=`<div class="t">第${String(ep.n).padStart(2,'0')}集</div>
<div class="s"><i class="dot ${cls}"></i>${label}</div>
${p>10?`<div class="prog"><i style="width:${Math.min(p/45*100,100)}%"></i></div>`:''}
<div class="acts">
<button title="重新检测" onclick="event.stopPropagation();checkOne(${i},true)">↻</button>
<button title="复制地址" onclick="event.stopPropagation();copyText('${ep.url}')">⧉</button>
</div>`;
el.onclick=()=>playIdx(i);
box.appendChild(el);
});
}
async function probe(url){
const target=url;
const ctrl=new AbortController();
const tm=setTimeout(()=>ctrl.abort(),12000);
try{
const res=await fetch(target,{signal:ctrl.signal,redirect:'follow'});
clearTimeout(tm);
if(!res.ok)return 'dead';
const txt=(await res.text()).slice(0,512);
return txt.includes('#EXTM3U')?'ok':'dead';
}catch(e){clearTimeout(tm);return 'unknown'}
}
async function checkOne(i,manual=false){
const ep=EPISODES[i];
statuses[ep.url]={s:'checking'};
renderList();renderStats();
const r=await probe(ep.url);
statuses[ep.url]={s:r,t:Date.now()};
saveStatuses();renderList();renderStats();
if(manual)toast(`第${ep.n}集检测结果:${{ok:'✅ 可用',dead:'❌ 已失效',unknown:'⚠️ 无法确认(可能跨域限制)'}[r]}`);
return r;
}
let stopFlag=false;
async function checkAll(){
if(checking){stopFlag=true;return}
checking=true;stopFlag=false;
$('btnAll').textContent='停止检测';
const queue=[...EPISODES.keys()];
let done=0;
const worker=async()=>{
while(queue.length&&!stopFlag){
const i=queue.shift();
await checkOne(i);
done++;
}
};
await Promise.all(Array.from({length:6},worker));
checking=false;$('btnAll').textContent='一键检测全部';
if(stopFlag)toast('已停止检测');
else{
let ok=0;EPISODES.forEach(e=>{if(stOf(e)==='ok')ok++});
toast(`检测完成:${ok}/${EPISODES.length} 集可用`);
}
}
function clearChecks(){statuses={};saveStatuses();renderList();renderStats();toast('已清除检测结果')}
function destroyHls(){if(hls){hls.destroy();hls=null}}
function playIdx(i){
if(i<0||i>=EPISODES.length)return;
cur=i;destroyHls();$('ovl').classList.remove('show');
const ep=EPISODES[i];
localStorage.setItem(LS_LAST,i);
const src=ep.url;
if(window.Hls&&Hls.isSupported()){
hls=new Hls({maxBufferLength:30,maxMaxBufferLength:60});
hls.loadSource(src);hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED,()=>{onCanStart()});
hls.on(Hls.Events.ERROR,(evt,data)=>{
if(data.fatal){
if(data.type===Hls.ErrorTypes.NETWORK_ERROR&&data.details==='manifestLoadError'){
statuses[ep.url]={s:'unknown',t:Date.now()};saveStatuses();renderList();renderStats();
showError('本集加载失败(网络或跨域限制),请稍后重试');
}else if(data.type===Hls.ErrorTypes.NETWORK_ERROR){hls.startLoad()}
else if(data.type===Hls.ErrorTypes.MEDIA_ERROR){hls.recoverMediaError()}
else{showError('播放出错:'+data.details)}
}
});
}else if(video.canPlayType('application/vnd.apple.mpegurl')){
video.src=src;onCanStart();
}else{showError('当前浏览器不支持HLS播放')}
function onCanStart(){
video.play().catch(()=>toast('浏览器阻止了自动播放,请点击播放按钮'));
const saved=progress[i];
if(saved&&saved>5){video.currentTime=saved;toast('已恢复上次进度')}
updateLabels();
}
function showError(msg){$('ovlMsg').textContent=`第${ep.n}集 · `+msg;$('ovl').classList.add('show')}
updateLabels();renderList();
}
function retryCur(){if(cur>=0)playIdx(cur)}
function updateLabels(){
if(cur<0)return;
const t=`第${String(EPISODES[cur].n).padStart(2,'0')}集`;
$('epLabel').textContent=t;$('nowTxt').textContent='浮生之白蛇前缘 '+t;
}
function pickPlayable(from,dir){
let i=from;
while(i>=0&&i<EPISODES.length){
if(stOf(EPISODES[i])==='ok')return i;
i+=dir;
}
return from;
}
function copyText(txt){
if(navigator.clipboard&&window.isSecureContext!==false){
navigator.clipboard.writeText(txt).then(()=>toast('已复制')).catch(()=>fallback());
}else fallback();
function fallback(){
const ta=document.createElement('textarea');ta.value=txt;document.body.appendChild(ta);
ta.select();try{document.execCommand('copy');toast('已复制')}catch(e){toast('复制失败,请手动复制')}
document.body.removeChild(ta);
}
}
function copyUrl(){if(cur>=0)copyText(EPISODES[cur].url);else toast('请先选择一集')}
let lastSave=0;
video.addEventListener('timeupdate',()=>{
if(cur<0)return;
const now=Date.now();
if(now-lastSave>4000){lastSave=now;progress[cur]=Math.floor(video.currentTime);saveProg()}
});
video.addEventListener('ended',()=>{
delete progress[cur];saveProg();
if($('autoNext').checked&&cur+1<EPISODES.length){
let nx=cur+1;
if($('skipDead').checked)nx=pickPlayable(nx,1);
playIdx(nx);
}
});
document.addEventListener('keydown',e=>{
if(/INPUT|TEXTAREA|SELECT/.test(document.activeElement.tagName))return;
if(e.code==='Space'){e.preventDefault();video.paused?video.play():video.pause()}
else if(e.code==='ArrowRight')video.currentTime+=10;
else if(e.code==='ArrowLeft')video.currentTime-=10;
else if(e.key==='n'||e.key==='N')playIdx(cur+1);
else if(e.key==='p'||e.key==='P')playIdx(cur-1);
});
renderStats();renderList();
toast('3秒后自动播放第1集…');
setTimeout(()=>playIdx(0),3000);
</script>
</body>
</html>