• 浮生之白蛇前缘.html 16.47 kB 2026-09-16 19:39
  • Position: 浮生之白蛇前缘.html

    <!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>
    

    Powered by kodbox V1.67

    Copyright © kodcloud.com.

    Files