diff --git a/internal/lua/plugins/ccquota.lua b/internal/lua/plugins/ccquota.lua index 83c9af4..b37cd11 100644 --- a/internal/lua/plugins/ccquota.lua +++ b/internal/lua/plugins/ccquota.lua @@ -299,7 +299,10 @@ PLUGIN.ui = { try{ var r=await fetch("/api/sources",{credentials:"same-origin"}); srcs=(await r.json()).sources||[]; - }catch(e){ render([]); return; } + }catch(e){ + var s0=document.getElementById("ccq-sub"); if(s0) s0.textContent="拉取源列表失败: "+e.message; + render([]); return; + } // Every source on the Command Code host is one account, keyed by its own // API key — two keys on that host are two seats, and both must be listed. var accts=srcs.filter(function(s){ @@ -310,6 +313,11 @@ PLUGIN.ui = { if(btn) btn.disabled=true; var auto=document.getElementById("ccq-auto")||document.querySelector(".ccq-auto"); if(auto) auto.textContent="拉取中…"; + if(!window.pluginAPI || typeof pluginAPI.call!=="function"){ + var sb=document.getElementById("ccq-sub"); + if(sb) sb.textContent="pluginAPI.call 不可用(内核版本过旧)"; + render([]); return; + } var out=[]; var errs=0; // One account at a time: the endpoints are independent, and a sequential @@ -331,11 +339,36 @@ PLUGIN.ui = { if(auto) auto.textContent="更新于 "+new Date().toLocaleTimeString(); try{ await pluginAPI.postState("ccquota",{reports:out,updated_at:Date.now()}); }catch(e){} } - document.addEventListener("DOMContentLoaded",function(){ + // The mount is injected long after DOMContentLoaded has already fired, so + // listening for that event here registered a handler for an event that had + // already been dispatched — the page rendered but stayed empty until a manual + // refresh. Wiring the button and fetching immediately is what makes the page + // populate on first open. + // The plugin mount is injected by the kernel and its