initial commit

This commit is contained in:
Jiao77
2025-09-29 05:57:18 +08:00
commit 9c0051c92b
73 changed files with 18737 additions and 0 deletions

View File

@@ -0,0 +1,218 @@
---
export interface Props {
title: string;
value: string | number;
change?: string;
changeType?: 'positive' | 'negative' | 'neutral';
icon?: string;
color?: 'primary' | 'success' | 'warning' | 'info';
}
const {
title,
value,
change,
changeType = 'neutral',
icon,
color = 'primary'
} = Astro.props;
const colorClasses = {
primary: 'metric-primary',
success: 'metric-success',
warning: 'metric-warning',
info: 'metric-info'
};
const changeClasses = {
positive: 'change-positive',
negative: 'change-negative',
neutral: 'change-neutral'
};
---
<div class={`metric-card ${colorClasses[color]}`}>
<div class="metric-header">
{icon && (
<div class="metric-icon">
<i class={icon}></i>
</div>
)}
<h3 class="metric-title">{title}</h3>
</div>
<div class="metric-body">
<div class="metric-value">{value}</div>
{change && (
<div class={`metric-change ${changeClasses[changeType]}`}>
<i class={changeType === 'positive' ? 'fas fa-arrow-up' : changeType === 'negative' ? 'fas fa-arrow-down' : 'fas fa-minus'}></i>
<span>{change}</span>
</div>
)}
</div>
<div class="metric-bg"></div>
</div>
<style>
.metric-card {
position: relative;
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(15px);
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 1.25rem;
padding: 1.5rem;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
overflow: hidden;
animation: scaleIn 0.5s ease-out;
}
.metric-card:hover {
transform: translateY(-4px) scale(1.02);
background: rgba(255, 255, 255, 0.15);
border-color: rgba(255, 255, 255, 0.3);
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.2);
}
.metric-header {
display: flex;
align-items: center;
gap: 0.75rem;
margin-bottom: 1rem;
}
.metric-icon {
width: 40px;
height: 40px;
border-radius: 0.75rem;
background: rgba(91, 119, 142, 0.2);
display: flex;
align-items: center;
justify-content: center;
font-size: 1.25rem;
color: #5b778e;
}
.metric-title {
font-size: 0.875rem;
font-weight: 500;
color: #011a2d;
margin: 0;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.metric-body {
position: relative;
z-index: 2;
}
.metric-value {
font-size: 2rem;
font-weight: 700;
color: #011a2d;
margin-bottom: 0.5rem;
line-height: 1;
}
.metric-change {
display: flex;
align-items: center;
gap: 0.375rem;
font-size: 0.875rem;
font-weight: 500;
}
.change-positive {
color: #064630;
}
.change-negative {
color: #720808;
}
.change-neutral {
color: #0a2c48;
}
.metric-bg {
position: absolute;
top: -50%;
right: -50%;
width: 200%;
height: 200%;
opacity: 0.03;
border-radius: 50%;
transition: all 0.3s ease;
}
.metric-card:hover .metric-bg {
opacity: 0.06;
transform: scale(1.1);
}
/* 颜色变体 */
.metric-primary .metric-bg {
background: linear-gradient(135deg, #5b778e, #b2c5d5);
}
.metric-primary .metric-icon {
background: rgba(91, 119, 142, 0.2);
color: #5b778e;
}
.metric-success .metric-bg {
background: linear-gradient(135deg, #b1d9d4, #aecedd);
}
.metric-success .metric-icon {
background: rgba(177, 217, 212, 0.2);
color: #10B981;
}
.metric-warning .metric-bg {
background: linear-gradient(135deg, #b2c5d5, #aecedd);
}
.metric-warning .metric-icon {
background: rgba(178, 197, 213, 0.2);
color: #F59E0B;
}
.metric-info .metric-bg {
background: linear-gradient(135deg, #aecedd, #b1d9d4);
}
.metric-info .metric-icon {
background: rgba(174, 206, 221, 0.2);
color: #5b778e;
}
@media (max-width: 768px) {
.metric-card {
padding: 1.25rem;
}
.metric-value {
font-size: 1.75rem;
}
.metric-icon {
width: 36px;
height: 36px;
font-size: 1.1rem;
}
}
@keyframes scaleIn {
from {
opacity: 0;
transform: scale(0.9);
}
to {
opacity: 1;
transform: scale(1);
}
}
</style>