shop-wx/src/pages/me/index.vue

462 lines
11 KiB
Vue
Raw Normal View History

<script lang="ts" setup>
import { computed, onMounted, ref } from 'vue'
import { useWxStore } from '@/pinia/stores/wx'
import { useAb98UserStore } from '@/pinia/stores/ab98-user'
import { storeToRefs } from 'pinia'
import { toHttpsUrl } from '@/utils'
import { generateDynamicCode } from '@/api/users'
import { DynamicCodeResponse } from '@/api/users/types'
import { useToast } from 'wot-design-uni'
definePage({
style: {
navigationBarTitleText: '我的',
},
})
const wxStore = useWxStore()
const ab98UserStore = useAb98UserStore()
const { balance, useBalance, balanceLimit, name: qyName, ab98User } = storeToRefs(wxStore)
const { name: userName, sex: userSex, face_img } = storeToRefs(ab98UserStore)
const name = computed(() => {
return userName.value || qyName.value || '未知用户'
})
const userAvatar = computed(() => face_img.value ? toHttpsUrl(face_img.value) : '/static/favicon.ico')
// 动态码相关
const dynamicCodeActionSheet = ref<boolean>(false)
const dynamicCodeData = ref<DynamicCodeResponse | null>(null)
const toast = useToast()
const ab98BalanceInYuan = computed(() => {
if (ab98User.value && ab98User.value.ab98Balance !== undefined) {
return (ab98User.value.ab98Balance / 100).toFixed(2)
}
return '0.00'
})
const handleLogout = () => {
uni.showModal({
title: '退出登录',
content: '确定要退出当前账号吗?',
success: (res) => {
if (res.confirm) {
ab98UserStore.clearUserInfo()
uni.switchTab({
url: '/pages/index/index'
})
}
}
})
}
// 统一的页面跳转函数
const navigateToPage = (pagePath: string, options: { type?: 'navigateTo' | 'switchTab' | 'redirectTo' } = {}) => {
const { type = 'navigateTo' } = options
try {
switch (type) {
case 'switchTab':
uni.switchTab({ url: pagePath })
break
case 'redirectTo':
uni.redirectTo({ url: pagePath })
break
default:
uni.navigateTo({ url: pagePath })
}
} catch (error) {
console.error('页面跳转失败:', error)
uni.showToast({
title: '页面跳转失败',
icon: 'none'
})
}
}
onMounted(() => {
wxStore.refreshBalance()
})
// 生成动态码
const handleGenerateDynamicCode = async () => {
if (!wxStore.openid) {
toast.show('用户信息异常,请重新登录')
return
}
try {
const res = await generateDynamicCode(wxStore.openid)
if (res && res.code == 0) {
dynamicCodeData.value = res.data
dynamicCodeActionSheet.value = true
} else {
toast.show(res?.msg || '获取动态码失败')
}
} catch (error) {
console.error('获取动态码失败:', error)
toast.show('获取动态码失败')
}
}
</script>
<template>
<view class="me-page">
<!-- 用户卡片 -->
<view class="user-card">
<view class="user-info">
<view class="avatar-wrapper">
<image
class="avatar"
:src="userAvatar"
mode="aspectFill"
@click="handleLogout"
/>
</view>
<view class="user-details">
<view class="user-name">{{ name }}</view>
</view>
</view>
</view>
<!-- 余额区域 -->
<view class="balance-card">
<view class="section-title">借呗信息</view>
<view class="balance-content-wrapper">
<view class="balance-item">
<view class="balance-icon">
<wd-icon name="money-circle" size="28px" color="#FFD700"></wd-icon>
</view>
<view class="balance-content">
<view class="balance-label">借呗总额</view>
<view class="balance-value">{{ balanceLimit }}</view>
</view>
</view>
<view class="balance-item">
<view class="balance-content">
<view class="balance-label">未还借呗</view>
<view class="balance-value">{{ useBalance }}</view>
</view>
</view>
<view class="balance-item">
<view class="balance-content">
<view class="balance-label">剩余借呗</view>
<view class="balance-value">{{ balance }}</view>
</view>
</view>
</view>
</view>
<!-- 个人中心按钮 -->
<view class="button-group">
<view class="section-title">个人中心</view>
<view class="button-row">
<!-- <view class="button-item" @click="navigateToPage('/pages/order/index')">
<wd-icon name="list" size="20px" color="#fff"></wd-icon>
<text>订单列表</text>
</view> -->
<view class="button-item" @click="navigateToPage('/pages/rental/index')">
<wd-icon name="star" size="20px" color="#fff"></wd-icon>
<text>我的柜子</text>
</view>
<view class="button-item" @click="handleGenerateDynamicCode">
<wd-icon name="qrcode" size="20px" color="#fff"></wd-icon>
<text>绑定汇邦云</text>
</view>
<view class="button-placeholder"></view>
<!-- <view v-if="wxStore.isCabinetAdmin" class="button-item" @click="navigateToPage('/pages/cabinet/index')">
<wd-icon name="tools" size="20px" color="#fff"></wd-icon>
<text>柜机管理</text>
</view> -->
</view>
<!-- <view class="button-row">
<view v-if="wxStore.isCabinetAdmin" class="button-item" @click="navigateToPage('/pages/approval/list/index')">
<wd-icon name="secured" size="20px" color="#fff"></wd-icon>
<text>审批中心</text>
</view>
<view v-if="wxStore.isCabinetAdmin" class="button-item" @click="navigateToPage('/pages/approvalAsset/list/index')">
<wd-icon name="edit-1" size="20px" color="#fff"></wd-icon>
<text>耗材核销</text>
</view>
<view class="button-placeholder"></view>
</view> -->
</view>
<!-- 动态码弹窗 -->
<wd-action-sheet
v-model="dynamicCodeActionSheet"
title="动态码"
cancel-text="关闭"
:close-on-click-modal="true"
@close="dynamicCodeActionSheet = false"
>
<view style="padding: 30px 30px 80px 30px; text-align: center;">
<view style="font-size: 24px; font-weight: bold; color: #409EFF; margin-bottom: 8px;">
{{ dynamicCodeData?.dynamicCode || '' }}
</view>
<view style="font-size: 14px; color: #999; margin-top: 8px;">
有效时间{{ dynamicCodeData?.validityMinutes || '0' }} 分钟
</view>
<view style="font-size: 12px; color: #666; margin-top: 16px; padding: 8px 12px; background: #f5f5f5; border-radius: 4px;">
请使用该动态码在企业微信中绑定汇邦云账号
</view>
</view>
</wd-action-sheet>
</view>
</template>
<style scoped lang="scss">
.me-page {
background: #f7f8fa;
min-height: 100%;
}
.user-card {
margin: 12px;
padding: 20px 16px;
background: white;
border-radius: 16px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
position: relative;
overflow: hidden;
transition: all 0.3s ease;
border: 1px solid rgba(0, 0, 0, 0.05);
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg, rgba(64, 158, 255, 0.02) 0%, rgba(102, 126, 234, 0.02) 100%);
z-index: 1;
}
&:active {
transform: translateY(2px);
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
}
.user-info {
display: flex;
align-items: center;
position: relative;
z-index: 2;
.avatar-wrapper {
margin-right: 16px;
position: relative;
}
.avatar {
width: 60px;
height: 60px;
border-radius: 50%;
border: 3px solid rgba(64, 158, 255, 0.2);
box-shadow: 0 4px 12px rgba(64, 158, 255, 0.15);
transition: all 0.3s ease;
}
.avatar:active {
transform: scale(0.95);
}
.user-details {
flex: 1;
.user-name {
font-size: 18px;
font-weight: 600;
color: #1a1a1a;
letter-spacing: 0.5px;
}
}
}
}
.balance-card {
margin: 12px;
padding: 20px 16px;
background: white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
.section-title {
font-size: 16px;
font-weight: 600;
color: #1a1a1a;
margin-bottom: 16px;
padding-left: 8px;
position: relative;
letter-spacing: 0.5px;
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 3px;
height: 16px;
background: linear-gradient(135deg, #409EFF 0%, #66B1FF 100%);
border-radius: 2px;
}
}
.balance-content-wrapper {
display: flex;
justify-content: space-between;
}
.balance-item {
display: flex;
align-items: center;
flex: 1;
min-width: 0;
padding: 0 8px;
font-weight: 500;
&:first-child {
padding-left: 0;
}
&:last-child {
padding-right: 0;
}
.balance-icon {
margin-right: 8px;
flex-shrink: 0;
}
.balance-content {
flex: 1;
min-width: 0;
text-align: center;
.balance-label {
font-size: 12px;
color: #666;
margin-bottom: 6px;
line-height: 1.2;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.balance-value {
font-size: 16px;
font-weight: bold;
color: #409EFF;
line-height: 1.2;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
}
.button-group {
margin: 12px;
padding: 16px;
background: white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
.section-title {
font-size: 16px;
font-weight: 600;
color: #1a1a1a;
margin-bottom: 16px;
padding-left: 8px;
position: relative;
letter-spacing: 0.5px;
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 3px;
height: 16px;
background: linear-gradient(135deg, #409EFF 0%, #66B1FF 100%);
border-radius: 2px;
}
}
.button-row {
display: flex;
margin-bottom: 8px;
&:last-child {
margin-bottom: 0;
}
.button-item {
flex: 1;
height: 80px;
background: linear-gradient(135deg, #409EFF 0%, #66B1FF 100%);
border: none;
border-radius: 12px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin-right: 12px;
box-shadow: 0 4px 12px rgba(64, 158, 255, 0.3);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
cursor: pointer;
&:last-child {
margin-right: 0;
}
&::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
transition: left 0.5s ease;
}
wd-icon {
position: relative;
z-index: 2;
filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1));
}
text {
font-size: 13px;
color: white;
margin-top: 8px;
font-weight: 500;
position: relative;
z-index: 2;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}
}
.button-placeholder {
flex: 1;
height: 80px;
}
}
}
</style>