JewelryMall/miniprogram/pages/mine/index.vue
2026-03-03 01:40:42 +08:00

310 lines
8.1 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="custom-navbar" :style="{ paddingTop: statusBarHeight + 'px' }">
<view class="custom-navbar__content" :style="{ height: navBarHeight + 'px' }">
<text class="custom-navbar__title">我的</text>
</view>
</view>
<!-- 顶部用户卡片 -->
<view class="user-card" @click="handleUserCardClick">
<image class="user-card__avatar" :src="userStore.user?.avatar || '/static/logo.png'" mode="aspectFill" />
<view class="user-card__info">
<text class="user-card__name">{{ isLoggedIn ? (userStore.user?.nickname || '微信用户') : '点击注册/登录' }}</text>
<text v-if="isLoggedIn" class="user-card__id">ID: {{ userStore.user?.id }}</text>
</view>
<text class="user-card__arrow"></text>
</view>
<!-- 我的订单 -->
<view class="order-entry" @click="navigateTo('/pages/order/list')">
<image class="order-entry__icon" src="/static/tab/me_s.png" mode="aspectFit" />
<text class="order-entry__text">我的订单 {{ orderCount }}</text>
<text class="order-entry__arrow"></text>
</view>
<!-- 功能菜单 -->
<view class="menu-group">
<view class="menu-item" @click="navigateTo('/pages/address/index')">
<image class="menu-item__icon" src="/static/ic_address.png" mode="aspectFit" />
<text class="menu-item__label">收货地址</text>
<text class="menu-item__arrow"></text>
</view>
<view class="menu-item" @click="showQrCode = true">
<image class="menu-item__icon" src="/static/ic_customer.png" mode="aspectFit" />
<text class="menu-item__label">联系客服</text>
<text class="menu-item__arrow"></text>
</view>
<view class="menu-item" @click="showAbout = true">
<image class="menu-item__icon" src="/static/ic_about.png" mode="aspectFit" />
<text class="menu-item__label">关于我们</text>
<text class="menu-item__arrow"></text>
</view>
<view class="menu-item" @click="showAgreement('user')">
<image class="menu-item__icon" src="/static/ic_agreement1.png" mode="aspectFit" />
<text class="menu-item__label">用户协议</text>
<text class="menu-item__arrow"></text>
</view>
<view class="menu-item" @click="showAgreement('privacy')">
<image class="menu-item__icon" src="/static/ic_agreement2.png" mode="aspectFit" />
<text class="menu-item__label">隐私协议</text>
<text class="menu-item__arrow"></text>
</view>
<view v-if="isLoggedIn" class="menu-item" @click="handleLogout">
<image class="menu-item__icon" src="/static/ic_loginout.png" mode="aspectFit" />
<text class="menu-item__label">退出登录</text>
<text class="menu-item__arrow"></text>
</view>
</view>
<!-- 客服二维码弹窗 -->
<CustomerServiceBtn v-if="showQrCode" mode="qrcode" @close="showQrCode = false" />
<!-- 关于我们弹窗 -->
<view class="modal-mask" v-if="showAbout" @click="showAbout = false">
<view class="modal-popup" @click.stop>
<text class="modal-popup__title">关于我们</text>
<text class="modal-popup__content">珠宝商城 —— 专注珠宝零售,为您提供优质珠宝商品和贴心服务。</text>
<view class="modal-popup__close" @click="showAbout = false">关闭</view>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import { useUserStore } from '../../store/user'
import { getOrderList } from '../../api/order'
import CustomerServiceBtn from '../../components/CustomerServiceBtn.vue'
const userStore = useUserStore()
const showQrCode = ref(false)
const showAbout = ref(false)
const orderCount = ref(0)
const isLoggedIn = ref(false)
const statusBarHeight = ref(20)
const navBarHeight = ref(44)
try {
const sysInfo = uni.getSystemInfoSync()
statusBarHeight.value = sysInfo.statusBarHeight || 20
// #ifdef MP-WEIXIN
const menuBtn = uni.getMenuButtonBoundingClientRect()
navBarHeight.value = (menuBtn.top - (sysInfo.statusBarHeight || 20)) * 2 + menuBtn.height
// #endif
} catch { /* fallback */ }
function refreshData() {
const token = uni.getStorageSync('token')
isLoggedIn.value = !!token
if (token) {
userStore.fetchProfile()
getOrderList().then((data: any) => {
orderCount.value = Array.isArray(data) ? data.length : (data?.total || 0)
}).catch(() => {})
}
}
onShow(() => {
refreshData()
})
function handleUserCardClick() {
if (!isLoggedIn.value) {
uni.navigateTo({ url: '/pages/login/index' })
}
}
function navigateTo(url: string) {
const token = uni.getStorageSync('token')
if (!token) {
uni.navigateTo({ url: '/pages/login/index' })
return
}
uni.navigateTo({ url })
}
function showAgreement(type: 'user' | 'privacy') {
const title = type === 'user' ? '用户协议' : '隐私协议'
uni.showModal({
title,
content: type === 'user'
? '欢迎使用珠宝商城小程序。使用本小程序即表示您同意遵守相关服务条款。'
: '我们重视您的隐私保护。我们仅收集必要的信息以提供服务,不会向第三方泄露您的个人信息。',
showCancel: false,
confirmText: '我知道了',
})
}
function handleLogout() {
uni.showModal({
title: '提示',
content: '确定要退出登录吗?',
success: (res) => {
if (res.confirm) {
userStore.logout()
isLoggedIn.value = false
orderCount.value = 0
uni.showToast({ title: '已退出登录', icon: 'success' })
setTimeout(() => {
uni.switchTab({ url: '/pages/index/index' })
}, 1000)
}
}
})
}
</script>
<style scoped>
.mine-page {
min-height: 100vh;
background: #f5f5f5;
}
.custom-navbar {
background: linear-gradient(to right, #FFCFDE, #FFA6C4);
}
.custom-navbar__content {
display: flex;
align-items: center;
justify-content: center;
}
.custom-navbar__title {
font-size: 34rpx;
font-weight: bold;
color: #333;
}
/* 用户卡片 */
.user-card {
display: flex;
align-items: center;
background: #fff;
margin: 0 24rpx;
padding: 32rpx;
border-radius: 16rpx;
}
.user-card__avatar {
width: 96rpx;
height: 96rpx;
border-radius: 50%;
background: #f0f0f0;
flex-shrink: 0;
}
.user-card__info {
flex: 1;
margin-left: 24rpx;
}
.user-card__name {
font-size: 32rpx;
color: #333;
font-weight: bold;
}
.user-card__id {
font-size: 24rpx;
color: #999;
margin-top: 8rpx;
display: block;
}
.user-card__arrow {
font-size: 36rpx;
color: #ccc;
}
/* 我的订单入口 */
.order-entry {
display: flex;
align-items: center;
margin: 20rpx 24rpx 0;
padding: 24rpx 32rpx;
background: linear-gradient(135deg, #fce4ec, #f8bbd0);
border-radius: 16rpx;
}
.order-entry__icon {
width: 40rpx;
height: 40rpx;
margin-right: 16rpx;
}
.order-entry__text {
flex: 1;
font-size: 28rpx;
color: #333;
font-weight: bold;
}
.order-entry__arrow {
font-size: 32rpx;
color: #999;
}
/* 功能菜单 */
.menu-group {
background: #fff;
margin: 20rpx 24rpx 0;
border-radius: 16rpx;
overflow: hidden;
}
.menu-item {
display: flex;
align-items: center;
padding: 30rpx 32rpx;
border-bottom: 1rpx solid #f5f5f5;
}
.menu-item:last-child {
border-bottom: none;
}
.menu-item__icon {
width: 40rpx;
height: 40rpx;
margin-right: 20rpx;
}
.menu-item__label {
flex: 1;
font-size: 28rpx;
color: #333;
}
.menu-item__arrow {
font-size: 32rpx;
color: #ccc;
}
/* 弹窗 */
.modal-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 999;
}
.modal-popup {
background: #fff;
border-radius: 16rpx;
padding: 40rpx;
text-align: center;
width: 560rpx;
}
.modal-popup__title {
font-size: 32rpx;
color: #333;
font-weight: bold;
display: block;
margin-bottom: 20rpx;
}
.modal-popup__content {
font-size: 26rpx;
color: #666;
line-height: 44rpx;
display: block;
}
.modal-popup__close {
margin-top: 28rpx;
font-size: 28rpx;
color: #999;
}
</style>