界面优化

This commit is contained in:
zzh 2026-01-05 10:27:58 +08:00
parent 9344fb9b6c
commit 2590a76cfd
4 changed files with 1287 additions and 63 deletions

View File

@ -0,0 +1,424 @@
/* Modern Dashboard Enhancements - Glassmorphism Design */
/* Metrics Card Redesign */
.metrics-card {
background: var(--surface);
backdrop-filter: var(--blur);
-webkit-backdrop-filter: var(--blur);
border: 1px solid var(--border);
border-radius: 20px;
padding: 24px;
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
cursor: pointer;
position: relative;
overflow: hidden;
box-shadow: var(--shadow);
height: 180px;
display: flex;
flex-direction: column;
}
.metrics-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2px;
background: linear-gradient(90deg, transparent, var(--primary), transparent);
opacity: 0;
transition: opacity 0.4s ease;
}
.metrics-card:hover {
transform: translateY(-4px) scale(1.02);
box-shadow: var(--shadow-xl);
border-color: var(--primary);
}
.metrics-card:hover::before {
opacity: 1;
}
/* Card Header */
.metrics-card-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 16px;
z-index: 2;
}
.metrics-card-title {
font-size: 15px;
font-weight: 600;
color: var(--text-2);
letter-spacing: 0.3px;
}
.metrics-card-icon {
width: 44px;
height: 44px;
border-radius: 14px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
box-shadow: var(--shadow-sm);
}
.metrics-card:hover .metrics-card-icon {
transform: scale(1.1) rotate(5deg);
box-shadow: var(--shadow);
}
/* Card Value */
.metrics-card-value {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
z-index: 2;
}
.metrics-value-main {
font-size: 36px;
font-weight: 800;
color: var(--text);
letter-spacing: -1.5px;
line-height: 1;
margin-bottom: 8px;
font-family: 'Poppins', sans-serif;
}
.metrics-value-unit {
font-size: 16px;
font-weight: 600;
color: var(--text-4);
margin-left: 8px;
}
/* Card Trend */
.metrics-card-trend {
display: flex;
align-items: center;
gap: 8px;
margin-top: 4px;
}
.trend-value {
font-size: 15px;
font-weight: 700;
display: flex;
align-items: center;
gap: 4px;
}
.trend-value.up {
color: var(--success);
}
.trend-value.down {
color: var(--danger);
}
.trend-label {
font-size: 13px;
color: var(--text-4);
font-weight: 500;
}
/* Background Wave Pattern */
.metrics-card-wave {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 70px;
z-index: 1;
pointer-events: none;
opacity: 0.6;
transition: opacity 0.3s ease;
}
.metrics-card:hover .metrics-card-wave {
opacity: 0.8;
}
/* Chart Container Enhancements */
.chart-container {
background: var(--surface);
backdrop-filter: var(--blur);
-webkit-backdrop-filter: var(--blur);
border: 1px solid var(--border);
border-radius: 20px;
padding: 28px;
box-shadow: var(--shadow);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
overflow: hidden;
}
.chart-container::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 1px;
background: linear-gradient(90deg, transparent, var(--primary-light), transparent);
opacity: 0.3;
}
.chart-container:hover {
box-shadow: var(--shadow-lg);
border-color: var(--primary);
}
.chart-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24px;
}
.chart-title {
font-size: 18px;
font-weight: 600;
color: var(--text);
font-family: 'Poppins', sans-serif;
letter-spacing: -0.3px;
}
.chart-controls {
display: flex;
gap: 8px;
align-items: center;
}
.chart-control-btn {
padding: 8px 16px;
border-radius: 8px;
border: 1px solid var(--border);
background: var(--surface-glass);
color: var(--text-3);
font-size: 13px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s ease;
}
.chart-control-btn:hover {
background: var(--surface-glass-hover);
color: var(--text);
border-color: var(--primary);
}
.chart-control-btn.active {
background: var(--primary);
color: white;
border-color: var(--primary);
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
/* Data Table Enhancements */
.data-table {
width: 100%;
border-collapse: separate;
border-spacing: 0;
font-size: 14px;
}
.data-table thead {
background: var(--surface-glass);
backdrop-filter: var(--blur);
-webkit-backdrop-filter: var(--blur);
}
.data-table th {
padding: 14px 16px;
text-align: left;
font-weight: 600;
color: var(--text-2);
font-size: 13px;
text-transform: uppercase;
letter-spacing: 0.5px;
border-bottom: 2px solid var(--border);
}
.data-table tbody tr {
transition: all 0.2s ease;
border-bottom: 1px solid var(--border-light);
}
.data-table tbody tr:hover {
background: var(--surface-glass-hover);
transform: scale(1.01);
}
.data-table td {
padding: 14px 16px;
color: var(--text);
font-weight: 500;
}
/* Status Indicators */
.status-indicator {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 12px;
border-radius: 8px;
font-size: 12px;
font-weight: 600;
letter-spacing: 0.3px;
}
.status-indicator::before {
content: '';
width: 6px;
height: 6px;
border-radius: 50%;
animation: pulse-dot 2s ease-in-out infinite;
}
.status-indicator.online {
background: var(--success-bg);
color: var(--success);
}
.status-indicator.online::before {
background: var(--success);
}
.status-indicator.offline {
background: var(--danger-bg);
color: var(--danger);
}
.status-indicator.offline::before {
background: var(--danger);
}
.status-indicator.pending {
background: var(--warning-bg);
color: var(--warning);
}
.status-indicator.pending::before {
background: var(--warning);
}
@keyframes pulse-dot {
0%, 100% {
opacity: 1;
transform: scale(1);
}
50% {
opacity: 0.5;
transform: scale(1.2);
}
}
/* Quick Stats Bar */
.quick-stats {
display: flex;
gap: 16px;
padding: 20px;
background: var(--surface);
backdrop-filter: var(--blur);
-webkit-backdrop-filter: var(--blur);
border: 1px solid var(--border);
border-radius: 16px;
margin-bottom: 24px;
box-shadow: var(--shadow-sm);
}
.quick-stat-item {
flex: 1;
display: flex;
flex-direction: column;
gap: 4px;
padding: 12px;
border-right: 1px solid var(--border-light);
}
.quick-stat-item:last-child {
border-right: none;
}
.quick-stat-label {
font-size: 12px;
color: var(--text-3);
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.quick-stat-value {
font-size: 24px;
font-weight: 700;
color: var(--text);
font-family: 'Poppins', sans-serif;
letter-spacing: -0.5px;
}
/* Loading States */
.skeleton {
background: linear-gradient(90deg, var(--surface) 25%, var(--surface-glass-hover) 50%, var(--surface) 75%);
background-size: 200% 100%;
animation: skeleton-loading 1.5s ease-in-out infinite;
border-radius: 8px;
}
@keyframes skeleton-loading {
0% {
background-position: 200% 0;
}
100% {
background-position: -200% 0;
}
}
/* Responsive Adjustments */
@media (max-width: 1024px) {
.metrics-card {
height: 160px;
padding: 20px;
}
.metrics-value-main {
font-size: 32px;
}
.chart-container {
padding: 24px;
}
}
@media (max-width: 640px) {
.metrics-card {
height: 140px;
padding: 16px;
}
.metrics-value-main {
font-size: 28px;
}
.quick-stats {
flex-direction: column;
gap: 12px;
}
.quick-stat-item {
border-right: none;
border-bottom: 1px solid var(--border-light);
padding-bottom: 12px;
}
.quick-stat-item:last-child {
border-bottom: none;
padding-bottom: 0;
}
}

View File

@ -1,16 +1,182 @@
:root{--bg:#0f1216;--surface:#151922;--surface-2:#1b2030;--primary:#4f8cff;--primary-600:#3b71db;--text:#e6e8ee;--text-2:#b3b8c6;--border:#2a3244;--success:#22c55e;--warning:#f59e0b;--danger:#ef4444;--info:#60a5fa;--info-bg:#1e3a5f;--success-bg:#14532d;--warning-bg:#422006} :root {
[data-theme="light"]{--bg:#f5f7fa;--surface:#ffffff;--surface-2:#f8f9fb;--primary:#4f8cff;--primary-600:#3b71db;--text:#1a1d23;--text-2:#6b7280;--border:#e5e7eb;--success:#22c55e;--warning:#f59e0b;--danger:#ef4444;--info:#2196f3;--info-bg:#e3f2fd;--success-bg:#e8f5e9;--warning-bg:#fff3e0} /* Modern Dark Theme - Glassmorphism Inspired */
--bg: #0a0e1a;
--bg-secondary: #0f1419;
--surface: rgba(30, 41, 59, 0.7);
--surface-2: rgba(51, 65, 85, 0.6);
--surface-glass: rgba(255, 255, 255, 0.05);
--surface-glass-hover: rgba(255, 255, 255, 0.08);
/* Primary Colors - Trust Blue */
--primary: #3b82f6;
--primary-600: #2563eb;
--primary-700: #1d4ed8;
--primary-light: #60a5fa;
--primary-lighter: #93c5fd;
/* Accent Colors */
--accent: #f97316;
--accent-light: #fb923c;
/* Text Colors */
--text: #f1f5f9;
--text-2: #cbd5e1;
--text-3: #94a3b8;
--text-4: #64748b;
/* Borders & Dividers */
--border: rgba(148, 163, 184, 0.12);
--border-light: rgba(148, 163, 184, 0.08);
--divider: rgba(148, 163, 184, 0.1);
/* Status Colors */
--success: #10b981;
--success-light: #34d399;
--warning: #f59e0b;
--warning-light: #fbbf24;
--danger: #ef4444;
--danger-light: #f87171;
--info: #60a5fa;
/* Background Overlays */
--info-bg: rgba(59, 130, 246, 0.1);
--success-bg: rgba(16, 185, 129, 0.1);
--warning-bg: rgba(245, 158, 11, 0.1);
--danger-bg: rgba(239, 68, 68, 0.1);
/* Chart Colors */
--chart-blue: #3b82f6;
--chart-green: #10b981;
--chart-orange: #f97316;
--chart-red: #ef4444;
--chart-purple: #a855f7;
--chart-cyan: #06b6d4;
/* Shadows */
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.3);
--shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 2px 4px -1px rgba(0, 0, 0, 0.3);
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.5), 0 4px 6px -2px rgba(0, 0, 0, 0.4);
--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.6), 0 10px 10px -5px rgba(0, 0, 0, 0.4);
/* Backdrop Blur */
--blur: blur(12px);
--blur-lg: blur(20px);
}
[data-theme="light"] {
/* Modern Light Theme - Clean & Professional */
--bg: #f8fafc;
--bg-secondary: #f1f5f9;
--surface: rgba(255, 255, 255, 0.9);
--surface-2: rgba(248, 250, 252, 0.9);
--surface-glass: rgba(255, 255, 255, 0.7);
--surface-glass-hover: rgba(255, 255, 255, 0.85);
/* Primary Colors */
--primary: #2563eb;
--primary-600: #1d4ed8;
--primary-700: #1e40af;
--primary-light: #3b82f6;
--primary-lighter: #60a5fa;
/* Accent Colors */
--accent: #f97316;
--accent-light: #fb923c;
/* Text Colors */
--text: #0f172a;
--text-2: #475569;
--text-3: #64748b;
--text-4: #94a3b8;
/* Borders & Dividers */
--border: rgba(226, 232, 240, 0.8);
--border-light: rgba(226, 232, 240, 0.5);
--divider: rgba(226, 232, 240, 0.6);
/* Status Colors */
--success: #10b981;
--success-light: #34d399;
--warning: #f59e0b;
--warning-light: #fbbf24;
--danger: #ef4444;
--danger-light: #f87171;
--info: #3b82f6;
/* Background Overlays */
--info-bg: rgba(59, 130, 246, 0.08);
--success-bg: rgba(16, 185, 129, 0.08);
--warning-bg: rgba(245, 158, 11, 0.08);
--danger-bg: rgba(239, 68, 68, 0.08);
/* Chart Colors */
--chart-blue: #3b82f6;
--chart-green: #10b981;
--chart-orange: #f97316;
--chart-red: #ef4444;
--chart-purple: #a855f7;
--chart-cyan: #06b6d4;
/* Shadows */
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
/* Backdrop Blur */
--blur: blur(12px);
--blur-lg: blur(20px);
}
*{box-sizing:border-box} *{box-sizing:border-box}
html,body{height:100%;overflow:hidden} html,body{height:100%;overflow:hidden}
body{margin:0;background:var(--bg);color:var(--text);font-family:Inter,system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,"Noto Sans",sans-serif;line-height:1.5} body {
margin: 0;
background: var(--bg);
color: var(--text);
font-family: 'Open Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
line-height: 1.6;
font-weight: 400;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-size: 14px;
}
/* Typography - Poppins for headings */
h1, h2, h3, h4, h5, h6, .heading {
font-family: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
font-weight: 600;
line-height: 1.3;
letter-spacing: -0.02em;
}
#app{display:flex;height:100vh;overflow:hidden} #app{display:flex;height:100vh;overflow:hidden}
.sidebar{position:relative;width:240px;min-width:240px;background:linear-gradient(180deg,var(--surface),var(--surface-2));border-right:1px solid var(--border);display:flex;flex-direction:column;height:100vh;overflow:visible;transition:width 0.3s ease,min-width 0.3s ease} .sidebar {
.sidebar.collapsed{width:60px;min-width:60px} position: relative;
.brand-container{position:relative;display:flex;align-items:center;justify-content:space-between;padding:12px 16px;gap:8px} width: 260px;
.loader-wrapper{position:relative;display:flex;align-items:center;gap:10px;height:40px;width:auto;user-select:none;flex:1;min-width:0} min-width: 260px;
background: var(--surface);
backdrop-filter: var(--blur);
-webkit-backdrop-filter: var(--blur);
border-right: 1px solid var(--border);
display: flex;
flex-direction: column;
height: 100vh;
overflow: visible;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: var(--shadow);
}
.sidebar.collapsed {
width: 72px;
min-width: 72px;
}
.brand-container{position:relative;display:flex;align-items:center;justify-content:space-between;padding:12px 16px;gap:8px;animation:fadeIn 0.5s ease-in-out}
.loader-wrapper{position:relative;display:flex;align-items:center;gap:10px;height:40px;width:auto;user-select:none;flex:1;min-width:0;animation:slideUp 0.5s ease-in-out}
.brand-logo{width:32px;height:32px;display:flex;align-items:center;justify-content:center;background:linear-gradient(135deg,var(--primary) 0%,var(--primary-600) 100%);border-radius:8px;flex-shrink:0;box-shadow:0 2px 8px rgba(79,140,255,0.3)} .brand-logo{width:32px;height:32px;display:flex;align-items:center;justify-content:center;background:linear-gradient(135deg,var(--primary) 0%,var(--primary-600) 100%);border-radius:8px;flex-shrink:0;box-shadow:0 2px 8px rgba(79,140,255,0.3)}
.brand-logo svg{width:18px;height:18px;color:#fff} .brand-logo svg{width:18px;height:18px;color:#fff}
.brand-logo.dollar-spinner{border-top:2px solid #eab308;background:#fde047;animation:spin 1s linear infinite;border-radius:50%;color:#a16207;font-weight:700;font-size:16px} .brand-logo.dollar-spinner{border-top:2px solid #eab308;background:#fde047;animation:spin 1s linear infinite;border-radius:50%;color:#a16207;font-weight:700;font-size:16px}
@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}
@keyframes slideUp{0%{opacity:0;transform:translateY(20px)}100%{opacity:1;transform:translateY(0)}}
@keyframes slideInRight{0%{opacity:0;transform:translateX(20px)}100%{opacity:1;transform:translateX(0)}}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:0.5}}
@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}} @keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}
.coin-wrapper{width:32px;height:32px;perspective:500px;flex-shrink:0} .coin-wrapper{width:32px;height:32px;perspective:500px;flex-shrink:0}
.coin{width:32px;height:32px;position:relative;animation:rotate_coin 7s infinite linear;transform-style:preserve-3d} .coin{width:32px;height:32px;position:relative;animation:rotate_coin 7s infinite linear;transform-style:preserve-3d}
@ -51,9 +217,46 @@ body{margin:0;background:var(--bg);color:var(--text);font-family:Inter,system-ui
.nav{flex:1;overflow-y:auto;overflow-x:hidden;padding:8px 8px 16px;min-height:0} .nav{flex:1;overflow-y:auto;overflow-x:hidden;padding:8px 8px 16px;min-height:0}
.nav-group{margin:8px 0} .nav-group{margin:8px 0}
.nav-group-title{padding:8px 12px;color:var(--text-2);font-size:12px;letter-spacing:.04em;text-transform:uppercase} .nav-group-title{padding:8px 12px;color:var(--text-2);font-size:12px;letter-spacing:.04em;text-transform:uppercase}
.nav-item{display:flex;align-items:center;gap:10px;padding:10px 12px;margin:4px;border-radius:8px;color:var(--text);text-decoration:none;font-size:14px} .nav-item {
.nav-item:hover{background:rgba(79,140,255,.12)} display: flex;
.nav-item.active{background:rgba(79,140,255,.18);outline:1px solid rgba(79,140,255,.4)} align-items: center;
gap: 12px;
padding: 12px 16px;
margin: 4px 8px;
border-radius: 12px;
color: var(--text);
text-decoration: none;
font-size: 14px;
font-weight: 500;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
cursor: pointer;
position: relative;
}
.nav-item:hover {
background: var(--surface-glass-hover);
color: var(--primary-light);
transform: translateX(4px);
}
.nav-item.active {
background: var(--info-bg);
color: var(--primary-light);
border: 1px solid var(--primary);
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
.nav-item.active::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 3px;
height: 60%;
background: var(--primary);
border-radius: 0 2px 2px 0;
}
.nav-item .icon{width:20px;text-align:center} .nav-item .icon{width:20px;text-align:center}
.nav-item.has-children{flex-direction:column;gap:0;padding:0;background:transparent} .nav-item.has-children{flex-direction:column;gap:0;padding:0;background:transparent}
.nav-item-btn{width:100%;display:flex;align-items:center;gap:10px;padding:10px 12px;margin:4px;border-radius:8px;background:transparent;border:0;color:var(--text);cursor:pointer;font-size:14px;font-family:inherit} .nav-item-btn{width:100%;display:flex;align-items:center;gap:10px;padding:10px 12px;margin:4px;border-radius:8px;background:transparent;border:0;color:var(--text);cursor:pointer;font-size:14px;font-family:inherit}
@ -69,27 +272,229 @@ body{margin:0;background:var(--bg);color:var(--text);font-family:Inter,system-ui
.theme-toggle-container{padding:16px;border-top:1px solid var(--border);margin-top:auto;display:flex;justify-content:center} .theme-toggle-container{padding:16px;border-top:1px solid var(--border);margin-top:auto;display:flex;justify-content:center}
.btn{border:0;border-radius:8px;padding:8px 12px;font-weight:600;cursor:pointer;background:var(--primary);color:#ffffff} .btn {
.btn:hover{background:var(--primary-600)} border: 0;
border-radius: 10px;
padding: 12px 24px;
font-weight: 600;
cursor: pointer;
background: linear-gradient(135deg, var(--primary) 0%, var(--primary-600) 100%);
color: #ffffff;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
font-size: 14px;
letter-spacing: 0.3px;
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);
position: relative;
overflow: hidden;
}
.btn::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
transition: left 0.5s ease;
}
.btn:hover {
background: linear-gradient(135deg, var(--primary-light) 0%, var(--primary) 100%);
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(59, 130, 246, 0.4);
}
.btn:hover::before {
left: 100%;
}
.btn:active {
transform: translateY(0);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);
}
.btn-secondary{background:#253045;color:var(--text)} .btn-secondary{background:#253045;color:var(--text)}
.btn-secondary:hover{background:#2b3750} .btn-secondary:hover{background:#2b3750}
[data-theme="light"] .btn-secondary{background:#e5e7eb;color:var(--text)} [data-theme="light"] .btn-secondary{background:#e5e7eb;color:var(--text)}
[data-theme="light"] .btn-secondary:hover{background:#d1d5db} [data-theme="light"] .btn-secondary:hover{background:#d1d5db}
.content{flex:1;min-width:0;display:flex;flex-direction:column;height:100vh;overflow:hidden;background:var(--bg)} .content{flex:1;min-width:0;display:flex;flex-direction:column;height:100vh;overflow:hidden;background:var(--bg)}
.content-header{display:flex;align-items:center;justify-content:space-between;padding:14px 20px;border-bottom:1px solid var(--border);background:var(--bg) !important;flex-shrink:0;position:relative;z-index:10} .content-header {
[data-theme="light"] .content-header{background:#f5f7fa !important} display: flex;
#breadcrumb{color:var(--text-2)} align-items: center;
justify-content: space-between;
padding: 20px 32px;
border-bottom: 1px solid var(--border);
background: var(--surface);
backdrop-filter: var(--blur);
-webkit-backdrop-filter: var(--blur);
flex-shrink: 0;
position: sticky;
top: 0;
z-index: 100;
box-shadow: var(--shadow-sm);
}
[data-theme="light"] .content-header {
background: var(--surface);
}
#breadcrumb {
color: var(--text-2);
font-size: 14px;
font-weight: 500;
display: flex;
align-items: center;
gap: 8px;
}
#actions{position:relative;z-index:999;display:flex;align-items:center;gap:8px} #actions{position:relative;z-index:999;display:flex;align-items:center;gap:8px}
.view{position:relative;padding:20px;flex:1;overflow-y:auto;overflow-x:hidden;background:var(--bg);min-height:0} .view {
.card{background:var(--surface-2);border:1px solid var(--border);border-radius:12px;padding:16px} position: relative;
.grid{display:grid;gap:12px} padding: 32px;
.grid.cols-2{grid-template-columns:repeat(2,minmax(0,1fr))} flex: 1;
.grid.cols-3{grid-template-columns:repeat(3,minmax(0,1fr))} overflow-y: auto;
.field{display:flex;flex-direction:column;gap:6px;margin-bottom:12px} overflow-x: hidden;
.field label{color:var(--text-2);font-size:13px} background: var(--bg);
.input,select{background:#0c0f14;color:var(--text);border:1px solid var(--border);border-radius:8px;padding:10px} min-height: 0;
.input:focus,select:focus{outline:1px solid var(--primary)} }
[data-theme="light"] .input,[data-theme="light"] select{background:#ffffff;color:var(--text)}
@media (max-width: 1024px) {
.view {
padding: 24px;
}
}
@media (max-width: 640px) {
.view {
padding: 16px;
}
}
.card {
background: var(--surface);
backdrop-filter: var(--blur);
-webkit-backdrop-filter: var(--blur);
border: 1px solid var(--border);
border-radius: 16px;
padding: 24px;
box-shadow: var(--shadow);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
overflow: hidden;
}
.card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 1px;
background: linear-gradient(90deg, transparent, var(--primary-light), transparent);
opacity: 0;
transition: opacity 0.3s ease;
}
.card:hover {
box-shadow: var(--shadow-lg);
transform: translateY(-2px);
border-color: var(--primary);
}
.card:hover::before {
opacity: 0.5;
}
[data-theme="light"] .card {
background: var(--surface);
box-shadow: var(--shadow);
}
[data-theme="light"] .card:hover {
box-shadow: var(--shadow-lg);
}
.grid {
display: grid;
gap: 20px;
}
.grid.cols-2 {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.grid.cols-3 {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.grid.cols-4 {
grid-template-columns: repeat(4, minmax(0, 1fr));
}
@media (max-width: 1280px) {
.grid.cols-4 {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
}
@media (max-width: 1024px) {
.grid.cols-3, .grid.cols-4 {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.grid {
gap: 16px;
}
}
@media (max-width: 640px) {
.grid.cols-2, .grid.cols-3, .grid.cols-4 {
grid-template-columns: 1fr;
}
.grid {
gap: 12px;
}
}
.field {
display: flex;
flex-direction: column;
gap: 8px;
margin-bottom: 16px;
}
.field label {
color: var(--text-2);
font-size: 13px;
font-weight: 600;
letter-spacing: 0.3px;
text-transform: uppercase;
}
.input, select {
background: var(--surface);
backdrop-filter: var(--blur);
-webkit-backdrop-filter: var(--blur);
color: var(--text);
border: 1px solid var(--border);
border-radius: 10px;
padding: 12px 16px;
font-size: 14px;
font-weight: 500;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: var(--shadow-sm);
}
.input:focus, select:focus {
outline: none;
border-color: var(--primary);
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1), var(--shadow);
background: var(--surface-glass-hover);
}
.input::placeholder {
color: var(--text-4);
font-weight: 400;
}
[data-theme="light"] .input,
[data-theme="light"] select {
background: var(--surface);
color: var(--text);
}
/* Input with prefix icon */ /* Input with prefix icon */
.input-wrapper{position:relative;display:flex;align-items:center} .input-wrapper{position:relative;display:flex;align-items:center}
.input-wrapper .input-prefix{position:absolute;left:12px;color:var(--text-2);font-size:16px;pointer-events:none;display:flex;align-items:center} .input-wrapper .input-prefix{position:absolute;left:12px;color:var(--text-2);font-size:16px;pointer-events:none;display:flex;align-items:center}
@ -141,16 +546,64 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover{
.row{display:flex;gap:12px;flex-wrap:wrap} .row{display:flex;gap:12px;flex-wrap:wrap}
.row .col{flex:1;min-width:240px} .row .col{flex:1;min-width:240px}
.actions{display:flex;gap:8px} .actions{display:flex;gap:8px}
.badge{display:inline-flex;align-items:center;gap:6px;border-radius:999px;padding:4px 10px;font-size:12px;background:#1f2535;color:var(--text-2)} .badge {
.badge.success{background:rgba(34,197,94,.15);color:#8be59f} display: inline-flex;
.badge.warning{background:rgba(245,158,11,.15);color:#f8cf88} align-items: center;
.badge.danger{background:rgba(239,68,68,.15);color:#f4a3a3} gap: 6px;
[data-theme="light"] .badge{background:#e5e7eb;color:#374151} border-radius: 8px;
[data-theme="light"] .badge.success{background:rgba(34,197,94,.15);color:#16a34a} padding: 6px 12px;
[data-theme="light"] .badge.warning{background:rgba(245,158,11,.15);color:#d97706} font-size: 12px;
[data-theme="light"] .badge.danger{background:rgba(239,68,68,.15);color:#dc2626} font-weight: 600;
background: var(--surface-glass);
color: var(--text-3);
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
letter-spacing: 0.3px;
border: 1px solid var(--border-light);
backdrop-filter: var(--blur);
-webkit-backdrop-filter: var(--blur);
}
.badge.success {
background: var(--success-bg);
color: var(--success-light);
border-color: var(--success);
}
.badge.warning {
background: var(--warning-bg);
color: var(--warning-light);
border-color: var(--warning);
}
.badge.danger {
background: var(--danger-bg);
color: var(--danger-light);
border-color: var(--danger);
}
[data-theme="light"] .badge {
background: var(--surface-glass);
color: var(--text-3);
}
[data-theme="light"] .badge.success {
background: var(--success-bg);
color: var(--success);
}
[data-theme="light"] .badge.warning {
background: var(--warning-bg);
color: var(--warning);
}
[data-theme="light"] .badge.danger {
background: var(--danger-bg);
color: var(--danger);
}
.list{list-style:none;padding:0;margin:0} .list{list-style:none;padding:0;margin:0}
.list li{display:flex;justify-content:space-between;padding:8px 10px;border-bottom:1px dashed var(--border)} .list li{display:flex;justify-content:space-between;padding:11px 14px;border-bottom:1px solid var(--border);transition:all 0.2s ease;border-radius:4px;margin-bottom:2px}
.list li:hover{background:rgba(59,130,246,0.06);border-left:2px solid var(--primary);padding-left:12px}
.list li:last-child{border-bottom:none;margin-bottom:0}
.list::-webkit-scrollbar,.nav::-webkit-scrollbar,.view::-webkit-scrollbar{width:8px;height:8px} .list::-webkit-scrollbar,.nav::-webkit-scrollbar,.view::-webkit-scrollbar{width:8px;height:8px}
.list::-webkit-scrollbar-track,.nav::-webkit-scrollbar-track,.view::-webkit-scrollbar-track{background:transparent} .list::-webkit-scrollbar-track,.nav::-webkit-scrollbar-track,.view::-webkit-scrollbar-track{background:transparent}
.list::-webkit-scrollbar-thumb,.nav::-webkit-scrollbar-thumb,.view::-webkit-scrollbar-thumb{background:rgba(255,255,255,.1);border-radius:4px} .list::-webkit-scrollbar-thumb,.nav::-webkit-scrollbar-thumb,.view::-webkit-scrollbar-thumb{background:rgba(255,255,255,.1);border-radius:4px}
@ -357,28 +810,29 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover{
align-items: center; align-items: center;
justify-content: center; justify-content: center;
gap: 6px; gap: 6px;
padding: 8px 16px; padding: 9px 16px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); background: linear-gradient(135deg, var(--primary) 0%, var(--primary-600) 100%);
color: white !important; color: white !important;
border: none; border: none;
border-radius: 8px; border-radius: 8px;
font-size: 13px; font-size: 13px;
font-weight: 600; font-weight: 600;
cursor: pointer; cursor: pointer;
transition: all 0.3s ease; transition: all 0.2s ease;
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3); box-shadow: 0 2px 6px rgba(59, 130, 246, 0.3);
white-space: nowrap; white-space: nowrap;
letter-spacing: 0.3px;
} }
.btn-summary:hover { .btn-summary:hover {
transform: translateY(-2px); transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4); box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4);
background: linear-gradient(135deg, #5a6fd8 0%, #6a4190 100%); background: linear-gradient(135deg, var(--primary-light) 0%, var(--primary) 100%);
} }
.btn-summary:active { .btn-summary:active {
transform: translateY(0); transform: translateY(0);
box-shadow: 0 2px 6px rgba(102, 126, 234, 0.3); box-shadow: 0 2px 4px rgba(59, 130, 246, 0.25);
} }
.btn-summary svg { .btn-summary svg {
@ -948,21 +1402,325 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover{
.dashboard-metrics-4col { .dashboard-metrics-4col {
display: grid; display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr)); grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 8px; gap: 12px;
margin-bottom: 0;
}
/* Modern metrics card redesign */
.metrics-card {
position: relative;
overflow: hidden;
background: var(--surface);
border-radius: 12px;
border: 1px solid var(--border);
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
cursor: pointer;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06), 0 1px 3px rgba(0, 0, 0, 0.1);
}
.metrics-card:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.15), 0 2px 6px rgba(0, 0, 0, 0.1);
border-color: var(--primary-light);
}
[data-theme="light"] .metrics-card {
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04), 0 1px 3px rgba(0, 0, 0, 0.06);
background: #ffffff;
}
[data-theme="light"] .metrics-card:hover {
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.12), 0 2px 6px rgba(0, 0, 0, 0.08);
}
/* Modern card styling */
.modern-card {
background: var(--surface);
border-radius: 12px;
border: 1px solid var(--border);
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06), 0 1px 3px rgba(0, 0, 0, 0.1);
}
.modern-card:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}
[data-theme="light"] .modern-card {
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}
[data-theme="light"] .modern-card:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
}
/* Dashboard container improvements */
.dashboard-container {
display: flex;
flex-direction: column;
height: 100%;
overflow: hidden;
gap: 12px;
}
/* 现代化图表工具提示 */
#chart-tooltip {
position: absolute;
background: linear-gradient(135deg, rgba(59, 130, 246, 0.95) 0%, rgba(37, 99, 235, 0.95) 100%);
color: #ffffff;
padding: 10px 14px;
border-radius: 10px;
font-size: 12px;
pointer-events: none;
display: none;
white-space: nowrap;
box-shadow: 0 8px 24px rgba(59, 130, 246, 0.4), 0 4px 12px rgba(0, 0, 0, 0.3);
border: 1px solid rgba(255, 255, 255, 0.2);
z-index: 1000;
backdrop-filter: blur(10px);
font-weight: 500;
letter-spacing: 0.3px;
}
#chart-tooltip::before {
content: '';
position: absolute;
top: -4px;
left: -4px;
right: -4px;
bottom: -4px;
background: linear-gradient(135deg, rgba(96, 165, 250, 0.3), rgba(59, 130, 246, 0.3));
border-radius: 12px;
z-index: -1;
filter: blur(8px);
}
[data-theme="light"] #chart-tooltip {
background: linear-gradient(135deg, rgba(59, 130, 246, 0.98) 0%, rgba(37, 99, 235, 0.98) 100%);
box-shadow: 0 8px 24px rgba(59, 130, 246, 0.35), 0 4px 12px rgba(0, 0, 0, 0.15);
}
/* 环形图工具提示 */
#donut-tooltip,
#shipment-donut-tooltip {
position: absolute;
background: linear-gradient(135deg, rgba(30, 41, 59, 0.98) 0%, rgba(15, 23, 42, 0.98) 100%);
color: #fff;
padding: 10px 14px;
border-radius: 10px;
font-size: 12px;
pointer-events: none;
display: none;
white-space: nowrap;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4), 0 4px 12px rgba(59, 130, 246, 0.2);
border: 1px solid rgba(255, 255, 255, 0.15);
z-index: 1000;
backdrop-filter: blur(12px);
font-weight: 500;
}
[data-theme="light"] #donut-tooltip,
[data-theme="light"] #shipment-donut-tooltip {
background: linear-gradient(135deg, rgba(255, 255, 255, 0.98) 0%, rgba(248, 250, 252, 0.98) 100%);
color: #1e293b;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15), 0 4px 12px rgba(59, 130, 246, 0.1);
border: 1px solid rgba(59, 130, 246, 0.2);
}
/* Trend chart card enhancements */
.trend-chart-card {
background: var(--surface);
border-radius: 12px;
border: 1px solid var(--border);
overflow: hidden;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06), 0 1px 3px rgba(0, 0, 0, 0.1);
transition: all 0.2s ease;
}
[data-theme="light"] .trend-chart-card {
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04), 0 1px 3px rgba(0, 0, 0, 0.06);
background: #ffffff;
}
/* Chart statistics bar */
.chart-stats-bar {
display: grid;
grid-template-columns: repeat(4, 1fr);
border-top: 1px solid var(--border);
background: var(--surface);
}
.chart-stat-item {
padding: 14px 16px;
text-align: center;
border-right: 1px solid var(--border);
transition: all 0.2s ease;
position: relative;
}
.chart-stat-item:last-child {
border-right: none;
}
.chart-stat-item:hover {
background: rgba(59, 130, 246, 0.06);
}
.chart-stat-item::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2px;
background: var(--primary);
transform: scaleX(0);
transition: transform 0.2s ease;
}
.chart-stat-item:hover::before {
transform: scaleX(1);
}
.chart-stat-label {
font-size: 11px;
color: var(--text-3);
text-transform: uppercase;
letter-spacing: 0.8px;
margin-bottom: 6px;
font-weight: 600;
}
.chart-stat-value {
font-size: 20px;
font-weight: 700;
line-height: 1.2;
color: var(--text);
}
/* Donut chart improvements */
.donut-chart-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
position: relative;
min-width: 0;
}
.donut-chart-title {
font-size: 12px;
color: var(--text-2);
margin-bottom: 12px;
font-weight: 500;
}
.donut-legend {
display: flex;
justify-content: center;
gap: 20px;
margin-top: 12px;
flex-wrap: wrap;
}
.donut-legend-item {
text-align: center;
}
.donut-legend-value {
font-size: 20px;
font-weight: 700;
line-height: 1.2;
}
.donut-legend-label {
display: flex;
align-items: center;
gap: 6px;
font-size: 11px;
color: var(--text-2);
margin-top: 4px;
justify-content: center;
}
.donut-legend-dot {
width: 8px;
height: 8px;
border-radius: 50%;
flex-shrink: 0;
}
/* Audit board card */
.audit-board-card {
background: var(--surface);
border-radius: 12px;
border: 1px solid var(--border);
display: flex;
flex-direction: column;
min-height: 0;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06), 0 1px 3px rgba(0, 0, 0, 0.1);
transition: all 0.2s ease;
}
.audit-board-card:hover {
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.1), 0 2px 6px rgba(0, 0, 0, 0.08);
}
[data-theme="light"] .audit-board-card {
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04), 0 1px 3px rgba(0, 0, 0, 0.06);
background: #ffffff;
}
[data-theme="light"] .audit-board-card:hover {
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.08), 0 2px 6px rgba(0, 0, 0, 0.06);
}
/* Trend tabs styling */
.trend-tab {
padding: 6px 12px;
border-radius: 6px;
cursor: pointer;
transition: all 0.2s ease;
font-size: 12px;
font-weight: 600;
color: var(--text-3);
letter-spacing: 0.3px;
}
.trend-tab:hover {
background: rgba(59, 130, 246, 0.12);
color: var(--text-2);
}
.trend-tab.active {
background: var(--primary);
color: #ffffff;
box-shadow: 0 2px 4px rgba(59, 130, 246, 0.3);
} }
@media(max-width: 768px) { @media(max-width: 768px) {
.dashboard-metrics-4col { .dashboard-metrics-4col {
gap: 6px; gap: 8px;
}
.dashboard-container {
gap: 12px;
} }
.dashboard-metrics-4col .card { .dashboard-metrics-4col .card {
padding: 8px !important; padding: 12px !important;
} }
.dashboard-metrics-4col .badge { .chart-stats-bar {
font-size: 14px !important; grid-template-columns: repeat(2, 1fr);
padding: 4px 8px !important; }
.chart-stat-item:nth-child(2) {
border-right: none;
}
.chart-stat-item:nth-child(3) {
border-top: 1px solid var(--border);
} }
} }

