1146 lines
29 KiB
Plaintext
1146 lines
29 KiB
Plaintext
<!-- 消费者端 - 个人中心 -->
|
||
<template>
|
||
<view class="consumer-profile">
|
||
<!-- 智能顶部导航栏 - 与消息页保持一致 -->
|
||
<view class="smart-navbar" :style="{ paddingTop: statusBarHeight + 'px' }">
|
||
<view class="nav-container">
|
||
<!-- 头像 -->
|
||
<image
|
||
:src="userInfo.avatar_url || '/static/default-avatar.png'"
|
||
class="nav-avatar"
|
||
@click="editProfile"
|
||
/>
|
||
|
||
<!-- 用户信息横向排列 (名字、积分、余额、优惠券) -->
|
||
<view class="nav-user-stats">
|
||
<text class="nav-user-name">{{ userInfo.nickname || userInfo.phone }}</text>
|
||
|
||
<view class="nav-stat-item">
|
||
<text class="nav-stat-label">积分</text>
|
||
<text class="nav-stat-value">{{ userStats.points }}</text>
|
||
</view>
|
||
|
||
<view class="nav-stat-item">
|
||
<text class="nav-stat-label">余额</text>
|
||
<text class="nav-stat-value">¥{{ userStats.balance }}</text>
|
||
</view>
|
||
|
||
<view class="nav-stat-item" @click="goToCoupons">
|
||
<text class="nav-stat-label">券</text>
|
||
<text class="nav-stat-value">{{ serviceCounts.coupons }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 设置按钮 (右侧) -->
|
||
<view class="nav-actions">
|
||
<view class="action-btn" @click="goToSettings">
|
||
<text class="action-icon">⚙️</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 导航栏占位符 - 恢复 -->
|
||
<view :style="{ height: (statusBarHeight + 10) + 'px' }"></view>
|
||
|
||
<!-- 我的服务 (移到订单上方) -->
|
||
<view class="my-services" style="margin-top: 10px;">
|
||
<view class="section-title">我的服务</view>
|
||
<view class="service-grid">
|
||
<view class="service-item" @click="goToCoupons">
|
||
<text class="service-icon">🎫</text>
|
||
<text class="service-text">优惠券</text>
|
||
<text v-if="serviceCounts.coupons > 0" class="service-badge">{{ serviceCounts.coupons }}</text>
|
||
</view>
|
||
<view class="service-item" @click="goToAddress">
|
||
<text class="service-icon">📍</text>
|
||
<text class="service-text">收货地址</text>
|
||
</view>
|
||
<view class="service-item" @click="goToFavorites">
|
||
<text class="service-icon">❤️</text>
|
||
<text class="service-text">我的收藏</text>
|
||
<text v-if="serviceCounts.favorites > 0" class="service-badge">{{ serviceCounts.favorites }}</text>
|
||
</view>
|
||
|
||
<view class="service-item" @click="goToFootprint">
|
||
<text class="service-icon">👣</text>
|
||
<text class="service-text">浏览足迹</text>
|
||
</view>
|
||
<view class="service-item" @click="goToRefund">
|
||
<text class="service-icon">🔄</text>
|
||
<text class="service-text">退款/售后</text>
|
||
</view>
|
||
<view class="service-item" @click="contactService">
|
||
<text class="service-icon">💬</text>
|
||
<text class="service-text">在线客服</text>
|
||
</view>
|
||
<view class="service-item" @click="goToMySubscriptions">
|
||
<text class="service-icon">🧩</text>
|
||
<text class="service-text">我的订阅</text>
|
||
</view>
|
||
<view class="service-item" @click="goToSubscriptions">
|
||
<text class="service-icon">📱</text>
|
||
<text class="service-text">软件订阅</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 订单状态快捷入口 -->
|
||
<view class="order-shortcuts">
|
||
<view class="section-title">我的订单</view>
|
||
<view class="order-tabs">
|
||
<view class="order-tab" :class="{ active: currentOrderTab === 'all' }" @click="switchOrderTab('all')">
|
||
<text class="tab-icon">📋</text>
|
||
<text class="tab-text">全部</text>
|
||
<text v-if="orderCounts.total > 0" class="tab-badge">{{ orderCounts.total }}</text>
|
||
</view>
|
||
<view class="order-tab" :class="{ active: currentOrderTab === 'pending' }" @click="switchOrderTab('pending')">
|
||
<text class="tab-icon">💰</text>
|
||
<text class="tab-text">待支付</text>
|
||
<text v-if="orderCounts.pending > 0" class="tab-badge">{{ orderCounts.pending }}</text>
|
||
</view>
|
||
<view class="order-tab" :class="{ active: currentOrderTab === 'shipped' }" @click="switchOrderTab('shipped')">
|
||
<text class="tab-icon">🚚</text>
|
||
<text class="tab-text">待收货</text>
|
||
<text v-if="orderCounts.shipped > 0" class="tab-badge">{{ orderCounts.shipped }}</text>
|
||
</view>
|
||
<view class="order-tab" :class="{ active: currentOrderTab === 'review' }" @click="switchOrderTab('review')">
|
||
<text class="tab-icon">⭐</text>
|
||
<text class="tab-text">待评价</text>
|
||
<text v-if="orderCounts.review > 0" class="tab-badge">{{ orderCounts.review }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 最近订单列表 (根据Tab切换显示) -->
|
||
<view class="recent-orders">
|
||
<view class="section-header">
|
||
<text class="section-title">{{ getOrderSectionTitle() }}</text>
|
||
<text class="view-all" @click="goToOrders(currentOrderTab)">查看更多 ></text>
|
||
</view>
|
||
|
||
<view v-if="filteredOrders.length === 0" class="empty-orders">
|
||
<text class="empty-text">暂无相关订单记录</text>
|
||
<button class="start-shopping" @click="goShopping">去逛逛</button>
|
||
</view>
|
||
|
||
<view v-for="order in filteredOrders" :key="order.id" class="order-item" @click="viewOrderDetail(order)">
|
||
<view class="order-header">
|
||
<text class="order-no">订单号: {{ order.order_no }}</text>
|
||
<text class="order-status" :class="getOrderStatusClass(order.status)">{{ getOrderStatusText(order.status) }}</text>
|
||
</view>
|
||
<view class="order-content">
|
||
<image :src="getOrderMainImage(order)" class="order-image" mode="aspectFill" />
|
||
<view class="order-info">
|
||
<text class="order-title">{{ getOrderTitle(order) }}</text>
|
||
<text class="order-amount">¥{{ order.actual_amount }}</text>
|
||
<text class="order-time">{{ formatTime(order.created_at) }}</text>
|
||
</view>
|
||
</view>
|
||
<view class="order-actions">
|
||
<button v-if="order.status === 1" class="action-btn pay" @click.stop="payOrder(order)">立即支付</button>
|
||
<button v-if="order.status === 3" class="action-btn confirm" @click.stop="confirmReceive(order)">确认收货</button>
|
||
<button v-if="order.status === 4" class="action-btn review" @click.stop="reviewOrder(order)">评价</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 我的服务 -->
|
||
<!-- <view class="my-services">
|
||
<view class="section-title">我的服务</view>
|
||
<view class="service-grid">
|
||
<view class="service-item" @click="goToCoupons">
|
||
<text class="service-icon">🎫</text>
|
||
<text class="service-text">优惠券</text>
|
||
<text v-if="serviceCounts.coupons > 0" class="service-badge">{{ serviceCounts.coupons }}</text>
|
||
</view>
|
||
<view class="service-item" @click="goToAddress">
|
||
<text class="service-icon">📍</text>
|
||
<text class="service-text">收货地址</text>
|
||
</view>
|
||
<view class="service-item" @click="goToFavorites">
|
||
<text class="service-icon">❤️</text>
|
||
<text class="service-text">我的收藏</text>
|
||
<text v-if="serviceCounts.favorites > 0" class="service-badge">{{ serviceCounts.favorites }}</text>
|
||
</view>
|
||
<view class="service-item" @click="goToFootprint">
|
||
<text class="service-icon">👣</text>
|
||
<text class="service-text">浏览足迹</text>
|
||
</view>
|
||
<view class="service-item" @click="goToRefund">
|
||
<text class="service-icon">🔄</text>
|
||
<text class="service-text">退款/售后</text>
|
||
</view>
|
||
<view class="service-item" @click="contactService">
|
||
<text class="service-icon">💬</text>
|
||
<text class="service-text">在线客服</text>
|
||
</view>
|
||
<view class="service-item" @click="goToMySubscriptions">
|
||
<text class="service-icon">🧩</text>
|
||
<text class="service-text">我的订阅</text>
|
||
</view>
|
||
<view class="service-item" @click="goToSubscriptions">
|
||
<text class="service-icon">🧩</text>
|
||
<text class="service-text">软件订阅</text>
|
||
</view>
|
||
</view>
|
||
</view> -->
|
||
|
||
<!-- 消费统计 -->
|
||
<view class="consumption-stats">
|
||
<view class="section-title">消费统计</view>
|
||
<view class="stats-period">
|
||
<text v-for="period in statsPeriods" :key="period.key"
|
||
class="period-tab"
|
||
:class="{ active: activeStatsPeriod === period.key }"
|
||
@click="switchStatsPeriod(period.key)">{{ period.label }}</text>
|
||
</view>
|
||
|
||
<view class="stats-content">
|
||
<view class="stat-card">
|
||
<text class="stat-value">¥{{ currentStats.total_amount }}</text>
|
||
<text class="stat-label">总消费</text>
|
||
</view>
|
||
<view class="stat-card">
|
||
<text class="stat-value">{{ currentStats.order_count }}</text>
|
||
<text class="stat-label">订单数</text>
|
||
</view>
|
||
<view class="stat-card">
|
||
<text class="stat-value">¥{{ currentStats.avg_amount }}</text>
|
||
<text class="stat-label">平均消费</text>
|
||
</view>
|
||
<view class="stat-card">
|
||
<text class="stat-value">{{ currentStats.save_amount }}</text>
|
||
<text class="stat-label">节省金额</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 账户安全 -->
|
||
<view class="account-security">
|
||
<view class="section-title">账户安全</view>
|
||
<view class="security-items">
|
||
<view class="security-item" @click="changePassword">
|
||
<text class="security-icon">🔒</text>
|
||
<text class="security-text">修改密码</text>
|
||
<text class="security-arrow">></text>
|
||
</view>
|
||
<view class="security-item" @click="bindPhone">
|
||
<text class="security-icon">📱</text>
|
||
<text class="security-text">手机绑定</text>
|
||
<view class="security-status">
|
||
<text class="status-text" :class="{ bound: userInfo.phone }">{{ userInfo.phone ? '已绑定' : '未绑定' }}</text>
|
||
<text class="security-arrow">></text>
|
||
</view>
|
||
</view>
|
||
<view class="security-item" @click="bindEmail">
|
||
<text class="security-icon">📧</text>
|
||
<text class="security-text">邮箱绑定</text>
|
||
<view class="security-status">
|
||
<text class="status-text" :class="{ bound: userInfo.email }">{{ userInfo.email ? '已绑定' : '未绑定' }}</text>
|
||
<text class="security-arrow">></text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { UserType, OrderType } from '@/types/mall-types.uts'
|
||
// import { supabase as supa } from '@/components/supadb/aksupainstance.uts'
|
||
|
||
type UserStatsType = {
|
||
points: number
|
||
balance: number
|
||
level: number
|
||
}
|
||
|
||
type OrderCountsType = {
|
||
total: number
|
||
pending: number
|
||
shipped: number
|
||
review: number
|
||
}
|
||
|
||
type ServiceCountsType = {
|
||
coupons: number
|
||
favorites: number
|
||
}
|
||
|
||
type ConsumptionStatsType = {
|
||
total_amount: number
|
||
order_count: number
|
||
avg_amount: number
|
||
save_amount: number
|
||
}
|
||
|
||
type StatsPeriodType = {
|
||
key: string
|
||
label: string
|
||
}
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
userInfo: {
|
||
id: '',
|
||
phone: '',
|
||
email: '',
|
||
nickname: '',
|
||
avatar_url: '',
|
||
gender: 0,
|
||
user_type: 0,
|
||
status: 0,
|
||
created_at: ''
|
||
} as UserType,
|
||
userStats: {
|
||
points: 0,
|
||
balance: 0,
|
||
level: 1
|
||
} as UserStatsType,
|
||
orderCounts: {
|
||
total: 0,
|
||
pending: 0,
|
||
shipped: 0,
|
||
review: 0
|
||
} as OrderCountsType,
|
||
serviceCounts: {
|
||
coupons: 0,
|
||
favorites: 0
|
||
} as ServiceCountsType,
|
||
recentOrders: [] as Array<OrderType>,
|
||
statsPeriods: [
|
||
{ key: 'month', label: '本月' },
|
||
{ key: 'quarter', label: '本季度' },
|
||
{ key: 'year', label: '本年' },
|
||
{ key: 'all', label: '全部' }
|
||
] as Array<StatsPeriodType>,
|
||
activeStatsPeriod: 'month',
|
||
currentStats: {
|
||
total_amount: 0,
|
||
order_count: 0,
|
||
avg_amount: 0,
|
||
save_amount: 0
|
||
} as ConsumptionStatsType,
|
||
statusBarHeight: 0,
|
||
currentOrderTab: 'all' as string, // 当前选中的订单Tab
|
||
allOrders: [] as Array<OrderType> // 存储所有订单数据
|
||
}
|
||
},
|
||
onLoad() {
|
||
this.initPage()
|
||
this.loadUserProfile()
|
||
this.loadOrders()
|
||
},
|
||
onShow() {
|
||
this.refreshData()
|
||
},
|
||
computed: {
|
||
// 根据当前Tab筛选订单
|
||
filteredOrders(): Array<OrderType> {
|
||
if (this.currentOrderTab === 'all') {
|
||
return this.allOrders
|
||
} else if (this.currentOrderTab === 'pending') {
|
||
return this.allOrders.filter((order: OrderType): boolean => order.status === 1)
|
||
} else if (this.currentOrderTab === 'shipped') {
|
||
return this.allOrders.filter((order: OrderType): boolean => order.status === 2 || order.status === 3)
|
||
} else if (this.currentOrderTab === 'review') {
|
||
return this.allOrders.filter((order: OrderType): boolean => order.status === 4)
|
||
}
|
||
return []
|
||
}
|
||
},
|
||
methods: {
|
||
// 加载订单数据
|
||
async loadOrders() {
|
||
const userStore = uni.getStorageSync('userInfo')
|
||
const userId = userStore?.id
|
||
if (!userId) return
|
||
|
||
try {
|
||
/* const { data, error } = await supa
|
||
.from('orders')
|
||
.select('*')
|
||
.eq('user_id', userId)
|
||
.order('created_at', { ascending: false })
|
||
|
||
if (error != null) {
|
||
console.error('加载订单失败', error)
|
||
return
|
||
}
|
||
|
||
if (data != null) {
|
||
this.allOrders = data as any[]
|
||
this.recentOrders = this.allOrders
|
||
|
||
// 更新角标统计
|
||
this.orderCounts = {
|
||
total: this.allOrders.length,
|
||
pending: this.allOrders.filter((o: any) => o.status === 1).length,
|
||
shipped: this.allOrders.filter((o: any) => o.status === 2 || o.status === 3).length,
|
||
review: this.allOrders.filter((o: any) => o.status === 4).length
|
||
}
|
||
} */
|
||
|
||
// MOCK ORDERS
|
||
this.allOrders = this.recentOrders
|
||
this.orderCounts = {
|
||
total: this.allOrders.length,
|
||
pending: this.allOrders.filter((o: any) => o.status === 1).length,
|
||
shipped: this.allOrders.filter((o: any) => o.status === 2 || o.status === 3).length,
|
||
review: this.allOrders.filter((o: any) => o.status === 4).length
|
||
}
|
||
} catch (e) {
|
||
console.error('加载订单异常', e)
|
||
}
|
||
},
|
||
|
||
// 切换订单Tab
|
||
switchOrderTab(tab: string) {
|
||
this.currentOrderTab = tab
|
||
},
|
||
|
||
// 获取当前订单部分标题
|
||
getOrderSectionTitle(): string {
|
||
const titles: Record<string, string> = {
|
||
'all': '全部订单',
|
||
'pending': '待支付订单',
|
||
'shipped': '待收货订单',
|
||
'review': '待评价订单'
|
||
}
|
||
return titles[this.currentOrderTab] || '我的订单'
|
||
},
|
||
|
||
initPage() {
|
||
const systemInfo = uni.getSystemInfoSync()
|
||
this.statusBarHeight = systemInfo.statusBarHeight || 0
|
||
},
|
||
loadUserProfile() {
|
||
// 模拟加载用户信息
|
||
this.userInfo = {
|
||
id: 'user_001',
|
||
phone: '13800138000',
|
||
email: 'user@example.com',
|
||
nickname: '张三',
|
||
avatar_url: '/static/avatar1.jpg',
|
||
gender: 1,
|
||
user_type: 1,
|
||
status: 1,
|
||
created_at: '2023-06-15T10:30:00'
|
||
}
|
||
|
||
this.userStats = {
|
||
points: 1580,
|
||
balance: 268.50,
|
||
level: 3
|
||
}
|
||
|
||
this.orderCounts = {
|
||
total: 23,
|
||
pending: 2,
|
||
shipped: 1,
|
||
review: 3
|
||
}
|
||
|
||
this.serviceCounts = {
|
||
coupons: 5,
|
||
favorites: 12
|
||
}
|
||
|
||
this.recentOrders = [
|
||
{
|
||
id: 'order_001',
|
||
order_no: 'ORD202401150001',
|
||
user_id: 'user_001',
|
||
merchant_id: 'merchant_001',
|
||
status: 3,
|
||
total_amount: 299.98,
|
||
discount_amount: 30.00,
|
||
delivery_fee: 8.00,
|
||
actual_amount: 277.98,
|
||
payment_method: 1,
|
||
payment_status: 1,
|
||
delivery_address: {},
|
||
created_at: '2024-01-15T14:30:00'
|
||
},
|
||
{
|
||
id: 'order_002',
|
||
order_no: 'ORD202401140002',
|
||
user_id: 'user_001',
|
||
merchant_id: 'merchant_002',
|
||
status: 4,
|
||
total_amount: 158.00,
|
||
discount_amount: 0,
|
||
delivery_fee: 6.00,
|
||
actual_amount: 164.00,
|
||
payment_method: 1,
|
||
payment_status: 1,
|
||
delivery_address: {},
|
||
created_at: '2024-01-14T09:20:00'
|
||
}
|
||
]
|
||
|
||
this.loadConsumptionStats()
|
||
},
|
||
|
||
loadConsumptionStats() {
|
||
// 模拟加载消费统计数据
|
||
const statsData: Record<string, ConsumptionStatsType> = {
|
||
month: {
|
||
total_amount: 1280.50,
|
||
order_count: 8,
|
||
avg_amount: 160.06,
|
||
save_amount: 85.20
|
||
},
|
||
quarter: {
|
||
total_amount: 3680.80,
|
||
order_count: 18,
|
||
avg_amount: 204.49,
|
||
save_amount: 256.30
|
||
},
|
||
year: {
|
||
total_amount: 15680.90,
|
||
order_count: 56,
|
||
avg_amount: 280.02,
|
||
save_amount: 986.50
|
||
},
|
||
all: {
|
||
total_amount: 25680.50,
|
||
order_count: 89,
|
||
avg_amount: 288.55,
|
||
save_amount: 1580.20
|
||
}
|
||
}
|
||
|
||
this.currentStats = statsData[this.activeStatsPeriod]
|
||
},
|
||
|
||
refreshData() {
|
||
// 刷新页面数据
|
||
this.loadUserProfile()
|
||
this.loadOrders()
|
||
this.updateCouponCount() // 更新优惠券数量
|
||
},
|
||
|
||
updateCouponCount() {
|
||
// 从本地存储读取领取的优惠券数量并叠加到基础数量上
|
||
const baseCoupons = 5
|
||
const claimedCoupons = uni.getStorageSync('claimedCoupons') || 0
|
||
this.serviceCounts.coupons = baseCoupons + (claimedCoupons as number)
|
||
},
|
||
|
||
getUserLevel(): string {
|
||
const levels = ['新手', '铜牌会员', '银牌会员', '金牌会员', '钻石会员']
|
||
return levels[this.userStats.level] || '新手'
|
||
},
|
||
|
||
getOrderStatusText(status: number): string {
|
||
const statusTexts = ['异常', '待支付', '待发货', '待收货', '已完成', '已取消']
|
||
return statusTexts[status] || '未知'
|
||
},
|
||
|
||
getOrderStatusClass(status: number): string {
|
||
const statusClasses = ['error', 'pending', 'processing', 'shipping', 'completed', 'cancelled']
|
||
return statusClasses[status] || 'error'
|
||
},
|
||
|
||
getOrderMainImage(order: OrderType): string {
|
||
// 模拟获取订单主图
|
||
return '/static/product1.jpg'
|
||
},
|
||
|
||
getOrderTitle(order: OrderType): string {
|
||
// 模拟获取订单标题
|
||
return '精选商品等多件商品'
|
||
},
|
||
|
||
formatTime(timeStr: string): string {
|
||
const date = new Date(timeStr)
|
||
const now = new Date()
|
||
const diff = now.getTime() - date.getTime()
|
||
const days = Math.floor(diff / (1000 * 60 * 60 * 24))
|
||
|
||
if (days === 0) {
|
||
return '今天'
|
||
} else if (days === 1) {
|
||
return '昨天'
|
||
} else {
|
||
return `${days}天前`
|
||
}
|
||
},
|
||
|
||
switchStatsPeriod(period: string) {
|
||
this.activeStatsPeriod = period
|
||
this.loadConsumptionStats()
|
||
},
|
||
|
||
editProfile() {
|
||
uni.navigateTo({
|
||
url: '/pages/mall/consumer/edit-profile'
|
||
})
|
||
},
|
||
|
||
goToSettings() {
|
||
uni.navigateTo({
|
||
url: '/pages/mall/consumer/settings'
|
||
})
|
||
},
|
||
|
||
goToOrders(type: string) {
|
||
uni.navigateTo({
|
||
url: `/pages/mall/consumer/orders?type=${type}`
|
||
})
|
||
},
|
||
|
||
goShopping() {
|
||
uni.switchTab({
|
||
url: '/pages/mall/consumer/index'
|
||
})
|
||
},
|
||
|
||
viewOrderDetail(order: OrderType) {
|
||
uni.navigateTo({
|
||
url: `/pages/mall/consumer/order-detail?orderId=${order.id}`
|
||
})
|
||
},
|
||
|
||
payOrder(order: OrderType) {
|
||
uni.navigateTo({
|
||
url: `/pages/mall/consumer/payment?orderId=${order.id}`
|
||
})
|
||
},
|
||
|
||
confirmReceive(order: OrderType) {
|
||
uni.showModal({
|
||
title: '确认收货',
|
||
content: '确认已收到商品吗?',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
uni.showToast({
|
||
title: '确认收货成功',
|
||
icon: 'success'
|
||
})
|
||
this.refreshData()
|
||
}
|
||
}
|
||
})
|
||
},
|
||
|
||
reviewOrder(order: OrderType) {
|
||
uni.navigateTo({
|
||
url: `/pages/mall/consumer/review?orderId=${order.id}`
|
||
})
|
||
},
|
||
|
||
goToCoupons() {
|
||
uni.navigateTo({
|
||
url: '/pages/mall/consumer/coupons'
|
||
})
|
||
},
|
||
|
||
goToAddress() {
|
||
// 暂时跳转到设置页的地址管理
|
||
uni.navigateTo({
|
||
url: '/pages/mall/consumer/address-list'
|
||
})
|
||
},
|
||
|
||
goToFavorites() {
|
||
uni.navigateTo({
|
||
url: '/pages/mall/consumer/favorites'
|
||
})
|
||
},
|
||
|
||
goToFootprint() {
|
||
uni.navigateTo({
|
||
url: '/pages/mall/consumer/footprint'
|
||
})
|
||
},
|
||
|
||
goToRefund() {
|
||
uni.navigateTo({
|
||
url: '/pages/mall/consumer/refund'
|
||
})
|
||
},
|
||
|
||
contactService() {
|
||
uni.navigateTo({
|
||
url: '/pages/mall/service/chat'
|
||
})
|
||
},
|
||
goToMySubscriptions() {
|
||
uni.navigateTo({
|
||
url: '/pages/mall/consumer/subscription/my-subscriptions'
|
||
})
|
||
},
|
||
goToSubscriptions() {
|
||
uni.navigateTo({
|
||
url: '/pages/mall/consumer/subscription/plan-list'
|
||
})
|
||
},
|
||
|
||
changePassword() {
|
||
uni.navigateTo({
|
||
url: '/pages/mall/consumer/change-password'
|
||
})
|
||
},
|
||
|
||
bindPhone() {
|
||
uni.navigateTo({
|
||
url: '/pages/mall/consumer/bind-phone'
|
||
})
|
||
},
|
||
|
||
bindEmail() {
|
||
uni.navigateTo({
|
||
url: '/pages/mall/consumer/bind-email'
|
||
})
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style>
|
||
.consumer-profile {
|
||
background-color: #f5f5f5;
|
||
min-height: 100vh;
|
||
}
|
||
|
||
/* 智能顶部导航栏 */
|
||
.smart-navbar {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
background: linear-gradient(135deg, #4CAF50 0%, #2E7D32 100%);
|
||
z-index: 1000;
|
||
box-shadow: 0 2px 12px rgba(76, 175, 80, 0.15);
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.nav-container {
|
||
padding: 0 16px;
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
width: 100%;
|
||
max-width: 1400px;
|
||
margin: 0 auto;
|
||
height: 44px;
|
||
}
|
||
|
||
/* 导航栏用户信息区域 */
|
||
.nav-user-stats {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: flex-start; /* 靠左对齐,紧跟头像 */
|
||
margin-right: 12px;
|
||
overflow: hidden; /* 防止溢出 */
|
||
}
|
||
|
||
.nav-user-name {
|
||
font-size: 16px;
|
||
font-weight: bold;
|
||
color: white;
|
||
margin-right: 12px;
|
||
max-width: 30%; /* 限制名字宽度 */
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.nav-stat-item {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
background: rgba(255, 255, 255, 0.2);
|
||
border-radius: 12px;
|
||
padding: 2px 8px;
|
||
margin-right: 8px;
|
||
flex-shrink: 0; /* 防止被压缩 */
|
||
}
|
||
|
||
.nav-stat-label {
|
||
font-size: 11px;
|
||
color: rgba(255, 255, 255, 0.9);
|
||
margin-right: 4px;
|
||
}
|
||
|
||
.nav-stat-value {
|
||
font-size: 12px;
|
||
font-weight: bold;
|
||
color: white;
|
||
}
|
||
|
||
.nav-avatar {
|
||
width: 36px;
|
||
height: 36px;
|
||
border-radius: 18px;
|
||
border: 2px solid rgba(255, 255, 255, 0.8);
|
||
margin-right: 12px;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.nav-actions {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.action-btn {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 32px;
|
||
height: 32px;
|
||
background: rgba(255, 255, 255, 0.2);
|
||
border-radius: 16px;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.action-icon {
|
||
font-size: 18px;
|
||
color: white;
|
||
}
|
||
|
||
/* 导航栏占位符 */
|
||
.navbar-placeholder {
|
||
width: 100%;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.order-shortcuts, .recent-orders, .my-services, .consumption-stats, .account-security {
|
||
background-color: #fff;
|
||
margin: 15px 15px; /* 顶部恢复 margin */
|
||
border-radius: 12px; /* 统一圆角 */
|
||
padding: 20px;
|
||
box-shadow: 0 2px 8px rgba(0,0,0,0.05);
|
||
}
|
||
|
||
.section-title {
|
||
font-size: 16px;
|
||
font-weight: bold;
|
||
color: #333;
|
||
margin-bottom: 16px;
|
||
}
|
||
|
||
.order-tabs {
|
||
display: flex;
|
||
flex-direction: row; /* 显式横向排列 */
|
||
justify-content: space-between;
|
||
width: 100%;
|
||
}
|
||
|
||
.order-tab {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: row; /* 关键:改为横向排列 */
|
||
align-items: center;
|
||
justify-content: center; /* 居中 */
|
||
position: relative;
|
||
padding: 8px 0;
|
||
}
|
||
|
||
.tab-icon {
|
||
font-size: 20px;
|
||
margin-right: 6px; /* 图标和文字间距 */
|
||
margin-bottom: 0; /* 移除底部间距 */
|
||
}
|
||
|
||
.tab-text {
|
||
font-size: 14px;
|
||
color: #333;
|
||
}
|
||
|
||
/* 选中状态的Tab */
|
||
.order-tab.active .tab-icon,
|
||
.order-tab.active .tab-text {
|
||
color: #4CAF50;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.order-tab.active {
|
||
background-color: #f0f9f0;
|
||
border-radius: 8px;
|
||
}
|
||
|
||
.tab-badge {
|
||
position: absolute;
|
||
top: 0;
|
||
right: 10%; /* 调整位置 */
|
||
background-color: #ff4444;
|
||
color: #fff;
|
||
font-size: 10px;
|
||
padding: 1px 5px;
|
||
border-radius: 8px;
|
||
min-width: 14px;
|
||
text-align: center;
|
||
line-height: 1.2;
|
||
}
|
||
|
||
.empty-orders {
|
||
text-align: center;
|
||
padding: 80rpx 0;
|
||
}
|
||
|
||
.empty-text {
|
||
font-size: 28rpx;
|
||
color: #999;
|
||
margin-bottom: 30rpx;
|
||
}
|
||
|
||
.start-shopping {
|
||
background-color: #007aff;
|
||
color: #fff;
|
||
padding: 20rpx 40rpx;
|
||
border-radius: 25rpx;
|
||
font-size: 26rpx;
|
||
border: none;
|
||
}
|
||
|
||
.order-item {
|
||
padding: 25rpx 0;
|
||
border-bottom: 1rpx solid #f5f5f5;
|
||
}
|
||
|
||
.order-item:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.order-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 15rpx;
|
||
}
|
||
|
||
.order-no {
|
||
font-size: 26rpx;
|
||
color: #333;
|
||
}
|
||
|
||
.order-status {
|
||
font-size: 24rpx;
|
||
padding: 6rpx 12rpx;
|
||
border-radius: 10rpx;
|
||
color: #fff;
|
||
}
|
||
|
||
.order-status.pending {
|
||
background-color: #ffa726;
|
||
}
|
||
|
||
.order-status.processing {
|
||
background-color: #2196f3;
|
||
}
|
||
|
||
.order-status.shipping {
|
||
background-color: #9c27b0;
|
||
}
|
||
|
||
.order-status.completed {
|
||
background-color: #4caf50;
|
||
}
|
||
|
||
.order-content {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 15rpx;
|
||
}
|
||
|
||
.order-image {
|
||
width: 100rpx;
|
||
height: 100rpx;
|
||
border-radius: 8rpx;
|
||
margin-right: 20rpx;
|
||
}
|
||
|
||
.order-info {
|
||
flex: 1;
|
||
}
|
||
|
||
.order-title {
|
||
font-size: 26rpx;
|
||
color: #333;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
|
||
.order-amount {
|
||
font-size: 28rpx;
|
||
color: #ff4444;
|
||
font-weight: bold;
|
||
margin-bottom: 5rpx;
|
||
}
|
||
|
||
.order-time {
|
||
font-size: 22rpx;
|
||
color: #999;
|
||
}
|
||
|
||
.order-actions {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
gap: 15rpx;
|
||
}
|
||
|
||
.action-btn {
|
||
padding: 12rpx 25rpx;
|
||
border-radius: 20rpx;
|
||
font-size: 24rpx;
|
||
border: none;
|
||
}
|
||
|
||
.action-btn.pay {
|
||
background-color: #ff4444;
|
||
color: #fff;
|
||
}
|
||
|
||
.action-btn.confirm {
|
||
background-color: #4caf50;
|
||
color: #fff;
|
||
}
|
||
|
||
.action-btn.review {
|
||
background-color: #ffa726;
|
||
color: #fff;
|
||
}
|
||
|
||
.service-grid {
|
||
display: flex;
|
||
flex-direction: row;
|
||
flex-wrap: wrap; /* 允许换行 */
|
||
gap: 16px 0; /* 行间距16px,列间距由 flex 控制 */
|
||
justify-content: flex-start; /* 从左开始排列 */
|
||
}
|
||
|
||
.service-item {
|
||
width: 25%; /* 每行4个 */
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
position: relative;
|
||
box-sizing: border-box; /* 确保 padding 不影响宽度 */
|
||
}
|
||
|
||
.service-icon {
|
||
font-size: 48rpx;
|
||
margin-bottom: 15rpx;
|
||
}
|
||
|
||
.service-text {
|
||
font-size: 24rpx;
|
||
color: #333;
|
||
}
|
||
|
||
.service-badge {
|
||
position: absolute;
|
||
top: -5rpx;
|
||
right: 10rpx;
|
||
background-color: #ff4444;
|
||
color: #fff;
|
||
font-size: 18rpx;
|
||
padding: 4rpx 6rpx;
|
||
border-radius: 8rpx;
|
||
min-width: 24rpx;
|
||
text-align: center;
|
||
}
|
||
|
||
.stats-period {
|
||
display: flex;
|
||
gap: 30rpx;
|
||
margin-bottom: 30rpx;
|
||
}
|
||
|
||
.period-tab {
|
||
font-size: 26rpx;
|
||
color: #666;
|
||
padding: 12rpx 24rpx;
|
||
border-radius: 20rpx;
|
||
background-color: #f0f0f0;
|
||
}
|
||
|
||
.period-tab.active {
|
||
background-color: #007aff;
|
||
color: #fff;
|
||
}
|
||
|
||
.stats-content {
|
||
display: flex;
|
||
gap: 20rpx;
|
||
}
|
||
|
||
.stat-card {
|
||
flex: 1;
|
||
text-align: center;
|
||
padding: 30rpx 0;
|
||
background-color: #f8f9fa;
|
||
border-radius: 10rpx;
|
||
}
|
||
|
||
.stat-value {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #333;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
|
||
.stat-label {
|
||
font-size: 22rpx;
|
||
color: #666;
|
||
}
|
||
|
||
.security-items {
|
||
margin-top: 25rpx;
|
||
}
|
||
|
||
.security-item {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 25rpx 0;
|
||
border-bottom: 1rpx solid #f5f5f5;
|
||
}
|
||
|
||
.security-item:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.security-icon {
|
||
font-size: 32rpx;
|
||
margin-right: 20rpx;
|
||
}
|
||
|
||
.security-text {
|
||
flex: 1;
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
}
|
||
|
||
.security-status {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.status-text {
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
margin-right: 10rpx;
|
||
}
|
||
|
||
.status-text.bound {
|
||
color: #4caf50;
|
||
}
|
||
|
||
.security-arrow {
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
}
|
||
</style>
|