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:
jacobxu666
2026-06-25 01:07:21 +08:00
co-authored by Claude
parent c062dee3e6
commit 5f1ab737e9
25 changed files with 2110 additions and 390 deletions
+81
View File
@@ -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;
}
}
+66
View File
@@ -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;
}
}
+143
View File
@@ -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;
+145
View File
@@ -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; }
+38
View File
@@ -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;
}