diff --git a/background.js b/background.js index 99db3b2..ce0bd02 100644 --- a/background.js +++ b/background.js @@ -1,13 +1,13 @@ -// 仅在插件安装时设置默认 popup 页面,不再在 startup 中干扰当前 UI -chrome.runtime.onInstalled.addListener(() => { - chrome.storage.local.get(["token", "loginAt"], (res) => { - const maxAge = 24 * 60 * 60 * 1000; // 1天有效期 - const now = Date.now(); - - if (!res.token || !res.loginAt || (now - res.loginAt > maxAge)) { - chrome.action.setPopup({ popup: "./pages/login.html" }); - } else { - chrome.action.setPopup({ popup: "./pages/popup.html" }); - } - }); -}); +// // 仅在插件安装时设置默认 popup 页面,不再在 startup 中干扰当前 UI +// chrome.runtime.onInstalled.addListener(() => { +// chrome.storage.local.get(["token", "loginAt"], (res) => { +// const maxAge = 24 * 60 * 60 * 1000; // 1天有效期 +// const now = Date.now(); +// +// if (!res.token || !res.loginAt || (now - res.loginAt > maxAge)) { +// chrome.action.setPopup({ popup: "./pages/login.html" }); +// } else { +// chrome.action.setPopup({ popup: "./pages/popup.html" }); +// } +// }); +// }); diff --git a/manifest.json b/manifest.json index f5d4cb1..cea2096 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "渠道应用开发部知识库", - "version": "2.0.0", + "version": "2.0.1", "description": "通过关键词快速搜索内部文档", "permissions": ["storage"], "host_permissions": [ diff --git a/pages/index.html b/pages/index.html index eeaeb0e..70c2d00 100644 --- a/pages/index.html +++ b/pages/index.html @@ -9,6 +9,8 @@
正在加载,请稍候...
+ + diff --git a/pages/settings.html b/pages/settings.html index cf2cacf..3362a5b 100644 --- a/pages/settings.html +++ b/pages/settings.html @@ -130,10 +130,15 @@

通用设置

