diff --git a/style.css b/style.css index 52b1d6e..0260fb9 100644 --- a/style.css +++ b/style.css @@ -4625,6 +4625,10 @@ border-color: var(--bme-accent2, #4edea3); } +#bme-floating-ball[data-status="cloud-success"]::after { + border-color: #60a5fa; +} + #bme-floating-ball[data-status="error"]::after { border-color: #f44336; } @@ -4633,6 +4637,11 @@ border-color: #ffc107; } +#bme-floating-ball[data-status="cloud-success"] .bme-fab-icon, +#bme-floating-ball[data-status="cloud-success"]:hover .bme-fab-icon { + color: #60a5fa; +} + @keyframes bme-fab-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } diff --git a/ui/panel.js b/ui/panel.js index 4c6209a..c2ef630 100644 --- a/ui/panel.js +++ b/ui/panel.js @@ -3967,6 +3967,27 @@ function _bindActions() { rollbackLastRestore: "\u56de\u6eda\u4e0a\u6b21\u6062\u590d", }; + const manualCloudFabBehaviors = { + backupToCloud: { + successStatus: "cloud-success", + successTooltip: "备份云端完成", + errorTooltip: "备份到云端失败", + }, + restoreFromCloud: { + successStatus: "cloud-success", + successTooltip: "云端备份已提取", + errorTooltip: "从云端获取备份失败", + }, + manageServerBackups: { + suppressFab: true, + }, + rollbackLastRestore: { + successStatus: "cloud-success", + successTooltip: "回滚完成", + errorTooltip: "回滚上次恢复失败", + }, + }; + for (const [elementId, actionKey] of Object.entries(bindings)) { const btn = document.getElementById(elementId); if (!btn) continue; @@ -3979,6 +4000,8 @@ function _bindActions() { if (!handler) return; const label = actionLabels[actionKey] || actionKey; + const fabBehavior = manualCloudFabBehaviors[actionKey] || null; + const suppressFab = fabBehavior?.suppressFab === true; // 防止重复点击 if (btn.disabled) return; @@ -3986,11 +4009,17 @@ function _bindActions() { btn.style.opacity = "0.5"; _showActionProgressUi(label); + if (suppressFab) { + _syncFloatingBallWithRuntimeStatus(); + } toastr.info(`${label} 进行中…`, "ST-BME", { timeOut: 2000 }); try { const result = await handler(); if (result?.cancelled) { + if (!suppressFab) { + _syncFloatingBallWithRuntimeStatus(); + } return; } if (!result?.skipDashboardRefresh) { @@ -4014,9 +4043,21 @@ function _bindActions() { if (!result?.handledToast) { toastr.success(`${label} 完成`, "ST-BME"); } + if (fabBehavior?.successTooltip) { + updateFloatingBallStatus( + fabBehavior.successStatus || "success", + fabBehavior.successTooltip, + ); + } void _refreshCloudBackupManualUi(); } catch (error) { console.error(`[ST-BME] Action ${actionKey} failed:`, error); + if (!suppressFab) { + updateFloatingBallStatus( + fabBehavior?.errorStatus || "error", + fabBehavior?.errorTooltip || `${label}失败`, + ); + } if (!error?._stBmeToastHandled) { toastr.error(`${label} 失败: ${error?.message || error}`, "ST-BME"); } @@ -10171,6 +10212,13 @@ function _showActionProgressUi(label, meta = "请稍候…") { updateFloatingBallStatus("running", `${label}中`); } +function _syncFloatingBallWithRuntimeStatus() { + const status = _getRuntimeStatus?.() || {}; + const level = String(status.level || "idle"); + const fabStatus = level === "info" ? "idle" : level; + updateFloatingBallStatus(fabStatus, status.text || "BME 记忆图谱"); +} + function _patchSettings(patch = {}, options = {}) { const settings = _updateSettings?.(patch) || _getSettings?.() || {}; if (options.refreshGuards) _refreshGuardedConfigStates(settings);