feat(ui): rename workflows tab, restore card action buttons, and redesign toolbox as bottom-left icon grid
This commit is contained in:
+16
-15
@@ -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
@@ -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
@@ -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
@@ -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 = '×';
|
||||
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
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user