import { useState, useEffect } from 'react'; import Taro from '@tarojs/taro'; import { User } from '@/api/system/user/model'; import { getUserInfo, updateUserInfo, loginByOpenId } from '@/api/layout'; import {getStoredInviteParams, handleInviteRelation} from '@/utils/invite'; // 用户Hook export const useUser = () => { const [user, setUser] = useState(null); const [isLoggedIn, setIsLoggedIn] = useState(false); const [loading, setLoading] = useState(true); // 自动登录(通过OpenID) const autoLoginByOpenId = async () => { try { const res = await new Promise((resolve, reject) => { Taro.login({ success: (loginRes) => { loginByOpenId({ code: loginRes.code, tenantId: 10519 }).then(async (data) => { if (data) { // 保存登录信息 saveUserToStorage(data.access_token, data.user); setUser(data.user); setIsLoggedIn(true); // 处理邀请关系 if (data.user?.userId) { try { const inviteSuccess = await handleInviteRelation(data.user.userId); if (inviteSuccess) { console.log('自动登录时邀请关系建立成功'); } } catch (error) { console.error('自动登录时处理邀请关系失败:', error); } } resolve(data.user); } else { reject(new Error('自动登录失败')); } }).catch(_ => { // 首次注册,跳转到邀请注册页面 const pages = Taro.getCurrentPages(); const currentPage = pages[pages.length - 1]; const inviteParams = getStoredInviteParams() if (currentPage?.route !== 'dealer/apply/add' && inviteParams?.inviter) { return Taro.navigateTo({ url: '/dealer/apply/add' }); } }); }, fail: reject }); }); return res; } catch (error) { console.error('自动登录失败:', error); return null; } }; // 从本地存储加载用户数据 const loadUserFromStorage = async () => { try { const token = Taro.getStorageSync('access_token'); const userData = Taro.getStorageSync('User'); const userId = Taro.getStorageSync('UserId'); const tenantId = Taro.getStorageSync('TenantId'); if (token && userData) { const userInfo = typeof userData === 'string' ? JSON.parse(userData) : userData; setUser(userInfo); setIsLoggedIn(true); } else if (token && userId) { // 如果有token和userId但没有完整用户信息,标记为已登录但需要获取用户信息 setIsLoggedIn(true); setUser({ userId, tenantId } as User); } else { // 没有本地登录信息,尝试自动登录 console.log('没有本地登录信息,尝试自动登录...'); const autoLoginResult = await autoLoginByOpenId(); if (!autoLoginResult) { setUser(null); setIsLoggedIn(false); } } } catch (error) { console.error('加载用户数据失败:', error); setUser(null); setIsLoggedIn(false); } finally { setLoading(false); } }; // 保存用户数据到本地存储 const saveUserToStorage = (token: string, userInfo: User) => { try { Taro.setStorageSync('access_token', token); Taro.setStorageSync('User', userInfo); // 确保关键字段不为空时才保存,避免覆盖现有数据 if (userInfo.userId) { Taro.setStorageSync('UserId', userInfo.userId); } if (userInfo.tenantId) { Taro.setStorageSync('TenantId', userInfo.tenantId); } if (userInfo.phone) { Taro.setStorageSync('Phone', userInfo.phone); } // 保存头像和昵称信息 if (userInfo.avatar) { Taro.setStorageSync('Avatar', userInfo.avatar); } if (userInfo.nickname) { Taro.setStorageSync('Nickname', userInfo.nickname); } } catch (error) { console.error('保存用户数据失败:', error); } }; // 登录用户 const loginUser = (token: string, userInfo: User) => { setUser(userInfo); setIsLoggedIn(true); saveUserToStorage(token, userInfo); }; // 退出登录 const logoutUser = () => { setUser(null); setIsLoggedIn(false); // 清除本地存储 try { Taro.removeStorageSync('access_token'); Taro.removeStorageSync('User'); Taro.removeStorageSync('UserId'); Taro.removeStorageSync('TenantId'); Taro.removeStorageSync('Phone'); Taro.removeStorageSync('userInfo'); } catch (error) { console.error('清除用户数据失败:', error); } }; // 从服务器获取最新用户信息 const fetchUserInfo = async () => { if (!isLoggedIn) { return null; } try { setLoading(true); const userInfo = await getUserInfo(); setUser(userInfo); // 更新本地存储 const token = Taro.getStorageSync('access_token'); if (token) { saveUserToStorage(token, userInfo); } return userInfo; } catch (error) { console.error('获取用户信息失败:', error); // 如果获取失败,可能是token过期,清除登录状态 const errorMessage = error instanceof Error ? error.message : String(error); if (errorMessage?.includes('401') || errorMessage?.includes('未授权')) { logoutUser(); } return null; } finally { setLoading(false); } }; // 更新用户信息 const updateUser = async (userData: Partial) => { if (!user) { throw new Error('用户未登录'); } try { // 先获取最新的用户信息,确保我们有完整的数据 const latestUserInfo = await getUserInfo(); // 合并最新的用户信息和要更新的数据 const updatedUser = { ...latestUserInfo, ...userData }; // 调用API更新用户信息 await updateUserInfo(updatedUser); // 更新本地状态 setUser(updatedUser); // 更新本地存储 const token = Taro.getStorageSync('access_token'); if (token) { saveUserToStorage(token, updatedUser); } Taro.showToast({ title: '更新成功', icon: 'success', duration: 1500 }); return updatedUser; } catch (error) { console.error('更新用户信息失败:', error); Taro.showToast({ title: '更新失败', icon: 'error', duration: 1500 }); throw error; } }; // 检查是否有特定权限 const hasPermission = (permission: string) => { if (!user || !user.authorities) { return false; } return user.authorities.some(auth => auth.authority === permission); }; // 检查是否有特定角色 const hasRole = (roleCode: string) => { if (!user || !user.roles) { return false; } return user.roles.some(role => role.roleCode === roleCode); }; // 获取用户头像URL const getAvatarUrl = () => { return user?.avatar || user?.avatarUrl || ''; }; const getUserId = () => { return user?.userId; }; // 获取用户显示名称 const getDisplayName = () => { return user?.nickname || user?.realName || user?.username || '未登录'; }; // 获取用户显示的角色(同步版本) const getRoleName = () => { if(hasRole('superAdmin')){ return '超级管理员'; } if(hasRole('admin')){ return '管理员'; } if(hasRole('staff')){ return '员工'; } if(hasRole('vip')){ return 'VIP会员'; } return '注册用户'; } // 检查用户是否已实名认证 const isCertified = () => { return user?.certification === true; }; // 检查用户是否是管理员 const isAdmin = () => { return user?.isAdmin === true; }; const isSuperAdmin = () => { return user?.isSuperAdmin === true; }; // 获取用户余额 const getBalance = () => { return user?.balance || 0; }; // 获取用户积分 const getPoints = () => { return user?.points || 0; }; // 初始化时加载用户数据 useEffect(() => { loadUserFromStorage().catch(error => { console.error('初始化用户数据失败:', error); setLoading(false); }); }, []); return { // 状态 user, isLoggedIn, loading, // 方法 loginUser, logoutUser, fetchUserInfo, updateUser, loadUserFromStorage, autoLoginByOpenId, // 工具方法 hasPermission, hasRole, getAvatarUrl, getDisplayName, getRoleName, isCertified, isAdmin, getBalance, getPoints, getUserId, isSuperAdmin }; };