/* app.wxss — 全局共享样式 */ /* ========== CSS 变量 ========== */ page { --color-price: #ff4444; --color-text-main: #333; --color-text-gray: #999; --color-border-light: #f0f0f0; --bg-white: #ffffff; --bg-gray-hover: #f5f5f5; --radius-lg: 30rpx; --radius-normal: 25rpx; --radius-full: 50%; --padding-base: 40rpx; --shadow-modal: 0 20rpx 60rpx rgba(0, 0, 0, 0.2); box-sizing: border-box; } /* ========== 动画 ========== */ @keyframes spin { to { transform: rotate(360deg); } } @keyframes pulse { 0%, 100% { opacity: 0.8; transform: scale(1); } 50% { opacity: 1; transform: scale(1.2); } } @keyframes modalShow { from { opacity: 0; transform: scale(0.9); } to { opacity: 1; transform: scale(1); } } @keyframes marquee { 0% { transform: translateX(100%); } 100% { transform: translateX(-100%); } } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } @keyframes slideUp { from { transform: translateY(100%); } to { transform: translateY(0); } } @keyframes slideDown { from { transform: translateY(0); } to { transform: translateY(100%); } } /* ========== 加载提示 ========== */ .loading-toast { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: rgba(0, 0, 0, 0.7); backdrop-filter: blur(10px); padding: 30rpx 50rpx; border-radius: var(--radius-normal); display: flex; flex-direction: column; align-items: center; z-index: 999; } .loading-spinner { width: 60rpx; height: 60rpx; border: 6rpx solid rgba(255, 255, 255, 0.3); border-top-color: #fff; border-radius: var(--radius-full); animation: spin 1s linear infinite; margin-bottom: 20rpx; } .loading-text { font-size: 26rpx; color: #fff; } /* ========== 价格组件 ========== */ .price-wrap { color: var(--color-price); font-weight: bold; } .price-icon { font-size: 24rpx; margin-right: 2rpx; } .price-integer { font-size: 32rpx; } .price-decimal { font-size: 24rpx; } /* ========== 弹窗基础 ========== */ .modal-mask { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.5); backdrop-filter: blur(5px); z-index: 1000; display: flex; align-items: center; justify-content: center; } .modal-content { width: 600rpx; background: var(--bg-white); border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow-modal); z-index: 1001; animation: modalShow 0.3s ease-out; } .modal-header { padding: var(--padding-base); border-bottom: 2rpx solid var(--color-border-light); display: flex; justify-content: space-between; align-items: center; } .modal-title { font-size: 32rpx; font-weight: bold; color: var(--color-text-main); } .modal-close { font-size: 40rpx; color: var(--color-text-gray); width: 60rpx; height: 60rpx; display: flex; justify-content: center; align-items: center; border-radius: var(--radius-full); flex-shrink: 0; } .modal-close:active { background: var(--bg-gray-hover); } .modal-body { max-height: 600rpx; padding: var(--padding-base); overflow-y: auto; } .modal-text { font-size: 28rpx; color: var(--color-text-main); line-height: 1.6; white-space: normal; word-break: break-word; } /* ========== Flex 工具类 ========== */ .flex-center { display: flex; align-items: center; justify-content: center; } .flex-between { display: flex; align-items: center; justify-content: space-between; } .flex-column { display: flex; flex-direction: column; } .flex-column-center { display: flex; flex-direction: column; align-items: center; justify-content: center; } .flex-1 { flex: 1; min-width: 0; } .flex-shrink-0 { flex-shrink: 0; } .flex-wrap { flex-wrap: wrap; } /* ========== 文本工具类 ========== */ .text-ellipsis { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .text-ellipsis-2 { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; text-overflow: ellipsis; } .text-ellipsis-3 { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; text-overflow: ellipsis; } .text-center { text-align: center; } .text-right { text-align: right; } .text-bold { font-weight: bold; } .text-gray { color: var(--color-text-gray); } .text-main { color: var(--color-text-main); } /* ========== 安全区域 ========== */ .safe-bottom { padding-bottom: env(safe-area-inset-bottom); } .safe-bottom-fixed { position: fixed; bottom: 0; left: 0; right: 0; padding-bottom: env(safe-area-inset-bottom); } /* ========== 通用卡片 ========== */ .card { background: var(--bg-white); border-radius: var(--radius-lg); box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05); overflow: hidden; } .card-padding { padding: var(--padding-base); } /* ========== 毛玻璃 ========== */ .glass { background: rgba(255, 255, 255, 0.72); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); } .glass-dark { background: rgba(0, 0, 0, 0.55); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); } /* ========== 圆形头像 ========== */ .avatar-circle { border-radius: var(--radius-full); border: 2rpx solid #fff; object-fit: cover; flex-shrink: 0; } .avatar-sm { width: 64rpx; height: 64rpx; } .avatar-md { width: 88rpx; height: 88rpx; } .avatar-lg { width: 120rpx; height: 120rpx; } /* ========== 红点/角标 ========== */ .badge-dot { position: absolute; top: -6rpx; right: -6rpx; width: 16rpx; height: 16rpx; background: #fa5151; border-radius: var(--radius-full); border: 2rpx solid #fff; } .badge-num { position: absolute; top: -10rpx; right: -10rpx; min-width: 32rpx; height: 32rpx; line-height: 32rpx; padding: 0 8rpx; background: #fa5151; color: #fff; font-size: 20rpx; font-weight: 600; border-radius: 16rpx; text-align: center; border: 2rpx solid #fff; } /* ========== 空状态 ========== */ .empty-state { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 120rpx 40rpx; } .empty-icon { width: 200rpx; height: 200rpx; margin-bottom: 30rpx; opacity: 0.5; } .empty-text { font-size: 30rpx; color: var(--color-text-gray); margin-bottom: 10rpx; } .empty-subtext { font-size: 26rpx; color: #ccc; } /* ========== 分割线 ========== */ .divider { height: 2rpx; background: var(--color-border-light); margin: 20rpx 0; } .divider-light { height: 1rpx; background: rgba(0, 0, 0, 0.04); margin: 16rpx 0; } .divider-gradient { height: 2rpx; background: linear-gradient(90deg, transparent, rgba(0, 0, 0, 0.1), transparent); margin: 20rpx 0; } /* ========== 固定底部按钮区 ========== */ .fixed-bottom { position: fixed; left: 0; right: 0; bottom: 0; padding: 20rpx 30rpx; padding-bottom: calc(20rpx + env(safe-area-inset-bottom)); background: linear-gradient(transparent, rgba(255, 255, 255, 0.95) 30%); z-index: 100; } /* ========== 列表项 ========== */ .list-item { display: flex; align-items: center; padding: 24rpx 28rpx; border-bottom: 1rpx solid rgba(0, 0, 0, 0.04); } .list-item:last-child { border-bottom: none; } .list-icon { width: 36rpx; height: 36rpx; margin-right: 16rpx; flex-shrink: 0; } .list-text { flex: 1; font-size: 28rpx; color: var(--color-text-main); } .list-arrow { width: 20rpx; height: 20rpx; opacity: 0.4; flex-shrink: 0; } /* ========== 标签 ========== */ .tag { display: inline-flex; align-items: center; padding: 4rpx 14rpx; border-radius: 999rpx; font-size: 20rpx; font-weight: 600; line-height: 1.4; } .tag-primary { background: rgba(64, 156, 255, 0.1); color: #409cff; } .tag-success { background: rgba(82, 196, 26, 0.1); color: #52c41a; } .tag-warning { background: rgba(250, 173, 20, 0.1); color: #faad14; } .tag-danger { background: rgba(255, 77, 79, 0.1); color: #ff4d4f; } .tag-gold { background: rgba(201, 169, 98, 0.1); color: #C9A962; } /* ========== 页面容器 ========== */ .page-container { min-height: 100vh; position: relative; } .page-bg { position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 0; pointer-events: none; } /* ========== 按钮 ========== */ .btn { display: flex; align-items: center; justify-content: center; border-radius: 48rpx; font-weight: 600; text-align: center; border: none; position: relative; overflow: hidden; transition: all 0.2s ease; } .btn:active { transform: scale(0.98); } /* 主按钮(全宽) */ .btn-primary { width: 100%; height: 96rpx; line-height: 96rpx; font-size: 34rpx; color: #fff; } .btn-primary--gold { background: linear-gradient(135deg, #C9A962, #D4B56A); box-shadow: 0 8rpx 20rpx rgba(201, 169, 98, 0.3); } .btn-primary--green { background: linear-gradient(135deg, #52c41a, #389e0d); box-shadow: 0 8rpx 20rpx rgba(82, 196, 26, 0.3); } .btn-primary--blue { background: linear-gradient(135deg, #409cff, #3080e0); box-shadow: 0 8rpx 20rpx rgba(64, 156, 255, 0.3); } .btn-primary--orange { background: linear-gradient(135deg, #ffb347, #ff8c1a); box-shadow: 0 8rpx 20rpx rgba(255, 140, 26, 0.3); } .btn-primary--purple { background: linear-gradient(135deg, #6a11cb, #2575fc); box-shadow: 0 8rpx 20rpx rgba(106, 17, 203, 0.3); } .btn-primary--red { background: linear-gradient(135deg, #ff4d4f, #cf1322); box-shadow: 0 8rpx 20rpx rgba(255, 77, 79, 0.3); } /* 次要按钮 */ .btn-secondary { background: rgba(0, 0, 0, 0.04); color: var(--color-text-main); font-size: 28rpx; padding: 16rpx 32rpx; } .btn-secondary:active { background: rgba(0, 0, 0, 0.08); } /* 小型按钮 */ .btn-sm { padding: 14rpx 32rpx; font-size: 26rpx; color: #fff; border-radius: 40rpx; } .btn-sm--gold { background: linear-gradient(135deg, #ffcc00, #ffaa00); box-shadow: 0 6rpx 16rpx rgba(255, 170, 0, 0.3); } .btn-sm--green { background: linear-gradient(135deg, #52c41a, #389e0d); box-shadow: 0 6rpx 16rpx rgba(82, 196, 26, 0.3); } .btn-sm--blue { background: linear-gradient(135deg, #409cff, #3080e0); box-shadow: 0 6rpx 16rpx rgba(64, 156, 255, 0.3); } .btn-sm--red { background: linear-gradient(135deg, #ff4d4f, #cf1322); box-shadow: 0 6rpx 16rpx rgba(255, 77, 79, 0.3); } .btn-sm--dark { background: linear-gradient(135deg, #3d4f66, #2c3e50); box-shadow: 0 6rpx 16rpx rgba(44, 62, 80, 0.3); } /* 幽灵按钮(描边) */ .btn-ghost { background: transparent; border: 2rpx solid currentColor; padding: 14rpx 32rpx; font-size: 26rpx; font-weight: 600; } .btn-ghost--primary { color: #409cff; border-color: #409cff; } .btn-ghost--gold { color: #C9A962; border-color: #C9A962; } /* 禁用状态 */ .btn[disabled], .btn-disabled { opacity: 0.5; pointer-events: none; } /* ========== 输入框 ========== */ .input-rounded { width: 100%; height: 88rpx; background: #fff; border-radius: 44rpx; padding: 0 32rpx; font-size: 28rpx; color: var(--color-text-main); box-sizing: border-box; border: none; } .input-rounded--dark { background: rgba(255, 255, 255, 0.15); color: #fff; border: 1rpx solid rgba(255, 255, 255, 0.3); } .input-rounded--dark::placeholder { color: rgba(255, 255, 255, 0.5); } .input-inline { flex: 1; font-size: 32rpx; color: var(--color-text-main); height: 50rpx; line-height: 50rpx; border: none; background: transparent; } .input-box { background: #F7F3ED; border-radius: 24rpx; padding: 0 24rpx; } /* ========== 搜索框 ========== */ .search-box { display: flex; align-items: center; background: #f0f0f0; border-radius: 40rpx; padding: 0 20rpx; height: 68rpx; } .search-box--glass { background: rgba(255, 255, 255, 0.85); backdrop-filter: blur(20px); border: 1rpx solid rgba(255, 255, 255, 0.3); box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06); height: 84rpx; border-radius: 50rpx; padding: 0 28rpx; } .search-input { flex: 1; height: 100%; font-size: 28rpx; margin-left: 10rpx; } .search-icon { width: 32rpx; height: 32rpx; opacity: 0.5; flex-shrink: 0; } /* ========== Tab 标签栏 ========== */ .tab-bar { display: flex; background: #fff; border-bottom: 1rpx solid #f0f0f0; } .tab-item { flex: 1; display: flex; justify-content: center; align-items: center; padding: 24rpx 0; position: relative; color: #666; font-size: 28rpx; transition: color 0.3s; } .tab-item--active { color: var(--color-price); font-weight: 600; } .tab-indicator { position: absolute; bottom: 0; left: 50%; transform: translateX(-50%); width: 60rpx; height: 6rpx; background: var(--color-price); border-radius: 3rpx; } /* 胶囊式 Tab */ .tab-capsule { display: inline-flex; flex-direction: column; align-items: center; justify-content: center; height: 60rpx; padding: 0 30rpx; margin-right: 20rpx; border-radius: 30rpx; background: #f5f5f5; color: #666; font-size: 28rpx; flex-shrink: 0; transition: all 0.3s ease; } .tab-capsule--active { background: #e8f5e9; color: #2e7d32; font-weight: 500; box-shadow: 0 4rpx 12rpx rgba(46, 125, 50, 0.1); } /* ========== 加载遮罩 ========== */ .loading-mask { position: fixed; top: 0; left: 0; right: 0; bottom: 0; display: flex; align-items: center; justify-content: center; z-index: 9999; } .loading-mask--dark { background: rgba(0, 0, 0, 0.7); backdrop-filter: blur(10px); } .loading-mask--light { background: rgba(255, 255, 255, 0.85); } /* 旋转器尺寸变体 */ .spinner { border-radius: var(--radius-full); animation: spin 0.8s linear infinite; } .spinner--sm { width: 40rpx; height: 40rpx; border: 3rpx solid rgba(0, 0, 0, 0.08); border-top-color: var(--color-text-main); } .spinner--md { width: 60rpx; height: 60rpx; border: 5rpx solid rgba(0, 0, 0, 0.08); border-top-color: var(--color-text-main); } .spinner--lg { width: 80rpx; height: 80rpx; border: 6rpx solid rgba(0, 0, 0, 0.08); border-top-color: var(--color-text-main); } .spinner--white { border-color: rgba(255, 255, 255, 0.3); border-top-color: #fff; } /* ========== 刷新按钮 ========== */ .refresh-btn { position: fixed; top: 36rpx; right: 32rpx; width: 56rpx; height: 56rpx; border-radius: var(--radius-full); display: flex; align-items: center; justify-content: center; z-index: 20; } .refresh-btn--light { background: rgba(255, 255, 255, 0.8); backdrop-filter: blur(12rpx); border: 1rpx solid rgba(255, 255, 255, 0.6); box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.05); } .refresh-btn--dark { background: rgba(0, 0, 0, 0.5); backdrop-filter: blur(10rpx); } .refresh-icon { width: 28rpx; height: 28rpx; } /* ========== 状态标签 ========== */ .status-tag { display: inline-flex; align-items: center; padding: 6rpx 16rpx; border-radius: 20rpx; font-size: 24rpx; font-weight: 500; white-space: nowrap; } .status-tag--danger { background: #fff5f5; color: #ff6b6b; } .status-tag--success { background: #f0fff0; color: #52c41a; } .status-tag--warning { background: #fffbe6; color: #faad14; } .status-tag--info { background: #e6f7ff; color: #1890ff; } .status-tag--default { background: #f5f5f5; color: #999; } /* ========== 加载更多 ========== */ .load-more { display: flex; align-items: center; justify-content: center; padding: 40rpx 0; } .load-more-text { font-size: 26rpx; color: var(--color-text-gray); } .no-more { text-align: center; padding: 40rpx 0; font-size: 26rpx; color: #ccc; }