130 lines
3.4 KiB
JavaScript

const HAIYI_BASE_PATH = window.location.pathname === "/haiyi" || window.location.pathname.startsWith("/haiyi/") ? "/haiyi" : "";
function appPath(path) {
const normalized = typeof path === "string" && path.startsWith("/") ? path : `/${path || ""}`;
return `${HAIYI_BASE_PATH}${normalized}` || "/";
}
function loginRedirectPath() {
return `/login?next=${encodeURIComponent(`${window.location.pathname}${window.location.search}`)}`;
}
async function readJsonResponse(response) {
const text = await response.text();
if (!text) {
return {};
}
try {
return JSON.parse(text);
} catch (error) {
throw new Error(text);
}
}
window.addEventListener("DOMContentLoaded", async () => {
const bootIndicator = document.getElementById("boot-indicator");
const root = document.getElementById("haiyi-root");
const errorNode = document.getElementById("haiyi-error");
const usernameNode = document.getElementById("haiyi-username");
const healthNode = document.getElementById("haiyi-health");
const refreshButton = document.getElementById("haiyi-refresh");
const logoutButton = document.getElementById("haiyi-logout");
const showPage = () => {
if (bootIndicator) {
bootIndicator.hidden = true;
}
if (root) {
root.hidden = false;
}
};
const setError = (message) => {
if (!errorNode) {
return;
}
errorNode.textContent = message || "";
errorNode.hidden = !message;
};
const loadSession = async () => {
const response = await fetch(appPath("/api/auth/session"), {
cache: "no-store",
credentials: "same-origin",
});
const payload = await readJsonResponse(response);
if (response.status === 401) {
window.location.replace(loginRedirectPath());
return false;
}
if (!response.ok) {
throw new Error(payload.error || `HTTP ${response.status}`);
}
if (usernameNode) {
usernameNode.textContent = payload.username || "";
usernameNode.hidden = !payload.username;
}
return true;
};
const loadHealth = async () => {
const response = await fetch(appPath("/api/health"), {
cache: "no-store",
credentials: "same-origin",
});
const payload = await readJsonResponse(response);
if (!response.ok) {
throw new Error(payload.error || `HTTP ${response.status}`);
}
if (healthNode) {
healthNode.textContent = payload.status === "ok" ? "在线" : "异常";
healthNode.className = payload.status === "ok" ? "badge ok" : "badge bad";
}
};
try {
const ok = await loadSession();
if (!ok) {
return;
}
await loadHealth();
} catch (error) {
setError(error instanceof Error ? error.message : String(error));
} finally {
showPage();
}
if (refreshButton instanceof HTMLButtonElement) {
refreshButton.addEventListener("click", async () => {
refreshButton.disabled = true;
setError("");
try {
await loadHealth();
} catch (error) {
setError(error instanceof Error ? error.message : String(error));
} finally {
refreshButton.disabled = false;
}
});
}
if (logoutButton instanceof HTMLButtonElement) {
logoutButton.addEventListener("click", async () => {
logoutButton.disabled = true;
try {
await fetch(appPath("/api/auth/logout"), {
method: "POST",
credentials: "same-origin",
});
} finally {
window.location.replace("/login");
}
});
}
});