优化仪表盘自动刷新UI布局

- 调整Element Plus日期选择器宽度为400px,确保时间完整显示
- 重新设计自动刷新控制的样式和布局
- 统一控制栏所有元素的高度,保持视觉一致性
- 使用更精致的开关组件和优化的交互效果

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
shaw
2025-07-30 15:36:52 +08:00
parent 1ca753c79a
commit 7116a6e043
29 changed files with 3869 additions and 2344 deletions

View File

@@ -1,6 +1,9 @@
<template>
<Teleport to="body">
<Transition name="modal" appear>
<Transition
name="modal"
appear
>
<div
v-if="isVisible"
class="fixed inset-0 modal z-[100] flex items-center justify-center p-4"
@@ -9,29 +12,36 @@
<div class="modal-content w-full max-w-md p-6 mx-auto">
<div class="flex items-start gap-4 mb-6">
<div class="flex-shrink-0 w-12 h-12 bg-gradient-to-br from-amber-500 to-amber-600 rounded-xl flex items-center justify-center">
<i class="fas fa-exclamation-triangle text-white text-lg"></i>
<i class="fas fa-exclamation-triangle text-white text-lg" />
</div>
<div class="flex-1">
<h3 class="text-lg font-semibold text-gray-900 mb-2">{{ title }}</h3>
<div class="text-gray-600 leading-relaxed whitespace-pre-line">{{ message }}</div>
<h3 class="text-lg font-semibold text-gray-900 mb-2">
{{ title }}
</h3>
<div class="text-gray-600 leading-relaxed whitespace-pre-line">
{{ message }}
</div>
</div>
</div>
<div class="flex items-center justify-end gap-3">
<button
@click="handleCancel"
class="btn bg-gray-100 text-gray-700 hover:bg-gray-200 px-6 py-3"
:disabled="isProcessing"
@click="handleCancel"
>
{{ cancelText }}
</button>
<button
@click="handleConfirm"
class="btn btn-warning px-6 py-3"
:class="{ 'opacity-50 cursor-not-allowed': isProcessing }"
:disabled="isProcessing"
@click="handleConfirm"
>
<div v-if="isProcessing" class="loading-spinner mr-2"></div>
<div
v-if="isProcessing"
class="loading-spinner mr-2"
/>
{{ confirmText }}
</button>
</div>

View File

@@ -1,27 +1,34 @@
<template>
<Teleport to="body">
<div v-if="show" class="fixed inset-0 modal z-50 flex items-center justify-center p-4">
<div
v-if="show"
class="fixed inset-0 modal z-50 flex items-center justify-center p-4"
>
<div class="modal-content w-full max-w-md p-6 mx-auto">
<div class="flex items-start gap-4 mb-6">
<div class="w-12 h-12 bg-gradient-to-br from-yellow-400 to-yellow-500 rounded-full flex items-center justify-center flex-shrink-0">
<i class="fas fa-exclamation text-white text-xl"></i>
<i class="fas fa-exclamation text-white text-xl" />
</div>
<div class="flex-1">
<h3 class="text-lg font-bold text-gray-900 mb-2">{{ title }}</h3>
<p class="text-gray-600 text-sm leading-relaxed whitespace-pre-line">{{ message }}</p>
<h3 class="text-lg font-bold text-gray-900 mb-2">
{{ title }}
</h3>
<p class="text-gray-600 text-sm leading-relaxed whitespace-pre-line">
{{ message }}
</p>
</div>
</div>
<div class="flex gap-3">
<button
@click="$emit('cancel')"
class="flex-1 px-4 py-2.5 bg-gray-100 text-gray-700 rounded-xl font-medium hover:bg-gray-200 transition-colors"
@click="$emit('cancel')"
>
{{ cancelText }}
</button>
<button
@click="$emit('confirm')"
class="flex-1 px-4 py-2.5 bg-gradient-to-r from-yellow-500 to-orange-500 text-white rounded-xl font-medium hover:from-yellow-600 hover:to-orange-600 transition-colors shadow-sm"
@click="$emit('confirm')"
>
{{ confirmText }}
</button>

