${escapeHtml(request.client_id)}来源 ${escapeHtml(request.client_address)} · ${escapeHtml(request.requested_at)}const activeLease = document.querySelector("#activeLease"); const pendingRequests = document.querySelector("#pendingRequests"); const pendingCount = document.querySelector("#pendingCount"); const revokeButton = document.querySelector("#revokeButton"); const message = document.querySelector("#message"); let snapshot = null; function escapeHtml(value) { const node = document.createElement("span"); node.textContent = String(value ?? ""); return node.innerHTML; } function showMessage(value, error = false) { message.textContent = value; message.style.color = error ? "#ff8797" : "#7fbbff"; } async function api(path, body) { const response = await fetch(path, { method: body ? "POST" : "GET", credentials: "same-origin", headers: body ? { "Content-Type": "application/json" } : {}, body: body ? JSON.stringify(body) : undefined, }); if (response.status === 401) { location.replace(`/login?next=${encodeURIComponent(location.pathname)}`); throw new Error("请先登录本机服务"); } const payload = await response.json(); if (!response.ok) throw new Error(payload.message || payload.error); return payload; } function render(data) { snapshot = data; pendingCount.textContent = String(data.pending.length); if (data.active) { const lease = data.active; activeLease.className = "lease-details"; activeLease.innerHTML = `
${escapeHtml(lease.client_id)}来源 ${escapeHtml(lease.client_address)} · 最近执行 ${escapeHtml(lease.last_activity_at)}${escapeHtml(request.client_id)}来源 ${escapeHtml(request.client_address)} · ${escapeHtml(request.requested_at)}