const textFields = [ "apiBaseUrl", "webBaseUrl", "accessToken", "defaultPrompt", "workerId", "taskPollIntervalSeconds", "taskPageLoadTimeoutSeconds", ]; const checkboxFields = [ "autoDiscoverServiceUrl", "tokenSyncEnabled", "pageAssistantEnabled", "taskPollingEnabled", "closeTaskTabs", ]; function formatServiceStatus(settings) { if (!settings.lastServiceSyncAt) { return `当前服务地址:${settings.webBaseUrl || DEER_CLIPPER_DEFAULTS.webBaseUrl};API:${settings.apiBaseUrl || DEER_CLIPPER_DEFAULTS.apiBaseUrl}`; } return `当前服务地址:${settings.webBaseUrl || ""};API:${settings.apiBaseUrl || ""}\n上次识别:${settings.lastServiceSyncAt}(${settings.lastServiceSyncSource || "unknown source"})`; } function formatTokenStatus(settings) { if (!settings.lastTokenSyncAt) { return "Token 尚未自动同步。"; } return `上次 token 同步:${settings.lastTokenSyncAt}(${settings.lastTokenSyncSource || "unknown source"})`; } async function loadSettings() { const settings = await chrome.storage.sync.get(DEER_CLIPPER_DEFAULTS); if (!settings.workerId) { settings.workerId = deerMakeWorkerId(); await chrome.storage.sync.set({ workerId: settings.workerId }); } document.getElementById("apiBaseUrl").placeholder = DEER_CLIPPER_DEFAULTS.apiBaseUrl || "在 config.js 中配置默认 API 地址"; document.getElementById("webBaseUrl").placeholder = DEER_CLIPPER_DEFAULTS.webBaseUrl || "在 config.js 中配置默认前端地址"; for (const field of textFields) { document.getElementById(field).value = settings[field] ?? ""; } for (const field of checkboxFields) { document.getElementById(field).checked = Boolean(settings[field]); } document.getElementById("serviceStatus").textContent = formatServiceStatus(settings); document.getElementById("tokenStatus").textContent = formatTokenStatus(settings); } async function saveSettings() { const next = {}; for (const field of textFields) { next[field] = document.getElementById(field).value.trim(); } for (const field of checkboxFields) { next[field] = document.getElementById(field).checked; } next.apiBaseUrl = deerNormalizeBaseUrl(next.apiBaseUrl || DEER_CLIPPER_DEFAULTS.apiBaseUrl); next.webBaseUrl = deerNormalizeBaseUrl(next.webBaseUrl || DEER_CLIPPER_DEFAULTS.webBaseUrl); next.defaultPrompt = next.defaultPrompt || DEER_CLIPPER_DEFAULT_PROMPT; next.workerId = next.workerId || deerMakeWorkerId(); next.taskPollIntervalSeconds = Math.max(3, Number(next.taskPollIntervalSeconds || DEER_CLIPPER_DEFAULTS.taskPollIntervalSeconds)); next.taskPageLoadTimeoutSeconds = Math.max(5, Number(next.taskPageLoadTimeoutSeconds || DEER_CLIPPER_DEFAULTS.taskPageLoadTimeoutSeconds)); await chrome.storage.sync.set(next); const settings = await chrome.storage.sync.get(DEER_CLIPPER_DEFAULTS); document.getElementById("status").textContent = "已保存。"; document.getElementById("serviceStatus").textContent = formatServiceStatus(settings); document.getElementById("tokenStatus").textContent = formatTokenStatus(settings); } function sendDiscoverServiceMessage() { return new Promise((resolve, reject) => { chrome.runtime.sendMessage({ type: "zncm-discover-service" }, (response) => { const error = chrome.runtime.lastError; if (error) { reject(new Error(error.message)); return; } resolve(response || { ok: false, message: "服务地址识别没有返回结果。" }); }); }); } function sendSyncTokenMessage() { return new Promise((resolve, reject) => { chrome.runtime.sendMessage({ type: "zncm-sync-token" }, (response) => { const error = chrome.runtime.lastError; if (error) { reject(new Error(error.message)); return; } resolve(response || { ok: false, message: "Token 同步没有返回结果。" }); }); }); } async function discoverServiceNow() { const button = document.getElementById("discoverService"); button.disabled = true; document.getElementById("serviceStatus").textContent = "正在识别服务地址..."; try { await chrome.storage.sync.set({ autoDiscoverServiceUrl: document.getElementById("autoDiscoverServiceUrl").checked, apiBaseUrl: deerNormalizeBaseUrl(document.getElementById("apiBaseUrl").value || DEER_CLIPPER_DEFAULTS.apiBaseUrl), webBaseUrl: deerNormalizeBaseUrl(document.getElementById("webBaseUrl").value || DEER_CLIPPER_DEFAULTS.webBaseUrl), }); const response = await sendDiscoverServiceMessage(); const settings = await chrome.storage.sync.get(DEER_CLIPPER_DEFAULTS); document.getElementById("apiBaseUrl").value = settings.apiBaseUrl || ""; document.getElementById("webBaseUrl").value = settings.webBaseUrl || ""; document.getElementById("serviceStatus").textContent = response.message || formatServiceStatus(settings); } catch (error) { document.getElementById("serviceStatus").textContent = error instanceof Error ? error.message : "服务地址识别失败。"; } finally { button.disabled = false; } } async function syncTokenNow() { const button = document.getElementById("syncToken"); button.disabled = true; document.getElementById("tokenStatus").textContent = "正在同步 zncm token..."; try { await chrome.storage.sync.set({ tokenSyncEnabled: document.getElementById("tokenSyncEnabled").checked, apiBaseUrl: deerNormalizeBaseUrl(document.getElementById("apiBaseUrl").value || DEER_CLIPPER_DEFAULTS.apiBaseUrl), webBaseUrl: deerNormalizeBaseUrl(document.getElementById("webBaseUrl").value || DEER_CLIPPER_DEFAULTS.webBaseUrl), }); const response = await sendSyncTokenMessage(); const settings = await chrome.storage.sync.get(DEER_CLIPPER_DEFAULTS); document.getElementById("accessToken").value = settings.accessToken || ""; document.getElementById("apiBaseUrl").value = settings.apiBaseUrl || ""; document.getElementById("webBaseUrl").value = settings.webBaseUrl || ""; document.getElementById("serviceStatus").textContent = formatServiceStatus(settings); document.getElementById("tokenStatus").textContent = response.message || formatTokenStatus(settings); } catch (error) { document.getElementById("tokenStatus").textContent = error instanceof Error ? error.message : "Token 同步失败。"; } finally { button.disabled = false; } } document.getElementById("save").addEventListener("click", saveSettings); document.getElementById("discoverService").addEventListener("click", discoverServiceNow); document.getElementById("syncToken").addEventListener("click", syncTokenNow); void loadSettings();