import { app } from "../../../scripts/app.js"; app.registerExtension({ name: "o1key.hideSidebarItems", async setup() { const hide = () => { // 隐藏侧边栏的"说明"、"应用"、"模型"、"节点"按钮 const hiddenLabels = ["说明", "帮助", "Help", "应用", "Apps", "模型", "Models", "节点", "Nodes"]; document.querySelectorAll(".side-bar-button, [class*='sidebar'] button, .p-togglebutton").forEach(btn => { const label = btn.getAttribute("aria-label") || btn.textContent || ""; if (hiddenLabels.some(k => label.includes(k))) { btn.style.display = "none"; } }); // 隐藏左上角下拉菜单中的"帮助"项 document.querySelectorAll(".p-menuitem, .p-menu-item, [class*='menu'] li, [class*='Menu'] li").forEach(item => { const text = item.textContent || ""; if (text.trim() === "帮助" || text.trim() === "Help") { item.style.display = "none"; } }); // 隐藏登录/注册弹框(Google/Github 登录对话框) document.querySelectorAll("[class*='dialog'], [class*='Dialog'], [class*='modal'], [class*='Modal']").forEach(dialog => { const text = dialog.textContent || ""; if ((text.includes("Google") || text.includes("Github")) && (text.includes("登录") || text.includes("注册"))) { dialog.style.display = "none"; const mask = dialog.previousElementSibling; if (mask && mask.className && mask.className.includes("mask")) { mask.style.display = "none"; } } }); // 在右侧内容区隐藏"登录/注册"按钮并注入 API Key injectApiKeyPanel(); }; async function injectApiKeyPanel() { // 找到右侧内容区中包含"我的用户设置"的区域 let contentArea = null; document.querySelectorAll("h1, h2, h3, h4, span, div").forEach(el => { const t = (el.textContent || "").trim(); if (t === "我的用户设置" || t === "My User Settings") { contentArea = el.closest("div"); } }); if (!contentArea) return; // 隐藏"登录/注册"按钮和"登录您的账户"文字 contentArea.querySelectorAll("button, a, span, p, div").forEach(el => { const t = (el.textContent || "").trim(); if (t.includes("登录") || t.includes("注册") || t === "Sign In" || t === "Sign Up" || t.includes("登录您的账户") || t.includes("Log in")) { if (el.tagName === "BUTTON" || el.tagName === "A" || t.includes("登录您的账户")) { el.style.display = "none"; } } }); // 检查是否已注入(DOM 中已存在则跳过) if (document.querySelector("#o1key-apikey-box")) return; // 创建 API Key 输入区域 const box = document.createElement("div"); box.id = "o1key-apikey-box"; box.style.cssText = "margin-top:24px;padding:20px;border:1px solid #444;border-radius:8px;background:#1e1e1e;"; box.innerHTML = `
O1Key API 密钥
输入您的 API 密钥,测试通过后方可保存
`; contentArea.appendChild(box); // 加载当前状态 try { const resp = await fetch("/o1key/api_key"); const data = await resp.json(); const status = box.querySelector("#o1key-apikey-status"); if (data.has_key) { status.textContent = "当前密钥: " + data.masked; status.style.color = "#3b8"; } else { status.textContent = "尚未配置 API 密钥"; status.style.color = "#a84"; } } catch (e) {} const saveBtn = box.querySelector("#o1key-apikey-save"); const testBtn = box.querySelector("#o1key-apikey-test"); let testPassed = false; // 输入变化时重置测试状态 box.querySelector("#o1key-apikey-input").addEventListener("input", () => { testPassed = false; saveBtn.disabled = true; saveBtn.style.background = "#555"; saveBtn.style.color = "#999"; saveBtn.style.cursor = "not-allowed"; }); // 测试令牌按钮 testBtn.addEventListener("click", async () => { const input = box.querySelector("#o1key-apikey-input"); const status = box.querySelector("#o1key-apikey-status"); const key = input.value.trim(); if (!key) { status.textContent = "请输入密钥"; status.style.color = "#a44"; return; } testBtn.disabled = true; testBtn.textContent = "验证中..."; status.textContent = "正在验证密钥..."; status.style.color = "#999"; try { const resp = await fetch("/o1key/test_key", { method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify({api_key: key}) }); const data = await resp.json(); if (data.valid) { testPassed = true; status.textContent = "验证通过,可以保存"; status.style.color = "#3b8"; saveBtn.disabled = false; saveBtn.style.background = "#3b8"; saveBtn.style.color = "#fff"; saveBtn.style.cursor = "pointer"; } else { testPassed = false; status.textContent = data.error || "验证失败"; status.style.color = "#a44"; } } catch (e) { status.textContent = "网络错误"; status.style.color = "#a44"; } testBtn.disabled = false; testBtn.textContent = "测试令牌"; }); // 保存按钮(仅测试通过后可用) saveBtn.addEventListener("click", async () => { if (!testPassed) return; const input = box.querySelector("#o1key-apikey-input"); const status = box.querySelector("#o1key-apikey-status"); const key = input.value.trim(); try { const resp = await fetch("/o1key/api_key", { method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify({api_key: key}) }); const data = await resp.json(); if (data.success) { status.textContent = "密钥已保存"; status.style.color = "#3b8"; input.value = ""; testPassed = false; saveBtn.disabled = true; saveBtn.style.background = "#555"; saveBtn.style.color = "#999"; saveBtn.style.cursor = "not-allowed"; } else { status.textContent = data.error || "保存失败"; status.style.color = "#a44"; } } catch (e) { status.textContent = "网络错误"; status.style.color = "#a44"; } }); // 清空密钥按钮 const clearBtn = box.querySelector("#o1key-apikey-clear"); clearBtn.addEventListener("click", async () => { if (!confirm("确定要清空 API 密钥吗?")) return; const status = box.querySelector("#o1key-apikey-status"); try { const resp = await fetch("/o1key/api_key", { method: "DELETE" }); const data = await resp.json(); if (data.success) { status.textContent = "API 密钥已清空"; status.style.color = "#a84"; box.querySelector("#o1key-apikey-input").value = ""; testPassed = false; saveBtn.disabled = true; saveBtn.style.background = "#555"; saveBtn.style.color = "#999"; saveBtn.style.cursor = "not-allowed"; } else { status.textContent = data.error || "清空失败"; status.style.color = "#a44"; } } catch (e) { status.textContent = "网络错误"; status.style.color = "#a44"; } }); } const observer = new MutationObserver(hide); observer.observe(document.body, { childList: true, subtree: true }); setTimeout(hide, 1000); setTimeout(hide, 3000); }, });