完成llm token过期时间的配置化
This commit is contained in:
parent
7cd51825ca
commit
adf7eee7f4
@ -1,13 +1,13 @@
|
|||||||
// 仅在插件安装时设置默认 popup 页面,不再在 startup 中干扰当前 UI
|
// // 仅在插件安装时设置默认 popup 页面,不再在 startup 中干扰当前 UI
|
||||||
chrome.runtime.onInstalled.addListener(() => {
|
// chrome.runtime.onInstalled.addListener(() => {
|
||||||
chrome.storage.local.get(["token", "loginAt"], (res) => {
|
// chrome.storage.local.get(["token", "loginAt"], (res) => {
|
||||||
const maxAge = 24 * 60 * 60 * 1000; // 1天有效期
|
// const maxAge = 24 * 60 * 60 * 1000; // 1天有效期
|
||||||
const now = Date.now();
|
// const now = Date.now();
|
||||||
|
//
|
||||||
if (!res.token || !res.loginAt || (now - res.loginAt > maxAge)) {
|
// if (!res.token || !res.loginAt || (now - res.loginAt > maxAge)) {
|
||||||
chrome.action.setPopup({ popup: "./pages/login.html" });
|
// chrome.action.setPopup({ popup: "./pages/login.html" });
|
||||||
} else {
|
// } else {
|
||||||
chrome.action.setPopup({ popup: "./pages/popup.html" });
|
// chrome.action.setPopup({ popup: "./pages/popup.html" });
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"manifest_version": 3,
|
"manifest_version": 3,
|
||||||
"name": "渠道应用开发部知识库",
|
"name": "渠道应用开发部知识库",
|
||||||
"version": "2.0.0",
|
"version": "2.0.1",
|
||||||
"description": "通过关键词快速搜索内部文档",
|
"description": "通过关键词快速搜索内部文档",
|
||||||
"permissions": ["storage"],
|
"permissions": ["storage"],
|
||||||
"host_permissions": [
|
"host_permissions": [
|
||||||
|
|||||||
@ -9,6 +9,8 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div style="padding: 1rem; font-size: 14px;">正在加载,请稍候...</div>
|
<div style="padding: 1rem; font-size: 14px;">正在加载,请稍候...</div>
|
||||||
|
<script src="../scripts/utils.js"></script>
|
||||||
|
<script src="../scripts/config.js"></script>
|
||||||
<script src="../scripts/index.js"></script>
|
<script src="../scripts/index.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@ -130,10 +130,15 @@
|
|||||||
<div class="section">
|
<div class="section">
|
||||||
<h3>通用设置</h3>
|
<h3>通用设置</h3>
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<label for="tokenExpireHours">Token 有效期(小时,最大 168)</label>
|
<label for="tokenExpireHours">登录 Token 有效期(小时,最大 168)</label>
|
||||||
<input id="tokenExpireHours" type="number" min="1" max="168" />
|
<input id="tokenExpireHours" type="number" min="1" max="168" />
|
||||||
<div class="desc">超出有效期将要求重新登录</div>
|
<div class="desc">超出有效期将要求重新登录</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="llmTokenExpireHours">LLM Token 有效期(小时,最大 168)</label>
|
||||||
|
<input id="llmTokenExpireHours" type="number" min="1" max="168" />
|
||||||
|
<div class="desc">超出有效期将重新获取</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="section" id="endpointSection">
|
<div class="section" id="endpointSection">
|
||||||
@ -146,6 +151,7 @@
|
|||||||
<button id="saveBtn">保存设置</button>
|
<button id="saveBtn">保存设置</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script src="../scripts/utils.js"></script>
|
||||||
<script src="../scripts/config.js"></script>
|
<script src="../scripts/config.js"></script>
|
||||||
<script src="../scripts/settings.js"></script>
|
<script src="../scripts/settings.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
## 修订记录
|
## 修订记录
|
||||||
| 时间 | 版本 | 修订人 | 说明 |
|
| 时间 | 版本 | 修订人 | 说明 |
|
||||||
| ---------- | ------ | ------- | ------------------ |
|
|------------|--------|---------|---------------------|
|
||||||
| 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过期时间的配置化 |
|
||||||
|
|
||||||
|
|||||||
@ -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() {
|
function handleLogout() {
|
||||||
chrome.storage.local.remove(["token", "loginAt", "username"], () => {
|
chrome.storage.local.remove(["token", "loginAt", "username"], () => {
|
||||||
window.location.href = chrome.runtime.getURL("pages/login.html");
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
const defaultConfig = {
|
const defaultConfig = {
|
||||||
tokenExpireHours: 24,
|
tokenExpireHours: 24,
|
||||||
|
llmTokenExpireHours: 24,
|
||||||
apiConfig: {
|
apiConfig: {
|
||||||
materialPublicUrl: {
|
materialPublicUrl: {
|
||||||
name: "材料公开地址",
|
name: "材料公开地址",
|
||||||
@ -79,7 +80,10 @@ function loadMergedConfig() {
|
|||||||
chrome.storage.local.get(["customConfig"], (res) => {
|
chrome.storage.local.get(["customConfig"], (res) => {
|
||||||
const merged = JSON.parse(JSON.stringify(defaultConfig));
|
const merged = JSON.parse(JSON.stringify(defaultConfig));
|
||||||
if (res.customConfig && typeof res.customConfig === "object") {
|
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) {
|
for (const key in merged.apiConfig) {
|
||||||
const override = res.customConfig.apiConfig?.[key];
|
const override = res.customConfig.apiConfig?.[key];
|
||||||
if (override) {
|
if (override) {
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
|
loadMergedConfig().then(config => {
|
||||||
chrome.storage.local.get(["token", "loginAt"], (res) => {
|
chrome.storage.local.get(["token", "loginAt"], (res) => {
|
||||||
const maxAge = 24 * 60 * 60 * 1000;
|
const expireMs = config.tokenExpireHours * 60 * 60 * 1000;
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const popup = (!res.token || !res.loginAt || (now - res.loginAt > maxAge))
|
const popup = (!res.token || !res.loginAt || (now - res.loginAt > expireMs))
|
||||||
? "pages/login.html"
|
? "pages/login.html"
|
||||||
: "pages/popup.html";
|
: "pages/popup.html";
|
||||||
window.location.href = chrome.runtime.getURL(popup);
|
window.location.href = chrome.runtime.getURL(popup);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
@ -1,5 +1,3 @@
|
|||||||
const LLM_TOKEN_EXPIRE_MS = 23 * 60 * 60 * 1000;
|
|
||||||
|
|
||||||
async function resolveJumpLinks(titles) {
|
async function resolveJumpLinks(titles) {
|
||||||
if (!titles || titles.length === 0) return {};
|
if (!titles || titles.length === 0) return {};
|
||||||
|
|
||||||
@ -225,25 +223,76 @@ function insertCopyFullAnswerBtn(msgBox, answerStr) {
|
|||||||
msgBox.appendChild(copyBtn);
|
msgBox.appendChild(copyBtn);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getLLMPassword() {
|
function promptLLMPasswordModal() {
|
||||||
return new Promise((resolve) => {
|
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 = `
|
||||||
|
<div style="font-size:1rem;margin-bottom:13px;">LLM Token 已过期,请输入新的 LLM 密码:</div>
|
||||||
|
<input id="llm-password-input" type="password" style="width:95%;padding:7px 8px;font-size:1rem;border-radius:6px;border:1px solid #bbb;margin-bottom:10px;" autofocus />
|
||||||
|
<div>
|
||||||
|
<button id="llm-password-ok" style="margin-right:10px;padding:6px 18px;">确定</button>
|
||||||
|
<button id="llm-password-cancel" style="padding:6px 18px;">取消</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
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) {
|
async function getLLMToken(forceRefresh = false) {
|
||||||
const config = await loadMergedConfig();
|
const config = await loadMergedConfig();
|
||||||
const tokenCfg = config.apiConfig.llmToken;
|
const tokenCfg = config.apiConfig.llmToken;
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
chrome.storage.local.get(["llmToken", "llmTokenAt"], async (res) => {
|
chrome.storage.local.get(["llmToken", "llmTokenAt"], async (res) => {
|
||||||
const now = Date.now();
|
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);
|
resolve(res.llmToken);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
const pwd = await getLLMPassword();
|
// 这里不再用 getLLMPassword(),而是直接弹窗
|
||||||
|
let pwd = await promptLLMPasswordModal();
|
||||||
|
if (!pwd) {
|
||||||
|
reject("未输入密码,无法获取 LLM Token");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 可选:此处不自动存储 llmPassword,提升安全性
|
||||||
const body = {};
|
const body = {};
|
||||||
body[tokenCfg.requestParams[0].field] = pwd;
|
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;
|
const tokenField = tokenCfg.responseParams.find(p => p.label.includes("Token")).field;
|
||||||
if (data[tokenField]) {
|
if (data[tokenField]) {
|
||||||
chrome.storage.local.set({ llmToken: data[tokenField], llmTokenAt: now });
|
chrome.storage.local.set({ llmToken: data[tokenField], llmTokenAt: now });
|
||||||
|
log("请求llmToken成功!");
|
||||||
resolve(data[tokenField]);
|
resolve(data[tokenField]);
|
||||||
} else {
|
} else {
|
||||||
|
log("LLM token获取失败!");
|
||||||
reject("LLM token获取失败");
|
reject("LLM token获取失败");
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -277,7 +328,10 @@ async function getLLMWorkspaceSlug(token, forceRefresh = false) {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
chrome.storage.local.get(["llmWorkspaceSlug", "llmWorkspaceAt"], async (res) => {
|
chrome.storage.local.get(["llmWorkspaceSlug", "llmWorkspaceAt"], async (res) => {
|
||||||
const now = Date.now();
|
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);
|
resolve(res.llmWorkspaceSlug);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
@ -290,6 +344,7 @@ async function getLLMWorkspaceSlug(token, forceRefresh = false) {
|
|||||||
const list = data[workspacesField] || [];
|
const list = data[workspacesField] || [];
|
||||||
if (list.length > 0 && list[0].slug) {
|
if (list.length > 0 && list[0].slug) {
|
||||||
chrome.storage.local.set({ llmWorkspaceSlug: list[0].slug, llmWorkspaceAt: now });
|
chrome.storage.local.set({ llmWorkspaceSlug: list[0].slug, llmWorkspaceAt: now });
|
||||||
|
log("获取llmWorkspaceSlug: " + JSON.stringify(list))
|
||||||
resolve(list[0].slug);
|
resolve(list[0].slug);
|
||||||
} else {
|
} else {
|
||||||
reject("未获取到LLM工作区slug");
|
reject("未获取到LLM工作区slug");
|
||||||
|
|||||||
@ -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 input = document.getElementById("searchInput");
|
||||||
const searchBtn = document.getElementById("searchBtn");
|
const searchBtn = document.getElementById("searchBtn");
|
||||||
const clearBtn = document.getElementById("clearHistoryBtn");
|
const clearBtn = document.getElementById("clearHistoryBtn");
|
||||||
@ -176,6 +156,8 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|||||||
},
|
},
|
||||||
body: JSON.stringify(requestBody)
|
body: JSON.stringify(requestBody)
|
||||||
});
|
});
|
||||||
|
log("已使用前端接口配置:" + JSON.stringify(endpoint));
|
||||||
|
log("请求后端接口参数:" + JSON.stringify(requestBody));
|
||||||
|
|
||||||
if (response.status === 401) return handleLogout();
|
if (response.status === 401) return handleLogout();
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|||||||
@ -1,31 +1,10 @@
|
|||||||
// scripts/settings.js
|
|
||||||
|
|
||||||
function getMergedConfig(callback) {
|
function getMergedConfig(callback) {
|
||||||
chrome.storage.local.get(["customConfig"], (res) => {
|
loadMergedConfig().then(callback);
|
||||||
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);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderConfig(config) {
|
function renderConfig(config) {
|
||||||
document.getElementById("tokenExpireHours").value = config.tokenExpireHours;
|
document.getElementById("tokenExpireHours").value = config.tokenExpireHours;
|
||||||
|
document.getElementById("llmTokenExpireHours").value = config.llmTokenExpireHours;
|
||||||
const container = document.getElementById("endpointSection");
|
const container = document.getElementById("endpointSection");
|
||||||
container.innerHTML = "";
|
container.innerHTML = "";
|
||||||
|
|
||||||
@ -76,7 +55,12 @@ function renderConfig(config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function collectUserConfig() {
|
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 apiConfig = {};
|
||||||
|
|
||||||
const inputs = document.querySelectorAll("input[data-key]");
|
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", () => {
|
document.getElementById("saveBtn").addEventListener("click", () => {
|
||||||
const newConfig = collectUserConfig();
|
const newConfig = collectUserConfig();
|
||||||
chrome.storage.local.set({ customConfig: newConfig }, () => {
|
chrome.storage.local.set({ customConfig: newConfig }, () => {
|
||||||
|
log("配置已保存:" + JSON.stringify(newConfig));
|
||||||
alert("设置已保存!");
|
alert("设置已保存!");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user