From 8a9a91b3d2fbe601df9366dcc381fc098f711b10 Mon Sep 17 00:00:00 2001
From: DemonGatanjieu <1027066412@qq.com>
Date: Thu, 10 Sep 2026 16:50:14 +0800
Subject: [PATCH] fix(ui): distinguish scan wizard from reset layout with
vector radar scanner and distinct layout icon
---
ARCHITECTURE.md | 6 ++++-
web/modules/locales.js | 8 +++---
web/modules/ui_sidebar.js | 41 +++++++++++++++-------------
web/styles.css | 56 +++++++++++++++++++++++++++++++++++++++
4 files changed, 87 insertions(+), 24 deletions(-)
diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md
index 3d61084..26797fe 100644
--- a/ARCHITECTURE.md
+++ b/ARCHITECTURE.md
@@ -79,7 +79,11 @@ DOM or live LiteGraph state.
native command/keybinding integration.
- `ui_sidebar.js`, `ui_grid.js`, `ui_detail.js`, and `ui_gallery.js` own the
primary model-browser surfaces, including the frosted-glass capsule parameter inspection
- button with lightweight vector SVG icons and GPU-accelerated micro-interactions.
+ button with lightweight vector SVG icons and GPU-accelerated micro-interactions;
+ the sidebar bottom-left scan action (`#anomalous-scan-btn`) features a dedicated high-precision
+ vector radar SVG (`SCAN_RADAR_ICON_SVG`) with GPU-accelerated continuous sweep animation (`.anomalous-radar-spinning`),
+ completely decoupling from the settings modal's default layout reset button (`sidebarResetLayout: '📐 恢复默认窗口布局'`)
+ to eliminate visual collision and disambiguate user mental models.
- `ui_gallery_detail.js` owns the studio modal Image Detail Workbench,
multi-dimensional image navigation (keyboard shortcuts, floating glass arrows,
left vertical thumbnail rail), streamlined workflow/material action buttons,
diff --git a/web/modules/locales.js b/web/modules/locales.js
index 1dc8eb9..75a07e7 100644
--- a/web/modules/locales.js
+++ b/web/modules/locales.js
@@ -636,7 +636,7 @@ export const i18n = {
sidebarAssistant: '节点助手',
sidebarPreflight: '📥 预检导入工作流',
sidebarSettings: '设置中心',
- sidebarScanWizard: '🔄 扫描向导 (Scan Wizard)',
+ sidebarScanWizard: '📡 模型扫描向导',
sidebarScanComplete: '✅ 扫描/重命名已完成!数据已为您更新。',
sidebarScanWizardTitle: '扫描向导',
sidebarGlobalScanWizard: '全局扫描向导',
@@ -708,7 +708,7 @@ export const i18n = {
sidebarInfoComplete: '✅ 补全完成',
sidebarAllInfoComplete: '✨ 所有模型信息已完整',
sidebarUiScale: 'UI 缩放',
- sidebarResetLayout: '🔄 重置界面布局',
+ sidebarResetLayout: '📐 恢复默认窗口布局',
sidebarResetConfirm: '确认重置窗口位置、缩放和停靠状态吗?',
sidebarInjectHash: '🟢 注入工作流哈希',
sidebarSkipHash: '⚪ 不注入工作流哈希',
@@ -1696,7 +1696,7 @@ export const i18n = {
sidebarAssistant: 'Node Assistant',
sidebarPreflight: '📥 Preflight Import',
sidebarSettings: 'Settings Hub',
- sidebarScanWizard: '🔄 Scan Wizard',
+ sidebarScanWizard: '📡 Model Scan Wizard',
sidebarScanComplete: '✅ Scan/Rename completed! Data updated.',
sidebarScanWizardTitle: 'Scan Wizard',
sidebarGlobalScanWizard: 'Global Scan Wizard',
@@ -1768,7 +1768,7 @@ export const i18n = {
sidebarInfoComplete: '✅ Info Complete',
sidebarAllInfoComplete: '✨ All Model Info is Complete',
sidebarUiScale: 'UI Scale',
- sidebarResetLayout: '🔄 Reset Layout',
+ sidebarResetLayout: '📐 Reset Window Layout',
sidebarResetConfirm: 'Reset window position, scale and dock state?',
sidebarInjectHash: '🟢 Inject Workflow Hash',
sidebarSkipHash: '⚪ Skip Workflow Hash',
diff --git a/web/modules/ui_sidebar.js b/web/modules/ui_sidebar.js
index c241c46..77f54e1 100644
--- a/web/modules/ui_sidebar.js
+++ b/web/modules/ui_sidebar.js
@@ -10,7 +10,15 @@ import { updateScanProgress, finishScanProgress, failScanProgress } from './scan
const t = (key, params) => translate(key, params);
+const SCAN_RADAR_ICON_SVG = ``;
+function setScanButtonState(btn, isScanning) {
+ if (!btn) return;
+ btn.innerHTML = SCAN_RADAR_ICON_SVG;
+ btn.classList.toggle('anomalous-radar-spinning', Boolean(isScanning));
+ btn.style.opacity = isScanning ? '0.85' : '1';
+ btn.style.animation = '';
+}
export function createDOM() {
localStorage.removeItem('anomalous_api_key');
@@ -342,7 +350,8 @@ export function createDOM() {
const scanBtn = document.createElement('button');
scanBtn.id = 'anomalous-scan-btn';
scanBtn.title = t('sidebarScanWizard');
- scanBtn.innerHTML = `🔄`;
+ scanBtn.setAttribute('aria-label', t('sidebarScanWizard'));
+ setScanButtonState(scanBtn, false);
scanBtn.style.background = 'transparent';
scanBtn.style.color = '#ccc';
scanBtn.style.border = 'none';
@@ -351,8 +360,8 @@ export function createDOM() {
scanBtn.style.fontSize = '1.1em';
scanBtn.style.cursor = 'pointer';
scanBtn.style.transition = 'all 0.2s ease';
- scanBtn.onmouseover = () => { scanBtn.style.background = 'rgba(255,255,255,0.1)'; scanBtn.style.color = '#fff'; };
- scanBtn.onmouseout = () => { scanBtn.style.background = 'transparent'; scanBtn.style.color = '#ccc'; };
+ scanBtn.onmouseover = () => { scanBtn.style.background = 'rgba(255,255,255,0.1)'; scanBtn.style.color = '#38bdf8'; };
+ scanBtn.onmouseout = () => { scanBtn.style.background = 'transparent'; scanBtn.style.color = scanBtn.classList.contains('anomalous-radar-spinning') ? '#38bdf8' : '#ccc'; };
let isCurrentlyScanning = false;
setInterval(async () => {
@@ -383,12 +392,10 @@ export function createDOM() {
if (isScanning && !isCurrentlyScanning) {
isCurrentlyScanning = true;
- scanBtn.innerHTML = `⏳`;
- scanBtn.style.opacity = '0.7';
+ setScanButtonState(scanBtn, true);
} else if (!isScanning && isCurrentlyScanning) {
isCurrentlyScanning = false;
- scanBtn.innerHTML = `🔄`;
- scanBtn.style.opacity = '1';
+ setScanButtonState(scanBtn, false);
finishScanProgress();
this.loadModels();
if (window.anomalous_reload_hashes) await window.anomalous_reload_hashes();
@@ -892,8 +899,7 @@ export function createDOM() {
document.body.removeChild(wizard);
if (typeof scanBtn !== 'undefined') {
- scanBtn.innerHTML = `⏳`;
- scanBtn.style.animation = 'anomalous-spin 2s linear infinite';
+ setScanButtonState(scanBtn, true);
}
const customFolders = Array.from(selectedForScan.entries()).filter(([, files]) => files.size > 0);
@@ -957,8 +963,7 @@ export function createDOM() {
}
if (typeof scanBtn !== 'undefined') {
- scanBtn.innerHTML = `🔄`;
- scanBtn.style.animation = '';
+ setScanButtonState(scanBtn, false);
}
finishScanProgress();
if (enableAutoCheck && window.anomalous_resolve_all_missing_nodes) {
@@ -994,8 +999,7 @@ export function createDOM() {
if (data.status === 'ok') {
updateScanProgress({ scanning: true, phase: 'preparing', recovered: data.recovered });
if (typeof scanBtn !== 'undefined') {
- scanBtn.innerHTML = `⏳`;
- scanBtn.style.animation = 'anomalous-spin 2s linear infinite';
+ setScanButtonState(scanBtn, true);
}
// Start polling
@@ -1014,8 +1018,7 @@ export function createDOM() {
if (statusData.interrupted) failScanProgress(t('scanProgressInterrupted'));
else finishScanProgress();
if (typeof scanBtn !== 'undefined') {
- scanBtn.innerHTML = `🔄`;
- scanBtn.style.animation = '';
+ setScanButtonState(scanBtn, false);
}
if (enableAutoCheck && window.anomalous_resolve_all_missing_nodes) {
@@ -1026,8 +1029,7 @@ export function createDOM() {
} catch (err) {
clearInterval(poll);
if (typeof scanBtn !== 'undefined') {
- scanBtn.innerHTML = `🔄`;
- scanBtn.style.animation = '';
+ setScanButtonState(scanBtn, false);
}
}
}, 2000);
@@ -1141,8 +1143,9 @@ export function createDOM() {
updateLangClass();
modelsBtn.innerHTML = `🏠 ${t('models')}`;
galleryBtn.innerHTML = `🖼️ ${t('gallery')}`;
- scanBtn.title = t('scanTitle');
- scanBtn.innerHTML = `🔄`;
+ scanBtn.title = t('sidebarScanWizard');
+ scanBtn.setAttribute('aria-label', t('sidebarScanWizard'));
+ setScanButtonState(scanBtn, isCurrentlyScanning);
helpBtn.innerHTML = `❓ ${t('help')}`;
nbBtn.title = t('recipeTitle');
nbBtn.innerHTML = `📑 ${t('recipeTitle')}`;
diff --git a/web/styles.css b/web/styles.css
index 532eeca..b9edc94 100644
--- a/web/styles.css
+++ b/web/styles.css
@@ -10531,5 +10531,61 @@ html.theme-abyssal-scarlet dialog.anomalous-gallery-viewer {
box-shadow: 0 25px 80px rgba(0, 0, 0, 0.88), 0 0 40px rgba(220, 20, 60, 0.18) !important;
}
+/* 9. Model Scanner Radar Button & Spin Animation */
+#anomalous-scan-btn {
+ display: inline-flex !important;
+ align-items: center !important;
+ justify-content: center !important;
+ width: 32px !important;
+ height: 32px !important;
+ border-radius: 6px !important;
+ box-sizing: border-box !important;
+ vertical-align: middle !important;
+}
+
+#anomalous-scan-btn svg {
+ transition: transform 0.2s ease, filter 0.2s ease;
+ transform-origin: center center;
+}
+
+#anomalous-scan-btn:hover svg {
+ filter: drop-shadow(0 0 4px rgba(56, 189, 248, 0.6));
+}
+
+#anomalous-scan-btn.anomalous-radar-spinning {
+ color: #38bdf8 !important;
+ background: rgba(56, 189, 248, 0.12) !important;
+ border: 1px solid rgba(56, 189, 248, 0.35) !important;
+}
+
+#anomalous-scan-btn.anomalous-radar-spinning svg {
+ animation: anomalous-radar-spin 1.4s linear infinite !important;
+ filter: drop-shadow(0 0 6px rgba(56, 189, 248, 0.75)) !important;
+}
+
+@keyframes anomalous-radar-spin {
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+.theme-abyssal-scarlet #anomalous-scan-btn:hover svg {
+ filter: drop-shadow(0 0 5px rgba(255, 77, 109, 0.75));
+}
+
+.theme-abyssal-scarlet #anomalous-scan-btn.anomalous-radar-spinning {
+ color: #ff4d6d !important;
+ background: rgba(255, 77, 109, 0.14) !important;
+ border: 1px solid rgba(255, 77, 109, 0.4) !important;
+}
+
+.theme-abyssal-scarlet #anomalous-scan-btn.anomalous-radar-spinning svg {
+ filter: drop-shadow(0 0 7px rgba(255, 77, 109, 0.85)) !important;
+}
+
+