diff --git a/dev-js.sh b/dev-js.sh index 93f793d..8f59d5b 100644 --- a/dev-js.sh +++ b/dev-js.sh @@ -5,4 +5,5 @@ esbuild ./frontend/js/main.js \ --outdir=./web/static/js \ --splitting \ --format=esm \ + --loader:.css=css \ --watch=forever diff --git a/frontend/input.css b/frontend/input.css index e49011d..7d4d583 100644 --- a/frontend/input.css +++ b/frontend/input.css @@ -104,7 +104,7 @@ .flatpickr-calendar { /* --- 主题样式 --- */ - @apply bg-background text-foreground rounded-lg shadow-lg border border-border border-zinc-500/30 w-auto font-sans; + @apply bg-background text-foreground rounded-lg shadow-lg border border-zinc-500/30 w-auto font-sans; animation: var(--animation-panel-in); width: 200px; /* --- 核心结构样式 --- */ @@ -168,7 +168,7 @@ .flatpickr-current-month .cur-month { @apply font-semibold; } .flatpickr-current-month .flatpickr-monthDropdown-months { - @apply w-[5.5rem] font-semibold bg-transparent border-0 p-0 text-sm text-foreground text-right; + @apply w-22 font-semibold bg-transparent border-0 p-0 text-sm text-foreground text-right; @apply appearance-none focus:outline-none focus:ring-0; @@ -191,7 +191,7 @@ focus-visible:outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[(var(--ring))] disabled:pointer-events-none disabled:opacity-50 hover:text-accent-foreground - h-7 w-7 flex-shrink-0; + h-7 w-7 shrink-0; position: relative; } .flatpickr-prev-month svg, @@ -213,7 +213,7 @@ box-sizing: border-box; } .flatpickr-day { - @apply w-4 h-6.5 flex items-center justify-center rounded-full border-0 text-foreground transition-colors flex-shrink-0; /* <--- 从 w-9 h-9 缩小 */ + @apply w-4 h-6.5 flex items-center justify-center rounded-full border-0 text-foreground transition-colors shrink-0; /* <--- 从 w-9 h-9 缩小 */ flex-basis: 14.2857%; line-height: 1; cursor: pointer; @@ -363,8 +363,8 @@ @apply w-[1.2rem] text-center; @apply transition-all duration-300 ease-in-out; /* 悬停和激活状态 */ - @apply group-hover:text-[#60a5fa] group-hover:[filter:drop-shadow(0_0_5px_rgba(59,130,246,0.5))]; - @apply group-data-[active='true']:text-[#60a5fa] group-data-[active='true']:[filter:drop-shadow(0_0_5px_rgba(59,130,246,0.7))]; + @apply group-hover:text-[#60a5fa] group-hover:filter-[drop-shadow(0_0_5px_rgba(59,130,246,0.5))]; + @apply group-data-[active='true']:text-[#60a5fa] group-data-[active='true']:filter-[drop-shadow(0_0_5px_rgba(59,130,246,0.7))]; } /* 4. 指示器 */ .nav-indicator { @@ -392,13 +392,13 @@ @apply flex items-start p-3 w-full rounded-lg shadow-lg ring-1 ring-black/5 dark:ring-white/10 bg-white/80 dark:bg-zinc-800/80 backdrop-blur-md pointer-events-auto; } .toast-icon { - @apply flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center text-white mr-3; + @apply shrink-0 w-8 h-8 rounded-full flex items-center justify-center text-white mr-3; } .toast-icon-loading {@apply bg-blue-500;} .toast-icon-success {@apply bg-green-500;} .toast-icon-error {@apply bg-red-500;} .toast-content { - @apply flex-grow; + @apply grow } .toast-title { @apply font-semibold text-sm text-zinc-800 dark:text-zinc-100; @@ -422,7 +422,7 @@ /* --- 任务项主内容区 (左栏) --- */ .task-item-main { - @apply flex items-center justify-between flex-grow gap-1; /* flex-grow 使其占据所有可用空间 */ + @apply flex items-center justify-between grow gap-1; /* flex-grow 使其占据所有可用空间 */ } /* 2. 任务项头部: 包含标题和时间戳 */ .task-item-header { @@ -434,7 +434,7 @@ } .task-item-timestamp { /* 融合了您原有的字体样式 */ - @apply text-xs self-start pt-1.5 pl-2 text-zinc-400 dark:text-zinc-500 flex-shrink-0; + @apply text-xs self-start pt-1.5 pl-2 text-zinc-400 dark:text-zinc-500 shrink-0 } /* 3. [新增] 阶段动画的核心容器 */ @@ -447,13 +447,13 @@ @apply flex items-center gap-2 p-1.5 rounded-md transition-all duration-300 ease-in-out relative; } .task-stage-icon { - @apply w-4 h-4 relative flex-shrink-0 text-zinc-400; + @apply w-4 h-4 relative shrink-0 text-zinc-400; } .task-stage-icon i { @apply absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 opacity-0 transition-opacity duration-200; } .task-stage-content { - @apply flex-grow flex justify-between items-baseline text-xs; + @apply grow justify-between items-baseline text-xs; } .task-stage-name { @apply text-zinc-600 dark:text-zinc-400; @@ -522,7 +522,7 @@ } /* --- 4. 折叠/展开的雪佛兰图标 --- */ .task-toggle-icon { - @apply transition-transform duration-300 ease-in-out text-zinc-400 flex-shrink-0 ml-2; + @apply transition-transform duration-300 ease-in-out text-zinc-400 shrink-0 ml-2; } /* --- 5. 展开状态下的图标旋转 --- */ /* @@ -619,7 +619,7 @@ * 2. 【新增】移动端首屏的 "当前分组" 选择器样式 */ .mobile-group-selector { - @apply flex-grow flex items-center justify-between p-3 border border-zinc-200 dark:border-zinc-700 rounded-lg; + @apply grow flex items-center justify-between p-3 border border-zinc-200 dark:border-zinc-700 rounded-lg; } /* 移动端群组下拉列表样式 */ .mobile-group-menu-active { @@ -770,7 +770,7 @@ /* Tag Input Component */ .tag-input-container { - @apply flex flex-wrap items-center gap-2 mt-1 w-full rounded-md bg-white dark:bg-zinc-700 border border-zinc-300 dark:border-zinc-600 p-2 min-h-[40px] focus-within:border-blue-500 focus-within:ring-1 focus-within:ring-blue-500; + @apply flex flex-wrap items-center gap-2 mt-1 w-full rounded-md bg-white dark:bg-zinc-700 border border-zinc-300 dark:border-zinc-600 p-2 min-h-10 focus-within:border-blue-500 focus-within:ring-1 focus-within:ring-blue-500; } .tag-item { @apply flex items-center gap-x-1.5 bg-blue-100 dark:bg-blue-500/20 text-blue-800 dark:text-blue-200 text-sm font-medium rounded-full px-2.5 py-0.5; @@ -780,7 +780,7 @@ } .tag-input-new { /* 使其在容器内垂直居中,感觉更好 */ - @apply flex-grow bg-transparent focus:outline-none text-sm self-center; + @apply grow bg-transparent focus:outline-none text-sm self-center; } /* 为复制按钮提供基础样式 */ @@ -851,7 +851,7 @@ } /* .tooltip-text is now dynamically generated by JS */ .global-tooltip { - @apply fixed z-[9999] w-max max-w-xs whitespace-normal rounded-lg bg-zinc-800 px-3 py-2 text-sm font-medium text-white shadow-lg transition-opacity duration-200; + @apply fixed z-9999 w-max max-w-xs whitespace-normal rounded-lg bg-zinc-800 px-3 py-2 text-sm font-medium text-white shadow-lg transition-opacity duration-200; } } diff --git a/frontend/js/main.js b/frontend/js/main.js index 42cab31..804761f 100644 --- a/frontend/js/main.js +++ b/frontend/js/main.js @@ -1,5 +1,7 @@ // Filename: frontend/js/main.js - +import Swal from './vendor/sweetalert2.esm.js'; +import './vendor/sweetalert2.min.css'; +import anime from './vendor/anime.esm.js'; // === 1. 导入通用组件 (这些是所有页面都可能用到的,保持静态导入) === import SlidingTabs from './components/slidingTabs.js'; import CustomSelect from './components/customSelect.js'; @@ -48,3 +50,5 @@ window.modalManager = modalManager; window.taskCenterManager = taskCenterManager; window.toastManager = toastManager; window.uiPatterns = uiPatterns; +window.Swal = Swal; +window.anime = anime; \ No newline at end of file diff --git a/frontend/js/pages/keys/apiKeyList.js b/frontend/js/pages/keys/apiKeyList.js index 790e0d5..596ac08 100644 --- a/frontend/js/pages/keys/apiKeyList.js +++ b/frontend/js/pages/keys/apiKeyList.js @@ -427,7 +427,7 @@ class ApiKeyList { contentHtml = `
-
+

验证任务出错: ${maskedKey}

${safeError}

@@ -443,7 +443,7 @@ class ApiKeyList { contentHtml = `
-
+

${title}: ${maskedKey}

${safeMessage}

@@ -455,7 +455,7 @@ class ApiKeyList { contentHtml = `
-
+

正在验证: ${maskedKey}

运行中... (${data.processed}/${data.total})

@@ -495,7 +495,7 @@ class ApiKeyList { data-mapping-id="${mappingId}"> -
+

${maskedKey}

失败: ${errorCount} 次

@@ -854,7 +854,7 @@ class ApiKeyList { contentHtml = `
-
+

批量验证 ${data.total} 个Key

运行中... (${data.processed}/${data.total})

@@ -867,7 +867,7 @@ class ApiKeyList { contentHtml = `
-
+

批量验证任务出错

${data.error}

@@ -893,7 +893,7 @@ class ApiKeyList { return `
-
+

${maskedKey}

${safeMessage}

@@ -902,7 +902,7 @@ class ApiKeyList { return `
-
+

${maskedKey}

${safeMessage}

@@ -913,7 +913,7 @@ class ApiKeyList { contentHtml = `
-
+

${summaryTitle}

@@ -1248,7 +1248,7 @@ class ApiKeyList { contentHtml = `
-
+

${title}

运行中... (${data.processed}/${data.total})

@@ -1258,7 +1258,7 @@ class ApiKeyList { contentHtml = `
-
+

${title}任务出错

${safeError}

@@ -1295,7 +1295,7 @@ class ApiKeyList { contentHtml = `
-
+

${title}

${safeSummary}

diff --git a/frontend/js/pages/logs/index.js b/frontend/js/pages/logs/index.js index d44aa6e..7c882c7 100644 --- a/frontend/js/pages/logs/index.js +++ b/frontend/js/pages/logs/index.js @@ -1,3 +1,4 @@ +// Filename: frontend/js/pages/logs/index.js import { apiFetchJson } from '../../services/api.js'; import LogList from './logList.js'; import CustomSelectV2 from '../../components/customSelectV2.js'; @@ -145,6 +146,7 @@ class LogsPage { switchToView(viewName) { if (this.state.currentView === viewName && this.elements.contentContainer.innerHTML !== '') return; + if (this.systemLogTerminal) { this.systemLogTerminal.disconnect(); this.systemLogTerminal = null; @@ -153,25 +155,22 @@ class LogsPage { this.fp.destroy(); this.fp = null; } - if (this.themeObserver) { this.themeObserver.disconnect(); this.themeObserver = null; } - this.state.currentView = viewName; this.elements.contentContainer.innerHTML = ''; - if (viewName === 'error') { - this.elements.errorFilters.classList.remove('hidden'); - this.elements.systemControls.classList.add('hidden'); + const isErrorView = viewName === 'error'; + this.elements.errorFilters.style.display = isErrorView ? 'flex' : 'none'; + this.elements.systemControls.style.display = isErrorView ? 'none' : 'flex'; + if (isErrorView) { const template = this.elements.errorTemplate.content.cloneNode(true); this.elements.contentContainer.appendChild(template); requestAnimationFrame(() => { this._initErrorLogView(); }); } else if (viewName === 'system') { - this.elements.errorFilters.classList.add('hidden'); - this.elements.systemControls.classList.remove('hidden'); const template = this.elements.systemTemplate.content.cloneNode(true); this.elements.contentContainer.appendChild(template); requestAnimationFrame(() => { @@ -328,7 +327,7 @@ class LogsPage { template.className = 'custom-select-panel-template'; template.innerHTML = ` -