273 lines
6.5 KiB
Vue
273 lines
6.5 KiB
Vue
<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>
|