const tokenInput = document.querySelector("#tokenInput"); const statusBar = document.querySelector("#statusBar"); const refreshButton = document.querySelector("#refreshButton"); const form = document.querySelector("#serviceForm"); const settingsForm = document.querySelector("#settingsForm"); const rowsEl = document.querySelector("#serviceRows"); const adminBrand = document.querySelector("#adminBrand"); const browserTitleInput = document.querySelector("#browserTitleInput"); const brandInput = document.querySelector("#brandInput"); const titleInput = document.querySelector("#titleInput"); const subtitleInput = document.querySelector("#subtitleInput"); const originalIdInput = document.querySelector("#originalIdInput"); const idInput = document.querySelector("#idInput"); const nameInput = document.querySelector("#nameInput"); const groupInput = document.querySelector("#groupInput"); const urlInput = document.querySelector("#urlInput"); const noteInput = document.querySelector("#noteInput"); const resetButton = document.querySelector("#resetButton"); const serviceFormTitle = document.querySelector("#serviceFormTitle"); const newFromListButton = document.querySelector("#newFromListButton"); const tabButtons = document.querySelectorAll(".tab-button"); const quickActionButtons = document.querySelectorAll(".quick-action"); const adminSections = document.querySelectorAll(".admin-section"); let services = []; let settings = {}; function setStatus(message, isError = false) { statusBar.textContent = message; statusBar.classList.toggle("error", isError); } function showPanel(panelId) { for (const button of tabButtons) { button.classList.toggle("active", button.dataset.target === panelId); } for (const button of quickActionButtons) { button.classList.toggle("active", button.dataset.target === panelId); } for (const section of adminSections) { section.classList.toggle("active", section.dataset.panel === panelId); } } function formatTime(value) { if (!value) return "-"; const date = new Date(value); if (Number.isNaN(date.getTime())) return value; return new Intl.DateTimeFormat("zh-CN", { month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" }).format(date); } function getToken() { return tokenInput.value.trim(); } function apiUrl(path) { const url = new URL(path, window.location.origin); const token = getToken(); if (token) url.searchParams.set("token", token); return url; } function loadSavedToken() { tokenInput.value = localStorage.getItem("stun-nav-admin-token") || ""; } function saveToken() { localStorage.setItem("stun-nav-admin-token", getToken()); } function applySettings(nextSettings = {}) { settings = nextSettings; document.title = settings.browserTitle ? `${settings.browserTitle} - 管理` : "导航管理"; adminBrand.textContent = settings.brand || "STUN NAV"; browserTitleInput.value = settings.browserTitle || ""; brandInput.value = settings.brand || ""; titleInput.value = settings.title || ""; subtitleInput.value = settings.subtitle || ""; } function clearForm() { originalIdInput.value = ""; form.reset(); tokenInput.value = localStorage.getItem("stun-nav-admin-token") || tokenInput.value; serviceFormTitle.textContent = "新增导航"; showPanel("servicePanel"); idInput.focus(); } function fillForm(service) { originalIdInput.value = service.id; idInput.value = service.id; nameInput.value = service.name || ""; groupInput.value = service.group || ""; urlInput.value = service.url || ""; noteInput.value = service.note || ""; serviceFormTitle.textContent = "编辑导航"; showPanel("servicePanel"); window.scrollTo({ top: 0, behavior: "smooth" }); } async function requestJson(url, options = {}) { const response = await fetch(url, { ...options, headers: { "content-type": "application/json", ...(options.headers || {}) } }); const data = await response.json().catch(() => ({})); if (!response.ok || data.ok === false) { throw new Error(data.error || `请求失败:${response.status}`); } return data; } function renderRows() { rowsEl.replaceChildren(); if (!services.length) { const row = document.createElement("tr"); const cell = document.createElement("td"); cell.colSpan = 6; cell.className = "empty-cell"; cell.textContent = "还没有导航项"; row.append(cell); rowsEl.append(row); return; } for (const service of services) { const row = document.createElement("tr"); row.innerHTML = `