huangye-parking/miniapp/pages/mine/index.vue
2026-03-11 22:20:56 +08:00

273 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">
<NavBar title="我的" :showBack="false" />
<!-- 用户信息区域 -->
<view class="user-card" @click="goProfile">
<image class="avatar" :src="userInfo.avatar || '/static/logo.png'" mode="aspectFill"></image>
<view class="user-info">
<text class="nickname">{{ userInfo.nickname || '未登录' }}</text>
<text class="uid" v-if="userInfo.uid">UID: {{ userInfo.uid }}</text>
</view>
<text class="arrow-right"></text>
</view>
<!-- 积分和优惠券概览 -->
<view class="stats-card">
<view class="stat-item" @click="goPoints">
<text class="stat-value">{{ userInfo.points || 0 }}</text>
<text class="stat-label">积分</text>
</view>
<view class="stat-divider"></view>
<view class="stat-item" @click="goCoupons">
<text class="stat-value">{{ userInfo.couponCount || 0 }}</text>
<text class="stat-label">优惠券</text>
</view>
</view>
<!-- 功能入口列表 -->
<view class="menu-list">
<view class="menu-item" @click="goVerifyRecords">
<image class="menu-icon" src="/static/ic_write.png" mode="aspectFit" />
<text class="menu-text">核销记录</text>
<text class="arrow-right"></text>
</view>
<view class="menu-item">
<image class="menu-icon" src="/static/ic_contact.png" mode="aspectFit" />
<text class="menu-text">联系我们</text>
<text class="arrow-right"></text>
<!-- 透明客服按钮覆盖整个菜单项 -->
<button class="contact-btn" open-type="contact"></button>
</view>
<view class="menu-item" @click="goAgreement('user-agreement')">
<image class="menu-icon" src="/static/ic_agreement.png" mode="aspectFit" />
<text class="menu-text">用户协议</text>
<text class="arrow-right"></text>
</view>
<view class="menu-item" @click="goAgreement('privacy-policy')">
<image class="menu-icon" src="/static/ic_agreement2.png" mode="aspectFit" />
<text class="menu-text">隐私政策</text>
<text class="arrow-right"></text>
</view>
<view v-if="isLogin && userInfo.isMerchant" class="menu-item" @click="goRoleSelect">
<image class="menu-icon" src="/static/ic_switch.png" mode="aspectFit" />
<text class="menu-text">切换身份</text>
<text class="arrow-right"></text>
</view>
<view v-if="isLogin" class="menu-item" @click="showLogoutConfirm">
<image class="menu-icon" src="/static/login_out.png" mode="aspectFit" />
<text class="menu-text">退出登录</text>
<text class="arrow-right"></text>
</view>
</view>
<!-- 退出确认弹窗 -->
<ConfirmDialog
:visible="logoutVisible"
title="退出登录"
message="确定要退出登录吗?"
@confirm="doLogout"
@cancel="logoutVisible = false"
/>
</view>
</template>
<script>
import { getProfile } from '@/api/user'
import { logout } from '@/api/auth'
import { isLoggedIn, clearAuth, checkLogin } from '@/utils/auth'
import ConfirmDialog from '@/components/ConfirmDialog.vue'
import NavBar from '@/components/NavBar.vue'
export default {
components: { ConfirmDialog, NavBar },
data() {
return {
isLogin: false,
userInfo: {},
logoutVisible: false
}
},
onShow() {
this.isLogin = isLoggedIn()
if (this.isLogin) {
this.loadProfile()
}
},
methods: {
/** 加载用户信息 */
async loadProfile() {
try {
const res = await getProfile()
this.userInfo = res.data || res || {}
} catch (err) {
console.error('加载用户信息失败:', err)
}
},
/** 跳转个人资料页 */
goProfile() {
if (!checkLogin()) return
uni.navigateTo({ url: '/pages/mine/profile' })
},
/** 跳转积分页 */
goPoints() {
uni.switchTab({ url: '/pages/points/index' })
},
/** 跳转我的优惠券 */
goCoupons() {
if (!checkLogin()) return
uni.navigateTo({ url: '/pages/coupon/my-coupons' })
},
/** 跳转核销记录 */
goVerifyRecords() {
if (!checkLogin()) return
uni.navigateTo({ url: '/pages/mine/verify-records' })
},
/** 联系客服 */
contactService() {
// 微信小程序自带客服功能,需要在 button 上使用 open-type="contact"
// 这里用 showToast 提示,实际可替换为客服按钮
uni.showToast({ title: '请使用页面底部客服按钮', icon: 'none' })
},
/** 跳转协议页 */
goAgreement(type) {
uni.navigateTo({ url: `/pages/mine/agreement?type=${type}` })
},
/** 切换身份 */
goRoleSelect() {
uni.navigateTo({ url: '/pages/login/role-select' })
},
/** 显示退出确认弹窗 */
showLogoutConfirm() {
this.logoutVisible = true
},
/** 执行退出登录 */
async doLogout() {
this.logoutVisible = false
try {
await logout()
} catch (err) {
// 即使接口失败也清除本地状态
}
clearAuth()
uni.reLaunch({ url: '/pages/index/index' })
}
}
}
</script>
<style scoped>
.mine-page {
padding: 20rpx;
padding-bottom: 40rpx;
}
.user-card {
display: flex;
align-items: center;
background: #fff;
border-radius: 16rpx;
padding: 32rpx 24rpx;
margin-bottom: 20rpx;
}
.avatar {
width: 100rpx;
height: 100rpx;
border-radius: 50%;
flex-shrink: 0;
}
.user-info {
flex: 1;
margin-left: 24rpx;
}
.nickname {
display: block;
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 6rpx;
}
.uid {
font-size: 24rpx;
color: #999;
}
.arrow-right {
font-size: 36rpx;
color: #ccc;
flex-shrink: 0;
}
.stats-card {
display: flex;
background: #fff;
border-radius: 16rpx;
padding: 32rpx 0;
margin-bottom: 20rpx;
}
.stat-item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
}
.stat-value {
font-size: 40rpx;
font-weight: bold;
color: #007aff;
margin-bottom: 8rpx;
}
.stat-label {
font-size: 26rpx;
color: #999;
}
.stat-divider {
width: 1rpx;
background: #eee;
}
.menu-list {
background: #fff;
border-radius: 16rpx;
margin-bottom: 40rpx;
overflow: hidden;
}
.menu-item {
display: flex;
align-items: center;
padding: 28rpx 24rpx;
border-bottom: 1rpx solid #f5f5f5;
position: relative;
}
.menu-item:last-child {
border-bottom: none;
}
.menu-item:active {
background: #f8f8f8;
}
.menu-icon {
width: 40rpx;
height: 40rpx;
margin-right: 16rpx;
flex-shrink: 0;
}
.menu-text {
flex: 1;
font-size: 30rpx;
color: #333;
}
.contact-btn {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
z-index: 1;
}
</style>