San3yuan | 4d0e803 | 2025-04-04 17:21:40 +0800 | [diff] [blame] | 1 | import { Navigate, Outlet } from 'react-router-dom' |
San3yuan | 292794c | 2025-06-08 20:02:46 +0800 | [diff] [blame] | 2 | import React, { useEffect, useState } from 'react' |
San3yuan | 2534d42 | 2025-04-08 21:43:18 +0800 | [diff] [blame] | 3 | import { useSelector } from 'react-redux' |
San3yuan | 292794c | 2025-06-08 20:02:46 +0800 | [diff] [blame] | 4 | import { useApi } from '@/hooks/request' |
| 5 | import request from '@/utils/request' |
| 6 | import { getUserInfo } from '@/api/user' |
| 7 | import { useAppDispatch } from '@/hooks/store' |
San3yuan | 4d0e803 | 2025-04-04 17:21:40 +0800 | [diff] [blame] | 8 | |
| 9 | interface PrivateRouteProps { |
San3yuan | 2534d42 | 2025-04-08 21:43:18 +0800 | [diff] [blame] | 10 | role: number |
San3yuan | 4d0e803 | 2025-04-04 17:21:40 +0800 | [diff] [blame] | 11 | redirectPath?: string |
| 12 | children?: React.ReactNode |
| 13 | } |
| 14 | |
| 15 | const PrivateRoute = ({ |
San3yuan | 2534d42 | 2025-04-08 21:43:18 +0800 | [diff] [blame] | 16 | role, |
San3yuan | 4d0e803 | 2025-04-04 17:21:40 +0800 | [diff] [blame] | 17 | redirectPath = '/login', |
| 18 | children |
| 19 | }: PrivateRouteProps) => { |
San3yuan | 2534d42 | 2025-04-08 21:43:18 +0800 | [diff] [blame] | 20 | const isLogin = useSelector((state: any) => state.user.isLogin) |
| 21 | const userRole = useSelector((state: any) => state.user.role) |
San3yuan | 292794c | 2025-06-08 20:02:46 +0800 | [diff] [blame] | 22 | const userId = useSelector((state: any) => state.user.userId) |
| 23 | const dispatch = useAppDispatch() |
| 24 | const [hasFetchedUser, setHasFetchedUser] = useState(false) // 防止重复请求 |
| 25 | const { refresh: getUserInfoRefresh } = useApi( |
| 26 | () => request.get(getUserInfo), |
| 27 | false |
| 28 | ) |
| 29 | |
| 30 | useEffect(() => { |
| 31 | if (isLogin && !userId && !hasFetchedUser) { |
| 32 | const fetchUserInfo = async () => { |
| 33 | try { |
| 34 | const userInfo = await getUserInfoRefresh() |
| 35 | if (userInfo && !(userInfo as any).error) { |
| 36 | dispatch({ type: 'user/getUserInfo', payload: userInfo.userInfo }) |
| 37 | setHasFetchedUser(true) // 标记已请求 |
| 38 | } |
| 39 | } catch (error) { |
| 40 | console.error('获取用户信息失败:', error) |
| 41 | } |
| 42 | } |
| 43 | fetchUserInfo() |
| 44 | } |
| 45 | }, [isLogin, userId, hasFetchedUser, dispatch, getUserInfoRefresh]) |
San3yuan | 2534d42 | 2025-04-08 21:43:18 +0800 | [diff] [blame] | 46 | |
| 47 | if (!isLogin) { |
San3yuan | 4d0e803 | 2025-04-04 17:21:40 +0800 | [diff] [blame] | 48 | return <Navigate to={redirectPath} replace /> |
| 49 | } |
| 50 | |
San3yuan | 2534d42 | 2025-04-08 21:43:18 +0800 | [diff] [blame] | 51 | if (role && role >= userRole) { |
| 52 | return <Navigate to={redirectPath} replace /> |
| 53 | } |
| 54 | |
San3yuan | 292794c | 2025-06-08 20:02:46 +0800 | [diff] [blame] | 55 | return children ? <>{children}</> : <Outlet /> |
San3yuan | 4d0e803 | 2025-04-04 17:21:40 +0800 | [diff] [blame] | 56 | } |
| 57 | |
| 58 | export default PrivateRoute |