Files
ZhiQiXiaoYuan/styles/premium-components.wxss
ChuXun eaab9a762a 1
2025-10-19 20:28:31 +08:00

756 lines
14 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* ============================================
* 🎨 企业级通用组件样式库
* ============================================
* 参考Ant Design、Material Design、iOS HIG
*/
@import './design-tokens.wxss';
/* ==================== 按钮组件 ==================== */
.btn {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
gap: var(--space-2);
padding: var(--space-4) var(--space-8);
border-radius: var(--radius-xl);
font-size: var(--font-size-base);
font-weight: var(--font-weight-medium);
line-height: var(--line-height-tight);
transition: var(--transition-base);
border: none;
outline: none;
overflow: hidden;
user-select: none;
-webkit-tap-highlight-color: transparent;
}
.btn::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
border-radius: 50%;
background: rgba(255, 255, 255, 0.3);
transform: translate(-50%, -50%);
transition: width var(--duration-moderate) var(--ease-out),
height var(--duration-moderate) var(--ease-out);
}
.btn:active::before {
width: 200%;
height: 200%;
}
/* 主要按钮 */
.btn-primary {
background: var(--gradient-purple-dream);
color: var(--text-inverse);
box-shadow: var(--shadow-primary);
}
.btn-primary:active {
transform: translateY(2rpx);
box-shadow: var(--shadow-sm);
}
/* 次要按钮 */
.btn-secondary {
background: var(--bg-secondary);
color: var(--text-primary);
box-shadow: var(--shadow-sm);
}
/* 幽灵按钮 */
.btn-ghost {
background: transparent;
border: 2rpx solid var(--border-base);
color: var(--text-primary);
}
/* 文本按钮 */
.btn-text {
background: transparent;
color: var(--brand-primary);
padding: var(--space-2) var(--space-4);
}
/* 危险按钮 */
.btn-danger {
background: linear-gradient(135deg, #FF6B6B 0%, #FF4757 100%);
color: var(--text-inverse);
box-shadow: var(--shadow-error);
}
/* 按钮尺寸 */
.btn-large {
padding: var(--space-6) var(--space-12);
font-size: var(--font-size-lg);
border-radius: var(--radius-2xl);
}
.btn-small {
padding: var(--space-2) var(--space-6);
font-size: var(--font-size-sm);
border-radius: var(--radius-md);
}
.btn-mini {
padding: var(--space-1) var(--space-4);
font-size: var(--font-size-xs);
border-radius: var(--radius-sm);
}
/* 块级按钮 */
.btn-block {
width: 100%;
}
/* 禁用状态 */
.btn-disabled {
opacity: 0.4;
pointer-events: none;
}
/* 加载状态 */
.btn-loading {
pointer-events: none;
}
.btn-loading::after {
content: '';
display: inline-block;
width: 28rpx;
height: 28rpx;
margin-left: var(--space-2);
border: 3rpx solid currentColor;
border-right-color: transparent;
border-radius: 50%;
animation: btn-spin 0.6s linear infinite;
}
@keyframes btn-spin {
to { transform: rotate(360deg); }
}
/* ==================== 卡片组件 ==================== */
.card {
background: var(--bg-primary);
border-radius: var(--radius-2xl);
box-shadow: var(--shadow-sm);
overflow: hidden;
transition: var(--transition-base);
}
.card-hover {
cursor: pointer;
}
.card-hover:active {
transform: scale(0.98);
box-shadow: var(--shadow-md);
}
/* 卡片头部 */
.card-header {
padding: var(--space-6);
border-bottom: 1rpx solid var(--divider);
}
.card-title {
font-size: var(--font-size-lg);
font-weight: var(--font-weight-semibold);
color: var(--text-primary);
}
.card-subtitle {
margin-top: var(--space-1);
font-size: var(--font-size-sm);
color: var(--text-tertiary);
}
/* 卡片内容 */
.card-body {
padding: var(--space-6);
}
/* 卡片底部 */
.card-footer {
padding: var(--space-6);
border-top: 1rpx solid var(--divider);
background: var(--bg-secondary);
}
/* 渐变卡片 */
.card-gradient {
background: var(--gradient-purple-dream);
color: var(--text-inverse);
box-shadow: var(--shadow-primary);
}
/* 毛玻璃卡片 */
.card-glass {
background: var(--glass-white);
backdrop-filter: blur(var(--blur-lg));
border: 1rpx solid var(--glass-border);
box-shadow: var(--glass-shadow);
}
/* 边框卡片 */
.card-bordered {
border: 1rpx solid var(--border-base);
box-shadow: none;
}
/* 无阴影卡片 */
.card-flat {
box-shadow: none;
}
/* ==================== 头像组件 ==================== */
.avatar {
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: var(--radius-full);
overflow: hidden;
background: var(--bg-tertiary);
color: var(--text-tertiary);
font-weight: var(--font-weight-medium);
}
.avatar-sm {
width: 48rpx;
height: 48rpx;
font-size: var(--font-size-xs);
}
.avatar-base {
width: 64rpx;
height: 64rpx;
font-size: var(--font-size-sm);
}
.avatar-lg {
width: 80rpx;
height: 80rpx;
font-size: var(--font-size-base);
}
.avatar-xl {
width: 120rpx;
height: 120rpx;
font-size: var(--font-size-lg);
}
.avatar-2xl {
width: 160rpx;
height: 160rpx;
font-size: var(--font-size-xl);
}
.avatar-img {
width: 100%;
height: 100%;
object-fit: cover;
}
/* 头像组 */
.avatar-group {
display: inline-flex;
align-items: center;
}
.avatar-group .avatar {
margin-left: calc(var(--space-2) * -1);
border: 3rpx solid var(--bg-primary);
}
.avatar-group .avatar:first-child {
margin-left: 0;
}
/* ==================== 徽标组件 ==================== */
.badge {
position: relative;
display: inline-flex;
}
.badge-dot {
position: absolute;
top: 0;
right: 0;
width: 16rpx;
height: 16rpx;
border-radius: 50%;
background: var(--color-error);
border: 3rpx solid var(--bg-primary);
}
.badge-count {
position: absolute;
top: -8rpx;
right: -8rpx;
min-width: 32rpx;
height: 32rpx;
padding: 0 8rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: var(--radius-full);
background: var(--color-error);
color: var(--text-inverse);
font-size: var(--font-size-xs);
font-weight: var(--font-weight-medium);
line-height: 1;
white-space: nowrap;
border: 2rpx solid var(--bg-primary);
box-shadow: var(--shadow-sm);
}
/* 标签徽标 */
.tag {
display: inline-flex;
align-items: center;
gap: var(--space-1);
padding: var(--space-1) var(--space-3);
border-radius: var(--radius-base);
font-size: var(--font-size-xs);
font-weight: var(--font-weight-medium);
line-height: var(--line-height-tight);
white-space: nowrap;
}
.tag-primary {
background: rgba(102, 126, 234, 0.1);
color: var(--brand-primary);
}
.tag-success {
background: var(--color-success-bg);
color: var(--color-success);
}
.tag-warning {
background: var(--color-warning-bg);
color: var(--color-warning);
}
.tag-error {
background: var(--color-error-bg);
color: var(--color-error);
}
.tag-info {
background: var(--color-info-bg);
color: var(--color-info);
}
/* ==================== 分割线组件 ==================== */
.divider {
height: 1rpx;
background: var(--divider);
border: none;
margin: var(--space-6) 0;
}
.divider-vertical {
width: 1rpx;
height: auto;
margin: 0 var(--space-4);
display: inline-block;
}
.divider-text {
position: relative;
text-align: center;
margin: var(--space-6) 0;
}
.divider-text::before,
.divider-text::after {
content: '';
position: absolute;
top: 50%;
width: calc(50% - 60rpx);
height: 1rpx;
background: var(--divider);
}
.divider-text::before {
left: 0;
}
.divider-text::after {
right: 0;
}
.divider-text-content {
position: relative;
padding: 0 var(--space-4);
color: var(--text-tertiary);
font-size: var(--font-size-sm);
background: var(--bg-primary);
}
/* ==================== 空状态组件 ==================== */
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: var(--space-20) var(--space-6);
text-align: center;
}
.empty-icon {
font-size: 120rpx;
margin-bottom: var(--space-6);
opacity: 0.5;
}
.empty-title {
font-size: var(--font-size-lg);
font-weight: var(--font-weight-medium);
color: var(--text-secondary);
margin-bottom: var(--space-2);
}
.empty-description {
font-size: var(--font-size-sm);
color: var(--text-tertiary);
line-height: var(--line-height-relaxed);
max-width: 400rpx;
}
.empty-action {
margin-top: var(--space-8);
}
/* ==================== 骨架屏组件 ==================== */
.skeleton {
background: linear-gradient(90deg,
var(--bg-tertiary) 25%,
var(--bg-secondary) 50%,
var(--bg-tertiary) 75%
);
background-size: 200% 100%;
animation: skeleton-loading 1.5s ease-in-out infinite;
border-radius: var(--radius-base);
}
@keyframes skeleton-loading {
0% {
background-position: 200% 0;
}
100% {
background-position: -200% 0;
}
}
.skeleton-text {
height: 28rpx;
margin-bottom: var(--space-3);
}
.skeleton-title {
height: 40rpx;
width: 60%;
margin-bottom: var(--space-4);
}
.skeleton-avatar {
width: 80rpx;
height: 80rpx;
border-radius: var(--radius-full);
}
.skeleton-image {
width: 100%;
height: 400rpx;
border-radius: var(--radius-xl);
}
.skeleton-button {
height: 72rpx;
width: 160rpx;
border-radius: var(--radius-xl);
}
/* ==================== 加载组件 ==================== */
.loading-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: var(--space-12);
}
.loading-spinner {
width: 64rpx;
height: 64rpx;
border: 6rpx solid var(--border-light);
border-top-color: var(--brand-primary);
border-radius: 50%;
animation: spinner-rotate 0.8s linear infinite;
}
@keyframes spinner-rotate {
to { transform: rotate(360deg); }
}
.loading-dots {
display: flex;
gap: var(--space-3);
}
.loading-dot {
width: 16rpx;
height: 16rpx;
border-radius: 50%;
background: var(--brand-primary);
animation: dot-bounce 1.4s ease-in-out infinite;
}
.loading-dot:nth-child(1) {
animation-delay: -0.32s;
}
.loading-dot:nth-child(2) {
animation-delay: -0.16s;
}
@keyframes dot-bounce {
0%, 80%, 100% {
transform: scale(0);
opacity: 0.5;
}
40% {
transform: scale(1);
opacity: 1;
}
}
.loading-text {
margin-top: var(--space-4);
font-size: var(--font-size-sm);
color: var(--text-tertiary);
}
/* ==================== 遮罩组件 ==================== */
.overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: var(--bg-mask);
z-index: var(--z-index-modal-backdrop);
animation: overlay-fadein var(--duration-normal) var(--ease-out);
}
@keyframes overlay-fadein {
from { opacity: 0; }
to { opacity: 1; }
}
/* ==================== 模态框组件 ==================== */
.modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
align-items: center;
justify-content: center;
padding: var(--space-8);
z-index: var(--z-index-modal);
animation: modal-fadein var(--duration-normal) var(--ease-out);
}
@keyframes modal-fadein {
from {
opacity: 0;
transform: scale(0.9);
}
to {
opacity: 1;
transform: scale(1);
}
}
.modal-content {
width: 100%;
max-width: 600rpx;
background: var(--bg-primary);
border-radius: var(--radius-2xl);
box-shadow: var(--shadow-2xl);
overflow: hidden;
animation: modal-slideup var(--duration-moderate) var(--ease-out);
}
@keyframes modal-slideup {
from {
opacity: 0;
transform: translateY(40rpx);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.modal-header {
position: relative;
padding: var(--space-8);
border-bottom: 1rpx solid var(--divider);
}
.modal-title {
font-size: var(--font-size-xl);
font-weight: var(--font-weight-semibold);
color: var(--text-primary);
text-align: center;
}
.modal-close {
position: absolute;
top: var(--space-6);
right: var(--space-6);
width: 56rpx;
height: 56rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: var(--radius-full);
background: var(--bg-hover);
color: var(--text-tertiary);
font-size: var(--font-size-lg);
transition: var(--transition-fast);
}
.modal-close:active {
background: var(--bg-active);
transform: scale(0.9);
}
.modal-body {
padding: var(--space-8);
max-height: 800rpx;
overflow-y: auto;
}
.modal-footer {
padding: var(--space-6) var(--space-8);
border-top: 1rpx solid var(--divider);
display: flex;
gap: var(--space-4);
}
.modal-footer .btn {
flex: 1;
}
/* ==================== Toast 组件 ==================== */
.toast {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: var(--space-6) var(--space-8);
background: rgba(0, 0, 0, 0.8);
backdrop-filter: blur(var(--blur-md));
color: var(--text-inverse);
border-radius: var(--radius-xl);
font-size: var(--font-size-base);
text-align: center;
z-index: var(--z-index-notification);
animation: toast-show var(--duration-normal) var(--ease-out);
max-width: 500rpx;
box-shadow: var(--shadow-lg);
}
@keyframes toast-show {
from {
opacity: 0;
transform: translate(-50%, -50%) scale(0.8);
}
to {
opacity: 1;
transform: translate(-50%, -50%) scale(1);
}
}
.toast-icon {
font-size: 64rpx;
margin-bottom: var(--space-3);
}
/* ==================== 输入框组件 ==================== */
.input-group {
margin-bottom: var(--space-6);
}
.input-label {
display: block;
margin-bottom: var(--space-2);
font-size: var(--font-size-sm);
font-weight: var(--font-weight-medium);
color: var(--text-secondary);
}
.input-field {
width: 100%;
padding: var(--space-4) var(--space-6);
border: 2rpx solid var(--border-base);
border-radius: var(--radius-xl);
font-size: var(--font-size-base);
color: var(--text-primary);
background: var(--bg-primary);
transition: var(--transition-fast);
}
.input-field:focus {
border-color: var(--brand-primary);
box-shadow: 0 0 0 6rpx rgba(102, 126, 234, 0.1);
}
.input-field::placeholder {
color: var(--text-quaternary);
}
.input-error {
border-color: var(--color-error);
}
.input-error:focus {
box-shadow: 0 0 0 6rpx var(--color-error-bg);
}
.input-helper {
margin-top: var(--space-2);
font-size: var(--font-size-xs);
color: var(--text-tertiary);
}
.input-error-text {
color: var(--color-error);
}