(function () { function fmtVer(v) { if (!v || !v.online) return v && v.msg ? String(v.msg) : "离线"; const short = v.short_sha || (v.sha ? String(v.sha).slice(0, 7) : ""); const branch = v.branch ? v.branch + " · " : ""; if (!short) return "未知版本"; return branch + short + (v.dirty ? " (dirty)" : ""); } async function refreshVersion(row) { const iid = row.getAttribute("data-id"); const verEl = row.querySelector("[data-inst-version]"); if (!iid || !verEl) return; verEl.textContent = "…"; verEl.className = "update-version muted"; try { const r = await fetch("/api/instances/" + iid + "/version", { credentials: "same-origin", headers: { Accept: "application/json" }, }); const v = await r.json(); if (v && v.online) { verEl.textContent = fmtVer(v); verEl.className = "update-version online"; } else { verEl.textContent = (v && v.msg) || "离线"; verEl.className = "update-version offline"; } } catch (e) { verEl.textContent = "探测失败"; verEl.className = "update-version offline"; } } function bindTokenToggles(root) { (root || document).querySelectorAll(".inst-token-toggle").forEach(function (btn) { if (btn.dataset.bound) return; btn.dataset.bound = "1"; btn.addEventListener("click", function () { const wrap = btn.closest(".inst-token-wrap"); const input = wrap && wrap.querySelector(".inst-token-input"); if (!input) return; const show = input.type === "password"; input.type = show ? "text" : "password"; btn.textContent = show ? "隐藏" : "显示"; }); }); } function boot() { bindTokenToggles(document); document.querySelectorAll("tr.inst-row[data-id]").forEach(function (row) { refreshVersion(row); const btn = row.querySelector("[data-inst-refresh-ver]"); if (btn) { btn.addEventListener("click", function (e) { e.preventDefault(); refreshVersion(row); }); } }); } if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", boot); } else { boot(); } })();