Files
PolyWeather/extension/options.js
T
2026-06-14 23:13:37 +08:00

146 lines
4.7 KiB
JavaScript

const DEFAULT_CONFIG = {
apiBase: "https://polyweather.top",
siteBase: "https://polyweather.top",
authToken: "",
selectedCity: ""
};
const locale = String(navigator.language || "en").toLowerCase().startsWith("zh")
? "zh"
: "en";
const I18N = {
zh: {
settingsTitle: "PolyWeather 侧边栏设置",
tokenLabel: "Bearer Token(可选)",
tokenPlaceholder: "公开模式留空即可;仅当后端返回 401 时再填写。",
save: "保存",
test: "测试 /api/cities",
saved: "已保存。公开模式下 Token 可留空。",
connectOk: "连接成功,返回城市数",
tokenOptional: "Token 可留空",
testFailed: "测试失败",
backendAuthHint: "说明后端仍要求鉴权;若你要公开插件,请先放开 /api/cities 与 /api/city/*/detail。"
},
en: {
settingsTitle: "PolyWeather Side Panel Settings",
tokenLabel: "Bearer Token (Optional)",
tokenPlaceholder: "Leave empty in public mode; only fill it if the backend returns 401.",
save: "Save",
test: "Test /api/cities",
saved: "Saved. Token can be empty in public mode.",
connectOk: "Connected successfully, city count",
tokenOptional: "Token can be empty",
testFailed: "Test failed",
backendAuthHint: "The backend still requires auth. If the extension should be public, allow /api/cities and /api/city/*/detail."
}
};
function t(key) {
return I18N[locale][key] || I18N.zh[key] || key;
}
const apiBaseInput = document.getElementById("apiBaseInput");
const siteBaseInput = document.getElementById("siteBaseInput");
const tokenInput = document.getElementById("tokenInput");
const resultBox = document.getElementById("resultBox");
const settingsTitle = document.getElementById("settingsTitle");
const siteBaseLabel = document.getElementById("siteBaseLabel");
const apiBaseLabel = document.getElementById("apiBaseLabel");
const tokenLabel = document.getElementById("tokenLabel");
const saveBtn = document.getElementById("saveBtn");
const testBtn = document.getElementById("testBtn");
function normalizeBase(url) {
return String(url || "").trim().replace(/\/+$/, "");
}
function writeResult(text) {
resultBox.textContent = text;
}
function getStorage() {
return new Promise((resolve) => {
chrome.storage.sync.get(DEFAULT_CONFIG, (items) => resolve(items));
});
}
function setStorage(values) {
return new Promise((resolve) => {
chrome.storage.sync.set(values, resolve);
});
}
async function loadForm() {
const cfg = await getStorage();
apiBaseInput.value = cfg.apiBase || DEFAULT_CONFIG.apiBase;
siteBaseInput.value = cfg.siteBase || cfg.apiBase || DEFAULT_CONFIG.siteBase;
tokenInput.value = cfg.authToken || "";
}
async function saveForm() {
const next = {
apiBase: normalizeBase(apiBaseInput.value),
siteBase: normalizeBase(siteBaseInput.value || apiBaseInput.value),
authToken: String(tokenInput.value || "").trim()
};
await setStorage(next);
writeResult(t("saved"));
}
async function testApi() {
const apiBase = normalizeBase(apiBaseInput.value);
const authToken = String(tokenInput.value || "").trim();
try {
const headers = { Accept: "application/json" };
if (authToken) headers.Authorization = `Bearer ${authToken}`;
const res = await fetch(`${apiBase}/api/cities`, {
headers,
cache: "no-store"
});
const text = await res.text();
let data = null;
try {
data = text ? JSON.parse(text) : null;
} catch (_e) {
data = text;
}
if (!res.ok) {
throw new Error(`HTTP ${res.status}: ${typeof data === "string" ? data : JSON.stringify(data)}`);
}
const count = Array.isArray(data)
? data.length
: Array.isArray(data?.cities)
? data.cities.length
: 0;
writeResult(`${t("connectOk")}: ${count} (${t("tokenOptional")})`);
} catch (err) {
const msg = String(err?.message || err || "");
if (msg.includes("HTTP 401")) {
writeResult(`${t("testFailed")}: ${msg}\n${t("backendAuthHint")}`);
return;
}
writeResult(`${t("testFailed")}: ${msg}`);
}
}
function applyStaticTranslations() {
document.documentElement.lang = locale === "zh" ? "zh-CN" : "en";
if (settingsTitle) settingsTitle.textContent = t("settingsTitle");
if (tokenLabel) tokenLabel.textContent = t("tokenLabel");
if (tokenInput) tokenInput.placeholder = t("tokenPlaceholder");
if (saveBtn) saveBtn.textContent = t("save");
if (testBtn) testBtn.textContent = t("test");
if (siteBaseLabel) siteBaseLabel.textContent = "Site Base URL";
if (apiBaseLabel) apiBaseLabel.textContent = "API Base URL";
}
document.getElementById("saveBtn").addEventListener("click", () => {
void saveForm();
});
document.getElementById("testBtn").addEventListener("click", () => {
void testApi();
});
applyStaticTranslations();
void loadForm();