View File

@ -5,11 +5,12 @@
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<title>韬智生产管理系统</title> <title>韬智生产管理系统</title>
<link rel="icon" type="image/svg+xml" href="./assets/favicon.svg" /> <link rel="icon" type="image/svg+xml" href="./assets/favicon.svg" />
<!-- 暂时注释掉Google Fonts以提高加载速度 --> <!-- Modern Professional Typography -->
<!-- <link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Poppins:wght@600&display=swap" rel="stylesheet" /> --> <link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;500;600;700&family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="./assets/styles.css?v=20251122" /> <link rel="stylesheet" href="./assets/styles.css?v=20251122" />
<link rel="stylesheet" href="./assets/dashboard-enhancements.css" />
<link rel="stylesheet" href="./assets/mod.css" /> <link rel="stylesheet" href="./assets/mod.css" />
</head> </head>
<body> <body>
@ -224,7 +225,8 @@
</div> </div>
<div class="sidebar-actions"> <div class="sidebar-actions">
<label class="switch"> <!-- 主题切换按钮已隐藏 -->
<label class="switch" style="display: none;">
<input id="theme-toggle-checkbox" type="checkbox" /> <input id="theme-toggle-checkbox" type="checkbox" />
<span class="slider"> <span class="slider">
<div class="star star_1"></div> <div class="star star_1"></div>

