campus-errand/miniapp/pages/mine/mine.vue
2026-03-12 18:12:10 +08:00

315 lines
6.5 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="mine-page">
<!-- 用户信息区域 -->
<view class="user-header">
<image class="user-avatar" :src="userInfo.avatarUrl || '/static/logo.png'" mode="aspectFill"></image>
<text class="user-name">{{ userInfo.nickname || '用户' }}</text>
</view>
<!-- 订单统计 -->
<view class="stats-section">
<view class="stats-row">
<view class="stats-block" @click="goMyOrders">
<text class="stats-title">我的下单</text>
<view class="stats-nums">
<view class="stats-item">
<text class="stats-num">{{ stats.orderCount }}</text>
<text class="stats-label">下单数</text>
</view>
<view class="stats-item">
<text class="stats-num">{{ stats.orderCompleted }}</text>
<text class="stats-label">完成数</text>
</view>
</view>
</view>
<view class="stats-block" @click="goMyTaken">
<text class="stats-title">我的接单</text>
<view class="stats-nums">
<view class="stats-item">
<text class="stats-num">{{ stats.takenCount }}</text>
<text class="stats-label">接单数</text>
</view>
<view class="stats-item">
<text class="stats-num">{{ stats.takenCompleted }}</text>
<text class="stats-label">完成数</text>
</view>
</view>
</view>
</view>
</view>
<!-- 功能入口 -->
<view class="menu-section">
<view class="menu-item" @click="contactService">
<text class="menu-icon">📞</text>
<text class="menu-text">联系客服</text>
<text class="menu-arrow"></text>
</view>
<view class="menu-item" @click="goQrcode">
<text class="menu-icon">📱</text>
<text class="menu-text">客服二维码</text>
<text class="menu-arrow"></text>
</view>
<view class="menu-item" @click="goCertification">
<text class="menu-icon">🏃</text>
<text class="menu-text">跑腿认证</text>
<text class="menu-arrow"></text>
</view>
<view class="menu-item" @click="goEarnings">
<text class="menu-icon">💰</text>
<text class="menu-text">我的收益</text>
<text class="menu-arrow"></text>
</view>
</view>
<view class="menu-section">
<view class="menu-item" @click="goAgreement">
<text class="menu-icon">📄</text>
<text class="menu-text">用户协议</text>
<text class="menu-arrow"></text>
</view>
<view class="menu-item" @click="goPrivacy">
<text class="menu-icon">🔒</text>
<text class="menu-text">隐私政策</text>
<text class="menu-arrow"></text>
</view>
</view>
<!-- 退出登录 -->
<view class="logout-section">
<view class="logout-btn" @click="onLogout">
<text>退出登录</text>
</view>
</view>
</view>
</template>
<script>
import { getMyOrders, getMyTaken } from '../../utils/api'
import { useUserStore } from '../../stores/user'
export default {
data() {
return {
userInfo: {},
stats: {
orderCount: 0,
orderCompleted: 0,
takenCount: 0,
takenCompleted: 0
}
}
},
onShow() {
const userStore = useUserStore()
this.userInfo = userStore.userInfo || {}
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.orderCount = orders.length
this.stats.orderCompleted = orders.filter(o => o.status === 'Completed').length
this.stats.takenCount = taken.length
this.stats.takenCompleted = taken.filter(o => o.status === 'Completed').length
} catch (e) {
// 静默处理
}
},
/** 跳转我的订单 */
goMyOrders() {
uni.navigateTo({ url: '/pages/order/my-orders' })
},
/** 跳转我的接单 */
goMyTaken() {
uni.navigateTo({ url: '/pages/order/my-taken' })
},
/** 联系客服 */
contactService() {
// 跳转小程序自带客服页
// uni-app 中通过 button open-type="contact" 实现,这里用 navigateTo 模拟
uni.showToast({ title: '请使用客服按钮', icon: 'none' })
},
/** 客服二维码 */
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' })
},
/** 退出登录 */
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;
}
/* 用户信息头部 */
.user-header {
display: flex;
flex-direction: column;
align-items: center;
padding: 60rpx 0 40rpx;
background-color: #007AFF;
}
.user-avatar {
width: 120rpx;
height: 120rpx;
border-radius: 60rpx;
border: 4rpx solid #ffffff;
margin-bottom: 16rpx;
}
.user-name {
font-size: 32rpx;
color: #ffffff;
font-weight: 500;
}
/* 订单统计 */
.stats-section {
margin: -20rpx 24rpx 24rpx;
}
.stats-row {
display: flex;
gap: 20rpx;
}
.stats-block {
flex: 1;
background-color: #ffffff;
border-radius: 16rpx;
padding: 24rpx;
}
.stats-title {
font-size: 28rpx;
color: #333333;
font-weight: 500;
display: block;
margin-bottom: 16rpx;
}
.stats-nums {
display: flex;
justify-content: space-around;
}
.stats-item {
display: flex;
flex-direction: column;
align-items: center;
}
.stats-num {
font-size: 36rpx;
color: #007AFF;
font-weight: bold;
}
.stats-label {
font-size: 22rpx;
color: #999999;
margin-top: 4rpx;
}
/* 菜单区域 */
.menu-section {
margin: 0 24rpx 24rpx;
background-color: #ffffff;
border-radius: 16rpx;
overflow: hidden;
}
.menu-item {
display: flex;
align-items: center;
padding: 28rpx 30rpx;
border-bottom: 1rpx solid #f5f5f5;
}
.menu-item:last-child {
border-bottom: none;
}
.menu-icon {
font-size: 36rpx;
margin-right: 20rpx;
}
.menu-text {
flex: 1;
font-size: 28rpx;
color: #333333;
}
.menu-arrow {
font-size: 32rpx;
color: #cccccc;
}
/* 退出登录 */
.logout-section {
margin: 40rpx 24rpx;
}
.logout-btn {
background-color: #ffffff;
border-radius: 16rpx;
padding: 28rpx 0;
text-align: center;
}
.logout-btn text {
font-size: 30rpx;
color: #e64340;
}
</style>