升级:直播源数据服务器保存

This commit is contained in:
admin
2026-10-02 05:54:08 +08:00
parent 2cf61f938f
commit 79b1722945
+33 -20
View File
@@ -63,8 +63,8 @@ footer{text-align:center;color:#5d8496;font-size:12px;margin-top:60px;}
</div> </div>
</div> </div>
<p class="stats" id="stats"></p> <p class="stats" id="stats"></p>
<div id="list"></div> <div id="list"><div class="empty">加载中…</div></div>
<footer>本页面仅作技术交流与源共享用途 · 数据保存在浏览器本地</footer> <footer>本页面仅作技术交流与源共享用途 · 数据保存在服务器,全站共享</footer>
</div> </div>
<div class="modal" id="pwdModal"> <div class="modal" id="pwdModal">
<div class="modal-box"> <div class="modal-box">
@@ -76,18 +76,11 @@ footer{text-align:center;color:#5d8496;font-size:12px;margin-top:60px;}
<div class="toast" id="toast"></div> <div class="toast" id="toast"></div>
<script> <script>
var ADMIN_PWD='iptv2026'; var ADMIN_PWD='iptv2026';
var KEY='iptv_share_sources'; var API='/api/iptv';
var DEFAULTS=[
{name:'示例 · 综合直播源(m3u)',url:'https://live.fanmingming.com/tv/m3u/ipv6.m3u'},
{name:'示例 · 央视卫视源(txt)',url:'http://example.com/cctv.txt'}
];
function load(){try{var v=JSON.parse(localStorage.getItem(KEY));if(v&&v.length>=0)return v;}catch(e){}return DEFAULTS.slice();}
function save(v){try{localStorage.setItem(KEY,JSON.stringify(v));}catch(e){}}
var isAdmin=false; var isAdmin=false;
function toast(m){var t=document.getElementById('toast');t.textContent=m;t.classList.add('show');setTimeout(function(){t.classList.remove('show');},1800);} function toast(m){var t=document.getElementById('toast');t.textContent=m;t.classList.add('show');setTimeout(function(){t.classList.remove('show');},1800);}
function esc(s){return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');} function esc(s){return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');}
function render(){ function render(v){
var v=load();
document.getElementById('stats').textContent='共 '+v.length+' 个直播源'; document.getElementById('stats').textContent='共 '+v.length+' 个直播源';
var h=''; var h='';
if(v.length===0){h='<div class="empty">暂无直播源,管理员登录后可添加</div>';} if(v.length===0){h='<div class="empty">暂无直播源,管理员登录后可添加</div>';}
@@ -96,7 +89,34 @@ function render(){
} }
document.getElementById('list').innerHTML=h; document.getElementById('list').innerHTML=h;
} }
function copyUrl(i){var v=load()[i].url;navigator.clipboard?navigator.clipboard.writeText(v).then(function(){toast('已复制');},function(){fallback(v);}):fallback(v);} function fetchList(cb){
var x=new XMLHttpRequest();
x.open('GET',API,true);
x.onload=function(){if(x.status===200){try{cb(JSON.parse(x.responseText).sources||[]);}catch(e){cb([]);}}else{cb([]);}};
x.onerror=function(){cb([]);};
x.send(null);
}
function refresh(){fetchList(render);}
function saveToServer(list){
var x=new XMLHttpRequest();
x.open('POST',API,true);
x.setRequestHeader('Content-Type','application/json');
x.onload=function(){
if(x.status===200){toast('已保存到服务器');refresh();}
else if(x.status===403){toast('密码错误');}
else{toast('保存失败,请重试');}
};
x.onerror=function(){toast('网络错误');};
x.send(JSON.stringify({pwd:ADMIN_PWD,sources:list}));
}
function addItem(){
var n=document.getElementById('inName').value.trim(),u=document.getElementById('inUrl').value.trim();
if(!n||!u){toast('请填写标题和链接');return;}
fetchList(function(v){v.push({name:n,url:u});saveToServer(v);});
document.getElementById('inName').value='';document.getElementById('inUrl').value='';
}
function delItem(i){fetchList(function(v){v.splice(i,1);saveToServer(v);});}
function copyUrl(i){fetchList(function(v){var u=v[i].url;navigator.clipboard?navigator.clipboard.writeText(u).then(function(){toast('已复制');},function(){fallback(u);}):fallback(u);});}
function fallback(t){var ta=document.createElement('textarea');ta.value=t;document.body.appendChild(ta);ta.select();document.execCommand('copy');document.body.removeChild(ta);toast('已复制');} function fallback(t){var ta=document.createElement('textarea');ta.value=t;document.body.appendChild(ta);ta.select();document.execCommand('copy');document.body.removeChild(ta);toast('已复制');}
function adminClick(){ function adminClick(){
if(isAdmin){isAdmin=false;document.body.classList.remove('admin');document.getElementById('addPanel').classList.remove('show');document.getElementById('adminBtn').textContent='管理员';document.getElementById('adminBtn').classList.remove('unlock');toast('已退出管理员');} if(isAdmin){isAdmin=false;document.body.classList.remove('admin');document.getElementById('addPanel').classList.remove('show');document.getElementById('adminBtn').textContent='管理员';document.getElementById('adminBtn').classList.remove('unlock');toast('已退出管理员');}
@@ -107,15 +127,8 @@ function doLogin(){
if(p===ADMIN_PWD){isAdmin=true;document.body.classList.add('admin');document.getElementById('pwdModal').classList.remove('show');document.getElementById('addPanel').classList.add('show');document.getElementById('adminBtn').textContent='管理员已解锁';document.getElementById('adminBtn').classList.add('unlock');toast('欢迎,管理员');} if(p===ADMIN_PWD){isAdmin=true;document.body.classList.add('admin');document.getElementById('pwdModal').classList.remove('show');document.getElementById('addPanel').classList.add('show');document.getElementById('adminBtn').textContent='管理员已解锁';document.getElementById('adminBtn').classList.add('unlock');toast('欢迎,管理员');}
else{toast('密码错误');} else{toast('密码错误');}
} }
function addItem(){
var n=document.getElementById('inName').value.trim(),u=document.getElementById('inUrl').value.trim();
if(!n||!u){toast('请填写标题和链接');return;}
var v=load();v.push({name:n,url:u});save(v);render();
document.getElementById('inName').value='';document.getElementById('inUrl').value='';toast('添加成功');
}
function delItem(i){var v=load();v.splice(i,1);save(v);render();toast('已删除');}
document.getElementById('pwdModal').addEventListener('click',function(e){if(e.target===this)this.classList.remove('show');}); document.getElementById('pwdModal').addEventListener('click',function(e){if(e.target===this)this.classList.remove('show');});
render(); refresh();
</script> </script>
</body> </body>
</html> </html>