From e41c300624e1a04a5d44e48bba2f2097745757ee Mon Sep 17 00:00:00 2001 From: zhuhengtan Date: Sat, 13 May 2023 18:31:56 +0800 Subject: [PATCH] feat: route without auth redirect to 404 --- src/app.tsx | 27 ++-- src/components/layout/index.tsx | 252 ++++++++------------------------ src/index.tsx | 7 +- src/routes/auth-routes.tsx | 142 ++++++++++++++++++ 4 files changed, 214 insertions(+), 214 deletions(-) create mode 100644 src/routes/auth-routes.tsx diff --git a/src/app.tsx b/src/app.tsx index 648fa11..6e69abb 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,35 +1,26 @@ import './lang/i18n' - +import React from 'react' import { useLocalStorageState } from 'ahooks' -import { ConfigProvider } from 'antd' -import React, { useEffect } from 'react' import { - BrowserRouter as Router, useRoutes, useParams, RouteObject, -} from 'react-router-dom' -import routes from '@/routes' -import theme from './antd-theme.json' -import { languageMap } from './utils' + ConfigProvider, +} from 'antd' -function GetRoutes() { - const elements = useRoutes(routes as RouteObject[]) +import useGetAuthRoutes from '@/routes/auth-routes' - return elements -} +import theme from './antd-theme.json' +import { languageMap } from './utils' function App() { const [language] = useLocalStorageState('LANGUAGE', { defaultValue: 'zh', }) - const [token] = useLocalStorageState('TOKEN', { - defaultValue: '', - }) + + const { authRoutes } = useGetAuthRoutes() return ( // 默认使用中文包,需要切换国际化时请自行配置 - - - + {authRoutes} ) } diff --git a/src/components/layout/index.tsx b/src/components/layout/index.tsx index 16eded6..7d27d34 100644 --- a/src/components/layout/index.tsx +++ b/src/components/layout/index.tsx @@ -1,4 +1,3 @@ -/* eslint-disable no-continue */ import './index.less' import 'antd/es/layout/style' @@ -8,7 +7,6 @@ import { useLocalStorageState, useRequest } from 'ahooks' import { Breadcrumb, Layout, Menu, - MenuProps, Space, } from 'antd' import React, { @@ -22,15 +20,14 @@ import { Outlet, Link } from 'react-router-dom' import allRoutes from '@/routes' import api from '@/service' -import { AdminAuthContext } from '@/context/AdminAuthContext' -import { AdminInfo, CustomRouteObject } from '@/type' +import { CustomRouteObject } from '@/type' + +import useGetAuthRoutes from '@/routes/auth-routes' import Avatar from './avatar' import GlobalLan from './global-lan' import Logo from './logo' -const { getAdminAuth: getAdminAuthRequest } = api - interface BreadcrumbItem { path: string name: string @@ -44,9 +41,6 @@ const CustomLayout = () => { const navigate = useNavigate() const [collapsed, setCollapsed] = useState(false) const { t } = useTranslation() - const [adminAuth, setAdminAuth] = useState({}) - const [finalAuth, setAuth] = useLocalStorageState('AUTH', {}) - const [admin] = useLocalStorageState('USER_INFO') // 如果没有登录,跳转登录页 const [token] = useLocalStorageState('TOKEN', { @@ -121,195 +115,63 @@ const CustomLayout = () => { setCollapsed(!collapsed) }, [collapsed]) - const goToPage = useCallback( - (menu: CustomRouteObject) => { - // const path = menu.path.toLocaleString(); - navigate(menu.path as any) - }, - [navigate], - ) - - function renderMenuItem(originRoutes: CustomRouteObject[]) { - return originRoutes - .filter((item) => !item.hidden) - .map((item) => { - const { path, icon, name } = item - const routes = (item.children || []).filter((item2) => !item2.hidden) - if (routes.length) { - return ( - - {renderMenuItem(routes)} - - ) - } - return ( - { - goToPage(item) - }} - title={name} - icon={icon} - > - {name} - - ) - }) - } - - const { run: getAdminAuth } = useRequest(() => getAdminAuthRequest({ id: (admin as AdminInfo).id }), { - manual: true, - onSuccess(e: any) { - setAdminAuth(e.auth) - setAuth(e.auth) - }, - }) - - useEffect(() => { - if (token) { - getAdminAuth() - } - }, [getAdminAuth, token]) - - // const filterRoutersByPermission = useCallback( - // (routers: RouteConfig[]) => { - // const arr: RouteConfig[] = [] - // routers.some((router) => { - // const obj = { ...router } - // if ( - // obj.checkAuth - // && Object.prototype.hasOwnProperty.call(adminAuth, obj.path as string) - // ) { - // arr.push(obj) - // } - // if (obj.routes && obj.routes.length) { - // const newRouters = filterRoutersByPermission(obj.routes) - // if (newRouters.length) { - // obj.routes = newRouters - // arr.push(obj) - // return true - // } - // return true - // } - // if (!obj.checkAuth) { - // arr.push(obj) - // } - // return false - // }) - // return arr - // }, - // [adminAuth], - // ) - - const routeItemsWithPermission = useMemo(() => { - const filterRoutersByPermission = (routers: CustomRouteObject[]): MenuProps['items'] => { - const arr: MenuProps['items'] = [] - for (let i = 0; i < routers.length; i++) { - const obj = { ...routers[i] } - if (obj.hidden) { - continue - } - if (obj.checkAuth) { - if (Object.hasOwn(adminAuth, obj.path as string)) { - arr.push({ - key: obj.path as string, - icon: obj.icon, - title: obj.name, - label: obj.name, - onClick: () => { - goToPage(obj) - }, - }) - continue - } - continue - } - if (obj.children && obj.children.length) { - const newRouters = filterRoutersByPermission(obj.children) - if (newRouters && newRouters.length) { - arr.push({ - key: obj.path as string, - icon: obj.icon, - title: obj.name, - label: obj.name, - children: newRouters, - }) - continue - } - continue - } - arr.push({ - key: obj.path as string, - icon: obj.icon, - title: obj.name, - label: obj.name, - onClick: () => { - goToPage(obj) - }, - }) - } - return arr - } - return filterRoutersByPermission(allRoutes) - }, [goToPage, adminAuth]) + const { menuList } = useGetAuthRoutes() return ( - - - - - - - -
-
- {React.createElement( - collapsed ? MenuUnfoldOutlined : MenuFoldOutlined, - { - onClick: toggleCollapse, - }, - )} - - {breadcrumbList.map((item: BreadcrumbItem) => { - if (typeof item === 'object') { - return ( - - {item.path ? ( - {t(item.name)} - ) : ( - t(item.name) - )} - - ) - } - return {item} - })} - -
- - - - -
- - - -
{t('APP NAME')}
-
+ + + + + + +
+
+ {React.createElement( + collapsed ? MenuUnfoldOutlined : MenuFoldOutlined, + { + onClick: toggleCollapse, + }, + )} + + {breadcrumbList.map((item: BreadcrumbItem) => { + if (typeof item === 'object') { + return ( + + {item.path ? ( + {t(item.name)} + ) : ( + t(item.name) + )} + + ) + } + return {item} + })} + +
+ + + + +
+ + + +
{t('APP NAME')}
- + ) } export default React.memo(CustomLayout) diff --git a/src/index.tsx b/src/index.tsx index 001e092..3003874 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,9 +1,14 @@ import React from 'react' import './index.less' import { createRoot } from 'react-dom/client' +import { BrowserRouter as Router } from 'react-router-dom' import App from './app' const container = document.getElementById('root') const root = createRoot(container!) // createRoot(container!) if you use TypeScript -root.render() +root.render( + + + , +) diff --git a/src/routes/auth-routes.tsx b/src/routes/auth-routes.tsx new file mode 100644 index 0000000..975aca4 --- /dev/null +++ b/src/routes/auth-routes.tsx @@ -0,0 +1,142 @@ +/* eslint-disable no-continue */ +import routes from '@/routes' +import { CustomRouteObject, AdminInfo } from '@/type' +import { + useNavigate, + useRoutes, + RouteObject, +} from 'react-router' + +import React, { + useEffect, useState, useMemo, useCallback, +} from 'react' +import { MenuProps } from 'antd' +import { useLocalStorageState, useRequest } from 'ahooks' +import api from '@/service' +import { AdminAuthContext } from '@/context/AdminAuthContext' + +export default function useGetAuthRoutes() { + const navigate = useNavigate() + const [adminAuth, setAdminAuth] = useState({}) + const [finalAuth, setAuth] = useLocalStorageState('AUTH', {}) + // 如果没有登录,跳转登录页 + const [token] = useLocalStorageState('TOKEN', { + defaultValue: '', + }) + const [admin] = useLocalStorageState('USER_INFO') + + const { run: getAdminAuth } = useRequest(() => api.getAdminAuth({ id: (admin as AdminInfo).id }), { + manual: true, + onSuccess(e: any) { + setAdminAuth(e.auth) + setAuth(e.auth) + }, + }) + + useEffect(() => { + if (token) { + getAdminAuth() + } + }, [getAdminAuth, token]) + + // 这里直接过滤掉没有权限的path + const goToPage = useCallback( + (menu: CustomRouteObject) => { + // const path = menu.path.toLocaleString(); + navigate(menu.path as any) + }, + [navigate], + ) + + const authedRoutes = useMemo( + () => { + const filterRoutersByPermission = (routers: CustomRouteObject[]): CustomRouteObject[] => { + const arr: CustomRouteObject[] = [] + routers.forEach((router) => { + const obj = { ...router } + if (obj.children && obj.children.length) { + const childRouters = filterRoutersByPermission(obj.children) + if (childRouters.length) { + obj.children = childRouters + arr.push(obj) + } + } else { + if (obj.checkAuth && Object.prototype.hasOwnProperty.call(adminAuth, obj.path as string)) { + arr.push(obj) + } + if (!obj.checkAuth) { + arr.push(obj) + } + } + }) + return arr + } + return filterRoutersByPermission(routes) + }, + [adminAuth], + ) + + const menuList = useMemo(() => { + const formatMenus = (routers: CustomRouteObject[]): MenuProps['items'] => { + const arr: MenuProps['items'] = [] + for (let i = 0; i < routers.length; i++) { + const obj = { ...routers[i] } + if (obj.hidden) { + continue + } + if (obj.checkAuth) { + if (Object.hasOwn(adminAuth, obj.path as string)) { + arr.push({ + key: obj.path as string, + icon: obj.icon, + title: obj.name, + label: obj.name, + onClick: () => { + goToPage(obj) + }, + }) + continue + } + continue + } + if (obj.children && obj.children.length) { + const newRouters = formatMenus(obj.children) + if (newRouters && newRouters.length) { + arr.push({ + key: obj.path as string, + icon: obj.icon, + title: obj.name, + label: obj.name, + children: newRouters, + }) + continue + } + continue + } + arr.push({ + key: obj.path as string, + icon: obj.icon, + title: obj.name, + label: obj.name, + onClick: () => { + goToPage(obj) + }, + }) + } + return arr + } + return formatMenus(routes) + }, [goToPage, adminAuth]) + + const elements = useRoutes(authedRoutes as RouteObject[]) + + return { + authedRoutes, + menuList, + authRoutes: ( + + {elements} + + ), + } +}