feat: UI redesign with uv-ui color system and landscape imagery
- Replace all colors with uv-ui design tokens (primary #3c9cff, warning #f9ae3d, etc.) - Hero section: Wugong Mountain landscape photo with dark overlay - Super Player card: photo background, large typography, warning-color price/CTA, value comparison (¥198 vs ¥3800+) - Spots section: landscape thumbnails instead of CSS gradients, warning-color prices - Profile page: landscape hero header, CSS menu icons, floating card layout - Card list page: landscape hero header, filter pills, empty state design - TabBar: rename '入园码' to '旅游卡', Lucide-style PNG icons (home/card/profile) - Typography: corrected font weights (semibold for prices, medium for labels) - Remove broken font-loader (lxgw-wen-kai CDN 404) - Skip wx.getPrivacySetting in devtools to avoid framework timeout - Replace all inline SVG with CSS-only icons for mini-program compatibility - Add design system files (styles/, components/, animations) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
// ============================================
|
||||
// Keyframe Animations
|
||||
// ============================================
|
||||
|
||||
@keyframes pulse {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.4; }
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0%, 100% { transform: translateY(0); }
|
||||
50% { transform: translateY(-10rpx); }
|
||||
}
|
||||
|
||||
@keyframes rotate {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
@keyframes fadeInUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(24rpx);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes scaleIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.92);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideInRight {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(30rpx);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
// === Animation utility classes ===
|
||||
|
||||
.animate-pulse {
|
||||
animation: pulse 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.animate-float {
|
||||
animation: float 3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.animate-rotate {
|
||||
animation: rotate 1s linear infinite;
|
||||
}
|
||||
|
||||
.animate-fade-in-up {
|
||||
animation: fadeInUp 0.4s ease-out forwards;
|
||||
}
|
||||
|
||||
.animate-scale-in {
|
||||
animation: scaleIn 0.3s ease-out forwards;
|
||||
}
|
||||
|
||||
// Stagger delays for list entrance
|
||||
@for $i from 1 through 10 {
|
||||
.stagger-#{$i} {
|
||||
animation-delay: #{$i * 0.08}s;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// ============================================
|
||||
// SCSS Mixins
|
||||
// ============================================
|
||||
|
||||
// === FLEX ===
|
||||
|
||||
@mixin flex-center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@mixin flex-between {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
@mixin flex-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
// === TYPOGRAPHY ===
|
||||
|
||||
@mixin text-display {
|
||||
font-family: $font-family-display;
|
||||
font-weight: $font-weight-bold;
|
||||
line-height: $line-height-tight;
|
||||
}
|
||||
|
||||
@mixin text-body {
|
||||
font-family: $font-family-body;
|
||||
font-weight: $font-weight-normal;
|
||||
line-height: $line-height-normal;
|
||||
}
|
||||
|
||||
@mixin text-mono {
|
||||
font-family: $font-family-mono;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
// === VISUAL ===
|
||||
|
||||
@mixin gradient-text {
|
||||
background: $gradient-accent;
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
@mixin card-base {
|
||||
background: $color-card;
|
||||
border-radius: $radius-lg;
|
||||
box-shadow: $shadow-base;
|
||||
}
|
||||
|
||||
// === INTERACTION ===
|
||||
|
||||
@mixin press-effect {
|
||||
transition: transform $transition-fast, opacity $transition-fast;
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
// ============================================
|
||||
// Design Tokens — Minimalist Modern
|
||||
// ============================================
|
||||
|
||||
// === COLORS ===
|
||||
|
||||
// Brand accent — Electric Blue
|
||||
$color-accent: #0052FF;
|
||||
$color-accent-secondary: #4D7CFF;
|
||||
$color-accent-foreground: #FFFFFF;
|
||||
|
||||
// Semantic
|
||||
$color-success: #10B981;
|
||||
$color-warning: #F59E0B;
|
||||
$color-error: #EF4444;
|
||||
|
||||
// Neutrals
|
||||
$color-background: #FAFAFA;
|
||||
$color-foreground: #0F172A;
|
||||
$color-muted: #F1F5F9;
|
||||
$color-muted-foreground: #64748B;
|
||||
$color-border: #E2E8F0;
|
||||
$color-card: #FFFFFF;
|
||||
$color-ring: #0052FF;
|
||||
|
||||
// Gradients
|
||||
$gradient-accent: linear-gradient(135deg, #{$color-accent}, #{$color-accent-secondary});
|
||||
|
||||
// === TYPOGRAPHY ===
|
||||
|
||||
$font-family-display: 'Noto Serif SC', 'STSong', 'SimSun', serif;
|
||||
$font-family-body: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'HarmonyOS Sans SC', 'Microsoft YaHei', sans-serif;
|
||||
$font-family-mono: 'Menlo', 'Monaco', 'Courier New', monospace;
|
||||
|
||||
$font-size-xs: 20rpx;
|
||||
$font-size-sm: 24rpx;
|
||||
$font-size-base: 28rpx;
|
||||
$font-size-lg: 32rpx;
|
||||
$font-size-xl: 36rpx;
|
||||
$font-size-2xl: 44rpx;
|
||||
$font-size-3xl: 56rpx;
|
||||
$font-size-display: 72rpx;
|
||||
|
||||
$font-weight-normal: 400;
|
||||
$font-weight-medium: 500;
|
||||
$font-weight-semibold: 600;
|
||||
$font-weight-bold: 700;
|
||||
|
||||
$line-height-tight: 1.2;
|
||||
$line-height-normal: 1.5;
|
||||
$line-height-relaxed: 1.75;
|
||||
|
||||
// === SPACING (rpx) ===
|
||||
|
||||
$spacing-0: 0;
|
||||
$spacing-1: 8rpx;
|
||||
$spacing-2: 16rpx;
|
||||
$spacing-3: 24rpx;
|
||||
$spacing-4: 32rpx;
|
||||
$spacing-5: 40rpx;
|
||||
$spacing-6: 48rpx;
|
||||
$spacing-8: 64rpx;
|
||||
$spacing-10: 80rpx;
|
||||
$spacing-12: 96rpx;
|
||||
$spacing-16: 128rpx;
|
||||
$spacing-20: 160rpx;
|
||||
|
||||
// === BORDER RADIUS ===
|
||||
|
||||
$radius-sm: 8rpx;
|
||||
$radius-base: 16rpx;
|
||||
$radius-lg: 24rpx;
|
||||
$radius-xl: 32rpx;
|
||||
$radius-2xl: 48rpx;
|
||||
$radius-full: 9999rpx;
|
||||
|
||||
// === SHADOWS ===
|
||||
|
||||
$shadow-sm: 0 2rpx 8rpx rgba(15, 23, 42, 0.04);
|
||||
$shadow-base: 0 4rpx 16rpx rgba(15, 23, 42, 0.08);
|
||||
$shadow-lg: 0 8rpx 32rpx rgba(15, 23, 42, 0.12);
|
||||
$shadow-xl: 0 16rpx 48rpx rgba(15, 23, 42, 0.16);
|
||||
$shadow-accent: 0 8rpx 24rpx rgba(0, 82, 255, 0.25);
|
||||
|
||||
// === TRANSITIONS ===
|
||||
|
||||
$transition-fast: 150ms ease;
|
||||
$transition-base: 250ms ease;
|
||||
$transition-slow: 400ms ease;
|
||||
|
||||
// === Z-INDEX ===
|
||||
|
||||
$z-base: 0;
|
||||
$z-dropdown: 100;
|
||||
$z-sticky: 200;
|
||||
$z-modal: 300;
|
||||
$z-toast: 400;
|
||||
|
||||
// === BORDER ===
|
||||
|
||||
$border-width: 1rpx;
|
||||
|
||||
// ============================================
|
||||
// Legacy $uni-* compatibility (for uni-ui)
|
||||
// ============================================
|
||||
|
||||
$uni-color-primary: $color-accent;
|
||||
$uni-color-success: $color-success;
|
||||
$uni-color-warning: $color-warning;
|
||||
$uni-color-error: $color-error;
|
||||
$uni-text-color: $color-foreground;
|
||||
$uni-text-color-inverse: #FFFFFF;
|
||||
$uni-text-color-grey: $color-muted-foreground;
|
||||
$uni-text-color-placeholder: #808080;
|
||||
$uni-text-color-disable: #c0c0c0;
|
||||
$uni-bg-color: $color-background;
|
||||
$uni-bg-color-grey: $color-muted;
|
||||
$uni-bg-color-hover: #f1f1f1;
|
||||
$uni-bg-color-mask: rgba(0, 0, 0, 0.4);
|
||||
$uni-border-color: $color-border;
|
||||
$uni-font-size-sm: $font-size-sm;
|
||||
$uni-font-size-base: $font-size-base;
|
||||
$uni-font-size-lg: $font-size-lg;
|
||||
$uni-font-size-title: 40rpx;
|
||||
$uni-font-size-subtitle: $font-size-xl;
|
||||
$uni-font-size-paragraph: 30rpx;
|
||||
$uni-img-size-sm: 40rpx;
|
||||
$uni-img-size-base: 52rpx;
|
||||
$uni-img-size-lg: 80rpx;
|
||||
$uni-border-radius-sm: $radius-sm;
|
||||
$uni-border-radius-base: $radius-base;
|
||||
$uni-border-radius-lg: $radius-lg;
|
||||
$uni-border-radius-circle: 50%;
|
||||
$uni-spacing-row-sm: 10rpx;
|
||||
$uni-spacing-row-base: 20rpx;
|
||||
$uni-spacing-row-lg: 30rpx;
|
||||
$uni-spacing-col-sm: 8rpx;
|
||||
$uni-spacing-col-base: 16rpx;
|
||||
$uni-spacing-col-lg: 24rpx;
|
||||
$uni-opacity-disabled: 0.3;
|
||||
$uni-color-title: $color-foreground;
|
||||
$uni-color-subtitle: $color-muted-foreground;
|
||||
$uni-color-paragraph: #3f536e;
|
||||
@@ -0,0 +1,145 @@
|
||||
// ============================================
|
||||
// Utility Classes
|
||||
// ============================================
|
||||
|
||||
// === TEXT SIZE ===
|
||||
|
||||
.text-xs { font-size: $font-size-xs; }
|
||||
.text-sm { font-size: $font-size-sm; }
|
||||
.text-base { font-size: $font-size-base; }
|
||||
.text-lg { font-size: $font-size-lg; }
|
||||
.text-xl { font-size: $font-size-xl; }
|
||||
.text-2xl { font-size: $font-size-2xl; }
|
||||
.text-3xl { font-size: $font-size-3xl; }
|
||||
.text-display { font-size: $font-size-display; }
|
||||
|
||||
// === FONT WEIGHT ===
|
||||
|
||||
.font-normal { font-weight: $font-weight-normal; }
|
||||
.font-medium { font-weight: $font-weight-medium; }
|
||||
.font-semibold { font-weight: $font-weight-semibold; }
|
||||
.font-bold { font-weight: $font-weight-bold; }
|
||||
|
||||
// === TEXT COLOR ===
|
||||
|
||||
.text-primary { color: $color-foreground; }
|
||||
.text-secondary { color: $color-muted-foreground; }
|
||||
.text-accent { color: $color-accent; }
|
||||
.text-success { color: $color-success; }
|
||||
.text-error { color: $color-error; }
|
||||
.text-white { color: #FFFFFF; }
|
||||
.text-gradient {
|
||||
background: $gradient-accent;
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
// === FONT FAMILY ===
|
||||
|
||||
.font-display { font-family: $font-family-display; }
|
||||
.font-body { font-family: $font-family-body; }
|
||||
.font-mono { font-family: $font-family-mono; }
|
||||
|
||||
// === SPACING ===
|
||||
|
||||
$spacing-map: (
|
||||
'0': $spacing-0,
|
||||
'1': $spacing-1,
|
||||
'2': $spacing-2,
|
||||
'3': $spacing-3,
|
||||
'4': $spacing-4,
|
||||
'5': $spacing-5,
|
||||
'6': $spacing-6,
|
||||
'8': $spacing-8,
|
||||
'10': $spacing-10,
|
||||
);
|
||||
|
||||
@each $key, $val in $spacing-map {
|
||||
.m-#{$key} { margin: $val; }
|
||||
.mt-#{$key} { margin-top: $val; }
|
||||
.mb-#{$key} { margin-bottom: $val; }
|
||||
.ml-#{$key} { margin-left: $val; }
|
||||
.mr-#{$key} { margin-right: $val; }
|
||||
.mx-#{$key} { margin-left: $val; margin-right: $val; }
|
||||
.my-#{$key} { margin-top: $val; margin-bottom: $val; }
|
||||
.p-#{$key} { padding: $val; }
|
||||
.pt-#{$key} { padding-top: $val; }
|
||||
.pb-#{$key} { padding-bottom: $val; }
|
||||
.pl-#{$key} { padding-left: $val; }
|
||||
.pr-#{$key} { padding-right: $val; }
|
||||
.px-#{$key} { padding-left: $val; padding-right: $val; }
|
||||
.py-#{$key} { padding-top: $val; padding-bottom: $val; }
|
||||
}
|
||||
|
||||
// === FLEX ===
|
||||
|
||||
.flex { display: flex; }
|
||||
.flex-col { flex-direction: column; }
|
||||
.flex-row { flex-direction: row; }
|
||||
.flex-wrap { flex-wrap: wrap; }
|
||||
.flex-1 { flex: 1; }
|
||||
.flex-center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.flex-between {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.items-center { align-items: center; }
|
||||
.items-start { align-items: flex-start; }
|
||||
.items-end { align-items: flex-end; }
|
||||
.justify-center { justify-content: center; }
|
||||
.justify-between { justify-content: space-between; }
|
||||
.justify-end { justify-content: flex-end; }
|
||||
.gap-1 { gap: $spacing-1; }
|
||||
.gap-2 { gap: $spacing-2; }
|
||||
.gap-3 { gap: $spacing-3; }
|
||||
.gap-4 { gap: $spacing-4; }
|
||||
.gap-5 { gap: $spacing-5; }
|
||||
|
||||
// === BACKGROUND ===
|
||||
|
||||
.bg-page { background-color: $color-background; }
|
||||
.bg-card { background-color: $color-card; }
|
||||
.bg-muted { background-color: $color-muted; }
|
||||
.bg-accent { background-color: $color-accent; }
|
||||
.bg-foreground { background-color: $color-foreground; }
|
||||
.bg-gradient-accent { background: $gradient-accent; }
|
||||
|
||||
// === BORDER RADIUS ===
|
||||
|
||||
.rounded-sm { border-radius: $radius-sm; }
|
||||
.rounded { border-radius: $radius-base; }
|
||||
.rounded-lg { border-radius: $radius-lg; }
|
||||
.rounded-xl { border-radius: $radius-xl; }
|
||||
.rounded-2xl { border-radius: $radius-2xl; }
|
||||
.rounded-full { border-radius: $radius-full; }
|
||||
|
||||
// === SHADOW ===
|
||||
|
||||
.shadow-sm { box-shadow: $shadow-sm; }
|
||||
.shadow { box-shadow: $shadow-base; }
|
||||
.shadow-lg { box-shadow: $shadow-lg; }
|
||||
.shadow-xl { box-shadow: $shadow-xl; }
|
||||
|
||||
// === INTERACTION ===
|
||||
|
||||
.press-effect {
|
||||
transition: transform $transition-fast, opacity $transition-fast;
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
// === DISPLAY ===
|
||||
|
||||
.w-full { width: 100%; }
|
||||
.h-full { height: 100%; }
|
||||
.overflow-hidden { overflow: hidden; }
|
||||
.relative { position: relative; }
|
||||
.absolute { position: absolute; }
|
||||
@@ -0,0 +1,38 @@
|
||||
// ============================================
|
||||
// Design System — Main Entry
|
||||
// ============================================
|
||||
// Imported globally via App.vue <style lang="scss">
|
||||
// Token variables are separately injected via uni.scss
|
||||
|
||||
@import 'tokens';
|
||||
@import 'mixins';
|
||||
@import 'animations';
|
||||
@import 'utilities';
|
||||
|
||||
// === GLOBAL BASE ===
|
||||
|
||||
page {
|
||||
background-color: $color-background;
|
||||
color: $color-foreground;
|
||||
font-family: $font-family-body;
|
||||
font-size: $font-size-base;
|
||||
line-height: $line-height-normal;
|
||||
}
|
||||
|
||||
view, text, scroll-view {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
// === TYPOGRAPHY CLASSES ===
|
||||
|
||||
.heading-display {
|
||||
@include text-display;
|
||||
}
|
||||
|
||||
.body-text {
|
||||
@include text-body;
|
||||
}
|
||||
|
||||
.mono-text {
|
||||
@include text-mono;
|
||||
}
|
||||
Reference in New Issue
Block a user