All checks were successful
continuous-integration/drone/push Build is passing
360 lines
8.7 KiB
Vue
360 lines
8.7 KiB
Vue
<template>
|
||
<view class="mine-page">
|
||
<!-- 顶部渐变导航栏 -->
|
||
<view class="header-bg">
|
||
<view :style="{ height: statusBarHeight + 'px' }"></view>
|
||
<view class="nav-bar">
|
||
<text class="nav-title">我的</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 用户信息卡片 -->
|
||
<view class="user-card" @click="onUserClick">
|
||
<image class="user-avatar" :src="userInfo.avatarUrl || '/static/logo.png'" mode="aspectFill"></image>
|
||
<view class="user-info">
|
||
<text class="user-name">{{ isLoggedIn ? (userInfo.nickname || '用户') : '点击注册/登录' }}</text>
|
||
<text class="user-uid" v-if="isLoggedIn">UID:{{ userInfo.uid || userInfo.id }}</text>
|
||
</view>
|
||
<image class="arrow-icon" src="/static/ic_arrow.png" mode="aspectFit"></image>
|
||
</view>
|
||
|
||
<!-- 我的订单 -->
|
||
<view class="card" @click="goMyOrders">
|
||
<view class="card-header">
|
||
<text class="card-title">我的订单</text>
|
||
<image class="arrow-icon" src="/static/ic_arrow.png" mode="aspectFit"></image>
|
||
</view>
|
||
<view class="card-stats">
|
||
<view class="stat-item" @click.stop="goMyOrders('InProgress')">
|
||
<text class="stat-label">进行中</text>
|
||
<text class="stat-num">{{ stats.orderOngoing }}</text>
|
||
</view>
|
||
<view class="stat-divider"></view>
|
||
<view class="stat-item" @click.stop="goMyOrders('Completed')">
|
||
<text class="stat-label">已完成</text>
|
||
<text class="stat-num">{{ stats.orderCompleted }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 我的接单 -->
|
||
<view class="card" @click="goMyTaken">
|
||
<view class="card-header">
|
||
<text class="card-title">我的接单</text>
|
||
<image class="arrow-icon" src="/static/ic_arrow.png" mode="aspectFit"></image>
|
||
</view>
|
||
<view class="card-stats">
|
||
<view class="stat-item" @click.stop="goMyTaken('InProgress')">
|
||
<text class="stat-label">进行中</text>
|
||
<text class="stat-num">{{ stats.takenOngoing }}</text>
|
||
</view>
|
||
<view class="stat-divider"></view>
|
||
<view class="stat-item" @click.stop="goMyTaken('Completed')">
|
||
<text class="stat-label">已完成</text>
|
||
<text class="stat-num">{{ stats.takenCompleted }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 菜单列表 -->
|
||
<view class="menu-list">
|
||
<view class="menu-item" @click="goQrcode">
|
||
<image class="menu-icon" src="/static/ic_customer_service.png" mode="aspectFit"></image>
|
||
<text class="menu-text">联系客服</text>
|
||
<image class="menu-arrow" src="/static/ic_arrow.png" mode="aspectFit"></image>
|
||
</view>
|
||
<view class="menu-item" @click="goCertification">
|
||
<image class="menu-icon" src="/static/ic_certification.png" mode="aspectFit"></image>
|
||
<text class="menu-text">跑腿认证</text>
|
||
<image class="menu-arrow" src="/static/ic_arrow.png" mode="aspectFit"></image>
|
||
</view>
|
||
<view class="menu-item" @click="goEarnings">
|
||
<image class="menu-icon" src="/static/ic_revenue.png" mode="aspectFit"></image>
|
||
<text class="menu-text">我的收益</text>
|
||
<image class="menu-arrow" src="/static/ic_arrow.png" mode="aspectFit"></image>
|
||
</view>
|
||
<view class="menu-item" @click="goAgreement">
|
||
<image class="menu-icon" src="/static/ic_agreement1.png" mode="aspectFit"></image>
|
||
<text class="menu-text">用户协议</text>
|
||
<image class="menu-arrow" src="/static/ic_arrow.png" mode="aspectFit"></image>
|
||
</view>
|
||
<view class="menu-item" @click="goPrivacy">
|
||
<image class="menu-icon" src="/static/ic_agreement2.png" mode="aspectFit"></image>
|
||
<text class="menu-text">隐私协议</text>
|
||
<image class="menu-arrow" src="/static/ic_arrow.png" mode="aspectFit"></image>
|
||
</view>
|
||
<view class="menu-item" @click="goRunnerAgreement">
|
||
<image class="menu-icon" src="/static/ic_agreement3.png" mode="aspectFit"></image>
|
||
<text class="menu-text">跑腿协议</text>
|
||
<image class="menu-arrow" src="/static/ic_arrow.png" mode="aspectFit"></image>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 退出登录 -->
|
||
<view v-if="isLoggedIn" class="logout-section" @click="onLogout">
|
||
<text class="logout-text">退出登录</text>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { getMyOrders, getMyTaken } from '../../utils/api'
|
||
import { useUserStore } from '../../stores/user'
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
userInfo: {},
|
||
isLoggedIn: false,
|
||
statusBarHeight: 0,
|
||
stats: {
|
||
orderOngoing: 0,
|
||
orderCompleted: 0,
|
||
takenOngoing: 0,
|
||
takenCompleted: 0
|
||
}
|
||
}
|
||
},
|
||
onShow() {
|
||
const sysInfo = uni.getSystemInfoSync()
|
||
this.statusBarHeight = sysInfo.statusBarHeight || 0
|
||
const userStore = useUserStore()
|
||
this.userInfo = userStore.userInfo || {}
|
||
this.isLoggedIn = userStore.isLoggedIn
|
||
if (this.isLoggedIn) {
|
||
this.loadStats()
|
||
}
|
||
},
|
||
methods: {
|
||
/** 加载订单统计 */
|
||
async loadStats() {
|
||
try {
|
||
const [ordersRes, takenRes] = await Promise.all([
|
||
getMyOrders({}),
|
||
getMyTaken({})
|
||
])
|
||
const orders = ordersRes?.items || ordersRes || []
|
||
const taken = takenRes?.items || takenRes || []
|
||
this.stats.orderOngoing = orders.filter(o => o.status === 'InProgress' || o.status === 'WaitConfirm').length
|
||
this.stats.orderCompleted = orders.filter(o => o.status === 'Completed').length
|
||
this.stats.takenOngoing = taken.filter(o => o.status === 'InProgress' || o.status === 'WaitConfirm').length
|
||
this.stats.takenCompleted = taken.filter(o => o.status === 'Completed').length
|
||
} catch (e) {
|
||
// 静默处理
|
||
}
|
||
},
|
||
/** 点击用户区域 */
|
||
onUserClick() {
|
||
if (!this.isLoggedIn) {
|
||
uni.navigateTo({ url: '/pages/login/login' })
|
||
} else {
|
||
uni.navigateTo({ url: '/pages/mine/profile' })
|
||
}
|
||
},
|
||
goMyOrders(status) {
|
||
const query = status ? `?status=${status}` : ''
|
||
uni.navigateTo({ url: '/pages/order/my-orders' + query })
|
||
},
|
||
goMyTaken(status) {
|
||
const query = status ? `?status=${status}` : ''
|
||
uni.navigateTo({ url: '/pages/order/my-taken' + query })
|
||
},
|
||
goQrcode() { uni.navigateTo({ url: '/pages/config/qrcode' }) },
|
||
goCertification() { uni.navigateTo({ url: '/pages/runner/certification' }) },
|
||
goEarnings() { uni.navigateTo({ url: '/pages/mine/earnings' }) },
|
||
goAgreement() { uni.navigateTo({ url: '/pages/config/agreement' }) },
|
||
goPrivacy() { uni.navigateTo({ url: '/pages/config/privacy' }) },
|
||
goRunnerAgreement() {
|
||
uni.navigateTo({ url: '/pages/config/runner-agreement' })
|
||
},
|
||
/** 退出登录 */
|
||
onLogout() {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '确定退出登录?',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
const userStore = useUserStore()
|
||
userStore.logout()
|
||
}
|
||
}
|
||
})
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.mine-page {
|
||
min-height: 100vh;
|
||
background-color: #f5f5f5;
|
||
padding-bottom: 140rpx;
|
||
}
|
||
|
||
/* 顶部渐变背景 */
|
||
.header-bg {
|
||
background: linear-gradient(90deg, #FFB700 0%, #FFD59B 100%);
|
||
}
|
||
|
||
.nav-bar {
|
||
height: 88rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.nav-title {
|
||
font-size: 34rpx;
|
||
color: #333;
|
||
font-weight: bold;
|
||
}
|
||
|
||
/* 用户信息卡片 */
|
||
.user-card {
|
||
display: flex;
|
||
align-items: center;
|
||
margin: 20rpx 30rpx 0;
|
||
background: #fff;
|
||
border-radius: 20rpx;
|
||
padding: 30rpx;
|
||
}
|
||
|
||
.user-avatar {
|
||
width: 90rpx;
|
||
height: 90rpx;
|
||
border-radius: 50%;
|
||
margin-right: 24rpx;
|
||
background-color: #f0f0f0;
|
||
}
|
||
|
||
.user-info {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.user-name {
|
||
font-size: 32rpx;
|
||
color: #333;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.user-uid {
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
margin-top: 6rpx;
|
||
}
|
||
|
||
.arrow-icon {
|
||
width: 32rpx;
|
||
height: 32rpx;
|
||
}
|
||
|
||
/* 卡片 */
|
||
.card {
|
||
margin: 20rpx 30rpx 0;
|
||
background: #fff;
|
||
border-radius: 20rpx;
|
||
padding: 30rpx;
|
||
}
|
||
|
||
.card-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
position: relative;
|
||
margin-bottom: 30rpx;
|
||
}
|
||
|
||
.card-title {
|
||
font-size: 32rpx;
|
||
color: #FFB700;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.card-header .arrow-icon {
|
||
position: absolute;
|
||
right: 0;
|
||
}
|
||
|
||
.card-stats {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.stat-item {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
}
|
||
|
||
.stat-label {
|
||
font-size: 26rpx;
|
||
color: #999;
|
||
margin-bottom: 12rpx;
|
||
}
|
||
|
||
.stat-num {
|
||
font-size: 48rpx;
|
||
color: #333;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.stat-divider {
|
||
width: 2rpx;
|
||
height: 60rpx;
|
||
background-color: #e0e0e0;
|
||
}
|
||
|
||
/* 菜单列表 */
|
||
.menu-list {
|
||
margin: 20rpx 30rpx 0;
|
||
background: #fff;
|
||
border-radius: 20rpx;
|
||
padding: 0 30rpx;
|
||
}
|
||
|
||
.menu-item {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 30rpx 0;
|
||
border-bottom: 1rpx solid #f5f5f5;
|
||
}
|
||
|
||
.menu-item:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.menu-icon {
|
||
width: 44rpx;
|
||
height: 44rpx;
|
||
margin-right: 24rpx;
|
||
}
|
||
|
||
.menu-text {
|
||
flex: 1;
|
||
font-size: 30rpx;
|
||
color: #333;
|
||
}
|
||
|
||
.menu-arrow {
|
||
width: 28rpx;
|
||
height: 28rpx;
|
||
}
|
||
|
||
/* 退出登录 */
|
||
.logout-section {
|
||
margin: 40rpx 30rpx 120rpx;
|
||
background: #fff;
|
||
border-radius: 20rpx;
|
||
padding: 28rpx 0;
|
||
text-align: center;
|
||
}
|
||
.logout-text {
|
||
font-size: 30rpx;
|
||
color: #e64340;
|
||
}
|
||
</style>
|