From 6c808ed5adb73c2552b34bfdfebfd83b5a0119d8 Mon Sep 17 00:00:00 2001
From: Youzini-afk <13153778771cx@gmail.com>
Date: Tue, 14 Apr 2026 16:59:26 +0800
Subject: [PATCH] fix: harden panel entry bootstrap
---
ui/panel-bridge.js | 80 +++++++++++++++++++++++++++++++++++-----------
ui/panel.js | 36 ++++++++++++---------
2 files changed, 82 insertions(+), 34 deletions(-)
diff --git a/ui/panel-bridge.js b/ui/panel-bridge.js
index 52bb7b9..92b886f 100644
--- a/ui/panel-bridge.js
+++ b/ui/panel-bridge.js
@@ -27,43 +27,85 @@ export function openPanelController(runtime) {
}
function injectOptionsMenuEntry(runtime) {
- if (runtime.document.getElementById("option_st_bme_panel")) {
+ const doc = runtime.document;
+ if (!doc || doc.getElementById("option_st_bme_panel")) {
return true;
}
-
- const $menuItem = runtime.$(`
-
-
- 记忆图谱
-
- `).on("click", async () => {
+ const menuItem = doc.createElement("a");
+ menuItem.id = "option_st_bme_panel";
+ menuItem.innerHTML =
+ '记忆图谱';
+ menuItem.addEventListener("click", async () => {
try {
await ensurePanelBridgeReady(runtime);
openPanelController(runtime);
- runtime.$("#options").hide();
+ runtime.$?.("#options")?.hide?.();
} catch (error) {
runtime.console.error("[ST-BME] 点击菜单打开面板失败:", error);
globalThis.toastr?.error?.("记忆图谱面板加载失败,请查看控制台报错", "ST-BME");
}
});
- const $optionsContent = runtime.$("#options .options-content");
- const $anchor = runtime.$("#option_toggle_logprobs");
+ const anchor = doc.getElementById("option_toggle_logprobs");
+ const optionsContent = doc.querySelector("#options .options-content");
- if ($anchor.length > 0) {
- $anchor.after($menuItem);
- return true;
- } else if ($optionsContent.length > 0) {
- $optionsContent.append($menuItem);
+ if (anchor?.parentNode) {
+ anchor.parentNode.insertBefore(menuItem, anchor.nextSibling);
+ return true;
+ }
+ if (optionsContent) {
+ optionsContent.appendChild(menuItem);
return true;
}
-
return false;
}
+function injectFloatingBootstrap(runtime) {
+ const doc = runtime.document;
+ if (!doc) return false;
+ let fab = doc.getElementById("bme-floating-ball");
+ if (!fab) {
+ fab = doc.createElement("div");
+ fab.id = "bme-floating-ball";
+ fab.setAttribute("data-status", "idle");
+ fab.setAttribute("data-bme-bootstrap", "true");
+ fab.innerHTML = `
+
+ BME 记忆图谱
+ `;
+ const mountTarget = doc.body || doc.documentElement;
+ if (!mountTarget) return false;
+ mountTarget.appendChild(fab);
+ }
+ if (fab.dataset.bmeBridgeBound === "true") {
+ return true;
+ }
+ fab.dataset.bmeBridgeBound = "true";
+ fab.addEventListener("click", async () => {
+ try {
+ await ensurePanelBridgeReady(runtime);
+ openPanelController(runtime);
+ } catch (error) {
+ runtime.console.error("[ST-BME] 点击悬浮球打开面板失败:", error);
+ globalThis.toastr?.error?.("记忆图谱面板加载失败,请查看控制台报错", "ST-BME");
+ }
+ });
+ return true;
+}
+
function scheduleOptionsMenuInjection(runtime, attempt = 0) {
- if (injectOptionsMenuEntry(runtime)) {
- return;
+ try {
+ injectFloatingBootstrap(runtime);
+ } catch (error) {
+ runtime.console.warn("[ST-BME] 悬浮球入口预注入失败:", error);
+ }
+
+ try {
+ if (injectOptionsMenuEntry(runtime)) {
+ return;
+ }
+ } catch (error) {
+ runtime.console.warn("[ST-BME] 菜单入口注入失败,稍后重试:", error);
}
if (attempt >= MENU_ENTRY_MAX_ATTEMPTS) {
diff --git a/ui/panel.js b/ui/panel.js
index d0ef2e3..238aa8c 100644
--- a/ui/panel.js
+++ b/ui/panel.js
@@ -1021,21 +1021,21 @@ function _bindFabToggle() {
}
function _initFloatingBall() {
- const existing = document.getElementById("bme-floating-ball");
- if (existing) {
- _fabEl = existing;
- ensureFabMountedAtRoot();
- syncFabPosition();
- return;
+ let fab = document.getElementById("bme-floating-ball");
+ if (!fab) {
+ fab = document.createElement("div");
+ fab.id = "bme-floating-ball";
+ fab.setAttribute("data-status", "idle");
+ fab.innerHTML = `
+
+ BME 记忆图谱
+ `;
+ } else if (!fab.querySelector(".bme-fab-icon")) {
+ fab.innerHTML = `
+
+ BME 记忆图谱
+ `;
}
-
- const fab = document.createElement("div");
- fab.id = "bme-floating-ball";
- fab.setAttribute("data-status", "idle");
- fab.innerHTML = `
-
- BME 记忆图谱
- `;
_fabEl = fab;
ensureFabMountedAtRoot();
@@ -1047,11 +1047,17 @@ function _initFloatingBall() {
if (saved) {
fab.dataset.positionMode = "saved";
applyFabPosition(saved, fab);
- } else {
+ } else if (!fab.style.left || !fab.style.top) {
fab.dataset.positionMode = "default";
syncFabPosition();
}
+ if (fab.dataset.bmeFabBound === "true") {
+ return;
+ }
+ fab.dataset.bmeFabBound = "true";
+ delete fab.dataset.bmeBootstrap;
+
// 拖拽 + 点击逻辑
let isDragging = false;
let hasMoved = false;