fix: credentials.html JS parse error + assets.html SSH session UX

credentials.html: Remove broken nested ternary `Alpine?Alpine.store?...`
that caused "Unexpected token ':'" which killed the entire script block,
making all functions (showAddCred, loadCreds, etc.) undefined.

assets.html: Replace SSH session history list with server list +
double-click to open terminal, matching user's requested UX.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
Your Name
2026-05-25 19:17:09 +08:00
parent 3943ff4f3a
commit cf0725b037
2 changed files with 17 additions and 20 deletions
+16 -18
View File
@@ -23,6 +23,7 @@
</div>
<!-- SSH Sessions -->
<div id="sessionsSection" class="hidden">
<p class="text-slate-500 text-xs mb-3">双击服务器行打开SSH终端</p>
<div id="sessionsList" class="space-y-2"><div class="text-slate-500 text-center py-8">加载中...</div></div>
</div>
@@ -73,7 +74,7 @@
function showAddModal(){
const tab=document.getElementById('platformsSection').classList.contains('hidden')?
(document.getElementById('nodesSection').classList.contains('hidden')?'sessions':'nodes'):'platforms';
(document.getElementById('nodesSection').classList.contains('hidden')?null:'nodes'):'platforms';
if(tab==='platforms')showAddPlatform();
else if(tab==='nodes')showAddNode();
}
@@ -271,28 +272,25 @@
// ── SSH Sessions ──
async function loadSessions(){
try{
const [sessR,srvR]=await Promise.all([apiFetch(API+'/assets/ssh-sessions?limit=50'),apiFetch(API+'/servers/?per_page=500')]);
if(!sessR)return;
const sessions=await sessR.json();
// Build server name lookup
const srvMap={};
if(srvR&&srvR.ok){const sd=await srvR.json();(sd.items||sd).forEach(s=>srvMap[s.id]=s.name)}
if(!sessions.length){document.getElementById('sessionsList').innerHTML='<div class="text-slate-500 text-center py-8">暂无SSH会话记录</div>';return}
document.getElementById('sessionsList').innerHTML=sessions.map(s=>{
const statusColor=s.status==='active'?'text-green-400':s.status==='closed'?'text-slate-500':'text-yellow-400';
const statusLabel=s.status==='active'?'活跃':s.status==='closed'?'已关闭':'超时';
const srvName=srvMap[s.server_id]||('Server #'+s.server_id);
return `<div class="bg-slate-900 rounded-xl border border-slate-800 p-3 flex items-center justify-between">
const srvR=await apiFetch(API+'/servers/?per_page=500');
if(!srvR)return;
const data=await srvR.json();
const servers=data.items||data;
if(!servers.length){document.getElementById('sessionsList').innerHTML='<div class="text-slate-500 text-center py-8">暂无服务器,请先添加服务器</div>';return}
document.getElementById('sessionsList').innerHTML=servers.map(s=>{
const hasSSH=s.domain?'':'opacity-50';
const hint=s.domain?'双击连接':'未配置域名';
return `<div class="bg-slate-900 rounded-xl border border-slate-800 p-3 flex items-center justify-between cursor-pointer hover:border-brand/40 transition ${hasSSH}" ondblclick="${s.domain?`window.open('/app/terminal.html?server_id='+${s.id})`:''}" title="${hint}">
<div class="flex items-center gap-3">
<span class="${statusColor}"></span>
<span class="text-slate-500">🖥</span>
<div>
<span class="text-white text-sm">${esc(srvName)}</span>
<span class="text-slate-500 text-xs ml-2">${esc(s.remote_addr||'')}</span>
<span class="text-white text-sm">${esc(s.name)}</span>
<span class="text-slate-500 text-xs ml-2">${esc(s.domain||'')}</span>
</div>
</div>
<div class="text-right text-xs text-slate-500">
<div>${statusLabel}</div>
<div>${fmtTime(s.started_at)}</div>
<div>${esc(s.username||'root')}@${esc(s.domain||s.ip||'—')}</div>
<div>${hint}</div>
</div>
</div>`;
}).join('');
+1 -2
View File
@@ -88,8 +88,7 @@
}
function showAddCred(){
const t=Alpine?Alpine.store?'db':document.querySelector('[x-data]')?.__x?.$data?.tab:'db':'db';
// Check which tab is active
// Check which tab is active via DOM visibility
if(!document.getElementById('dbSection').classList.contains('hidden')){
['credName','credHost','credUser','credPass','credDb'].forEach(id=>document.getElementById(id).value='');
document.getElementById('credType').value='mysql';