1142 lines
24 KiB
Vue
1142 lines
24 KiB
Vue
<template>
|
||
<view class="page">
|
||
<view class="profile-card">
|
||
<view class="profile-header">
|
||
<view class="avatar-wrapper" @click="uploadAvatar">
|
||
<view class="avatar">
|
||
<image :src="avatarUrl" mode="aspectFill" @error="handleImageError"></image>
|
||
</view>
|
||
<view class="avatar-upload">📷</view>
|
||
</view>
|
||
<view class="profile-info">
|
||
<view class="title-row">
|
||
<text class="name">{{ userInfo.username }}</text>
|
||
<view class="vip-badge">
|
||
<text>品鉴会员</text>
|
||
</view>
|
||
</view>
|
||
<view class="meta-row">
|
||
<text class="meta-item">加入于 2025-01-15</text>
|
||
</view>
|
||
<view class="meta-row">
|
||
<text class="meta-item">上海市浦东新区张江高科技园区</text>
|
||
</view>
|
||
</view>
|
||
<view class="edit-btn" @click="navigateTo('/pages/my/editInfo/index')">编辑资料</view>
|
||
</view>
|
||
<view class="stats-grid">
|
||
<view class="stat-card" v-for="item in stats" :key="item.label">
|
||
<view class="stat-icon" :style="{ color: item.color }">{{ item.icon }}</view>
|
||
<text class="stat-value" :style="{ color: item.color }">{{ item.value }}</text>
|
||
<text class="stat-label">{{ item.label }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="tabs">
|
||
<view class="tab-item" v-for="(tab, index) in tabs" :key="tab" :class="{ active: index === currentTab }"
|
||
@click="handleTabClick(index)">
|
||
{{ tab }}
|
||
</view>
|
||
</view>
|
||
|
||
<view class="monthly-card" v-if="currentTab === 0">
|
||
<view class="monthly-title">本月数据</view>
|
||
<view class="monthly-list">
|
||
<view class="monthly-item" v-for="item in monthlyData" :key="item.label">
|
||
<text class="monthly-label">{{ item.label }}</text>
|
||
<text class="monthly-value" :style="{ color: item.color || '#1A1A1A' }">
|
||
{{ item.value }}
|
||
</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="orders-card" v-if="currentTab === 1">
|
||
<view class="orders-header">
|
||
<text class="orders-title">我的订单</text>
|
||
<view class="orders-more">查看全部</view>
|
||
</view>
|
||
<view class="order-list">
|
||
<view class="order-item" v-for="order in orders" :key="order.no">
|
||
<view class="order-top">
|
||
<text class="order-no">{{ order.no }}</text>
|
||
<view class="order-tags">
|
||
<view class="order-tag type">{{ order.type }}</view>
|
||
<view class="order-tag status" :class="order.statusClass">{{ order.status }}</view>
|
||
</view>
|
||
<text class="order-date">{{ order.date }}</text>
|
||
</view>
|
||
<view class="order-body">
|
||
<view class="order-thumb">60x60</view>
|
||
<view class="order-info">
|
||
<text class="order-name">{{ order.product }}</text>
|
||
<text class="order-spec">{{ order.spec }}</text>
|
||
</view>
|
||
</view>
|
||
<view class="order-footer">
|
||
<view class="order-amount">
|
||
<text class="amount-label">订单总额</text>
|
||
<text class="amount-value">{{ order.amount }}</text>
|
||
</view>
|
||
<view class="order-actions">
|
||
<view class="order-action" v-for="action in order.actions" :key="action.label">
|
||
{{ action.label }}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="favorites-card" v-if="currentTab === 2">
|
||
<view class="favorites-wrapper">
|
||
<view class="favorite-item" v-for="favorite in favorites" :key="favorite.title">
|
||
<view class="favorite-thumb">150x150</view>
|
||
<view class="favorite-info">
|
||
<view class="favorite-top">
|
||
<text class="favorite-title">{{ favorite.title }}</text>
|
||
<view class="favorite-heart">♡</view>
|
||
</view>
|
||
<view class="favorite-meta">
|
||
<text class="favorite-rating">⭐ {{ favorite.rating }}</text>
|
||
<text class="favorite-count">({{ favorite.count }})</text>
|
||
</view>
|
||
<view class="favorite-price">
|
||
<text class="favorite-current">{{ favorite.price }}</text>
|
||
<text class="favorite-origin">{{ favorite.origin }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="achievements-card" v-if="currentTab === 3">
|
||
<view class="achievement-item" v-for="achievement in achievements" :key="achievement.title"
|
||
:class="{ highlight: achievement.highlight }">
|
||
<view class="achievement-left">
|
||
<view class="achievement-icon" :style="{ backgroundColor: achievement.iconBg }">
|
||
<text class="achievement-icon-text">{{ achievement.icon }}</text>
|
||
</view>
|
||
<view class="achievement-info">
|
||
<text class="achievement-title">{{ achievement.title }}</text>
|
||
<text class="achievement-desc">{{ achievement.desc }}</text>
|
||
<view class="achievement-progress" v-if="achievement.progressText">
|
||
<view class="achievement-progress-bar">
|
||
<view class="achievement-progress-fill"
|
||
:style="{ width: achievement.progress + '%' }"></view>
|
||
</view>
|
||
<text class="achievement-progress-text">{{ achievement.progressText }}</text>
|
||
</view>
|
||
<text class="achievement-reward">奖励:{{ achievement.reward }}</text>
|
||
</view>
|
||
</view>
|
||
<text class="achievement-trophy">{{ achievement.trophy }}</text>
|
||
</view>
|
||
</view>
|
||
<view class="settings-card" v-if="currentTab === 4">
|
||
<view class="settings-section">
|
||
<text class="settings-section-title">账户设置</text>
|
||
<view class="settings-list">
|
||
<view class="settings-item" v-for="item in accountSettings" :key="item.title">
|
||
<view class="settings-left">
|
||
<view class="settings-icon">{{ item.icon }}</view>
|
||
<view class="settings-text">
|
||
<text class="settings-title">{{ item.title }}</text>
|
||
<text class="settings-desc">{{ item.desc }}</text>
|
||
</view>
|
||
</view>
|
||
<text class="settings-arrow">›</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="settings-section">
|
||
<text class="settings-section-title">其他设置</text>
|
||
<view class="settings-list">
|
||
<view class="settings-item" v-for="item in otherSettings" :key="item.title">
|
||
<view class="settings-left">
|
||
<view class="settings-icon">{{ item.icon }}</view>
|
||
<view class="settings-text">
|
||
<text class="settings-title">{{ item.title }}</text>
|
||
<text class="settings-desc">{{ item.desc }}</text>
|
||
</view>
|
||
</view>
|
||
<text class="settings-arrow">›</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="logout-btn">退出登录</view>
|
||
</view>
|
||
<view class="quick-card">
|
||
<view class="quick-title">快捷功能</view>
|
||
<view class="quick-grid">
|
||
<view class="quick-item" v-for="action in quickActions" :key="action.label" @click="handleQuickAction(action)">
|
||
<view class="quick-icon">{{ action.icon }}</view>
|
||
<text class="quick-label">{{ action.label }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import request from '@/api/request.js';
|
||
import uploadFile from '@/api/upload.js';
|
||
export default {
|
||
data() {
|
||
return {
|
||
userInfo: {},
|
||
currentTab: 0,
|
||
stats: [
|
||
{ icon: '🎁', value: '1280', label: '当前积分', color: '#7B43FF' },
|
||
{ icon: '🛍️', value: '23', label: '总订单数', color: '#2877FF' },
|
||
{ icon: '📈', value: '¥321', label: '累计省钱', color: '#26B95A' },
|
||
{ icon: '👥', value: '8', label: '团队人数', color: '#FF7A00' }
|
||
],
|
||
tabs: ['概览', '订单', '收藏', '成就', '设置'],
|
||
monthlyData: [
|
||
{ label: '本月订单', value: '5单' },
|
||
{ label: '本月消费', value: '¥450.00', color: '#26B95A' },
|
||
{ label: '分享次数', value: '18次', color: '#7B43FF' },
|
||
{ label: '分销佣金', value: '¥568.00', color: '#FF7A00' }
|
||
],
|
||
quickActions: [
|
||
{ icon: '💳', label: '我的钱包' },
|
||
{ icon: '📍', label: '地址管理', path: '/pages/address/index' },
|
||
{ icon: '🔔', label: '消息通知' },
|
||
{ icon: '❓', label: '帮助中心' }
|
||
],
|
||
favorites: [
|
||
{
|
||
title: '经典玫瑰香水30ml',
|
||
rating: '4.8',
|
||
count: 1250,
|
||
price: '¥199',
|
||
origin: '¥299'
|
||
}
|
||
],
|
||
achievements: [
|
||
{
|
||
title: '拼团达人',
|
||
desc: '成功参与10次拼团',
|
||
progress: 80,
|
||
progressText: '8/10',
|
||
reward: '专属优惠券',
|
||
icon: '👥',
|
||
iconBg: '#f3f4f8',
|
||
trophy: '',
|
||
highlight: false
|
||
},
|
||
{
|
||
title: '分享达人',
|
||
desc: '分享商品20次',
|
||
progress: 90,
|
||
progressText: '18/20',
|
||
reward: '500积分',
|
||
icon: '🔗',
|
||
iconBg: '#f3f4f8',
|
||
trophy: '',
|
||
highlight: false
|
||
},
|
||
{
|
||
title: '消费达人',
|
||
desc: '累计消费满2000元',
|
||
progress: 100,
|
||
progressText: '',
|
||
reward: 'VIP会员体验',
|
||
icon: '🛍️',
|
||
iconBg: '#ffeeb7',
|
||
trophy: '🏆',
|
||
highlight: true
|
||
}
|
||
],
|
||
accountSettings: [
|
||
{ icon: '👤', title: '个人信息', desc: '姓名、手机、邮箱' },
|
||
{ icon: '🛡️', title: '账户安全', desc: '密码、支付设置' },
|
||
{ icon: '🔔', title: '通知设置', desc: '消息推送偏好' }
|
||
],
|
||
otherSettings: [
|
||
{ icon: '📄', title: '隐私政策', desc: '查看隐私条款' },
|
||
{ icon: '❓', title: '帮助中心', desc: '常见问题解答' }
|
||
],
|
||
orders: [
|
||
{
|
||
no: 'ORD20250402001',
|
||
type: '拼团订单',
|
||
status: '已完成',
|
||
statusClass: 'success',
|
||
date: '2025-04-02',
|
||
product: '经典玫瑰香水30ml',
|
||
spec: '¥199 × 1',
|
||
amount: '¥199.00',
|
||
actions: [{ label: '查看详情' }, { label: '再次购买' }]
|
||
},
|
||
{
|
||
no: 'ORD20250401001',
|
||
type: '秒杀订单',
|
||
status: '待收货',
|
||
statusClass: 'warning',
|
||
date: '2025-04-01',
|
||
product: '小样体验包',
|
||
spec: '¥1 × 1',
|
||
amount: '¥1.00',
|
||
actions: [{ label: '查看详情' }]
|
||
},
|
||
{
|
||
no: 'ORD20250328001',
|
||
type: '普通订单',
|
||
status: '待付款',
|
||
statusClass: 'pending',
|
||
date: '2025-03-28',
|
||
product: '薰衣草精油礼盒',
|
||
spec: '¥299 × 1',
|
||
amount: '¥299.00',
|
||
actions: [{ label: '查看详情' }]
|
||
}
|
||
]
|
||
};
|
||
},
|
||
computed: {
|
||
avatarUrl() {
|
||
// 如果有头像URL且不为空,则使用头像URL,否则使用默认头像
|
||
if (this.userInfo && this.userInfo.avatar_url && this.userInfo.avatar_url.trim() !== '') {
|
||
return this.userInfo.avatar_url;
|
||
}
|
||
// 默认头像:使用base64编码的SVG头像占位符(预编码,兼容所有平台)
|
||
// 这是一个圆形灰色背景,带有用户图标的默认头像
|
||
return 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYwIiBoZWlnaHQ9IjE2MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48Y2lyY2xlIGN4PSI4MCIgY3k9IjgwIiByPSI4MCIgZmlsbD0iI2U1ZTdlYSIvPjxjaXJjbGUgY3g9IjgwIiBjeT0iNjUiIHI9IjI1IiBmaWxsPSIjOWZhMGFmIi8+PHBhdGggZD0iTSA4MCAxMDAgUSA1MCAxMDAgNTAgMTMwIEwgNTAgMTYwIEwgMTEwIDE2MCBMIDExMCAxMzAgUSAxMTAgMTAwIDgwIDEwMCBaIiBmaWxsPSIjOWZhMGFmIi8+PC9zdmc+';
|
||
}
|
||
},
|
||
onShow: function () {
|
||
const token = wx.getStorageSync('access_token');
|
||
if (!token) {
|
||
uni.navigateTo({
|
||
url: '/pages/login/index'
|
||
});
|
||
return;
|
||
} else {
|
||
this.loadProfile();
|
||
}
|
||
},
|
||
methods: {
|
||
handleImageError(e) {
|
||
// 图片加载失败时,使用默认头像
|
||
console.log('头像加载失败,使用默认头像', e);
|
||
},
|
||
loadProfile() {
|
||
try {
|
||
request('xcx/get_user_info', 'GET').then(res => {
|
||
this.userInfo = res
|
||
});
|
||
} catch (error) {
|
||
console.warn('加载个人信息失败', error);
|
||
}
|
||
},
|
||
uploadAvatar() {
|
||
console.log('uploadAvatar 被点击');
|
||
uni.chooseImage({
|
||
count: 1,
|
||
mediaType: ['image'],
|
||
sizeType: ['compressed', 'original'],
|
||
sourceType: ['album', 'camera'],
|
||
success: (res) => {
|
||
console.log('选择图片成功', res);
|
||
const tempFilePaths = res.tempFilePaths;
|
||
if (tempFilePaths && tempFilePaths.length > 0) {
|
||
uni.showLoading({
|
||
title: '上传中...'
|
||
});
|
||
uploadFile(tempFilePaths[0]).then((res) => {
|
||
console.log('上传成功', res);
|
||
this.userInfo.avatar_url = res;
|
||
request('xcx/set_user_info', 'POST', {
|
||
avatar_url: res,
|
||
username: this.userInfo.username,
|
||
sex: this.userInfo.sex,
|
||
mobile: this.userInfo.mobile,
|
||
}).then(res => {
|
||
uni.hideLoading({
|
||
title: '上传成功...'
|
||
});
|
||
console.log('设置头像成功', res);
|
||
}).catch((err) => {
|
||
uni.hideLoading({
|
||
title: '上传失败...'
|
||
});
|
||
console.error('设置头像失败', err);
|
||
})
|
||
});
|
||
}
|
||
},
|
||
fail: (err) => {
|
||
console.error('选择图片失败', err);
|
||
uni.showToast({
|
||
title: '选择图片失败',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
});
|
||
},
|
||
handleTabClick(index) {
|
||
this.currentTab = index;
|
||
},
|
||
navigateTo(url) {
|
||
uni.navigateTo({
|
||
url: url
|
||
});
|
||
},
|
||
handleQuickAction(action) {
|
||
if (action.path) {
|
||
this.navigateTo(action.path);
|
||
return;
|
||
}
|
||
this.$nextTick(() => {
|
||
uni.showToast({
|
||
title: '功能开发中',
|
||
icon: 'none'
|
||
});
|
||
});
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.page {
|
||
min-height: 100vh;
|
||
/* padding: 24rpx; */
|
||
background-color: #fff;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 24rpx;
|
||
padding-bottom: 24rpx;
|
||
}
|
||
|
||
.profile-card {
|
||
background-color: #ffffff;
|
||
/* border-radius: 24rpx; */
|
||
|
||
padding-bottom: 24rpx;
|
||
}
|
||
|
||
.profile-header {
|
||
background: linear-gradient(135deg, #8b40ff 0%, #ff3c8d 100%);
|
||
/* border-radius: 24rpx 24rpx 0 0; */
|
||
padding: 40rpx 32rpx;
|
||
display: flex;
|
||
align-items: flex-start;
|
||
gap: 24rpx;
|
||
color: #ffffff;
|
||
position: relative;
|
||
}
|
||
|
||
.avatar-wrapper {
|
||
position: relative;
|
||
}
|
||
|
||
.avatar {
|
||
width: 160rpx;
|
||
height: 160rpx;
|
||
border-radius: 50%;
|
||
background-color: rgba(255, 255, 255, 0.2);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 26rpx;
|
||
color: #ffffff;
|
||
border: 4rpx solid rgba(255, 255, 255, 0.4);
|
||
position: relative;
|
||
z-index: 0;
|
||
image {
|
||
width: 100%;
|
||
height: 100%;
|
||
border-radius: 50%;
|
||
}
|
||
}
|
||
|
||
.avatar-upload {
|
||
width: 56rpx;
|
||
height: 56rpx;
|
||
border-radius: 50%;
|
||
background-color: #ffffff;
|
||
color: #8b40ff;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
position: absolute;
|
||
z-index: 10;
|
||
bottom: 0;
|
||
right: 0;
|
||
font-size: 32rpx;
|
||
box-shadow: 0 8rpx 16rpx rgba(0, 0, 0, 0.1);
|
||
pointer-events: auto;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.profile-info {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 16rpx;
|
||
}
|
||
|
||
.title-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 16rpx;
|
||
}
|
||
|
||
.name {
|
||
font-size: 40rpx;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.vip-badge {
|
||
background-color: rgba(255, 255, 255, 0.2);
|
||
border-radius: 999rpx;
|
||
padding: 8rpx 20rpx;
|
||
font-size: 24rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.vip-badge text {
|
||
color: #ffe178;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.meta-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12rpx;
|
||
font-size: 24rpx;
|
||
opacity: 0.88;
|
||
}
|
||
|
||
.meta-item {
|
||
color: rgba(255, 255, 255, 0.9);
|
||
}
|
||
|
||
.edit-btn {
|
||
position: absolute;
|
||
right: 32rpx;
|
||
top: 40rpx;
|
||
padding: 12rpx 28rpx;
|
||
border-radius: 999rpx;
|
||
background-color: rgba(255, 255, 255, 0.15);
|
||
border: 2rpx solid rgba(255, 255, 255, 0.5);
|
||
font-size: 24rpx;
|
||
}
|
||
|
||
.stats-grid {
|
||
padding: 32rpx;
|
||
display: grid;
|
||
grid-template-columns: repeat(2, 1fr);
|
||
gap: 24rpx;
|
||
|
||
}
|
||
|
||
.stat-card {
|
||
background-color: #f9f9ff;
|
||
border-radius: 24rpx;
|
||
padding: 32rpx 24rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 12rpx;
|
||
box-shadow: inset 0 0 0 2rpx rgba(139, 64, 255, 0.05);
|
||
}
|
||
|
||
.stat-icon {
|
||
font-size: 44rpx;
|
||
}
|
||
|
||
.stat-value {
|
||
font-size: 44rpx;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.stat-label {
|
||
font-size: 26rpx;
|
||
color: #5f5f5f;
|
||
}
|
||
|
||
.tabs {
|
||
display: flex;
|
||
background-color: #ffffff;
|
||
border-radius: 999rpx;
|
||
padding: 12rpx;
|
||
margin: 0 24rpx;
|
||
gap: 12rpx;
|
||
box-shadow: 0 12rpx 24rpx 0 rgba(123, 67, 255, 0.08);
|
||
}
|
||
|
||
.tab-item {
|
||
flex: 1;
|
||
text-align: center;
|
||
padding: 16rpx 0;
|
||
border-radius: 999rpx;
|
||
font-size: 28rpx;
|
||
color: #757c8e;
|
||
}
|
||
|
||
.tab-item.active {
|
||
background: linear-gradient(135deg, #8b40ff 0%, #ff3c8d 100%);
|
||
color: #ffffff;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.monthly-card {
|
||
background-color: #ffffff;
|
||
border-radius: 24rpx;
|
||
padding: 32rpx;
|
||
margin: 0 24rpx;
|
||
box-shadow: 0 12rpx 24rpx 0 rgba(123, 67, 255, 0.08);
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 24rpx;
|
||
}
|
||
|
||
.monthly-title {
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
color: #1a1a1a;
|
||
}
|
||
|
||
.monthly-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 24rpx;
|
||
}
|
||
|
||
.monthly-item {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
font-size: 28rpx;
|
||
color: #404040;
|
||
}
|
||
|
||
.monthly-label {
|
||
color: #757c8e;
|
||
}
|
||
|
||
.monthly-value {
|
||
font-weight: 600;
|
||
}
|
||
|
||
.quick-card {
|
||
background-color: #ffffff;
|
||
border-radius: 24rpx;
|
||
padding: 32rpx;
|
||
margin: 0 24rpx;
|
||
box-shadow: 0 12rpx 24rpx 0 rgba(123, 67, 255, 0.08);
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 32rpx;
|
||
}
|
||
|
||
.quick-title {
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
color: #1a1a1a;
|
||
}
|
||
|
||
.quick-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(2, 1fr);
|
||
gap: 24rpx;
|
||
}
|
||
|
||
.quick-item {
|
||
background-color: #f6f8ff;
|
||
border-radius: 24rpx;
|
||
padding: 32rpx 24rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 16rpx;
|
||
border: 2rpx solid rgba(79, 116, 255, 0.1);
|
||
box-shadow: 0 6rpx 18rpx rgba(79, 116, 255, 0.08);
|
||
}
|
||
|
||
.quick-icon {
|
||
font-size: 48rpx;
|
||
color: #1a274c;
|
||
}
|
||
|
||
.quick-label {
|
||
font-size: 28rpx;
|
||
color: #1a274c;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.favorites-card {
|
||
margin: 0 24rpx;
|
||
padding: 24rpx 24rpx 36rpx;
|
||
background-color: #ffffff;
|
||
box-shadow: 0 12rpx 24rpx 0 rgba(123, 67, 255, 0.08);
|
||
border-radius: 24rpx;
|
||
}
|
||
|
||
.favorites-wrapper {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 24rpx;
|
||
}
|
||
|
||
.favorite-item {
|
||
background-color: #f6f8ff;
|
||
border-radius: 24rpx;
|
||
padding: 24rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 24rpx;
|
||
border: 2rpx solid rgba(79, 116, 255, 0.12);
|
||
box-shadow: inset 0 0 0 2rpx rgba(79, 116, 255, 0.04);
|
||
}
|
||
|
||
.favorite-thumb {
|
||
width: 100%;
|
||
height: 400rpx;
|
||
border-radius: 16rpx;
|
||
background-color: #eef2ff;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 44rpx;
|
||
color: #b3bac9;
|
||
}
|
||
|
||
.favorite-info {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 12rpx;
|
||
}
|
||
|
||
.favorite-top {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.favorite-title {
|
||
font-size: 30rpx;
|
||
color: #273248;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.favorite-heart {
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
border-radius: 12rpx;
|
||
background-color: #ffffff;
|
||
box-shadow: 0 6rpx 18rpx rgba(79, 116, 255, 0.08);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 26rpx;
|
||
color: #273248;
|
||
}
|
||
|
||
.favorite-meta {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12rpx;
|
||
font-size: 24rpx;
|
||
color: #8c94a3;
|
||
}
|
||
|
||
.favorite-rating {
|
||
color: #ffb400;
|
||
}
|
||
|
||
.favorite-price {
|
||
display: flex;
|
||
align-items: baseline;
|
||
gap: 12rpx;
|
||
}
|
||
|
||
.favorite-current {
|
||
font-size: 32rpx;
|
||
color: #ff2e2e;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.favorite-origin {
|
||
font-size: 26rpx;
|
||
color: #b3bac9;
|
||
text-decoration: line-through;
|
||
}
|
||
|
||
.settings-card {
|
||
margin: 0 24rpx;
|
||
padding: 24rpx;
|
||
background-color: #ffffff;
|
||
box-shadow: 0 12rpx 24rpx 0 rgba(123, 67, 255, 0.08);
|
||
border-radius: 24rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 32rpx;
|
||
}
|
||
|
||
.settings-section {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 24rpx;
|
||
background-color: #f8faff;
|
||
padding: 24rpx;
|
||
border-radius: 24rpx;
|
||
border: 2rpx solid rgba(79, 116, 255, 0.08);
|
||
box-shadow: inset 0 0 0 2rpx rgba(79, 116, 255, 0.04);
|
||
}
|
||
|
||
.settings-section-title {
|
||
font-size: 30rpx;
|
||
font-weight: 600;
|
||
color: #1a1a1a;
|
||
}
|
||
|
||
.settings-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 20rpx;
|
||
}
|
||
|
||
.settings-item {
|
||
background-color: #ffffff;
|
||
border-radius: 20rpx;
|
||
padding: 24rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
border: 2rpx solid rgba(79, 116, 255, 0.1);
|
||
box-shadow: 0 8rpx 18rpx rgba(79, 116, 255, 0.06);
|
||
}
|
||
|
||
.settings-left {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 20rpx;
|
||
}
|
||
|
||
.settings-icon {
|
||
width: 72rpx;
|
||
height: 72rpx;
|
||
border-radius: 20rpx;
|
||
background-color: #f0f4ff;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 34rpx;
|
||
color: #4f74ff;
|
||
}
|
||
|
||
.settings-text {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8rpx;
|
||
}
|
||
|
||
.settings-title {
|
||
font-size: 28rpx;
|
||
color: #273248;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.settings-desc {
|
||
font-size: 24rpx;
|
||
color: #8c94a3;
|
||
}
|
||
|
||
.settings-arrow {
|
||
font-size: 36rpx;
|
||
color: #c4cad6;
|
||
}
|
||
|
||
.logout-btn {
|
||
margin-top: 8rpx;
|
||
padding: 28rpx 0;
|
||
text-align: center;
|
||
border-radius: 20rpx;
|
||
border: 2rpx solid rgba(255, 99, 132, 0.2);
|
||
color: #ff4d6d;
|
||
font-size: 28rpx;
|
||
background-color: rgba(255, 99, 132, 0.08);
|
||
}
|
||
|
||
.achievements-card {
|
||
margin: 0 24rpx;
|
||
padding: 24rpx;
|
||
background-color: #ffffff;
|
||
box-shadow: 0 12rpx 24rpx 0 rgba(123, 67, 255, 0.08);
|
||
border-radius: 24rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 24rpx;
|
||
}
|
||
|
||
.achievement-item {
|
||
background-color: #f8faff;
|
||
border-radius: 24rpx;
|
||
padding: 24rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
border: 2rpx solid rgba(79, 116, 255, 0.08);
|
||
box-shadow: inset 0 0 0 2rpx rgba(79, 116, 255, 0.04);
|
||
}
|
||
|
||
.achievement-item.highlight {
|
||
background: linear-gradient(135deg, rgba(255, 238, 183, 0.55), rgba(255, 255, 255, 0.9));
|
||
border: 2rpx solid rgba(255, 200, 64, 0.5);
|
||
}
|
||
|
||
.achievement-left {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 24rpx;
|
||
flex: 1;
|
||
}
|
||
|
||
.achievement-icon {
|
||
width: 100rpx;
|
||
height: 100rpx;
|
||
border-radius: 999rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.achievement-icon-text {
|
||
font-size: 40rpx;
|
||
}
|
||
|
||
.achievement-info {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 12rpx;
|
||
}
|
||
|
||
.achievement-title {
|
||
font-size: 30rpx;
|
||
color: #273248;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.achievement-desc {
|
||
font-size: 24rpx;
|
||
color: #8c94a3;
|
||
}
|
||
|
||
.achievement-progress {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 16rpx;
|
||
margin-top: 12rpx;
|
||
}
|
||
|
||
.achievement-progress-bar {
|
||
flex: 1;
|
||
height: 18rpx;
|
||
border-radius: 12rpx;
|
||
background-color: rgba(79, 116, 255, 0.15);
|
||
overflow: hidden;
|
||
}
|
||
|
||
.achievement-progress-fill {
|
||
height: 100%;
|
||
border-radius: 12rpx;
|
||
background: linear-gradient(135deg, #fccc75, #f5b34b);
|
||
}
|
||
|
||
.achievement-progress-text {
|
||
font-size: 24rpx;
|
||
color: #273248;
|
||
}
|
||
|
||
.achievement-reward {
|
||
margin-top: 16rpx;
|
||
font-size: 24rpx;
|
||
color: #f5b34b;
|
||
padding: 16rpx 20rpx;
|
||
background-color: rgba(255, 190, 60, 0.15);
|
||
border-radius: 16rpx;
|
||
}
|
||
|
||
.achievement-trophy {
|
||
font-size: 44rpx;
|
||
color: #f5b34b;
|
||
align-self: flex-start;
|
||
}
|
||
|
||
.orders-card {
|
||
background-color: #ffffff;
|
||
padding: 32rpx;
|
||
margin: 0 24rpx;
|
||
box-shadow: 0 12rpx 24rpx 0 rgba(123, 67, 255, 0.08);
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 32rpx;
|
||
}
|
||
|
||
.orders-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
}
|
||
|
||
.orders-title {
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
color: #1a1a1a;
|
||
}
|
||
|
||
.orders-more {
|
||
font-size: 24rpx;
|
||
color: #4f5f7a;
|
||
padding: 12rpx 28rpx;
|
||
border-radius: 999rpx;
|
||
background-color: #f2f7ff;
|
||
}
|
||
|
||
.order-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 24rpx;
|
||
}
|
||
|
||
.order-item {
|
||
background-color: #ffffff;
|
||
border-radius: 24rpx;
|
||
border: 2rpx solid rgba(79, 116, 255, 0.12);
|
||
padding: 32rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 24rpx;
|
||
box-shadow: 0 10rpx 26rpx rgba(79, 116, 255, 0.06);
|
||
}
|
||
|
||
.order-top {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 16rpx;
|
||
}
|
||
|
||
.order-no {
|
||
font-size: 26rpx;
|
||
color: #212a3a;
|
||
font-weight: 600;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.order-tags {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12rpx;
|
||
}
|
||
|
||
.order-tag {
|
||
font-size: 22rpx;
|
||
padding: 8rpx 20rpx;
|
||
border-radius: 999rpx;
|
||
}
|
||
|
||
.order-tag.type {
|
||
background-color: rgba(79, 116, 255, 0.12);
|
||
color: #4f74ff;
|
||
}
|
||
|
||
.order-tag.status {
|
||
color: #ffffff;
|
||
}
|
||
|
||
.order-tag.status.success {
|
||
background-color: #6cd198;
|
||
}
|
||
|
||
.order-tag.status.warning {
|
||
background-color: #c79bff;
|
||
}
|
||
|
||
.order-tag.status.pending {
|
||
background-color: #f7c96b;
|
||
color: #5a3b00;
|
||
}
|
||
|
||
.order-date {
|
||
margin-left: auto;
|
||
font-size: 24rpx;
|
||
color: #8c94a3;
|
||
}
|
||
|
||
.order-body {
|
||
display: flex;
|
||
gap: 24rpx;
|
||
}
|
||
|
||
.order-thumb {
|
||
width: 120rpx;
|
||
height: 120rpx;
|
||
border-radius: 16rpx;
|
||
background-color: #eef2ff;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 24rpx;
|
||
color: #8c94a3;
|
||
}
|
||
|
||
.order-info {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 12rpx;
|
||
justify-content: center;
|
||
}
|
||
|
||
.order-name {
|
||
font-size: 30rpx;
|
||
color: #273248;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.order-spec {
|
||
font-size: 24rpx;
|
||
color: #8c94a3;
|
||
}
|
||
|
||
.order-footer {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 24rpx;
|
||
}
|
||
|
||
.order-amount {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12rpx;
|
||
}
|
||
|
||
.amount-label {
|
||
font-size: 24rpx;
|
||
color: #8c94a3;
|
||
}
|
||
|
||
.amount-value {
|
||
font-size: 32rpx;
|
||
color: #ff2e2e;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.order-actions {
|
||
margin-left: auto;
|
||
display: flex;
|
||
gap: 20rpx;
|
||
}
|
||
|
||
.order-action {
|
||
padding: 12rpx 28rpx;
|
||
border-radius: 999rpx;
|
||
border: 2rpx solid rgba(79, 116, 255, 0.35);
|
||
font-size: 24rpx;
|
||
color: #4f5f7a;
|
||
}
|
||
</style> |