View File

@@ -3,27 +3,45 @@
<!-- Logo区域 -->
<div class="w-12 h-12 bg-gradient-to-br from-blue-500/20 to-purple-500/20 border border-gray-300/30 rounded-xl flex items-center justify-center backdrop-blur-sm flex-shrink-0 overflow-hidden">
<template v-if="!loading">
<img v-if="logoSrc"
:src="logoSrc"
alt="Logo"
class="w-8 h-8 object-contain"
@error="handleLogoError">
<i v-else class="fas fa-cloud text-xl text-gray-700"></i>
<img
v-if="logoSrc"
:src="logoSrc"
alt="Logo"
class="w-8 h-8 object-contain"
@error="handleLogoError"
>
<i
v-else
class="fas fa-cloud text-xl text-gray-700"
/>
</template>
<div v-else class="w-8 h-8 bg-gray-300/50 rounded animate-pulse"></div>
<div
v-else
class="w-8 h-8 bg-gray-300/50 rounded animate-pulse"
/>
</div>
<!-- 标题区域 -->
<div class="flex flex-col justify-center min-h-[48px]">
<div class="flex items-center gap-3">
<template v-if="!loading && title">
<h1 :class="['text-2xl font-bold header-title leading-tight', titleClass]">{{ title }}</h1>
<h1 :class="['text-2xl font-bold header-title leading-tight', titleClass]">
{{ title }}
</h1>
</template>
<div v-else-if="loading" class="h-8 w-64 bg-gray-300/50 rounded animate-pulse"></div>
<div
v-else-if="loading"
class="h-8 w-64 bg-gray-300/50 rounded animate-pulse"
/>
<!-- 插槽用于版本信息等额外内容 -->
<slot name="after-title"></slot>
<slot name="after-title" />
</div>
<p v-if="subtitle" class="text-gray-600 text-sm leading-tight mt-0.5">{{ subtitle }}</p>
<p
v-if="subtitle"
class="text-gray-600 text-sm leading-tight mt-0.5"
>
{{ subtitle }}
</p>
</div>
</div>
</template>

View File

@@ -2,12 +2,21 @@
<div class="stat-card">
<div class="flex items-start justify-between">
<div class="flex-1">
<p class="text-sm font-medium text-gray-600 mb-1">{{ title }}</p>
<p class="text-3xl font-bold text-gray-800">{{ value }}</p>
<p v-if="subtitle" class="text-sm text-gray-500 mt-2">{{ subtitle }}</p>
<p class="text-sm font-medium text-gray-600 mb-1">
{{ title }}
</p>
<p class="text-3xl font-bold text-gray-800">
{{ value }}
</p>
<p
v-if="subtitle"
class="text-sm text-gray-500 mt-2"
>
{{ subtitle }}
</p>
</div>
<div :class="['stat-icon', iconBgClass]">
<i :class="icon"></i>
<i :class="icon" />
</div>
</div>
</div>

View File

@@ -13,24 +13,31 @@
>
<div class="toast-content">
<div class="toast-icon">
<i :class="getIconClass(toast.type)"></i>
<i :class="getIconClass(toast.type)" />
</div>
<div class="toast-body">
<div v-if="toast.title" class="toast-title">{{ toast.title }}</div>
<div class="toast-message">{{ toast.message }}</div>
<div
v-if="toast.title"
class="toast-title"
>
{{ toast.title }}
</div>
<div class="toast-message">
{{ toast.message }}
</div>
</div>
<button
class="toast-close"
@click.stop="removeToast(toast.id)"
>
<i class="fas fa-times"></i>
<i class="fas fa-times" />
</button>
</div>
<div
v-if="toast.duration > 0"
class="toast-progress"
:style="{ animationDuration: `${toast.duration}ms` }"
></div>
/>
</div>
</div>
</Teleport>