From 71407681dd37d814dc8b445c6df4fb0846020af5 Mon Sep 17 00:00:00 2001 From: hmo Date: Tue, 14 Jul 2026 00:01:13 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=97=AA=E7=83=81:=20fI?= =?UTF-8?q?=E5=86=85fill=E5=90=8E=E5=90=8C=E6=AD=A5appendChild=E4=B8=8D?= =?UTF-8?q?=E8=B7=A8tick?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - fill('infra',h)只含Platform+Ejabberd - 同一async函数内立即createElement+appendChild添加EasyTier/RDP - onclick通过.onclick赋值而非HTML属性 - 浏览器在JS执行完前不渲染,所有内容同时出现 - Playwright验证: 0 errors --- gateway/scripts/templates/dashboard.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gateway/scripts/templates/dashboard.html b/gateway/scripts/templates/dashboard.html index 983a9a1..7ab381d 100644 --- a/gateway/scripts/templates/dashboard.html +++ b/gateway/scripts/templates/dashboard.html @@ -103,7 +103,7 @@ async function fT(){try{var r=await fetch('/api/todos'),d=await r.json();fill('t async function fE(){try{var r=await fetch('/api/metagrowth'),d=await r.json();fill('meta','fixes: '+(d.total_fixes||0)+' commits: '+(d.commit_count||0))}catch(e){}} async function fF(){try{var r=await fetch('/api/expected'),d=await r.json();var ok=0;for(var i=0;i'+n+' tasks':'No tasks')}catch(e){}} -async function fI(){try{var r=await fetch('/api/platform'),d=await r.json();var h='

Platform

';for(var i=0;i'+esc(d[i].name)+'
';}h+='
';try{var r2=await fetch('/api/ejabberd'),e=await r2.json();var ea=e.alive||e.xmpp_bot_connected;h+='

Ejabberd

'+(ea?'ALIVE':'DOWN')+'
';}catch(e2){}fill('infra',h);await fetchEasyTierStatus();await fetchRdpStatus()}catch(e){}} +async function fI(){try{ var r=await fetch('/api/platform'),d=await r.json(); var h='

Platform

'; for(var i=0;i'+esc(d[i].name)+'
';} h+='
'; try{var r2=await fetch('/api/ejabberd'),e=await r2.json();var ea=e.alive||e.xmpp_bot_connected; h+='

Ejabberd

'+(ea?'ALIVE':'DOWN')+'
';}catch(e2){} fill('infra',h); /* EasyTier section */ try{var r3=await fetch('/api/easytier'),e3=await r3.json(),s=e3.status||{}; var et=document.createElement('div');et.className='ps';et.style.marginTop='16px'; var av=(e3.virtual_ips||{});var wip=av.windows||'';var tip=av['246']||''; et.innerHTML='

EasyTier VPN

Windows '+wip+'
246 '+tip+'
-
'; var ci=document.getElementById('ct-infra');if(ci)ci.appendChild(et); var e1=document.getElementById('et-w');if(e1)e1.className='d '+(s.windows==='running'?'ok':'stopped'); var e2=document.getElementById('et-246');if(e2)e2.className='d '+(s['246']==='running'?'ok':'stopped'); var allRun=Object.values(s).every(function(v){return v==='running'||v==='pending'}); var ob=document.getElementById('btn-et-on');var ofb=document.getElementById('btn-et-off');var stx=document.getElementById('et-status'); if(ob){ob.disabled=allRun;ob.onclick=function(){fetch('/api/easytier/toggle',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({action:'start'})}).then(function(){setTimeout(fI,500)}).catch(function(e){toast('ET Fail','err')})};} if(ofb){ofb.disabled=!allRun;ofb.onclick=function(){fetch('/api/easytier/toggle',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({action:'stop'})}).then(function(){setTimeout(fI,500)}).catch(function(e){toast('ET Fail','err')})};} if(stx)stx.textContent=allRun?'Connected':'Off';}catch(e3){} /* RDP section */ try{var r4=await fetch('/api/rdp'),e4=await r4.json(); var rd=document.createElement('div');rd.className='ps';rd.style.marginTop='16px'; rd.innerHTML='

RDP Remote Desktop

RDP '+esc(e4.public_endpoint||'')+'
Tunnel
-
'; var ci2=document.getElementById('ct-infra');if(ci2)ci2.appendChild(rd); var ee1=document.getElementById('rdp-st');if(ee1)ee1.className='d '+(e4.rdp_enabled?'ok':'stopped'); var ee2=document.getElementById('rdp-tun');if(ee2)ee2.className='d '+(e4.tunnel_running?'ok':'stopped'); var fOn=e4.rdp_enabled&&e4.tunnel_running; var ob2=document.getElementById('btn-rdp-on');var ofb2=document.getElementById('btn-rdp-off');var stx2=document.getElementById('rdp-status-txt'); if(ob2){ob2.disabled=fOn;ob2.onclick=function(){fetch('/api/rdp/toggle',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({action:'start'})}).then(function(){setTimeout(fI,500)}).catch(function(e){toast('RDP Fail','err')})};} if(ofb2){ofb2.disabled=!fOn;ofb2.onclick=function(){fetch('/api/rdp/toggle',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({action:'stop'})}).then(function(){setTimeout(fI,500)}).catch(function(e){toast('RDP Fail','err')})};} if(stx2)stx2.textContent=fOn?'Connected':e4.rdp_enabled?'Tunnel pending':'Disconnected';}catch(e4){} }catch(e){}} var FETCHES={agents:fa,git:fG,svc:fS,mon:fM,todos:fT,meta:fE,exp:fF,spec:fS2,kanban:fK,infra:fI,easytier:fE2,rdp:fR,principles:function(){return(FETCHES[as]||function(){})()}}; async function loadAll(){var d=new Date();qs('subtitle').textContent=d.getFullYear()+'-'+(d.getMonth()+1)+'-'+d.getDate()+' '+d.getHours()+':'+d.getMinutes();await Promise.all(Object.keys(FETCHES).map(function(k){return FETCHES[k]()}));}