Files
gpt_from_scratch/website/index.html
T
2026-06-12 17:19:26 +08:00

176 lines
5.8 KiB
HTML

<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>软件下载页面</title>
<style>
body{font-size:18px!important;line-height:2;font-family:sans-serif;margin:.5em 1.5em 2em}
h1{font-size:24px!important;margin-top:0;margin-bottom:.5em;border-bottom:2px solid #ccc;padding-bottom:.3em}
.breadcrumb{font-size:18px;margin-bottom:.75em}
.breadcrumb a{color:#0066cc;cursor:pointer}
.loading{font-size:20px;color:#666}
.error{color:#c00;font-size:18px}
.user-bar{margin-bottom:.4em;padding:.25em 0;display:flex;align-items:center;justify-content:flex-end;gap:1em}
.user-bar .logged-in{color:green}
.user-bar .logout-btn{padding:.3em .8em;font-size:16px;cursor:pointer;background:#0066cc;color:#fff;border:none;border-radius:4px}
.user-bar .logout-btn:hover{background:#0052a3}
.file-list{width:100%}
.file-table{width:100%;border-collapse:collapse;margin-top:.25em;table-layout:fixed}
.file-table th,.file-table td{padding:.45em .65em;border-bottom:1px solid #ddd;text-align:left;vertical-align:middle;word-break:break-word}
.file-table th{font-size:17px;font-weight:600;color:#333;background:#f5f5f5;border-bottom:2px solid #ccc}
.file-table td:nth-child(1){width:52%}
.file-table td:nth-child(2),.file-table td:nth-child(3){font-size:16px;color:#555;white-space:nowrap}
.file-table a{font-size:19px!important;color:#0066cc;text-decoration:none}
.file-table a:hover{text-decoration:underline}
.file-table .dir{font-weight:bold;cursor:pointer}
.file-table .empty-msg{text-align:center;color:#666;padding:1em}
</style>
</head>
<body>
<div class="user-bar">
<span class="logged-in">当前已登录: <span id="username-display"></span></span>
<button class="logout-btn" id="logout-btn">注销</button>
</div>
<h1>文件列表 <span id="path-display"></span></h1>
<div class="breadcrumb" id="breadcrumb"></div>
<div id="content">
<div class="loading" id="loading">正在加载...</div>
<div class="file-list" id="file-list" style="display:none"></div>
<div class="error" id="error" style="display:none"></div>
</div>
<script>
(function(){
var authHeader=sessionStorage.getItem("auth");
var username=sessionStorage.getItem("username");
if(!authHeader){
window.location.href="/login.html?return="+encodeURIComponent(window.location.pathname);
return;
}
document.getElementById("username-display").textContent=username||"";
loadFileList(getPath());
function getPath(){
var p=window.location.pathname;
if(p==="/"||p==="")return"";
if(p.endsWith("/"))p=p.slice(0,-1);
return p.replace(/^\//,"");
}
function shouldHideFile(filename){
var hiddenPatterns=[/\.php$/i,/\.html$/i,/\.backup$/i,/^api$/i,/^auth_check/i,/^login/i,/^logout/i,/^index\./i];
return hiddenPatterns.some(function(pattern){return pattern.test(filename)});
}
function escapeHtml(s){
if(s==null||s==="")return"";
return String(s).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;");
}
function formatSize(bytes){
if(!bytes)return"-";
if(bytes<1024)return bytes+" B";
if(bytes<1048576)return(bytes/1024).toFixed(1)+" K";
if(bytes<1073741824)return(bytes/1048576).toFixed(1)+" M";
return(bytes/1073741824).toFixed(1)+" G";
}
function formatMtime(mtime){
if(!mtime)return"";
try{
var d=new Date(mtime);
return isNaN(d)?mtime:d.toLocaleString();
}catch(e){
return mtime;
}
}
function renderBreadcrumb(path){
var parts=path?path.split("/").filter(Boolean):[];
if(parts.length===0){
document.getElementById("breadcrumb").innerHTML="";
return;
}
var html="";
var acc="";
for(var i=0;i<parts.length;i++){
acc+=(acc?"/":"")+parts[i];
if(i>0)html+=" / ";
html+='<a onclick="navigateTo(\'/'+acc+'/\')">'+ parts[i]+"</a>";
}
document.getElementById("breadcrumb").innerHTML=html;
}
window.navigateTo=function(path){
window.location.href=path;
};
function loadFileList(path){
var loadingEl=document.getElementById("loading");
var errorEl=document.getElementById("error");
var listEl=document.getElementById("file-list");
loadingEl.style.display="block";
errorEl.style.display="none";
listEl.style.display="none";
fetch("/list/"+(path?path+"/":""),{
headers:{Authorization:authHeader}
})
.then(function(r){
if(r.status===401){
sessionStorage.clear();
window.location.href="/login.html";
return;
}
if(!r.ok)throw new Error("加载失败");
return r.json();
})
.then(function(data){
if(!data)return;
loadingEl.style.display="none";
document.getElementById("path-display").textContent=path?"/"+path:"";
renderBreadcrumb(path);
var rows="";
var items=Array.isArray(data)?data:[];
items.forEach(function(item){
if(shouldHideFile(item.name))return;
var fullPath=(path?path+"/":"")+item.name;
var isDir=item.type==="directory";
var size=formatSize(item.size);
var mtime=formatMtime(item.mtime);
var nameEsc=escapeHtml(item.name);
if(isDir){
var navPath="/"+fullPath+"/";
rows+="<tr><td><a onclick=\"navigateTo("+JSON.stringify(navPath)+")\" class=\"dir\" href=\"javascript:void(0)\">"+nameEsc+"/</a></td><td>"+escapeHtml(size)+"</td><td>"+escapeHtml(mtime)+"</td></tr>";
}else{
rows+="<tr><td><a href=\"/"+fullPath+"?u="+encodeURIComponent(username)+"\" download>"+nameEsc+"</a></td><td>"+escapeHtml(size)+"</td><td>"+escapeHtml(mtime)+"</td></tr>";
}
});
var tableStart='<table class="file-table"><thead><tr><th>文件名称</th><th>文件大小</th><th>上传时间</th></tr></thead><tbody>';
var tableEnd="</tbody></table>";
if(!rows){
listEl.innerHTML=tableStart+'<tr><td class="empty-msg" colspan="3">目录为空</td></tr>'+tableEnd;
}else{
listEl.innerHTML=tableStart+rows+tableEnd;
}
listEl.style.display="block";
})
.catch(function(err){
loadingEl.style.display="none";
errorEl.textContent="加载失败: "+(err.message||"未知错误");
errorEl.style.display="block";
});
}
document.getElementById("logout-btn").addEventListener("click",function(){
sessionStorage.clear();
window.location.href="/login.html";
});
})();
</script>
</body>
</html>