feat(ui): rename workflows tab, restore card action buttons, and redesign toolbox as bottom-left icon grid

This commit is contained in:
DemonGatanjieu
2026-09-11 21:54:03 +08:00
parent f1edb2163e
commit c2f04e3cc9
5 changed files with 216 additions and 159 deletions
+16 -15
View File
@@ -81,21 +81,22 @@ DOM or live LiteGraph state.
primary model-browser surfaces, including the frosted-glass capsule parameter inspection
button with lightweight vector SVG icons and GPU-accelerated micro-interactions;
the sidebar bottom action bar (`#anomalous-sidebar-actions`) features intuitive, highly restrained glyphic vector SVG icons (`SIDEBAR_ICONS`):
(1) Toolbox Hub (`#anomalous-toolbox-btn`): Precision 18px vector toolbox icon (`TOOLBOX`) anchoring the leftmost action slot, triggering an elevated 310px utility popover (`#anomalous-toolbox-modal`, z-index 999999) with dynamic responsive offset (`left: 266px`, collapsed `72px`), extensible tool registry (`this.registerToolboxItem`), and mutual exclusivity against Settings Hub;
(2) Scan Wizard (`#anomalous-scan-btn`): Clean circular radar scope with range ring, crosshairs, and sweep beacon (`SCAN_RADAR_ICON_SVG`), animated only during active scanning;
(3) Model Doctor (`#anomalous-doctor-btn`): Sleek diagnostic medical stethoscope, instantly conveying health check semantics;
(4) AI Assistant (`#anomalous-assistant-btn`): Radiant AI copilot sparkles (`✦`), representing copilot intelligence;
(5) Material Library (`#anomalous-materials-btn`): 3D layered preset stack, distinguishing from individual model boxes;
(6) Settings Hub (`#anomalous-global-settings-btn`): Precision 8-tooth mechanical engineering gear with elevated popover (`#anomalous-settings-hub-modal`) mounted directly to container with `z-index: 999999` and dynamic responsive offset; hosts a clean 3-way Display Mode segmented controller (`#anomalous-view-mode-container` for Standard, Compact, and Aesthetic modes), UI scale controls, dynamic background atmosphere controls, folder manager, language toggles, a restrained inline 13px glyph question icon for Help (decoupling from `.anomalous-btn-icon` 32px box trap), and an intuitive reload arrow (`↺`) for window layout reset replacing esoteric drafting ruler emojis;
(7) Models & Floating Trigger: Precision 3D Isometric Asset Model Cube SVG (`box`), universally conveying 3D model, mesh, and asset package semantics with zero visual ambiguity;
adhering to a "low-stimulus idle, subtle-illumination on hover" philosophy where icons use calm `currentColor` in idle state and gently illuminate on interaction;
critical tool workbenches (`#anomalous-doctor-panel`, `#anomalous-assistant-panel`) strictly enforce 100% opaque, solid backgrounds (`background: var(--amb-bg-page, #131315) !important`) to eliminate background distraction during diagnostics;
the UI palette strictly adheres to a true neutral dark charcoal / obsidian studio aesthetic (`#131315`, `#1a1a1d`, `#202024`, `#28282d`) with zero cool-blue/navy cast, matching ComfyUI, Blender, and DaVinci Resolve workstation standards;
the sidebar action bar's circular astrological runic compass watermark (`#anomalous-sidebar-actions::before`) is completely disabled (`display: none !important`), and any backdrop textures are desaturated with `grayscale(100%)` to prevent blue color bleeding;
all primary action highlights, scan wizard controls, and switches use titanium white (`#e5e7eb` / `#ffffff`) with warm studio amber (`#f59e0b`) accents instead of cold blue/cyan;
the modal adopts a disciplined "workshop / archive" aesthetic: removing exaggerated `clip-path` chamfers in favor of clean 8px architectural engineering geometry (`border-radius: 8px; border: 1px solid rgba(255, 255, 255, 0.1)`);
the master header (`#anomalous-header`) and sidebar brand bar (`#anomalous-brand-bar`) are tightly calibrated to a 48px slim industrial profile; header navigation tabs (`#anomalous-models-btn`, `#anomalous-gallery-btn`, `#anomalous-notebook-btn`) and window control buttons (`#anomalous-dock-btn`, `#anomalous-close`) are unified to a compact 28px height, 6px border radius, 13px vector icons, active tab tracking, and persistent bilingual text labels (`.anomalous-btn-text` with `display: inline !important`, permanently removing legacy container query text suppression), perfectly harmonizing with adjacent dock and close controls;
supports 3 unified Display Modes sharing identical DOM structure and UX logic:
(1) Toolbox Hub (`#anomalous-toolbox-btn`): Precision 18px vector toolbox icon (`TOOLBOX`) anchoring the leftmost action slot, triggering an elevated 232px micro-utility drawer popover (`#anomalous-toolbox-modal`, z-index 999999) anchored directly above the action bar in the bottom-left corner (`bottom: 50px; left: 10px;`, collapsed `left: 68px`), presenting a high-density 3-column app/utility icon grid palette (`.anomalous-toolbox-grid`, `.anomalous-toolbox-tile`) with instant tooltips, amber status indicator dots, extensible tool registry (`this.registerToolboxItem`), zero obstruction to the central model grid, and mutual exclusivity against Settings Hub;
(2) Scan Wizard (`#anomalous-scan-btn`): Clean circular radar scope with range ring, crosshairs, and sweep beacon (`SCAN_RADAR_ICON_SVG`), animated only during active scanning;
(3) Model Doctor (`#anomalous-doctor-btn`): Sleek diagnostic medical stethoscope, instantly conveying health check semantics;
(4) AI Assistant (`#anomalous-assistant-btn`): Radiant AI copilot sparkles (`✦`), representing copilot intelligence;
(5) Material Library (`#anomalous-materials-btn`): 3D layered preset stack, distinguishing from individual model boxes;
(6) Settings Hub (`#anomalous-global-settings-btn`): Precision 8-tooth mechanical engineering gear with elevated popover (`#anomalous-settings-hub-modal`) mounted directly to container with `z-index: 999999` and dynamic responsive offset; hosts a clean 3-way Display Mode segmented controller (`#anomalous-view-mode-container` for Standard, Compact, and Aesthetic modes), UI scale controls, dynamic background atmosphere controls, folder manager, language toggles, a restrained inline 13px glyph question icon for Help (decoupling from `.anomalous-btn-icon` 32px box trap), and an intuitive reload arrow (`↺`) for window layout reset replacing esoteric drafting ruler emojis;
(7) Models & Floating Trigger: Precision 3D Isometric Asset Model Cube SVG (`box`), universally conveying 3D model, mesh, and asset package semantics with zero visual ambiguity;
adhering to a "low-stimulus idle, subtle-illumination on hover" philosophy where icons use calm `currentColor` in idle state and gently illuminate on interaction;
critical tool workbenches (`#anomalous-doctor-panel`, `#anomalous-assistant-panel`) strictly enforce 100% opaque, solid backgrounds (`background: var(--amb-bg-page, #131315) !important`) to eliminate background distraction during diagnostics;
the UI palette strictly adheres to a true neutral dark charcoal / obsidian studio aesthetic (`#131315`, `#1a1a1d`, `#202024`, `#28282d`) with zero cool-blue/navy cast, matching ComfyUI, Blender, and DaVinci Resolve workstation standards;
the sidebar action bar's circular astrological runic compass watermark (`#anomalous-sidebar-actions::before`) is completely disabled (`display: none !important`), and any backdrop textures are desaturated with `grayscale(100%)` to prevent blue color bleeding;
all primary action highlights, scan wizard controls, and switches use titanium white (`#e5e7eb` / `#ffffff`) with warm studio amber (`#f59e0b`) accents instead of cold blue/cyan;
the modal adopts a disciplined "workshop / archive" aesthetic: removing exaggerated `clip-path` chamfers in favor of clean 8px architectural engineering geometry (`border-radius: 8px; border: 1px solid rgba(255, 255, 255, 0.1)`);
the master header (`#anomalous-header`) and sidebar brand bar (`#anomalous-brand-bar`) are tightly calibrated to a 48px slim industrial profile; header navigation tabs (`#anomalous-models-btn`, `#anomalous-gallery-btn`, `#anomalous-notebook-btn`) and window control buttons (`#anomalous-dock-btn`, `#anomalous-close`) are unified to a compact 28px height, 6px border radius, 13px vector icons, active tab tracking, and persistent bilingual text labels (`[ 📦 模型 ]`, `[ 🖼️ 图库 ]`, `[ 🔗 工作流 ]` - simplified from "工作流配方" to balance width and match ComfyUI workflow mental model), perfectly harmonizing with adjacent dock and close controls;
cards feature restored and refined top-right micro-action buttons (`.anomalous-card-action-btn`: Apply ➕, Edit ✏️, Scan 🎯) with 22px frosted glass styling, smooth hover fade-in, and auto-clipping avoidance against the base model badge (`.anomalous-card-badge`);
supports 3 unified Display Modes sharing identical DOM structure and UX logic:
- Compact Mode (紧凑模式, primary default): 140px min-width, 220px card height, tight 10px gaps/14px rows, 5px sidebar folder rows, optimized for high-density scanning and instant visual discovery (Blender Asset Browser inspired);
- Standard Mode (标准模式, comfortable): Balanced 200px cards, 340px height, comfortable whitespace rhythm;
- Aesthetic Mode (沉浸模式): Subtle 8% grayscale ambient archive watermark with frosted glass borders;
+26 -2
View File
@@ -723,11 +723,23 @@ export const i18n = {
toolboxReady: '就绪',
toolboxHintFooter: '💡 持续扩展中:模型批量重整、孤立缓存清理、哈希重算等运维工具将在此聚合。',
toolOrphanCleanerTitle: '孤立缓存与临时文件清理',
toolOrphanCleanerShort: '缓存清理',
toolOrphanCleanerDesc: '扫描并清理已删除模型的未引用缩略图缓存与临时残余文件。',
toolBatchRenameTitle: '批量命名与标签重整',
toolBatchRenameShort: '批量重整',
toolBatchRenameDesc: '对指定目录下的模型批量规范命名规则或批量附加分类标签。',
toolCivitaiJumpTitle: 'Civitai 页面一键直达',
toolCivitaiJumpShort: 'Civitai',
toolCivitaiJumpDesc: '根据模型 SHA256 哈希或名称直接在浏览器打开对应发布页。',
toolHashRecalcTitle: '哈希快查',
toolHashRecalcShort: '哈希快查',
toolHashRecalcDesc: '快速计算并校验模型文件的 SHA256 哈希值。',
toolFormatConvertTitle: '格式转换',
toolFormatConvertShort: '格式转换',
toolFormatConvertDesc: '模型权重的 FP8/FP16 精度或格式互转辅助工具。',
toolCustomScriptsTitle: '扩展脚本',
toolCustomScriptsShort: '扩展脚本',
toolCustomScriptsDesc: '通过开放接口注册并执行自定义 Python / JS 运维动作。',
sidebarInjectHash: '🟢 注入工作流哈希',
sidebarSkipHash: '⚪ 不注入工作流哈希',
sidebarManageFolders: '文件夹管理',
@@ -775,7 +787,7 @@ export const i18n = {
closeSettings: '✖ 关闭设置面板',
doctorBtn: '节点助手',
importBtn: '导入 / 导出工作流 (分享码)',
recipeTitle: '工作流配方',
recipeTitle: '工作流',
recipeBetaNotice: '工作流配方仍在测试。更新插件以及导入、恢复、删除或应用参数前,请保存当前画布并备份用户 workflows 目录中的 anomalous_recipes 与 anomalous_parameters。',
recipeClose: '关闭工作流配方',
recipeSaveCurrent: '保存当前工作流',
@@ -1801,11 +1813,23 @@ export const i18n = {
toolboxReady: 'Ready',
toolboxHintFooter: '💡 Expanding: Batch organizer, orphan cache cleaner, and hash recalculation tools will be hosted here.',
toolOrphanCleanerTitle: 'Orphan Cache & Temp Cleaner',
toolOrphanCleanerShort: 'Cache Clean',
toolOrphanCleanerDesc: 'Scan and remove unreferenced thumbnails and temporary files for deleted models.',
toolBatchRenameTitle: 'Batch Rename & Tagging',
toolBatchRenameShort: 'Batch Rename',
toolBatchRenameDesc: 'Standardize model filenames or batch-assign taxonomy tags to folders.',
toolCivitaiJumpTitle: 'Civitai Quick Jump',
toolCivitaiJumpShort: 'Civitai',
toolCivitaiJumpDesc: 'Quickly open official model release pages in browser by SHA256 hash or title.',
toolHashRecalcTitle: 'Hash Check',
toolHashRecalcShort: 'Hash Check',
toolHashRecalcDesc: 'Quickly compute and verify model file SHA256 hash.',
toolFormatConvertTitle: 'Format Convert',
toolFormatConvertShort: 'Convert',
toolFormatConvertDesc: 'Helper tools for model FP8/FP16 precision and format conversion.',
toolCustomScriptsTitle: 'Custom Scripts',
toolCustomScriptsShort: 'Scripts',
toolCustomScriptsDesc: 'Register and run custom Python / JS maintenance scripts via API.',
sidebarInjectHash: '🟢 Inject Workflow Hash',
sidebarSkipHash: '⚪ Skip Workflow Hash',
sidebarManageFolders: 'Manage Folders',
@@ -1853,7 +1877,7 @@ export const i18n = {
closeSettings: '✖ Close Settings',
doctorBtn: 'Node Assistant',
importBtn: 'Import / Export Workflow (Share Code)',
recipeTitle: 'Workflow Recipes',
recipeTitle: 'Workflows',
recipeBetaNotice: 'Workflow Recipes are still in beta. Before updating the plugin or importing, restoring, deleting, or applying parameters, save the canvas and back up anomalous_recipes and anomalous_parameters under your user workflows directory.',
recipeClose: 'Close Workflow Recipes',
recipeSaveCurrent: 'Save Current Workflow',
+11 -17
View File
@@ -159,7 +159,7 @@ export async function loadModels() {
};
const applyBtn = document.createElement('button');
applyBtn.innerHTML = `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" style="display:block;"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>`;
applyBtn.innerHTML = `<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" style="display:block;"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>`;
applyBtn.className = 'anomalous-card-action-btn action-apply anomalous-tooltip-target';
applyBtn.removeAttribute('title');
applyBtn.setAttribute('data-tooltip', t('applyToCanvas'));
@@ -170,20 +170,8 @@ export async function loadModels() {
};
card.appendChild(applyBtn);
const singleScanBtn = document.createElement('button');
singleScanBtn.innerHTML = `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:block;"><circle cx="12" cy="12" r="10"/><line x1="22" y1="12" x2="18" y2="12"/><line x1="6" y1="12" x2="2" y2="12"/><line x1="12" y1="6" x2="12" y2="2"/><line x1="12" y1="22" x2="12" y2="18"/></svg>`;
singleScanBtn.className = 'anomalous-card-action-btn action-scan anomalous-tooltip-target';
singleScanBtn.removeAttribute('title');
singleScanBtn.setAttribute('data-tooltip', t('scanModelPrecisely'));
singleScanBtn.setAttribute('data-tooltip-pos', 'bottom');
singleScanBtn.onclick = (e) => {
e.stopPropagation();
createWizardModal(false, model.filename);
};
card.appendChild(singleScanBtn);
const editBtn = document.createElement('button');
editBtn.innerHTML = `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:block;"><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/></svg>`;
editBtn.innerHTML = `<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" style="display:block;"><path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"/><path d="m15 5 4 4"/></svg>`;
editBtn.className = 'anomalous-card-action-btn action-edit anomalous-tooltip-target';
editBtn.removeAttribute('title');
editBtn.setAttribute('data-tooltip', t('editModel'));
@@ -194,11 +182,17 @@ export async function loadModels() {
};
card.appendChild(editBtn);
applyBtn.onclick = (e) => {
const singleScanBtn = document.createElement('button');
singleScanBtn.innerHTML = `<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:block;"><circle cx="12" cy="12" r="10"/><line x1="22" y1="12" x2="18" y2="12"/><line x1="6" y1="12" x2="2" y2="12"/><line x1="12" y1="6" x2="12" y2="2"/><line x1="12" y1="22" x2="12" y2="18"/></svg>`;
singleScanBtn.className = 'anomalous-card-action-btn action-scan anomalous-tooltip-target';
singleScanBtn.removeAttribute('title');
singleScanBtn.setAttribute('data-tooltip', t('scanModelPrecisely'));
singleScanBtn.setAttribute('data-tooltip-pos', 'bottom');
singleScanBtn.onclick = (e) => {
e.stopPropagation();
this.applyModelToCanvas(this.currentType, this.currentSubfolder, model);
createWizardModal(false, model.filename);
};
card.appendChild(applyBtn);
card.appendChild(singleScanBtn);
fragment.appendChild(card);
+75 -108
View File
@@ -1898,7 +1898,8 @@ export function createDOM() {
headerRow.style.display = 'flex';
headerRow.style.alignItems = 'center';
headerRow.style.justifyContent = 'space-between';
headerRow.style.marginBottom = '2px';
headerRow.style.padding = '2px 4px 6px';
headerRow.style.borderBottom = '1px solid rgba(255, 255, 255, 0.06)';
const titleBox = document.createElement('div');
titleBox.style.display = 'flex';
@@ -1908,14 +1909,14 @@ export function createDOM() {
const titleText = document.createElement('span');
titleText.textContent = t('toolboxTitle');
titleText.style.fontWeight = '600';
titleText.style.fontSize = '1.05em';
titleText.style.fontSize = '12px';
titleText.style.color = '#fff';
const betaBadge = document.createElement('span');
betaBadge.textContent = 'Hub';
betaBadge.style.fontSize = '10px';
betaBadge.style.padding = '1px 6px';
betaBadge.style.borderRadius = '4px';
betaBadge.style.fontSize = '9px';
betaBadge.style.padding = '1px 5px';
betaBadge.style.borderRadius = '3px';
betaBadge.style.background = 'rgba(255, 255, 255, 0.08)';
betaBadge.style.color = '#a1a1aa';
betaBadge.style.fontWeight = '500';
@@ -1927,9 +1928,9 @@ export function createDOM() {
closeModalBtn.innerHTML = '&times;';
closeModalBtn.style.cursor = 'pointer';
closeModalBtn.style.color = '#888';
closeModalBtn.style.fontSize = '18px';
closeModalBtn.style.fontSize = '16px';
closeModalBtn.style.lineHeight = '1';
closeModalBtn.style.padding = '2px 6px';
closeModalBtn.style.padding = '2px 4px';
closeModalBtn.style.borderRadius = '4px';
closeModalBtn.onmouseover = () => { closeModalBtn.style.color = '#fff'; closeModalBtn.style.background = 'rgba(255,255,255,0.08)'; };
closeModalBtn.onmouseout = () => { closeModalBtn.style.color = '#888'; closeModalBtn.style.background = 'transparent'; };
@@ -1938,25 +1939,16 @@ export function createDOM() {
headerRow.appendChild(titleBox);
headerRow.appendChild(closeModalBtn);
const subtitle = document.createElement('div');
subtitle.textContent = t('toolboxSubtitle');
subtitle.style.fontSize = '11px';
subtitle.style.color = '#8a8d98';
subtitle.style.marginBottom = '8px';
toolboxModal.appendChild(headerRow);
toolboxModal.appendChild(subtitle);
const itemsContainer = document.createElement('div');
itemsContainer.className = 'anomalous-toolbox-items';
itemsContainer.style.display = 'flex';
itemsContainer.style.flexDirection = 'column';
itemsContainer.style.gap = '8px';
const gridContainer = document.createElement('div');
gridContainer.className = 'anomalous-toolbox-grid';
const defaultTools = [
{
id: 'orphan-cleaner',
icon: '🧹',
shortTitle: t('toolOrphanCleanerShort'),
title: t('toolOrphanCleanerTitle'),
desc: t('toolOrphanCleanerDesc'),
badge: t('toolboxPlanned')
@@ -1964,6 +1956,7 @@ export function createDOM() {
{
id: 'batch-rename',
icon: '🏷️',
shortTitle: t('toolBatchRenameShort'),
title: t('toolBatchRenameTitle'),
desc: t('toolBatchRenameDesc'),
badge: t('toolboxPlanned')
@@ -1971,115 +1964,89 @@ export function createDOM() {
{
id: 'civitai-jump',
icon: '🌐',
shortTitle: t('toolCivitaiJumpShort'),
title: t('toolCivitaiJumpTitle'),
desc: t('toolCivitaiJumpDesc'),
badge: t('toolboxPlanned')
},
{
id: 'hash-recalc',
icon: '⚡',
shortTitle: t('toolHashRecalcShort'),
title: t('toolHashRecalcTitle'),
desc: t('toolHashRecalcDesc'),
badge: t('toolboxPlanned')
},
{
id: 'format-convert',
icon: '📦',
shortTitle: t('toolFormatConvertShort'),
title: t('toolFormatConvertTitle'),
desc: t('toolFormatConvertDesc'),
badge: t('toolboxPlanned')
},
{
id: 'custom-scripts',
icon: '🧩',
shortTitle: t('toolCustomScriptsShort'),
title: t('toolCustomScriptsTitle'),
desc: t('toolCustomScriptsDesc'),
badge: t('toolboxPlanned')
}
];
const allTools = [...defaultTools, ...(this.customToolboxItems || [])];
allTools.forEach(tool => {
const card = document.createElement('div');
card.className = 'anomalous-toolbox-card';
card.style.display = 'flex';
card.style.alignItems = 'flex-start';
card.style.gap = '10px';
card.style.padding = '9px 11px';
card.style.background = 'rgba(255, 255, 255, 0.03)';
card.style.border = '1px solid rgba(255, 255, 255, 0.06)';
card.style.borderRadius = '8px';
card.style.cursor = 'pointer';
card.style.transition = 'all 0.15s ease';
card.onmouseover = () => {
card.style.background = 'rgba(255, 255, 255, 0.07)';
card.style.borderColor = 'rgba(255, 255, 255, 0.15)';
};
card.onmouseout = () => {
card.style.background = 'rgba(255, 255, 255, 0.03)';
card.style.borderColor = 'rgba(255, 255, 255, 0.06)';
};
if (tool.action) {
card.onclick = (e) => {
e.stopPropagation();
tool.action();
};
}
const iconBox = document.createElement('div');
iconBox.style.width = '26px';
iconBox.style.height = '26px';
iconBox.style.borderRadius = '6px';
iconBox.style.background = 'rgba(255, 255, 255, 0.05)';
iconBox.style.display = 'flex';
iconBox.style.alignItems = 'center';
iconBox.style.justifyContent = 'center';
iconBox.style.fontSize = '14px';
iconBox.style.flexShrink = '0';
iconBox.innerText = tool.icon;
const textCol = document.createElement('div');
textCol.style.flex = '1';
textCol.style.minWidth = '0';
const topRow = document.createElement('div');
topRow.style.display = 'flex';
topRow.style.alignItems = 'center';
topRow.style.justifyContent = 'space-between';
topRow.style.gap = '6px';
const cTitle = document.createElement('div');
cTitle.textContent = tool.title;
cTitle.style.fontWeight = '500';
cTitle.style.fontSize = '12px';
cTitle.style.color = '#e4e4e7';
cTitle.style.whiteSpace = 'nowrap';
cTitle.style.overflow = 'hidden';
cTitle.style.textOverflow = 'ellipsis';
topRow.appendChild(cTitle);
const tile = document.createElement('div');
tile.className = 'anomalous-toolbox-tile anomalous-tooltip-target';
tile.setAttribute('data-tooltip', `${tool.title}\n${tool.desc || ''}`);
tile.setAttribute('data-tooltip-pos', 'top');
if (tool.badge) {
const cBadge = document.createElement('span');
cBadge.textContent = tool.badge;
cBadge.style.fontSize = '10px';
cBadge.style.padding = '0 5px';
cBadge.style.borderRadius = '3px';
cBadge.style.background = 'rgba(245, 158, 11, 0.12)';
cBadge.style.color = '#f59e0b';
cBadge.style.fontWeight = '500';
cBadge.style.flexShrink = '0';
topRow.appendChild(cBadge);
const dot = document.createElement('span');
dot.className = 'anomalous-toolbox-tile-dot';
tile.appendChild(dot);
}
const cDesc = document.createElement('div');
cDesc.textContent = tool.desc;
cDesc.style.fontSize = '11px';
cDesc.style.color = '#8a8d98';
cDesc.style.lineHeight = '1.35';
cDesc.style.marginTop = '2px';
const iconEl = document.createElement('div');
iconEl.className = 'anomalous-toolbox-tile-icon';
iconEl.innerText = tool.icon || '🔧';
tile.appendChild(iconEl);
textCol.appendChild(topRow);
textCol.appendChild(cDesc);
const labelEl = document.createElement('div');
labelEl.className = 'anomalous-toolbox-tile-label';
labelEl.textContent = tool.shortTitle || tool.title;
tile.appendChild(labelEl);
card.appendChild(iconBox);
card.appendChild(textCol);
itemsContainer.appendChild(card);
tile.onclick = (e) => {
e.stopPropagation();
if (typeof tool.action === 'function') {
tool.action();
} else {
const alertMsg = window.anomalous_browser_lang === 'zh'
? `【${tool.title}】功能正在规划整合中,敬请期待!`
: `[${tool.title}] is currently in development!`;
if (typeof window.anomalous_notify === 'function') {
window.anomalous_notify(alertMsg, 'info');
} else {
alert(alertMsg);
}
}
};
gridContainer.appendChild(tile);
});
toolboxModal.appendChild(itemsContainer);
toolboxModal.appendChild(gridContainer);
const hintFooter = document.createElement('div');
hintFooter.textContent = t('toolboxHintFooter');
hintFooter.style.fontSize = '10.5px';
hintFooter.textContent = window.anomalous_browser_lang === 'zh' ? '💡 实用运维工具持续扩充中' : '💡 Utility toolset expanding...';
hintFooter.style.fontSize = '10px';
hintFooter.style.color = '#71717a';
hintFooter.style.lineHeight = '1.4';
hintFooter.style.background = 'rgba(255, 255, 255, 0.02)';
hintFooter.style.border = '1px dashed rgba(255, 255, 255, 0.08)';
hintFooter.style.padding = '7px 9px';
hintFooter.style.borderRadius = '6px';
hintFooter.style.marginTop = '4px';
hintFooter.style.textAlign = 'center';
hintFooter.style.padding = '4px 2px 0';
hintFooter.style.borderTop = '1px solid rgba(255, 255, 255, 0.05)';
toolboxModal.appendChild(hintFooter);
};
+88 -17
View File
@@ -566,10 +566,13 @@ html:not(.anomalous-floating-entry-enabled) [data-setting-id="Anomalous.ModelBro
#anomalous-container:not(.view-mode-standard):not(.view-mode-aesthetic) .anomalous-card-badge {
top: 6px !important;
left: 6px !important;
max-width: 65px !important;
max-width: 55px !important;
font-size: 0.65em !important;
padding: 1px 4px !important;
border-radius: 3px !important;
white-space: nowrap !important;
overflow: hidden !important;
text-overflow: ellipsis !important;
}
#anomalous-container.view-mode-compact .anomalous-card-action-btn,
@@ -586,13 +589,13 @@ html:not(.anomalous-floating-entry-enabled) [data-setting-id="Anomalous.ModelBro
right: 6px !important;
}
#anomalous-container.view-mode-compact .anomalous-card-action-btn.action-scan,
#anomalous-container:not(.view-mode-standard):not(.view-mode-aesthetic) .anomalous-card-action-btn.action-scan {
#anomalous-container.view-mode-compact .anomalous-card-action-btn.action-edit,
#anomalous-container:not(.view-mode-standard):not(.view-mode-aesthetic) .anomalous-card-action-btn.action-edit {
right: 32px !important;
}
#anomalous-container.view-mode-compact .anomalous-card-action-btn.action-edit,
#anomalous-container:not(.view-mode-standard):not(.view-mode-aesthetic) .anomalous-card-action-btn.action-edit {
#anomalous-container.view-mode-compact .anomalous-card-action-btn.action-scan,
#anomalous-container:not(.view-mode-standard):not(.view-mode-aesthetic) .anomalous-card-action-btn.action-scan {
right: 58px !important;
}
@@ -773,11 +776,11 @@ html:not(.anomalous-floating-entry-enabled) [data-setting-id="Anomalous.ModelBro
right: 8px;
}
.anomalous-card-action-btn.action-scan {
.anomalous-card-action-btn.action-edit {
right: 42px;
}
.anomalous-card-action-btn.action-edit {
.anomalous-card-action-btn.action-scan {
right: 76px;
}
@@ -1028,28 +1031,96 @@ html:not(.anomalous-floating-entry-enabled) [data-setting-id="Anomalous.ModelBro
#anomalous-toolbox-modal {
position: absolute;
bottom: 16px;
left: 266px;
width: 310px;
max-height: calc(100% - 32px);
bottom: 50px;
left: 10px;
width: 232px;
max-height: calc(100% - 64px);
overflow-y: auto;
box-sizing: border-box;
background: rgba(24, 24, 28, 0.98);
background: rgba(22, 22, 26, 0.98);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 10px;
padding: 14px;
box-shadow: 0 16px 48px rgba(0, 0, 0, 0.85), 0 0 0 1px rgba(255, 255, 255, 0.05);
padding: 10px;
box-shadow: 0 16px 40px rgba(0, 0, 0, 0.85), 0 0 0 1px rgba(255, 255, 255, 0.05);
z-index: 999999 !important;
transition: left 0.3s cubic-bezier(0.2, 0.8, 0.2, 1);
transition: left 0.25s cubic-bezier(0.2, 0.8, 0.2, 1), bottom 0.25s cubic-bezier(0.2, 0.8, 0.2, 1);
display: none;
flex-direction: column;
gap: 6px;
gap: 8px;
}
.anomalous-sidebar-closed #anomalous-toolbox-modal {
left: 72px !important;
left: 68px !important;
bottom: 12px !important;
}
.anomalous-toolbox-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 6px;
margin: 2px 0 4px;
}
.anomalous-toolbox-tile {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
padding: 9px 4px 7px;
min-height: 58px;
box-sizing: border-box;
background: rgba(255, 255, 255, 0.035);
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 8px;
cursor: pointer;
position: relative;
user-select: none;
transition: all 0.15s cubic-bezier(0.16, 1, 0.3, 1);
}
.anomalous-toolbox-tile:hover {
background: rgba(255, 255, 255, 0.08);
border-color: rgba(255, 255, 255, 0.18);
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.35);
}
.anomalous-toolbox-tile:active {
transform: scale(0.96);
}
.anomalous-toolbox-tile-icon {
font-size: 18px;
line-height: 1;
margin-bottom: 5px;
display: flex;
align-items: center;
justify-content: center;
}
.anomalous-toolbox-tile-label {
font-size: 11px;
font-weight: 500;
color: #d4d4d8;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
line-height: 1.2;
}
.anomalous-toolbox-tile-dot {
position: absolute;
top: 4px;
right: 4px;
width: 5px;
height: 5px;
border-radius: 50%;
background: #f59e0b;
box-shadow: 0 0 4px rgba(245, 158, 11, 0.6);
}
.anomalous-sidebar-closed #anomalous-sidebar-actions {