- +
超出有效期将要求重新登录
+
+ + +
超出有效期将重新获取
+
@@ -146,6 +151,7 @@
+ diff --git a/readme.md b/readme.md index 3ef0410..276efe9 100644 --- a/readme.md +++ b/readme.md @@ -1,7 +1,8 @@ ## 修订记录 -| 时间 | 版本 | 修订人 | 说明 | -| ---------- | ------ | ------- | ------------------ | -| 2025.06.02 | V2.0.0 | Luke.Ye | 完成插件配置化改造 | +| 时间 | 版本 | 修订人 | 说明 | +|------------|--------|---------|---------------------| +| 2025.06.02 | V2.0.0 | Luke.Ye | 完成插件配置化改造 | +| 2025.06.03 | V2.0.1 | Luke.Ye | 完成llm token过期时间的配置化 | diff --git a/scripts/auth.js b/scripts/auth.js index 8be933f..c5a0e67 100644 --- a/scripts/auth.js +++ b/scripts/auth.js @@ -1,23 +1,22 @@ -// scripts/auth.js -const TOKEN_EXPIRE_MS = 7 * 24 * 60 * 60 * 1000; // 7天 - -async function loadToken() { - return new Promise((resolve) => { - chrome.storage.local.get(["token", "loginAt", "username"], (res) => { - const now = Date.now(); - if (!res.token || !res.loginAt || isNaN(res.loginAt) || (now - res.loginAt > TOKEN_EXPIRE_MS)) { - log("token 不存在或已过期"); - resolve(null); - } else { - log("token 加载成功"); - resolve({ token: res.token, username: res.username || "用户" }); - } - }); - }); -} - function handleLogout() { chrome.storage.local.remove(["token", "loginAt", "username"], () => { window.location.href = chrome.runtime.getURL("pages/login.html"); }); } + +async function loadToken() { + return new Promise((resolve) => { + chrome.storage.local.get(["token", "username", "loginAt"], async (res) => { + const mergedConfig = await loadMergedConfig(); + const expireMs = mergedConfig.tokenExpireHours * 60 * 60 * 1000; + const now = Date.now(); + if (res.token && res.loginAt && now - res.loginAt < expireMs) { + log("token 加载成功"); + resolve({ token: res.token, username: res.username }); + } else { + log("token 不存在或已过期"); + resolve(null); + } + }); + }); +} \ No newline at end of file diff --git a/scripts/config.js b/scripts/config.js index 36f7c44..a5138fd 100644 --- a/scripts/config.js +++ b/scripts/config.js @@ -1,5 +1,6 @@ const defaultConfig = { tokenExpireHours: 24, + llmTokenExpireHours: 24, apiConfig: { materialPublicUrl: { name: "材料公开地址", @@ -79,7 +80,10 @@ function loadMergedConfig() { chrome.storage.local.get(["customConfig"], (res) => { const merged = JSON.parse(JSON.stringify(defaultConfig)); if (res.customConfig && typeof res.customConfig === "object") { - merged.tokenExpireHours = res.customConfig.tokenExpireHours || merged.tokenExpireHours; + merged.tokenExpireHours = + res.customConfig.tokenExpireHours != null ? res.customConfig.tokenExpireHours : merged.tokenExpireHours; + merged.llmTokenExpireHours = + res.customConfig.llmTokenExpireHours != null ? res.customConfig.llmTokenExpireHours : merged.llmTokenExpireHours; for (const key in merged.apiConfig) { const override = res.customConfig.apiConfig?.[key]; if (override) { diff --git a/scripts/index.js b/scripts/index.js index 0129e5c..e248370 100644 --- a/scripts/index.js +++ b/scripts/index.js @@ -1,8 +1,10 @@ -chrome.storage.local.get(["token", "loginAt"], (res) => { - const maxAge = 24 * 60 * 60 * 1000; - const now = Date.now(); - const popup = (!res.token || !res.loginAt || (now - res.loginAt > maxAge)) - ? "pages/login.html" - : "pages/popup.html"; - window.location.href = chrome.runtime.getURL(popup); -}); +loadMergedConfig().then(config => { + chrome.storage.local.get(["token", "loginAt"], (res) => { + const expireMs = config.tokenExpireHours * 60 * 60 * 1000; + const now = Date.now(); + const popup = (!res.token || !res.loginAt || (now - res.loginAt > expireMs)) + ? "pages/login.html" + : "pages/popup.html"; + window.location.href = chrome.runtime.getURL(popup); + }); +}); \ No newline at end of file diff --git a/scripts/llm.js b/scripts/llm.js index 8179986..39b31c9 100644 --- a/scripts/llm.js +++ b/scripts/llm.js @@ -1,5 +1,3 @@ -const LLM_TOKEN_EXPIRE_MS = 23 * 60 * 60 * 1000; - async function resolveJumpLinks(titles) { if (!titles || titles.length === 0) return {}; @@ -225,25 +223,76 @@ function insertCopyFullAnswerBtn(msgBox, answerStr) { msgBox.appendChild(copyBtn); } -async function getLLMPassword() { +function promptLLMPasswordModal() { return new Promise((resolve) => { - chrome.storage.local.get(["llmPassword"], (res) => { - resolve(res.llmPassword || ""); - }); + // 避免重复弹窗 + if (document.getElementById("llm-password-modal")) return; + + // 创建遮罩层 + const mask = document.createElement("div"); + mask.id = "llm-password-modal-mask"; + mask.style = ` + position: fixed; left:0; top:0; width:100vw; height:100vh; background:rgba(0,0,0,0.19); + z-index:9998;`; + + // 创建弹窗 + const modal = document.createElement("div"); + modal.id = "llm-password-modal"; + modal.style = ` + position: fixed; top: 45%; left: 50%; transform: translate(-50%, -50%); + background: #fff; border-radius: 10px; box-shadow: 0 8px 38px #0001; + padding: 24px 32px 18px 32px; z-index:9999; min-width:260px; text-align:center;`; + modal.innerHTML = ` +
LLM Token 已过期,请输入新的 LLM 密码:
+ +
+ + +
+ `; + + document.body.appendChild(mask); + document.body.appendChild(modal); + + function closeModal(val) { + document.body.removeChild(mask); + document.body.removeChild(modal); + resolve(val); + } + + document.getElementById("llm-password-ok").onclick = () => { + const pwd = document.getElementById("llm-password-input").value; + closeModal(pwd ? pwd.trim() : ""); + }; + document.getElementById("llm-password-cancel").onclick = () => closeModal(""); + document.getElementById("llm-password-input").onkeydown = (e) => { + if (e.key === "Enter") document.getElementById("llm-password-ok").click(); + }; }); } + + async function getLLMToken(forceRefresh = false) { const config = await loadMergedConfig(); const tokenCfg = config.apiConfig.llmToken; return new Promise((resolve, reject) => { chrome.storage.local.get(["llmToken", "llmTokenAt"], async (res) => { const now = Date.now(); - if (!forceRefresh && res.llmToken && res.llmTokenAt && now - res.llmTokenAt < LLM_TOKEN_EXPIRE_MS) { + const mergedConfig = await loadMergedConfig(); + const expireMs = mergedConfig.llmTokenExpireHours * 60 * 60 * 1000; + if (!forceRefresh && res.llmToken && res.llmTokenAt && now - res.llmTokenAt < expireMs) { + log("已从缓存中获取到llmToken. expireMs: " + expireMs); resolve(res.llmToken); } else { try { - const pwd = await getLLMPassword(); + // 这里不再用 getLLMPassword(),而是直接弹窗 + let pwd = await promptLLMPasswordModal(); + if (!pwd) { + reject("未输入密码,无法获取 LLM Token"); + return; + } + // 可选:此处不自动存储 llmPassword,提升安全性 const body = {}; body[tokenCfg.requestParams[0].field] = pwd; @@ -257,8 +306,10 @@ async function getLLMToken(forceRefresh = false) { const tokenField = tokenCfg.responseParams.find(p => p.label.includes("Token")).field; if (data[tokenField]) { chrome.storage.local.set({ llmToken: data[tokenField], llmTokenAt: now }); + log("请求llmToken成功!"); resolve(data[tokenField]); } else { + log("LLM token获取失败!"); reject("LLM token获取失败"); } } catch (e) { @@ -277,7 +328,10 @@ async function getLLMWorkspaceSlug(token, forceRefresh = false) { return new Promise((resolve, reject) => { chrome.storage.local.get(["llmWorkspaceSlug", "llmWorkspaceAt"], async (res) => { const now = Date.now(); - if (!forceRefresh && res.llmWorkspaceSlug && res.llmWorkspaceAt && now - res.llmWorkspaceAt < LLM_TOKEN_EXPIRE_MS) { + const mergedConfig = await loadMergedConfig(); + const expireMs = mergedConfig.llmTokenExpireHours * 60 * 60 * 1000; + if (!forceRefresh && res.llmWorkspaceSlug && res.llmWorkspaceAt && now - res.llmWorkspaceAt < expireMs) { + log("获取llmWorkspaceSlug. expireMs: " + expireMs) resolve(res.llmWorkspaceSlug); } else { try { @@ -290,6 +344,7 @@ async function getLLMWorkspaceSlug(token, forceRefresh = false) { const list = data[workspacesField] || []; if (list.length > 0 && list[0].slug) { chrome.storage.local.set({ llmWorkspaceSlug: list[0].slug, llmWorkspaceAt: now }); + log("获取llmWorkspaceSlug: " + JSON.stringify(list)) resolve(list[0].slug); } else { reject("未获取到LLM工作区slug"); diff --git a/scripts/popup.js b/scripts/popup.js index 5b906d4..0578ee7 100644 --- a/scripts/popup.js +++ b/scripts/popup.js @@ -29,26 +29,6 @@ document.addEventListener("DOMContentLoaded", async () => { }); } - async function loadToken() { - return new Promise((resolve) => { - chrome.storage.local.get(["token", "username", "loginAt"], async (res) => { - const mergedConfig = await loadMergedConfig(); - const expireMs = mergedConfig.tokenExpireHours * 60 * 60 * 1000; - const now = Date.now(); - if (res.token && res.loginAt && now - res.loginAt < expireMs) { - resolve({ token: res.token, username: res.username }); - } else { - resolve(null); - } - }); - }); - } - - async function handleLogout() { - await chrome.storage.local.remove(["token", "username", "loginAt"]); - location.href = chrome.runtime.getURL("pages/login.html"); - } - const input = document.getElementById("searchInput"); const searchBtn = document.getElementById("searchBtn"); const clearBtn = document.getElementById("clearHistoryBtn"); @@ -176,6 +156,8 @@ document.addEventListener("DOMContentLoaded", async () => { }, body: JSON.stringify(requestBody) }); + log("已使用前端接口配置:" + JSON.stringify(endpoint)); + log("请求后端接口参数:" + JSON.stringify(requestBody)); if (response.status === 401) return handleLogout(); const data = await response.json(); diff --git a/scripts/settings.js b/scripts/settings.js index b3444d7..0b4f999 100644 --- a/scripts/settings.js +++ b/scripts/settings.js @@ -1,31 +1,10 @@ -// scripts/settings.js - function getMergedConfig(callback) { - chrome.storage.local.get(["customConfig"], (res) => { - const merged = JSON.parse(JSON.stringify(defaultConfig)); - if (res.customConfig && typeof res.customConfig === "object") { - merged.tokenExpireHours = res.customConfig.tokenExpireHours || merged.tokenExpireHours; - for (const key in merged.apiConfig) { - const override = res.customConfig.apiConfig?.[key]; - if (override) { - merged.apiConfig[key].url = override.url || merged.apiConfig[key].url; - - merged.apiConfig[key].requestParams.forEach((param, i) => { - if (override.requestParams?.[i]?.field) param.field = override.requestParams[i].field; - }); - - merged.apiConfig[key].responseParams.forEach((param, i) => { - if (override.responseParams?.[i]?.field) param.field = override.responseParams[i].field; - }); - } - } - } - callback(merged); - }); + loadMergedConfig().then(callback); } function renderConfig(config) { document.getElementById("tokenExpireHours").value = config.tokenExpireHours; + document.getElementById("llmTokenExpireHours").value = config.llmTokenExpireHours; const container = document.getElementById("endpointSection"); container.innerHTML = ""; @@ -76,7 +55,12 @@ function renderConfig(config) { } function collectUserConfig() { - const tokenExpireHours = Math.min(168, parseInt(document.getElementById("tokenExpireHours").value) || 24); + let tokenExpireHours = parseInt(document.getElementById("tokenExpireHours").value); + if (isNaN(tokenExpireHours) || tokenExpireHours > 168 || tokenExpireHours < 0) tokenExpireHours = 24; + + let llmTokenExpireHours = parseInt(document.getElementById("llmTokenExpireHours").value); + if (isNaN(llmTokenExpireHours) || llmTokenExpireHours > 168 || llmTokenExpireHours < 0) llmTokenExpireHours = 24; + const apiConfig = {}; const inputs = document.querySelectorAll("input[data-key]"); @@ -98,12 +82,14 @@ function collectUserConfig() { } } - return { tokenExpireHours, apiConfig }; + return { tokenExpireHours, llmTokenExpireHours, apiConfig }; } + document.getElementById("saveBtn").addEventListener("click", () => { const newConfig = collectUserConfig(); chrome.storage.local.set({ customConfig: newConfig }, () => { + log("配置已保存:" + JSON.stringify(newConfig)); alert("设置已保存!"); }); });