wx-shop/pages/my/index.vue
2025-11-13 22:53:09 +08:00

1060 lines
21 KiB
Vue
Raw 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.

<template>
<view class="page">
<view class="profile-card">
<view class="profile-header">
<view class="avatar-wrapper">
<view class="avatar">100x100</view>
<view class="avatar-upload">📷</view>
</view>
<view class="profile-info">
<view class="title-row">
<text class="name">香香公主</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"
>
<view class="quick-icon">{{ action.icon }}</view>
<text class="quick-label">{{ action.label }}</text>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
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: '地址管理' },
{ 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: '查看详情' }]
}
]
};
},
methods: {
handleTabClick(index) {
this.currentTab = index;
},
navigateTo(url) {
uni.navigateTo({
url: url
});
}
}
};
</script>
<style scoped>
.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);
}
.avatar-upload {
width: 56rpx;
height: 56rpx;
border-radius: 50%;
background-color: #ffffff;
color: #8b40ff;
display: flex;
align-items: center;
justify-content: center;
position: absolute;
bottom: 0;
right: 0;
font-size: 32rpx;
box-shadow: 0 8rpx 16rpx rgba(0, 0, 0, 0.1);
}
.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>