import {Avatar, Tag, Space, Button} from '@nutui/nutui-react-taro' import {View, Text} from '@tarojs/components' import {getUserInfo, getWxOpenId} from '@/api/layout'; import Taro from '@tarojs/taro'; import {useEffect, useState, forwardRef, useImperativeHandle} from "react"; import {User} from "@/api/system/user/model"; import navTo from "@/utils/common"; import {TenantId} from "@/config/app"; import {useUser} from "@/hooks/useUser"; import {useUserData} from "@/hooks/useUserData"; import {getStoredInviteParams} from "@/utils/invite"; import UnifiedQRButton from "@/components/UnifiedQRButton"; import {useThemeStyles} from "@/hooks/useTheme"; import {getRootDomain} from "@/utils/domain"; import { getMyGltUserTicketTotal } from '@/api/glt/gltUserTicket' const UserCard = forwardRef((_, ref) => { const {data, refresh} = useUserData() const {getDisplayName} = useUser(); const [IsLogin, setIsLogin] = useState(false) const [userInfo, setUserInfo] = useState() const [ticketTotal, setTicketTotal] = useState(0) const themeStyles = useThemeStyles(); // 角色名称:优先取用户 roles 数组的第一个角色名称 const getRoleName = () => { return userInfo?.roles?.[0]?.roleName || userInfo?.roleName || '注册用户' } // 下拉刷新 const handleRefresh = async () => { await refresh() reloadTicketTotal() Taro.showToast({ title: '刷新成功', icon: 'success' }) } // 暴露方法给父组件 useImperativeHandle(ref, () => ({ handleRefresh })) useEffect(() => { // 独立于用户信息授权:只要有登录 token,就可以拉取水票总数 reloadTicketTotal() // Taro.getSetting:获取用户的当前设置。返回值中只会出现小程序已经向用户请求过的权限。 Taro.getSetting({ success: (res) => { if (res.authSetting['scope.userInfo']) { // 用户已经授权过,可以直接获取用户信息 console.log('用户已经授权过,可以直接获取用户信息') reload(); } else { // 用户未授权,需要弹出授权窗口 console.log('用户未授权,需要弹出授权窗口') showAuthModal(); } } }); }, []); const reloadTicketTotal = () => { const token = Taro.getStorageSync('access_token') if (!token) { setTicketTotal(0) return } getMyGltUserTicketTotal() .then((total) => setTicketTotal(typeof total === 'number' ? total : 0)) .catch((err) => { console.error('个人中心水票总数加载失败:', err) setTicketTotal(0) }) } const reload = () => { Taro.getUserInfo({ success: (res) => { const avatar = res.userInfo.avatarUrl; setUserInfo({ avatar, nickname: res.userInfo.nickName, sexName: res.userInfo.gender == 1 ? '男' : '女' }) getUserInfo().then((data) => { if (data) { setUserInfo(data) setIsLogin(true); Taro.setStorageSync('UserId', data.userId) // 登录态已就绪后刷新卡片统计(余额/积分/券/水票) refresh().then() reloadTicketTotal() // 获取openId if (!data.openid) { Taro.login({ success: (res) => { getWxOpenId({code: res.code}).then(() => { }) } }) } } }).catch(() => { console.log('未登录') }); } }); }; const showAuthModal = () => { Taro.showModal({ title: '授权提示', content: '需要获取您的用户信息', confirmText: '去授权', cancelText: '取消', success: (res) => { if (res.confirm) { // 用户点击确认,打开授权设置页面 openSetting(); } } }); }; const openSetting = () => { // Taro.openSetting:调起客户端小程序设置界面,返回用户设置的操作结果。设置界面只会出现小程序已经向用户请求过的权限。 Taro.openSetting({ success: (res) => { if (res.authSetting['scope.userInfo']) { // 用户授权成功,可以获取用户信息 reload(); } else { // 用户拒绝授权,提示授权失败 Taro.showToast({ title: '授权失败', icon: 'none' }); } } }); }; /* 获取用户手机号 */ const handleGetPhoneNumber = ({detail}: { detail: { code?: string, encryptedData?: string, iv?: string } }) => { const {code, encryptedData, iv} = detail // 判断用户是否已登录 if(IsLogin){ return navTo(`/user/profile/profile`) } // 获取存储的邀请参数 const inviteParams = getStoredInviteParams() const refereeId = inviteParams?.inviter ? parseInt(inviteParams.inviter) : 0 Taro.login({ success: function () { if (code) { Taro.request({ url: 'https://server.websoft.top/api/wx-login/loginByMpWxPhone', method: 'POST', data: { code, encryptedData, iv, notVerifyPhone: true, refereeId: refereeId, // 使用解析出的推荐人ID sceneType: 'save_referee', tenantId: TenantId }, header: { 'content-type': 'application/json', TenantId }, success: function (res) { if (res.data.code == 1) { Taro.showToast({ title: res.data.message, icon: 'error', duration: 2000 }) return false; } // 登录成功 Taro.setStorageSync('access_token', res.data.data.access_token) Taro.setStorageSync('UserId', res.data.data.user.userId) setUserInfo(res.data.data.user) setIsLogin(true) // 登录态已就绪后刷新卡片统计(余额/积分/券/水票) refresh().then() reloadTicketTotal() } }) } else { console.log('登录失败!') } } }) } return ( {/* 使用相对定位容器,让个人资料图片可以绝对定位在右上角 */} {IsLogin && ( navTo(`/user/profile/profile`)}> {getDisplayName() || '点击登录'} {getRootDomain() && ( {getRoleName()} )} )} {!IsLogin && ( )} {/*统一扫码入口 - 支持登录和核销*/} { console.log('统一扫码成功:', result); // 根据扫码类型给出不同的提示 if (result.type === 'verification') { const businessType = result?.data?.businessType; if (businessType === 'gift' && result?.data?.gift) { const gift = result.data.gift; Taro.showModal({ title: '核销成功', content: `已成功核销:${gift.goodsName || gift.name || '礼品'},面值¥${gift.faceValue}` }); return; } if (businessType === 'ticket' && result?.data?.ticket) { const ticket = result.data.ticket; const qty = result.data.qty || 1; Taro.showModal({ title: '核销成功', content: `已成功核销:${ticket.templateName || '水票'},本次使用${qty}次,剩余可用${ticket.availableQty ?? 0}次` }); return; } Taro.showModal({ title: '核销成功', content: '已成功核销' }); } }} onError={(error) => { console.error('统一扫码失败:', error); }} /> navTo('/user/wallet/wallet', true)}> 余额 {data?.balance || '0.00'} 积分 {data?.points || 0} navTo('/user/coupon/index', true)}> 优惠券 {data?.coupons || 0} navTo('/user/gift/index', true)}> 水票 {ticketTotal} ) }) export default UserCard;