View File

@ -659,9 +659,11 @@ const Dashboard = (() => {
ctx.fillStyle = colors.bg; ctx.fillStyle = colors.bg;
ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillRect(0, 0, canvas.width, canvas.height);
// 绘制网格线 // 绘制网格线(增强版 - 虚线样式)
ctx.strokeStyle = colors.grid; ctx.strokeStyle = colors.grid;
ctx.lineWidth = 1; ctx.lineWidth = 1;
ctx.globalAlpha = 0.5;
ctx.setLineDash([4, 4]);
for(let i = 0; i <= 4; i++){ for(let i = 0; i <= 4; i++){
const y = padding.top + (chartHeight / 4) * i; const y = padding.top + (chartHeight / 4) * i;
ctx.beginPath(); ctx.beginPath();
@ -669,6 +671,8 @@ const Dashboard = (() => {
ctx.lineTo(rect.width - padding.right, y); ctx.lineTo(rect.width - padding.right, y);
ctx.stroke(); ctx.stroke();
} }
ctx.setLineDash([]);
ctx.globalAlpha = 1;
// 绘制Y轴刻度大数值格式化显示 // 绘制Y轴刻度大数值格式化显示
const formatNumber = (n) => { const formatNumber = (n) => {
@ -706,20 +710,23 @@ const Dashboard = (() => {
// 绘制带填充区域的曲线(参考图样式) // 绘制带填充区域的曲线(参考图样式)
const today = new Date().toISOString().split('T')[0]; const today = new Date().toISOString().split('T')[0];
// 创建线条渐变 // 创建线条渐变(增强版 - Aurora UI 风格)
const createLineGradient = (gradientColors) => { const createLineGradient = (gradientColors) => {
const gradient = ctx.createLinearGradient(padding.left, 0, rect.width - padding.right, 0); const gradient = ctx.createLinearGradient(padding.left, 0, rect.width - padding.right, 0);
gradient.addColorStop(0, gradientColors[0]); gradient.addColorStop(0, gradientColors[0]);
gradient.addColorStop(0.5, gradientColors[1]); gradient.addColorStop(0.3, gradientColors[1]);
gradient.addColorStop(1, gradientColors[2] || gradientColors[1]); gradient.addColorStop(0.5, gradientColors[2] || gradientColors[1]);
gradient.addColorStop(0.7, gradientColors[1]);
gradient.addColorStop(1, gradientColors[0]);
return gradient; return gradient;
}; };
// 创建填充区域渐变(从上到下 // 创建填充区域渐变(从上到下 - 增强版
const createFillGradient = (fillColors) => { const createFillGradient = (fillColors) => {
const gradient = ctx.createLinearGradient(0, padding.top, 0, padding.top + chartHeight); const gradient = ctx.createLinearGradient(0, padding.top, 0, padding.top + chartHeight);
gradient.addColorStop(0, fillColors[0]); gradient.addColorStop(0, fillColors[0]);
gradient.addColorStop(1, fillColors[1]); gradient.addColorStop(0.5, fillColors[1] || fillColors[0].replace(/[\d.]+\)/, '0.15)'));
gradient.addColorStop(1, fillColors[1] || 'rgba(0,0,0,0)');
return gradient; return gradient;
}; };
@ -760,7 +767,23 @@ const Dashboard = (() => {
ctx.fill(); ctx.fill();
ctx.restore(); ctx.restore();
// 2. 绘制主线条 // 2. 绘制发光效果(外层)
ctx.save();
ctx.shadowColor = gradientColors[1];
ctx.shadowBlur = 12;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.strokeStyle = createLineGradient(gradientColors);
ctx.lineWidth = 3;
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
ctx.globalAlpha = 0.6;
ctx.beginPath();
drawCurvePath(points);
ctx.stroke();
ctx.restore();
// 3. 绘制主线条(内层 - 更清晰)
ctx.save(); ctx.save();
ctx.strokeStyle = createLineGradient(gradientColors); ctx.strokeStyle = createLineGradient(gradientColors);
ctx.lineWidth = 2.5; ctx.lineWidth = 2.5;
@ -771,7 +794,7 @@ const Dashboard = (() => {
ctx.stroke(); ctx.stroke();
ctx.restore(); ctx.restore();
// 3. 绘制数据点(只在今日或最后一个点显示) // 4. 绘制数据点(只在今日或最后一个点显示 - 增强版
const mainColor = gradientColors[1]; const mainColor = gradientColors[1];
counts.forEach((count, i) => { counts.forEach((count, i) => {
const x = points[i].x; const x = points[i].x;
@ -780,17 +803,34 @@ const Dashboard = (() => {
const isLast = i === counts.length - 1; const isLast = i === counts.length - 1;
if(isToday || isLast) { if(isToday || isLast) {
// 高亮点 // 外层发光圆环
ctx.save(); ctx.save();
ctx.shadowColor = mainColor;
ctx.shadowBlur = 15;
ctx.beginPath(); ctx.beginPath();
ctx.arc(x, y, 6, 0, Math.PI * 2); ctx.arc(x, y, 8, 0, Math.PI * 2);
ctx.fillStyle = mainColor.replace(')', ', 0.3)');
ctx.fill();
ctx.restore();
// 中层彩色圆
ctx.save();
ctx.shadowColor = mainColor;
ctx.shadowBlur = 8;
ctx.beginPath();
ctx.arc(x, y, 5, 0, Math.PI * 2);
ctx.fillStyle = mainColor; ctx.fillStyle = mainColor;
ctx.fill(); ctx.fill();
ctx.restore();
// 内层白色圆点
ctx.save();
ctx.beginPath(); ctx.beginPath();
ctx.arc(x, y, 3, 0, Math.PI * 2); ctx.arc(x, y, 2.5, 0, Math.PI * 2);
ctx.fillStyle = '#fff'; ctx.fillStyle = '#fff';
ctx.fill(); ctx.fill();
ctx.restore(); ctx.restore();
if(isToday) todayLabels.push({x, y, count, color: mainColor, key: labelKey}); if(isToday) todayLabels.push({x, y, count, color: mainColor, key: labelKey});
} }
}); });