frontend: support more missing dark mode style

This commit is contained in:
2026-01-03 12:58:27 +08:00
parent f46c2a039b
commit a05f7ec322
7 changed files with 307 additions and 39 deletions
+1 -1
View File
@@ -3,7 +3,7 @@ import { theme } from 'ant-design-vue'
/**
* Ant Design Vue 主题配置
* 匹配现有 Material Design 3 色彩系统
* @param {boolean} isDark - 是否为暗模式
* @param {boolean} isDark - 是否为暗模式
*/
export default function getAntdTheme(isDark = false) {
return {
+74
View File
@@ -330,6 +330,12 @@ onBeforeUnmount(() => {
border-radius: 4px;
padding: 16px;
background: #f5f7fa;
transition: all 0.3s;
}
.dark .crontab-editor {
border-color: #3a3a3c;
background: #2c2c2e;
}
.mode-tabs {
@@ -337,6 +343,11 @@ onBeforeUnmount(() => {
gap: 8px;
margin-bottom: 16px;
border-bottom: 2px solid #ebeef5;
transition: border-color 0.3s;
}
.dark .mode-tabs {
border-bottom-color: #3a3a3c;
}
.mode-tab {
@@ -351,11 +362,20 @@ onBeforeUnmount(() => {
transition: all 0.3s;
}
.dark .mode-tab {
color: #a0a0a3;
}
.mode-tab.active {
color: #409eff;
border-bottom-color: #409eff;
}
.dark .mode-tab.active {
color: #81c784;
border-bottom-color: #81c784;
}
.mode-content {
margin: 16px 0;
}
@@ -364,10 +384,20 @@ onBeforeUnmount(() => {
padding: 12px;
background: white;
border-radius: 4px;
transition: background 0.3s;
}
.dark .quick-option {
background: #1c1c1e;
}
.option-label {
font-weight: 600;
color: #1c1b1f;
}
.dark .option-label {
color: #e5e5e7;
}
.option-desc {
@@ -376,6 +406,10 @@ onBeforeUnmount(() => {
font-size: 12px;
}
.dark .option-desc {
color: #a0a0a3;
}
.expression-input {
margin: 12px 0;
}
@@ -386,11 +420,19 @@ onBeforeUnmount(() => {
font-size: 12px;
}
.dark .help-text {
color: #a0a0a3;
}
.help-text a {
color: #409eff;
text-decoration: none;
}
.dark .help-text a {
color: #81c784;
}
.help-text a:hover {
text-decoration: underline;
}
@@ -400,11 +442,21 @@ onBeforeUnmount(() => {
padding: 12px;
background: white;
border-radius: 4px;
transition: background 0.3s;
}
.dark .preview-section {
background: #1c1c1e;
}
.preview-section h4 {
margin: 0 0 8px 0;
font-size: 14px;
color: #1c1b1f;
}
.dark .preview-section h4 {
color: #e5e5e7;
}
.execution-list {
@@ -414,6 +466,10 @@ onBeforeUnmount(() => {
color: #606266;
}
.dark .execution-list {
color: #a0a0a3;
}
.validation-message {
padding: 8px 12px;
border-radius: 4px;
@@ -427,15 +483,33 @@ onBeforeUnmount(() => {
border: 1px solid #c6e2ff;
}
.dark .validation-message.success {
background: rgba(129, 199, 132, 0.1);
color: #81c784;
border-color: rgba(129, 199, 132, 0.3);
}
.validation-message.error {
background: #fef0f0;
color: #f56c6c;
border: 1px solid #fde7e7;
}
.dark .validation-message.error {
background: rgba(244, 67, 54, 0.1);
color: #ef5350;
border-color: rgba(244, 67, 54, 0.3);
}
.validation-message.info {
background: #f4f4f5;
color: #909399;
border: 1px solid #ebeef5;
}
.dark .validation-message.info {
background: #2c2c2e;
color: #a0a0a3;
border-color: #3a3a3c;
}
</style>
+1 -11
View File
@@ -281,15 +281,5 @@ const removeOption = (index) => {
</script>
<style scoped>
.field-config-editor {
background-color: #fafafa;
padding: 20px;
border-radius: 8px;
border: 1px solid #e5e7eb;
}
:deep(.ant-form-item-label) {
font-weight: 500;
color: #374151;
}
/* 样式已移至全局 CSS (style.css) 以保持统一性 */
</style>
+1 -1
View File
@@ -142,7 +142,7 @@
</a-tooltip>
<!-- Theme Toggle Button -->
<a-tooltip :title="isDark ? '切换到亮色模式' : '切换到暗模式'">
<a-tooltip :title="isDark ? '切换到亮色模式' : '切换到暗模式'">
<a-button
type="text"
class="!p-2 !flex !items-center !justify-center hover:!bg-gray-100 dark:hover:!bg-gray-700 transition-all"
+210 -6
View File
@@ -440,7 +440,7 @@
border-color: #3a3a3c;
}
/* Dropdown 暗模式 */
/* Dropdown 暗模式 */
.dark .ant-dropdown-menu {
background: #2c2c2e;
}
@@ -453,7 +453,7 @@
background: #3a3a3c;
}
/* 通用文本颜色 - 暗模式 */
/* 通用文本颜色 - 暗模式 */
.dark p,
.dark span,
.dark div {
@@ -465,7 +465,7 @@
color: #e5e5e7;
}
/* Select dropdown 暗模式 */
/* Select dropdown 暗模式 */
.dark .ant-select-dropdown {
background: #2c2c2e;
}
@@ -483,7 +483,7 @@
color: #81c784;
}
/* Drawer 暗模式 */
/* Drawer 暗模式 */
.dark .ant-drawer-content {
background: #1c1c1e;
}
@@ -606,7 +606,211 @@
color: #606266;
}
/* Material Design 3 卡片 - 暗模式统一样式 */
/* Material Design 3 卡片 - 暗模式统一样式 */
/* 字段树节点组件样式 */
.field-tree-node {
border: 2px solid #e5e7eb;
background: white;
transition: all 0.3s;
}
.dark .field-tree-node {
border-color: #3a3a3c;
background: #1c1c1e;
}
.field-tree-node .border-b {
transition: border-color 0.3s;
}
.dark .field-tree-node .border-b {
border-color: #3a3a3c !important;
}
.field-tree-node button:hover {
background: #f3f4f6;
}
.dark .field-tree-node button:hover {
background: #2c2c2e;
}
.field-tree-node svg.text-gray-600 {
color: #4b5563;
}
.dark .field-tree-node svg.text-gray-600 {
color: #9ca3af;
}
.field-tree-node .text-blue-600 {
color: #2563eb;
}
.dark .field-tree-node .text-blue-600 {
color: #60a5fa;
}
.field-tree-node .text-blue-700 {
color: #1d4ed8;
}
.dark .field-tree-node .text-blue-700 {
color: #93c5fd;
}
.field-tree-node .text-purple-600 {
color: #9333ea;
}
.dark .field-tree-node .text-purple-600 {
color: #c084fc;
}
.field-tree-node .text-purple-700 {
color: #7e22ce;
}
.dark .field-tree-node .text-purple-700 {
color: #d8b4fe;
}
.field-tree-node .text-green-600 {
color: #16a34a;
}
.dark .field-tree-node .text-green-600 {
color: #4ade80;
}
.field-tree-node .text-green-700 {
color: #15803d;
}
.dark .field-tree-node .text-green-700 {
color: #86efac;
}
.field-tree-node .bg-gray-50 {
background: #f9fafb;
}
.dark .field-tree-node .bg-gray-50 {
background: #2c2c2e;
}
.field-tree-node .bg-purple-50 {
background: #faf5ff;
}
.dark .field-tree-node .bg-purple-50 {
background: rgba(147, 51, 234, 0.1);
}
.field-tree-node .bg-green-50 {
background: #f0fdf4;
}
.dark .field-tree-node .bg-green-50 {
background: rgba(34, 197, 94, 0.1);
}
.field-tree-node .border-purple-200 {
border-color: #e9d5ff;
}
.dark .field-tree-node .border-purple-200 {
border-color: rgba(147, 51, 234, 0.3);
}
.field-tree-node .border-purple-300 {
border-color: #d8b4fe;
}
.dark .field-tree-node .border-purple-300 {
border-color: rgba(147, 51, 234, 0.4);
}
.field-tree-node .border-green-200 {
border-color: #bbf7d0;
}
.dark .field-tree-node .border-green-200 {
border-color: rgba(34, 197, 94, 0.3);
}
.field-tree-node .border-green-300 {
border-color: #86efac;
}
.dark .field-tree-node .border-green-300 {
border-color: rgba(34, 197, 94, 0.4);
}
.field-tree-node .text-gray-500 {
color: #6b7280;
}
.dark .field-tree-node .text-gray-500 {
color: #9ca3af;
}
.field-tree-node .bg-white {
background: white;
}
.dark .field-tree-node .bg-white {
background: #1c1c1e;
}
/* 字段配置编辑器样式 */
.field-config-editor {
background-color: #fafafa;
padding: 20px;
border-radius: 8px;
border: 1px solid #e5e7eb;
transition: all 0.3s;
}
.dark .field-config-editor {
background-color: #2c2c2e;
border-color: #3a3a3c;
}
.field-config-editor .text-gray-500 {
color: #6b7280;
}
.dark .field-config-editor .text-gray-500 {
color: #9ca3af;
}
.field-config-editor .text-gray-700 {
color: #374151;
}
.dark .field-config-editor .text-gray-700 {
color: #d1d5db;
}
.field-config-editor .bg-blue-50 {
background: #eff6ff;
}
.dark .field-config-editor .bg-blue-50 {
background: rgba(59, 130, 246, 0.1);
}
.field-config-editor .bg-gray-50 {
background: #f9fafb;
}
.dark .field-config-editor .bg-gray-50 {
background: #1c1c1e;
}
/* Material Design 3 卡片继续 */
.dark .md3-card,
.dark .md3-card-elevated {
background: #1c1c1e;
@@ -614,7 +818,7 @@
color: #e5e5e7;
}
/* Fluent Design 卡片 - 暗模式 */
/* Fluent Design 卡片 - 暗模式 */
.dark .fluent-card {
background: rgba(28, 28, 30, 0.8);
border-color: rgba(58, 58, 60, 0.5);
+19 -19
View File
@@ -7,7 +7,7 @@
<div class="flex items-center justify-between mb-6">
<div>
<h1 class="text-3xl font-bold text-gradient mb-2">任务模板管理</h1>
<p class="text-gray-600">JSON 映射架构 - 配置即结构字段名保持原样</p>
<p class="text-gray-600 dark:text-gray-400">JSON 映射架构 - 配置即结构字段名保持原样</p>
</div>
<button @click="showCreateDialog" class="md3-button-filled">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -29,8 +29,8 @@
<svg class="w-20 h-20 mx-auto text-gray-300 mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
<h3 class="text-xl font-semibold text-gray-700 mb-2">暂无模板</h3>
<p class="text-gray-500 mb-4">创建第一个模板让用户更轻松地创建打卡任务</p>
<h3 class="text-xl font-semibold text-gray-700 dark:text-gray-200 mb-2">暂无模板</h3>
<p class="text-gray-500 dark:text-gray-400 mb-4">创建第一个模板让用户更轻松地创建打卡任务</p>
<button @click="showCreateDialog" class="md3-button-filled">新建模板</button>
</div>
@@ -42,8 +42,8 @@
>
<div class="flex items-start justify-between mb-5">
<div class="flex-1">
<h3 class="text-lg font-semibold text-gray-800 mb-2">{{ template.name }}</h3>
<p class="text-sm text-gray-600 mb-3">{{ template.description || '无描述' }}</p>
<h3 class="text-lg font-semibold text-gray-800 dark:text-gray-100 mb-2">{{ template.name }}</h3>
<p class="text-sm text-gray-600 dark:text-gray-400 mb-3">{{ template.description || '无描述' }}</p>
<span :class="template.is_active ? 'status-success' : 'status-info'">
{{ template.is_active ? '已启用' : '已禁用' }}
</span>
@@ -77,7 +77,7 @@
<div class="grid grid-cols-2 gap-2">
<div></div>
<div class="flex justify-center">
<button @click="deleteTemplate(template)" class="md3-button-text text-sm text-red-600 flex-shrink-0">
<button @click="deleteTemplate(template)" class="md3-button-text text-sm !text-red-600 dark:!text-red-500 flex-shrink-0">
<svg class="w-4 h-4 mr-1.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
</svg>
@@ -156,7 +156,7 @@
<!-- 字段配置编辑器 -->
<div class="field-config-editor">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-bold text-gray-800">字段配置</h3>
<h3 class="text-lg font-bold text-gray-800 dark:text-gray-100">字段配置</h3>
<a-dropdown>
<a-button type="primary">
添加字段
@@ -188,12 +188,12 @@
</div>
<!-- 递归渲染字段树 -->
<div v-if="Object.keys(formData.field_config).length === 0" class="text-center py-12 border-2 border-dashed border-gray-300 rounded-lg bg-gray-50">
<svg class="w-16 h-16 mx-auto text-gray-400 mb-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div v-if="Object.keys(formData.field_config).length === 0" class="text-center py-12 border-2 border-dashed border-gray-300 dark:border-gray-600 rounded-lg bg-gray-50 dark:bg-gray-800/50">
<svg class="w-16 h-16 mx-auto text-gray-400 dark:text-gray-500 mb-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
<h3 class="text-lg font-semibold text-gray-700 mb-2">暂无字段配置</h3>
<p class="text-sm text-gray-500">点击上方"添加字段"开始配置模板</p>
<h3 class="text-lg font-semibold text-gray-700 dark:text-gray-300 mb-2">暂无字段配置</h3>
<p class="text-sm text-gray-500 dark:text-gray-400">点击上方"添加字段"开始配置模板</p>
</div>
<div v-else class="space-y-3">
@@ -215,7 +215,7 @@
<span class="text-lg font-bold">JSON 预览</span>
</a-divider>
<div class="bg-gray-900 text-green-400 p-4 rounded-lg font-mono text-sm overflow-auto max-h-96">
<div class="bg-gray-900 dark:bg-black text-green-400 p-4 rounded-lg font-mono text-sm overflow-auto max-h-96">
<pre>{{ JSON.stringify(formData.field_config, null, 2) }}</pre>
</div>
</a-form>
@@ -242,7 +242,7 @@
placeholder="例如: Id, Group1, DateTarget"
@keyup.enter="confirmAddField"
/>
<span class="text-xs text-gray-500 mt-1 block">
<span class="text-xs text-gray-500 dark:text-gray-400 mt-1 block">
💡 字段名将保持原样不会进行大小写转换
</span>
</a-form-item>
@@ -262,14 +262,14 @@
:style="isMobile ? { top: 0, maxWidth: '100vw' } : {}"
>
<div v-if="previewData" class="space-y-4">
<div class="bg-gray-50 rounded p-4">
<h4 class="font-semibold mb-2">生成的 Payload使用默认值</h4>
<pre class="text-xs bg-white p-3 rounded border overflow-auto max-h-96">{{ JSON.stringify(previewData.preview_payload, null, 2) }}</pre>
<div class="bg-gray-50 dark:bg-gray-800 rounded p-4">
<h4 class="font-semibold mb-2 text-gray-800 dark:text-gray-100">生成的 Payload使用默认值</h4>
<pre class="text-xs bg-white dark:bg-gray-900 text-gray-800 dark:text-gray-200 p-3 rounded border dark:border-gray-700 overflow-auto max-h-96">{{ JSON.stringify(previewData.preview_payload, null, 2) }}</pre>
</div>
<div class="bg-gray-50 rounded p-4">
<h4 class="font-semibold mb-2">字段配置</h4>
<pre class="text-xs bg-white p-3 rounded border overflow-auto max-h-96">{{ JSON.stringify(previewData.field_config, null, 2) }}</pre>
<div class="bg-gray-50 dark:bg-gray-800 rounded p-4">
<h4 class="font-semibold mb-2 text-gray-800 dark:text-gray-100">字段配置</h4>
<pre class="text-xs bg-white dark:bg-gray-900 text-gray-800 dark:text-gray-200 p-3 rounded border dark:border-gray-700 overflow-auto max-h-96">{{ JSON.stringify(previewData.field_config, null, 2) }}</pre>
</div>
</div>
+1 -1
View File
@@ -1,6 +1,6 @@
/** @type {import('tailwindcss').Config} */
export default {
darkMode: 'class', // 启用 class 模式的暗模式
darkMode: 'class', // 启用 class 模式的暗模式
content: [
"./index.html",
"./src/**/*.{vue,js,ts,jsx,tsx}",