-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy path360movie.html
More file actions
1 lines (1 loc) · 19.1 KB
/
Copy path360movie.html
File metadata and controls
1 lines (1 loc) · 19.1 KB
1
<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><title>360影视 WebHome</title><style>:root{--text:#f7fbff;--muted:rgba(247,251,255,.68);--line:rgba(255,255,255,.16);--soft:rgba(42,50,58,.44);--accent:#ff6b35;--accent2:#ffb86b;--radius:18px}*{box-sizing:border-box}html,body{margin:0;min-height:100%;background:transparent;color:var(--text);font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC",Arial,sans-serif}html:not(.fm-native),html:not(.fm-native) body{background:#222a32}.app{min-height:100vh;padding:10px}.bar{display:flex;align-items:center;gap:8px}.brand{font-size:21px;font-weight:900;white-space:nowrap}.brand b{color:var(--accent2)}.search{flex:1;display:flex;gap:8px;align-items:center;background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.14);border-radius:999px;padding:6px 7px 6px 13px}.search input{flex:1;min-width:0;background:transparent;border:0;outline:0;color:var(--text);font-size:15px}.search button,.btn{border:1px solid var(--line);background:var(--soft);color:var(--text);border-radius:999px;padding:8px 12px;font-size:14px}.search button,.primary{border-color:rgba(255,107,53,.45);background:linear-gradient(135deg,rgba(255,107,53,.9),rgba(255,184,107,.72));color:#17110d;font-weight:800}.tabs,.chips{display:flex;gap:8px;overflow:auto;padding:10px 2px 0;scrollbar-width:none}.tab,.chip{white-space:nowrap;border-radius:999px;padding:8px 14px;background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.12);color:var(--muted)}.tab.active,.chip.active{background:linear-gradient(135deg,rgba(255,107,53,.55),rgba(255,184,107,.3));color:var(--text);border-color:rgba(255,184,107,.58);font-weight:800}.status{margin:10px 2px;color:var(--muted);font-size:14px}.grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}.card{border-radius:15px;overflow:hidden;background:linear-gradient(180deg,rgba(255,255,255,.09),rgba(255,255,255,.045));border:1px solid rgba(255,255,255,.12)}.poster{aspect-ratio:3/4;background:rgba(255,255,255,.08);position:relative}.poster img{width:100%;height:100%;object-fit:cover}.noimg{height:100%;display:grid;place-items:center;color:var(--muted);font-size:28px}.badge{position:absolute;right:7px;top:7px;padding:3px 8px;border-radius:999px;background:rgba(0,0,0,.58);font-size:11px;font-weight:800}.meta{padding:8px}.name{font-weight:800;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.remark{margin-top:4px;color:var(--muted);font-size:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.sheet{position:fixed;inset:0;z-index:40;display:none;background:transparent;overflow:auto;padding:12px}.sheet.active{display:block}.panel{background:linear-gradient(135deg,rgba(64,35,30,.72),rgba(30,24,24,.58));border:1px solid rgba(255,255,255,.1);border-radius:22px;padding:16px 12px 24px}.head{display:grid;grid-template-columns:38% 1fr;gap:14px}.pic{width:100%;aspect-ratio:3/4;object-fit:cover;border-radius:16px;background:rgba(255,255,255,.08)}.title{font-size:22px;font-weight:700;line-height:1.25}.info{font-size:14px;line-height:1.65;color:rgba(255,255,255,.75);max-height:230px;overflow:hidden}.pill{display:inline-block;margin:18px 0 10px;padding:8px 18px;border-radius:999px;background:rgba(255,255,255,.1);border:1px solid rgba(255,184,107,.55);font-size:15px;font-weight:800}.desc{font-size:15px;line-height:1.75;color:rgba(255,255,255,.72)}.line-tabs{display:flex;gap:8px;overflow:auto;margin:8px 0 10px}.line-tab{white-space:nowrap;border-radius:999px;padding:8px 12px;background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.14);color:rgba(255,255,255,.82)}.line-tab.active{background:rgba(255,107,53,.36);border-color:rgba(255,184,107,.55);font-weight:800}.eps{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:9px}.ep{border-radius:12px;padding:10px 5px;background:rgba(255,255,255,.09);border:1px solid rgba(255,255,255,.14);color:rgba(255,255,255,.9);font-size:13px;text-align:center;min-height:42px}.empty{padding:34px 18px;text-align:center;color:var(--muted);background:var(--soft);border:1px dashed var(--line);border-radius:var(--radius)}.pager{display:flex;gap:8px;justify-content:center;margin:14px 0}.pager button{padding:8px 16px;border-radius:999px;background:rgba(255,255,255,.08);border:1px solid var(--line);color:var(--text)}.mask{position:fixed;inset:0;z-index:70;display:none;background:rgba(0,0,0,.35);padding:18px}.mask.active{display:grid;place-items:center}.cfg{width:min(620px,100%);background:rgba(35,42,50,.96);border:1px solid var(--line);border-radius:20px;padding:16px}.field{width:100%;min-height:42px;border-radius:12px;border:1px solid var(--line);background:rgba(255,255,255,.08);color:var(--text);padding:8px 10px;outline:0;margin:5px 0 10px}.hint{color:var(--muted);font-size:12px;line-height:1.45}@media(min-width:720px){.grid{grid-template-columns:repeat(5,1fr)}.head{grid-template-columns:180px 1fr}.pic{width:180px}.eps{grid-template-columns:repeat(5,1fr)}}@media(min-width:1100px){.grid{grid-template-columns:repeat(7,1fr)}.app{max-width:1380px;margin:0 auto}.sheet{max-width:1180px;margin:0 auto}}</style></head><body><div class="app"><div class="bar"><div class="brand">360<b>影视</b></div><form class="search" id="searchForm"><input id="kw" placeholder="搜索电影、剧集、动漫、综艺…"><button>搜索</button></form><button class="btn" id="cfgBtn">解析</button></div><div class="tabs" id="tabs"></div><div class="chips" id="parserChips"></div><div class="status" id="status">准备加载…</div><main id="content"></main></div><div class="sheet" id="sheet"><div class="panel" id="panel"></div></div><div class="mask" id="cfgMask"><div class="cfg"><h3>自定义解析</h3><p class="hint">每行一个解析器:名称|解析地址。解析地址可使用 {url} 占位;不写占位则自动拼接 encodeURIComponent(url)。留空地址表示原站直传。</p><textarea class="field" id="parserInput" rows="8"></textarea><label>当前解析器</label><select class="field" id="parserSelect"></select><div style="display:flex;gap:8px;margin-top:12px"><button class="btn primary" id="saveCfg">保存</button><button class="btn" id="closeCfg">关闭</button></div></div></div><script>(function(){'use strict';if(window.fongmiBridge||window.fm)document.documentElement.classList.add('fm-native');const API='https://api.web.360kan.com/v1',SO='https://api.so.360kan.com/index',CLASSES=[['2','电视剧'],['1','电影'],['4','动漫'],['3','综艺']],sitePriority=['qq','imgo','qiyi','youku','leshi','cntv','douyin','bilibili1','xigua','sohu'],parserDefault=[{name:'direct',label:'原站',tpl:''},{name:'xmflv',label:'虾米',tpl:'https://jx.xmflv.com/?url={url}'},{name:'fish',label:'岁岁',tpl:''}];let parsers=loadParsers(),activeParser=localStorage.getItem('movie360_parser')||parsers[0].name,state={tid:'1',page:1,last:[]},currentDetail=null;const $=s=>document.querySelector(s),content=$('#content'),status=$('#status'),tabs=$('#tabs'),chips=$('#parserChips');function esc(s){return String(s||'').replace(/[&<>'"]/g,c=>({'&':'&','<':'<','>':'>',"'":''','"':'"'}[c]))}function clean(s){return String(s||'').replace(/<[^>]+>/g,'').replace(/\s+/g,' ').trim()}function normPic(u){u=String(u||'');if(u&&u.startsWith('//'))u='https:'+u;return u}function qs(o){return Object.keys(o).filter(k=>o[k]!==undefined&&o[k]!==null&&o[k]!=='').map(k=>encodeURIComponent(k)+'='+encodeURIComponent(o[k])).join('&')}async function req(url,opt){status.textContent='请求:'+url;if(window.fm&&fm.req){let r=await fm.req(url,{method:opt&&opt.method||'GET',headers:Object.assign({'User-Agent':'Mozilla/5.0','Referer':'https://www.360kan.com'},opt&&opt.headers||{}),responseType:'text',timeout:25});if(!r.ok)throw new Error(r.error||('HTTP '+r.status));return r.body||''}let r=await fetch(url,{headers:Object.assign({'Referer':'https://www.360kan.com'},opt&&opt.headers||{})});return await r.text()}async function json(url,opt){let d=JSON.parse(await req(url,opt)||'{}');if(d.errno!==undefined&&d.errno!==0)throw new Error(d.msg||'接口错误');return d}function loadParsers(){let s=localStorage.getItem('movie360_parsers');if(!s)return parserDefault;try{let a=JSON.parse(s);return a.length?a:parserDefault}catch(e){return parserDefault}}function saveParsers(){localStorage.setItem('movie360_parsers',JSON.stringify(parsers));localStorage.setItem('movie360_parser',activeParser)}function parserText(){return parsers.map(p=>`${p.label}|${p.tpl}`).join('\n')}function parseParserText(t){return String(t||'').split(/\n+/).map((l,i)=>{let p=l.split('|'),label=clean(p[0]),tpl=clean(p.slice(1).join('|'));return label?{name:'p'+i+'_'+label,label,tpl}:null}).filter(Boolean)}function activeP(){return parsers.find(p=>p.name===activeParser)||parsers[0]}function applyParser(u){u=String(u||'');let p=activeP();if(!p||!p.tpl)return u;return p.tpl.includes('{url}')?p.tpl.replace('{url}',encodeURIComponent(u)):p.tpl+encodeURIComponent(u)}function toVod(x,tid){let id=x.vod_id||`${tid||x.cat||''}_${x.ent_id||x.id||''}`;return{vod_id:id,vod_name:x.vod_name||x.title||x.titleTxt||'',vod_pic:normPic(x.vod_pic||x.cover||x.cdncover||''),vod_remarks:x.vod_remarks||x.upinfo||x.doubanscore||x.comment||((x.coverInfo||{}).txt)||'',vod_content:x.vod_content||x.description||'',raw:x}}function renderTabs(){tabs.innerHTML=CLASSES.map(x=>`<button class="tab ${state.tid===x[0]?'active':''}" data-id="${x[0]}">${x[1]}</button>`).join('');tabs.querySelectorAll('.tab').forEach(b=>b.onclick=()=>{state.tid=b.dataset.id;state.page=1;loadCategory()})}function renderParserChips(){chips.innerHTML=parsers.map(p=>`<button class="chip ${activeParser===p.name?'active':''}" data-id="${p.name}">${esc(p.label)}</button>`).join('');chips.querySelectorAll('.chip').forEach(b=>{b.onclick=()=>{activeParser=b.dataset.id;saveParsers();renderParserChips();if(currentDetail)renderEpisodes(currentDetail.lines[0].name)}})}function card(v,i){return`<article class="card" data-i="${i}"><div class="poster">${v.vod_pic?`<img loading="lazy" referrerpolicy="no-referrer" src="${esc(v.vod_pic)}">`:'<div class="noimg">360</div>'}<span class="badge">${esc(v.vod_remarks||'影视')}</span></div><div class="meta"><div class="name">${esc(v.vod_name)}</div><div class="remark">${esc(v.vod_content||v.vod_remarks||'点击查看')}</div></div></article>`}function renderGrid(list,total,pager){state.last=list;content.innerHTML=list.length?`<div class="grid">${list.map(card).join('')}</div>${pager?`<div class="pager"><button id="prev" ${state.page<=1?'disabled':''}>上一页</button><button id="next" ${state.page>=Math.ceil((total||0)/21)?'disabled':''}>下一页</button></div>`:''}`:'<div class="empty">暂无内容</div>';content.querySelectorAll('.card').forEach(c=>c.onclick=()=>openDetail(list[parseInt(c.dataset.i)]));let p=$('#prev'),n=$('#next');if(p)p.onclick=()=>{if(state.page>1){state.page--;loadCategory()}};if(n)n.onclick=()=>{state.page++;loadCategory()}}async function home(){renderTabs();content.innerHTML='<div class="empty">加载中…</div>';try{let d=await json(API+'/rank?'+qs({cat:1,size:21}));let list=(d.data||[]).map(x=>toVod(x,x.cat||1));renderGrid(list,list.length,false);status.textContent='首页榜单 · '+list.length+' 条'}catch(e){content.innerHTML='<div class="empty">首页失败:'+esc(e.message)+'</div>'}}async function loadCategory(){renderTabs();content.innerHTML='<div class="empty">加载中…</div>';try{let d=await json(API+'/filter/list?'+qs({catid:state.tid,size:21,pageno:state.page}));let data=d.data||{},list=(data.movies||[]).map(x=>toVod(x,state.tid));renderGrid(list,data.total||0,true);status.textContent=`${(CLASSES.find(x=>x[0]===state.tid)||[])[1]} 第 ${state.page} 页 · ${list.length}/${data.total||0}`}catch(e){content.innerHTML='<div class="empty">分类失败:'+esc(e.message)+'</div>'}}async function search(q){q=clean(q);if(!q)return;content.innerHTML='<div class="empty">搜索中…</div>';try{let d=await json(SO+'?'+qs({kw:q})),rows=((d.data||{}).longData||{}).rows||[];let list=rows.map(x=>toVod({vod_id:`${x.cat_id}_${x.en_id}`,title:x.titleTxt,cover:x.cover,coverInfo:x.coverInfo,year:x.year},x.cat_id));renderGrid(list,list.length,false);status.textContent=`搜索:${q} · ${list.length} 条`}catch(e){content.innerHTML='<div class="empty">搜索失败:'+esc(e.message)+'</div>'}}async function detailApi(id){let a=String(id).split('_');return await json(API+'/detail?'+qs({cat:a[0],id:a[1]}))}async function openDetail(v){$('#sheet').classList.add('active');$('#panel').innerHTML='<div class="empty">读取详情…</div>';try{let ret=await detailApi(v.vod_id),data=ret.data||{},vod={vod_id:v.vod_id,vod_name:data.title||v.vod_name,vod_pic:normPic(data.cdncover||v.vod_pic),type_name:data.moviecategory?data.moviecategory.slice(-1)[0]:'',vod_year:data.pubdate||'',vod_area:(data.area||[]).join(', '),vod_remarks:data.doubanscore||v.vod_remarks,vod_actor:(data.actor||[]).join(', '),vod_director:(data.director||[]).join(', '),vod_content:data.description||''},lines=await buildLines(v.vod_id,data);currentDetail={vod,lines};$('#panel').innerHTML=`<button class="btn" id="closeBtn">返回</button><div class="head"><img class="pic" referrerpolicy="no-referrer" src="${esc(vod.vod_pic)}" onerror="this.style.display='none'"><div><div class="title">${esc(vod.vod_name)}</div><div class="info"><div><b>年份:</b>${esc(vod.vod_year)}</div><div><b>地区:</b>${esc(vod.vod_area)}</div><div><b>类型:</b>${esc(vod.type_name)}</div><div><b>导演:</b>${esc(vod.vod_director)}</div><div><b>演员:</b>${esc(vod.vod_actor)}</div></div></div></div><div class="pill">简介</div><div class="desc">${esc(vod.vod_content||'暂无简介')}</div><div class="pill">播放线路 · 当前解析:${esc(activeP().label)}</div><div class="line-tabs" id="lineTabs">${lines.map((x,i)=>`<button class="line-tab ${i===0?'active':''}" data-line="${esc(x.name)}">${esc(x.name)}(${x.eps.length})</button>`).join('')}</div><div class="eps" id="eps"></div>`;$('#closeBtn').onclick=closeDetail;$('#lineTabs').querySelectorAll('.line-tab').forEach(b=>b.onclick=()=>{$('#lineTabs').querySelectorAll('.line-tab').forEach(x=>x.classList.remove('active'));b.classList.add('active');renderEpisodes(b.dataset.line)});renderEpisodes(lines[0]&&lines[0].name)}catch(e){$('#panel').innerHTML='<button class="btn" onclick="window.__m360Close()">返回</button><div class="empty">详情失败:'+esc(e.message)+'</div>'}}async function buildLines(id,data){let a=String(id).split('_'),params={cat:a[0],id:a[1]},sites=data.playlink_sites||Object.keys(data.playlinksdetail||{});sites.sort((x,y)=>(sitePriority.indexOf(x)<0?999:sitePriority.indexOf(x))-(sitePriority.indexOf(y)<0?999:sitePriority.indexOf(y)));let smart={},lines=[];for(let site of sites){let eps=data.allepidetail&&data.allepidetail[site]||[],total=Number(data.allupinfo&&data.allupinfo[site]||0);if(!eps.length&&total>0){let r=await json(API+'/detail?'+qs(Object.assign({},params,{site,start:1,end:50}))).catch(()=>({data:{}}));eps=r.data&&r.data.allepidetail&&r.data.allepidetail[site]||[]}if(eps.length<total&&total>50){for(let p=1;p<Math.ceil(total/50);p++){let start=p*50+1,end=Math.min(start+49,total);let r=await json(API+'/detail?'+qs(Object.assign({},params,{site,start,end}))).catch(()=>({data:{}}));eps=eps.concat(r.data&&r.data.allepidetail&&r.data.allepidetail[site]||[])}}let list=[];eps.forEach(ep=>{if(ep.url&&ep.playlink_num){let u=clean(ep.url);list.push({name:String(ep.playlink_num),url:u,site});smart[ep.playlink_num]=smart[ep.playlink_num]||[];if(!smart[ep.playlink_num].includes(u))smart[ep.playlink_num].push(u)}});if(!list.length&&data.playlinksdetail&&data.playlinksdetail[site]&&data.playlinksdetail[site].default_url){let u=clean(data.playlinksdetail[site].default_url);list.push({name:site,url:u,site});smart['1']=smart['1']||[];smart['1'].push(u)}if(list.length)lines.push({name:site,eps:list})}let keys=Object.keys(smart).sort((a,b)=>parseFloat(a)-parseFloat(b));if(keys.length)lines.unshift({name:'智能线路',eps:keys.map(k=>({name:k,url:smart[k].join('|||'),site:'smart'}))});return lines}function renderEpisodes(line){let ln=currentDetail&¤tDetail.lines.find(x=>x.name===line),list=ln&&ln.eps||[],box=$('#eps');box.innerHTML=list.map((x,i)=>`<button class="ep" data-line="${esc(line)}" data-i="${i}">${esc(x.name)}</button>`).join('')||'<div class="empty">暂无播放地址</div>';box.querySelectorAll('.ep').forEach(b=>b.onclick=()=>playFull(b.dataset.line,parseInt(b.dataset.i),b.textContent))}function directMedia(u){return /m3u8|\.mp4|\.m4v|\.flv|\.ts|bytetos|byteimg|akamaized|cdn/i.test(String(u||''))}function firstUrl(u){let arr=String(u||'').split('|||').filter(Boolean);return arr[0]||u}function extractReal(t){try{let j=JSON.parse(t);let u=j.url||j.play||j.data&&j.data.url||j.data&&j.data.play||j.data;if(typeof u==='string'&&/^https?:/.test(u))return u}catch(e){}let s=String(t||'').replace(/\\\//g,'/');let m=s.match(/https?:[^"'<>\\\s]+?(?:m3u8|mp4|m4v|flv|bytetos|byteimg)[^"'<>\\\s]*/i);return m?m[0]:''}async function resolveOne(raw){let arr=String(raw||'').split('|||').filter(Boolean);if(!arr.length)arr=[raw];for(let u of arr){let p=applyParser(u);if(directMedia(p))return p;if(!activeP().tpl)return p;try{status.textContent='请求解析:'+activeP().label;let t=await req(p,{headers:{Referer:'https://www.360kan.com'}});let real=extractReal(t);if(real)return real}catch(e){}}return applyParser(firstUrl(raw))}async function resolveLine(ln){for(let i=0;i<(ln.eps||[]).length;i++){let e=ln.eps[i];if(!e.real){status.textContent='首次解析全集 '+(i+1)+'/'+ln.eps.length+':'+e.name;e.real=await resolveOne(e.url)}}}async function playFull(line,index,mark){let d=currentDetail.vod,lines=currentDetail.lines,ln=lines.find(x=>x.name===line)||lines[0],cur=ln.eps[index];if(!cur)return;await resolveLine(ln);let from=[],urlArray=[];lines.forEach(l=>{from.push(l.name);urlArray.push(l.eps.map(e=>`${e.name}$${e.real||applyParser(firstUrl(e.url))}`).join('#'))});let native=ln.eps.map(e=>({name:e.name,url:e.real||applyParser(firstUrl(e.url))})),u=cur.real||applyParser(firstUrl(cur.url));if(window.fm&&typeof fm.vodInline==='function'){await fm.vodInline({vod_id:d.vod_id,vod_name:d.vod_name,vod_pic:d.vod_pic,vod_year:d.vod_year,vod_area:d.vod_area,vod_remarks:d.vod_remarks,vod_actor:d.vod_actor,vod_director:d.vod_director,vod_content:d.vod_content,vod_play_from:from.join('$$$'),vod_play_url:urlArray.join('$$$'),play_from:line,mark:mark||cur.name,episodes:native,url:u});return}if(window.fm&&fm.play){await fm.play(u,d.vod_name+' '+(mark||cur.name));return}location.href=u}function closeDetail(){$('#sheet').classList.remove('active')}function openCfg(){parserInput.value=parserText();parserSelect.innerHTML=parsers.map(p=>`<option value="${esc(p.name)}" ${activeParser===p.name?'selected':''}>${esc(p.label)}</option>`).join('');cfgMask.classList.add('active')}searchForm.onsubmit=e=>{e.preventDefault();search(kw.value)};cfgBtn.onclick=openCfg;closeCfg.onclick=()=>cfgMask.classList.remove('active');saveCfg.onclick=()=>{let p=parseParserText(parserInput.value);parsers=p.length?p:parserDefault;activeParser=parserSelect.value;if(!parsers.find(x=>x.name===activeParser))activeParser=parsers[0].name;saveParsers();cfgMask.classList.remove('active');renderParserChips()};window.__m360Close=closeDetail;renderTabs();renderParserChips();home();})();</script></body></html>