分类导航
单片购买
¥
包时
¥
包天观看
¥

最多人看

按人气
链接已失效
请重新获取推广链接后再打开
* 覆盖默认值。主站是多域名轮换的(防封),配置化后换域名只改注入、不改本文件。 * 没有注入时回退到内置默认域名 GATEWAY_DEFAULT。 * * ⚠ 安全红线:这里**只能是对外网关的域名**。严禁写后端源站 IP、内网地址或 * 直连端口(:8080 之类)—— 一旦出现在前端,任何人都能照着直连、绕过 * CDN / 防盗链 / WAF,源站就此裸奔。配置注入侧同样必须守这条。 * ================================================================== */ var CFG = (typeof window !== 'undefined' && window.__SHELL_CFG__) ? window.__SHELL_CFG__ : {}; var GATEWAY_DEFAULT = "https://www.021888002.xyz"; // 兜底:一个对外域名,非源站 IP var API_BASE = String(CFG.gateway || CFG.api_base || GATEWAY_DEFAULT).replace(/\/+$/, ''); var ON_PAGES = /(^|\.)pages\.dev$/i.test(location.hostname); // 取值:显式配了网关就用它;否则同源(主站自托,随域名轮换走),仅 pages.dev 跨域时才用绝对域名。 var API = (CFG.gateway || CFG.api_base) ? API_BASE : (ON_PAGES ? API_BASE : ''); /* ------------------------------------------------------------------ * 紧凑参数。 * * entry.html:210 的导航公式是 shell_url + '?' + rawParams + '=' * 结尾那个 '=' 是它加的,必须在这里剥掉:AgentLinkService::pickShortQuery() * 按 & 拆段后会跳过任何含 '=' 的段(那是键值对),不剥就一定判成非法链接。 * ------------------------------------------------------------------ */ function readQ(){ var s = (location.search || '').replace(/^\?/, ''); if(!s) return ''; // 只取第一段(后面可能被别的东西追加了 &utm_xxx=) var seg = s.split('&')[0]; return seg.replace(/=+$/, ''); } var Q = readQ(); var grid = document.getElementById('grid'); var deadEl = document.getElementById('dead'); var LIMIT = 40; var page = 0, loading = false, done = false; var curCate = '', curSort = 'hot', mode = 'feed'; var SEED = Math.floor(Math.random()*2147483000)+1; var TOTAL = 0; var SITE = ''; // 主站基址,bootstrap 回的 site_base var BKEY = 'ds_seen_' + Q; // 看过的(按设备,localStorage) function dead(){ deadEl.classList.add('show'); } function esc(s){ return (s==null?'':String(s)).replace(/[&<>"]/g,function(m){ return {'&':'&','<':'<','>':'>','"':'"'}[m]; }); } function fmtViews(n){ n=parseInt(n,10)||0; if(n>=10000) return (n/10000).toFixed(1).replace(/\.0$/,'')+'万'; return n.toLocaleString('en-US'); } /* 内置 Base64 SVG 占位图:封面加载失败/缺省时的**最终兜底**。 * 用 data URI 而不是网络图(原来的 /public/moren.jpg)的原因: * · 壳页托在 pages.dev 外站时,任何指回主站的封面地址都可能因主站被墙/换域名 * 而拿不到;接口回的第三方封面(doubanio 之类)更是随时防盗链 403。 * · data URI 内联在文件里,零请求、永不 403、离线也在,是唯一稳的兜底。 * 挂到 window.DS_PH 上,好让每个 的内联 onerror(运行在全局作用域)够得着, * 又不必把这串 ~800 字节重复塞进每张卡片。 */ var DS_PH = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MDAiIGhlaWdodD0iMzAwIiB2aWV3Qm94PSIwIDAgNDAwIDMwMCI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJnIiB4MT0iMCIgeTE9IjAiIHgyPSIxIiB5Mj0iMSI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjMWUyOTNiIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMGIxNDI0Ii8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3Qgd2lkdGg9IjQwMCIgaGVpZ2h0PSIzMDAiIGZpbGw9InVybCgjZykiLz48Y2lyY2xlIGN4PSIyMDAiIGN5PSIxMzIiIHI9IjMzIiBmaWxsPSJub25lIiBzdHJva2U9IiMzMzQxNTUiIHN0cm9rZS13aWR0aD0iMyIvPjxwYXRoIGQ9Ik0xOTEgMTE2bDI3IDE2LTI3IDE2eiIgZmlsbD0iIzQ3NTU2OSIvPjx0ZXh0IHg9IjIwMCIgeT0iMjA1IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LWZhbWlseT0iLWFwcGxlLXN5c3RlbSxQaW5nRmFuZyBTQyxzYW5zLXNlcmlmIiBmb250LXNpemU9IjE1IiBmaWxsPSIjNDc1NTY5Ij7lsIHpnaLliqDovb3kuK08L3RleHQ+PC9zdmc+'; if (typeof window !== 'undefined') { window.DS_PH = DS_PH; } function fallbackCover(){ return DS_PH; } function cardHTML(it,i){ var photo = it.photo && it.photo!=='1' ? it.photo : fallbackCover(); var title = esc(it.name||'未命名视频'); var cate = it.cate ? esc(it.cate) : ''; var price = (it.money!=null && it.money!=='') ? it.money : it.sj; var href = it.dwz || '#'; var payload = esc(JSON.stringify({id:it.id,zykey:it.zykey,name:it.name,photo:it.photo, cate:it.cate,cs:it.cs,money:price,sj:it.sj,dwz:href})); return '' +'
' +'' +(cate?''+cate+'':'') +'
' +'
' +'
' +'
'+title+'
' +'
' +''+fmtViews(it.cs)+'' +(cate?''+cate+'':'') +'¥'+esc(price)+'' +'
' +'
'; } function setState(html){ grid.querySelectorAll('.state,.spinner').forEach(function(e){e.remove();}); if(html) grid.insertAdjacentHTML('beforeend', html); } function showSpinner(){ setState('
'); } /* 走原生 pathinfo 而不是 /shell/list 那种短路径:短路径依赖 nginx 重写, * 原生地址少一层依赖。注意翻页的方法名是 lists 不是 list —— * list 是 PHP 保留字,控制器里只能叫 lists。写成 list 会 500(方法不存在), * 而且因为 app_debug 关着,线上只看得到一句「页面错误!请稍后再试~」。 */ var EP = { boot:'bootstrap', page:'lists' }; function apiURL(path, params){ var qs = ['q=' + encodeURIComponent(Q)]; for(var k in params){ if(Object.prototype.hasOwnProperty.call(params,k) && params[k] !== '' && params[k] != null){ qs.push(k + '=' + encodeURIComponent(params[k])); } } return API + '/index.php/index/shell/' + path + '?' + qs.join('&'); } function ask(path, params){ return fetch(apiURL(path, params), {headers:{'X-Requested-With':'XMLHttpRequest'}}) .then(function(r){ return r.json(); }) .then(function(res){ if(!res || res.code !== 1) throw new Error(res && res.msg ? res.msg : 'bad response'); return res.data; }); } /* ===== 分类 ===== */ function renderCats(cats){ var box = document.getElementById('tags'); var frag = ''; (cats||[]).forEach(function(c){ frag += ''; }); box.innerHTML = frag; var n = (cats||[]).length; document.getElementById('catCount').textContent = n ? ('共 '+n+' 个分类') : ''; } /* ===== 价格条 ===== */ function renderPlans(p){ if(!p) return; document.getElementById('prTime').textContent = p.time_price; document.getElementById('prDay').textContent = p.day_price; document.getElementById('labTime').textContent = '包时' + (p.time_hours||0) + '小时'; document.getElementById('pricebar').classList.remove('hide'); } /* 单片价随片子走,取第一屏里最低的那个当“起”价 */ function renderSinglePrice(list){ var min = null; (list||[]).forEach(function(it){ var v = parseFloat(it.money!=null && it.money!=='' ? it.money : it.sj); if(!isNaN(v) && v > 0 && (min===null || v < min)) min = v; }); if(min !== null) document.getElementById('prSingle').textContent = min; } function updHead(){ var h2 = document.getElementById('feedTitle'); if(mode==='mine'){ h2.innerHTML = '看过的'+readSeen().length+' 支'; } else { h2.innerHTML = '最多人看'+TOTAL+' 支视频'; } } function appendList(list){ if(!list || !list.length){ done = true; setState(page===0 ? '
该分类下暂无视频
' : '
— 已经到底啦 —
'); return; } page++; var frag = ''; list.forEach(function(it,idx){ frag += cardHTML(it, idx); }); grid.insertAdjacentHTML('beforeend', frag); if(list.length < LIMIT){ done = true; setState('
— 已经到底啦 —
'); } } function loadMore(){ if(loading || done) return; loading = true; showSpinner(); ask(EP.page, {page:page+1, cate:curCate, sort:curSort, seed:SEED}) .then(function(d){ setState(''); TOTAL = d.count; appendList(d.list); if(page===1) renderSinglePrice(d.list); updHead(); loading = false; }) .catch(function(){ setState('
加载失败,点此重试
'); var s = grid.querySelector('.state'); if(s) s.onclick = function(){ setState(''); loading=false; loadMore(); }; loading = false; }); } function resetFeed(){ page=0; loading=false; done=false; grid.innerHTML=''; loadMore(); } /* ===== 分类切换 ===== */ document.getElementById('tags').addEventListener('click', function(e){ var b = e.target.closest('.tag'); if(!b) return; document.querySelectorAll('.tag').forEach(function(x){x.classList.remove('active');}); b.classList.add('active'); curCate = b.getAttribute('data-cate') || ''; document.getElementById('q').value = ''; mode = 'feed'; document.querySelectorAll('.nav').forEach(function(x){ x.classList.toggle('active', x.getAttribute('data-nav')==='hot'); }); window.scrollTo({top:0,behavior:'smooth'}); resetFeed(); }); document.getElementById('toggleMatrix').addEventListener('click', function(){ document.getElementById('tags').classList.toggle('collapsed'); }); /* ===== 搜索:只过滤已加载的卡片,和主站落地页同样口径 ===== */ function doSearch(){ var q = document.getElementById('q').value.trim(); var cnt = document.getElementById('count'); if(!q){ grid.querySelectorAll('.card').forEach(function(c){c.style.display='';}); updHead(); return; } var n = 0; grid.querySelectorAll('.card').forEach(function(c){ var t = c.querySelector('.title').textContent; var hit = t.indexOf(q) >= 0; c.style.display = hit ? '' : 'none'; if(hit) n++; }); if(cnt) cnt.textContent = n + ' 个结果'; if(n===0) toast('当前已加载列表无匹配,可下拉加载更多'); } document.getElementById('doSearch').addEventListener('click', doSearch); document.getElementById('q').addEventListener('keydown', function(e){ if(e.key==='Enter') doSearch(); }); /* ===== 看过的(本机记录)===== * 注意这里不是“已购买”:壳页在外站,拿不到主站的付费 cookie, * 也无从知道用户到底付没付。只记“点开过”,别拿购买状态骗人。 */ function readSeen(){ try{ return JSON.parse(localStorage.getItem(BKEY)||'[]')||[]; }catch(e){ return []; } } function pushSeen(it){ if(!it) return; try{ var arr = readSeen().filter(function(x){ return x.dwz !== it.dwz; }); arr.unshift(it); if(arr.length > 60) arr = arr.slice(0,60); localStorage.setItem(BKEY, JSON.stringify(arr)); }catch(e){} } function renderSeen(){ var arr = readSeen(); setState(''); grid.innerHTML = ''; if(!arr.length){ grid.insertAdjacentHTML('beforeend', '
还没有看过的视频
点开任意视频后会出现在这里
'); return; } var frag=''; arr.forEach(function(it,i){ frag += cardHTML(it,i); }); grid.insertAdjacentHTML('beforeend', frag); } /* ===== 卡片点击 → 回主站 ===== * 壳页不收款、不放片。dwz 是主站 ff.html 的绝对地址,落到主站的打赏页, * 由主站按 PlanPricingService 解析金额、走 dunpay 下单、过 shipinok 放行。 * 这里只做本机“看过的”记录,然后原样跳走。 */ grid.addEventListener('click', function(e){ var a = e.target.closest('.card'); if(!a) return; var raw = a.getAttribute('data-it'); if(raw){ try{ pushSeen(JSON.parse(raw)); }catch(err){} } // 不 preventDefault: 自己跳,JS 挂了也还能点 }); /* ===== 底部导航 ===== */ document.querySelectorAll('.nav').forEach(function(n){ var k = n.getAttribute('data-nav'); if(k==='rand') return; n.addEventListener('click', function(){ document.querySelectorAll('.nav').forEach(function(x){x.classList.remove('active');}); n.classList.add('active'); if(k==='hot'){ mode='feed'; curSort='hot'; updHead(); resetFeed(); window.scrollTo({top:0,behavior:'smooth'}); } else if(k==='mine'){ mode='mine'; done=true; loading=false; updHead(); renderSeen(); window.scrollTo({top:0,behavior:'smooth'}); } }); }); document.getElementById('randBtn').addEventListener('click', function(){ this.classList.remove('spin'); void this.offsetWidth; this.classList.add('spin'); if(mode==='mine'){ var arr = readSeen().slice().sort(function(){ return Math.random()-0.5; }); grid.innerHTML=''; var frag=''; arr.forEach(function(it,i){ frag+=cardHTML(it,i); }); grid.insertAdjacentHTML('beforeend', frag); window.scrollTo({top:0,behavior:'smooth'}); } else { // 换新种子 → 服务端重做一次热度加权随机,拿到不一样的一批 SEED = Math.floor(Math.random()*2147483000)+1; window.scrollTo({top:0,behavior:'smooth'}); resetFeed(); } }); /* ===== toast ===== */ var toastEl = document.getElementById('toast'), toastT; function toast(msg){ toastEl.textContent = msg; toastEl.classList.add('show'); clearTimeout(toastT); toastT = setTimeout(function(){ toastEl.classList.remove('show'); }, 2000); } /* ===== 无限滚动 ===== */ window.addEventListener('scroll', function(){ if(loading || done || mode==='mine') return; if(window.innerHeight + window.scrollY >= document.body.offsetHeight - 400) loadMore(); }, {passive:true}); /* ===== 首屏 ===== */ if(!Q){ dead(); return; } showSpinner(); ask(EP.boot, {sort:curSort, seed:SEED}) .then(function(d){ SITE = (d.site_base || '').replace(/\/+$/, ''); TOTAL = d.count; if(d.seed) SEED = d.seed; if(d.title) document.title = d.title; renderCats(d.cats); renderPlans(d.plans); setState(''); appendList(d.list); renderSinglePrice(d.list); updHead(); }) .catch(function(){ dead(); }); })();