赞
踩
技术思路:配置路由,用户登录后根据用户信息获取后台菜单。
技术思路: 使用umijs的运行时修改路由 patchRoutes({ routes }) UMIJS 参考文档 ,react umi 没有守护路由的功能 直接在 app.tsx 的 layout 下的 childrenRender 添加守护路由 实现登录后的菜单路由增加。登录后的菜单由登录接口 加个menu参数获取。 默认路由+动态登录路由+动态菜单
文件:/src/app.tsx
找到 layout 插入 menu
- menu: {
- locale: false,
- params: {
- userId: initialState?.currentUser?.userid,//引起菜单请求的参数
- },
- request: async (params, defaultMenuData) => {
- const { data } = await getAuthRoutes();
- return loopMenuItem(data);
- },
- },
完全版:
- /**
- * 映射菜单对应的图标
- * */
- const loopMenuItem = (menus: MenuDataItem[]): MenuDataItem[] =>
- menus.map(({ icon, routes, ...item }) => ({
- ...item,
- icon: icon && <Icon component={icons[icon]} />,
- routes: routes && loopMenuItem(routes),
- })
- );
-
- // ProLayout 支持的api https://procomponents.ant.design/components/layout
- export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) => {
-
- const onCollapse = (collapsed: boolean): void => {
- setInitialState({ ...initialState, collapsed }).then();
- };
- const onSettings = (settings: any): void => {
- setInitialState({ ...initialState, settings }).then();
- };
- return {
- // 自定义头内容的方法 我把 自定义侧边栏收缩按钮位置 方在这里
- headerContentRender: () => (
- <HeaderContent collapse={initialState?.collapsed} onCollapse={onCollapse} />
- ),
- rightContentRender: () => <RightContent onSettings={onSettings} />,
- disableContentMargin: false,
- waterMarkProps: {
- content: initialState?.currentUser?.name,
- },
- // 去掉系统自带
- collapsedButtonRender: false,
- // 指定配置collapsed
- collapsed: initialState?.collapsed,
- footerRender: () => <Footer />,
- onPageChange: () => {
- const { location } = history;
- // 如果没有登录,重定向到 login
- if (!initialState?.currentUser && location.pathname !== loginPath) {
- history.push(loginPath);
- }
- },
- menu: {
- locale: false,
- params: {
- userId: initialState?.currentUser?.userid,//引起菜单请求的参数
- },
- request: async (params, defaultMenuData) => {
- const { data } = await getAuthRoutes();
- return loopMenuItem(data);
- },
- },
- links: isDev
- ? [
- <Link key="openapi" to="/umi/plugin/openapi" target="_blank">
- <LinkOutlined />
- <span>OpenAPI 文档</span>
- </Link>,
- <Link to="/~docs" key="docs">
- <BookOutlined />
- <span>业务组件文档</span>
- </Link>,
- ]
- : [],
- menuHeaderRender: undefined,
- // 自定义 403 页面
- // unAccessible: <div>unAccessible</div>,
- // 增加一个 loading 的状态
- childrenRender: (children, props) => {
- // if (initialState?.loading) return <PageLoading />;
- const { location, route } = props;
- return (
- <>
- {children}
- {/* {!props.location?.pathname?.includes('/login') && (
- <SettingDrawer
- disableUrlParams
- enableDarkTheme
- settings={initialState?.settings}
- onSettingChange={(settings) => {
- setInitialState((preInitialState) => ({
- ...preInitialState,
- settings,
- }));
- }}
- />
- )} */}
- </>
- );
- },
- ...initialState?.settings,
- };
- };
技术思路:
使用umijs的运行时修改路由 patchRoutes({ routes }) UMIJS 参考文档 ,react umi 没有守护路由的功能 直接在 app.tsx 的 layout 下的 childrenRender 添加守护路由 实现登录后的菜单路由增加。登录后的菜单由登录接口 加个menu参数获取。 默认路由+动态登录路由
文件:config/config.ts
- // https://umijs.org/config/
- import { defineConfig } from 'umi';
- import { join } from 'path';
- import defaultSettings from './defaultSettings';
- import proxy from './proxy';
- import routes from './routes';
-
- const { REACT_APP_ENV } = process.env;
-
- export default defineConfig({
- hash: true,
- antd: {},
- dva: {
- hmr: true,
- },
- layout: {
- // https://umijs.org/zh-CN/plugins/plugin-layout
- locale: false,
- siderWidth: 208,
- ...defaultSettings,
- },
- // https://umijs.org/zh-CN/plugins/plugin-locale
- locale: {
- // default zh-CN
- default: 'zh-CN',
- antd: true,
- // default true, when it is true, will use `navigator.language` overwrite default
- baseNavigator: true,
- },
- dynamicImport: {
- loading: '@ant-design/pro-layout/es/PageLoading',
- },
- targets: {
- ie: 11,
- },
- // umi routes: https://umijs.org/docs/routing
- routes,
- access: {},
- // Theme for antd: https://ant.design/docs/react/customize-theme-cn
- theme: {
- // 如果不想要 configProvide 动态设置主题需要把这个设置为 default
- // 只有设置为 variable, 才能使用 configProvide 动态设置主色调
- // https://ant.design/docs/react/customize-theme-variable-cn
- 'root-entry-name': 'variable',
- },
- // esbuild is father build tools
- // https://umijs.org/plugins/plugin-esbuild
- esbuild: {},
- title: false,
- ignoreMomentLocale: true,
- proxy: proxy[REACT_APP_ENV || 'dev'],
- manifest: {
- basePath: '/',
- },
- // Fast Refresh 热更新
- fastRefresh: {},
- openAPI: [
- {
- requestLibPath: "import { request } from 'umi'",
- // 或者使用在线的版本
- // schemaPath: "https://gw.alipayobjects.com/os/antfincdn/M%24jrzTTYJN/oneapi.json"
- schemaPath: join(__dirname, 'oneapi.json'),
- mock: false,
- },
- {
- requestLibPath: "import { request } from 'umi'",
- schemaPath: 'https://gw.alipayobjects.com/os/antfincdn/CA1dOm%2631B/openapi.json',
- projectName: 'swagger',
- },
- ],
- nodeModulesTransform: {
- type: 'none',
- },
- mfsu: {},
- webpack5: {},
- exportStatic: {},
- });
文件:config/routes.ts
- import type { MenuDataItem } from '@ant-design/pro-layout';
-
- export default [
- {
- path: '/user',
- layout: false,
- routes: [
- {
- path: '/user/login',
- layout: false,
- name: 'login',
- component: '@/pages/modules/user/Login',
- },
- {
- path: '/user/openlogin',
- layout: false,
- name: 'login',
- component: '@/pages/modules/user/openlogin',
- },
- {
- path: '/user',
- redirect: '@/pages/modules/user/login',
- },
- {
- name: 'register-result',
- icon: 'smile',
- path: '/user/register-result',
- component: '@/pages/modules/user/register-result',
- },
- {
- name: 'register',
- icon: 'smile',
- path: '/user/register',
- component: '@/pages/modules/user/register',
- }
- ]
- },
- {
- path: '/',
- component: './layouts/commonLayout',
- flatMenu: true,
- routes: [
- // {
- // path: '/welcome',
- // name: '工作台',
- // component: '@/pages/modules/welcome',
- // }
- ]
- },
- {
- component: '404',
- },
- ];
app.tsx
- let extraRoutes;
-
- export function patchRoutes({ routes }) {
- if (extraRoutes) {
- // extraRoutes.forEach((element: any) => {
- routes.forEach((route: any) => {
- if (route.path == "/") {
- route.routes = mergeRoutes(extraRoutes);
- }
- });
- // });
-
- }
- console.log("--------------------路由-------------------------", routes);
- }
-
- // export function render(oldRender) {
- // getMenu().then((res: any) => {
- // if (res.code == 200) {
- // extraRoutes = res.result;
- // oldRender();
- // } else {
- // history.push('/login');
- // oldRender()
- // }
- // });
- // }
-
- // /**
- // * 映射菜单对应的图标
- // * */
- // const loopMenuItem = (menus: MenuDataItem[]): MenuDataItem[] =>
- // menus.map(({ icon, routes, ...item }) => ({
- // ...item,
- // icon: icon && <Icon component={icons[icon]} />,
- // routes: routes && loopMenuItem(routes),
- // })
- // );
-
- /**
- * @see https://umijs.org/zh-CN/plugins/plugin-initial-state
- * */
- export async function getInitialState(): Promise<{
- settings?: Partial<LayoutSettings>;
- currentUser?: API.CurrentUser;
- loading?: boolean;
- collapsed?: boolean;
- // menuData?: MenuDataItem[] | undefined;
- fetchUserInfo?: () => Promise<API.CurrentUser | undefined>;
- }> {
- const fetchUserInfo = async () => {
- try {
- const msg = await queryCurrentUser();
- return msg.data;
- } catch (error) {
- // 跳转到指定路由
- history.push(loginPath);
- }
- return undefined;
- };
- // 如果不是登录页面,执行
- if (history.location.pathname !== loginPath) {
- const currentUser = await fetchUserInfo();
- return {
- fetchUserInfo,
- currentUser,
- settings: defaultSettings,
- };
- }
- return {
- fetchUserInfo,
- settings: defaultSettings,
- };
- }
-
- // ProLayout 支持的api https://procomponents.ant.design/components/layout
- export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) => {
-
- const onCollapse = (collapsed: boolean): void => {
- setInitialState({ ...initialState, collapsed }).then();
- };
- const onSettings = (settings: any): void => {
- setInitialState({ ...initialState, settings }).then();
- };
- return {
- // 自定义头内容的方法 我把 自定义侧边栏收缩按钮位置 方在这里
- headerContentRender: () => (
- <HeaderContent collapse={initialState?.collapsed} onCollapse={onCollapse} />
- ),
- rightContentRender: () => <RightContent onSettings={onSettings} />,
- disableContentMargin: false,
- waterMarkProps: {
- content: initialState?.currentUser?.name,
- },
- // 去掉系统自带
- collapsedButtonRender: false,
- // 指定配置collapsed
- collapsed: initialState?.collapsed,
- footerRender: () => <Footer />,
- onPageChange: () => {
- const { location } = history;
- // 如果没有登录,重定向到 login
- if (!initialState?.currentUser && location.pathname !== loginPath) {
- history.push(loginPath);
- }
- },
- // menuDataRender: () => { return fixMenuItemIcon(initialState.menuData) },
- menu: {
- locale: false,
- params: {
- userId: initialState?.currentUser?.userid,//引起菜单请求的参数
- },
- request: async (params, defaultMenuData) => {
- // const msg = await getMenu();
- return fixMenuItemIcon(initialState?.currentUser?.menu);
- },
- },
- links: isDev
- ? [
- <Link key="openapi" to="/umi/plugin/openapi" target="_blank">
- <LinkOutlined />
- <span>OpenAPI 文档</span>
- </Link>,
- <Link to="/~docs" key="docs">
- <BookOutlined />
- <span>业务组件文档</span>
- </Link>,
- ]
- : [],
- menuHeaderRender: undefined,
- // 自定义 403 页面
- // unAccessible: <div>unAccessible</div>,
- // 增加一个 loading 的状态
- childrenRender: (children, props) => {
- // if (initialState?.loading) return <PageLoading />;
- const { location, route } = props;
-
- if (history.location.pathname !== loginPath && initialState?.currentUser?.menu) {
- // 路由守卫
- // const msg = await getMenu();
- extraRoutes = initialState?.currentUser?.menu;
- console.log("--------------------路由01-------------------------", extraRoutes);
- patchRoutes(route);
- }
-
- return (
- <>
- {children}
- {/* {!props.location?.pathname?.includes('/login') && (
- <SettingDrawer
- disableUrlParams
- enableDarkTheme
- settings={initialState?.settings}
- onSettingChange={(settings) => {
- setInitialState((preInitialState) => ({
- ...preInitialState,
- settings,
- }));
- }}
- />
- )} */}
- </>
- );
- },
- ...initialState?.settings,
- };
- };
src/utils/fixMenuItemIcon.tsx
- import React from 'react';
- import type { MenuDataItem } from '@ant-design/pro-layout';
- import * as allIcons from '@ant-design/icons';
-
- const fixMenuItemIcon = (menus: MenuDataItem[], iconType = 'Outlined'): MenuDataItem[] => {
- menus.forEach((item) => {
- const { icon, routes } = item
- if (typeof icon === 'string' && icon != null) {
- const fixIconName = icon.slice(0, 1).toLocaleUpperCase() + icon.slice(1) + iconType
- // eslint-disable-next-line no-param-reassign
- item.icon = React.createElement(allIcons[fixIconName] || allIcons[icon])
- }
- // eslint-disable-next-line no-param-reassign,@typescript-eslint/no-unused-expressions
- routes && routes.length > 0 ? item.routes = fixMenuItemIcon(routes) : null
- });
- return menus
- };
-
- export default fixMenuItemIcon;
src/utils/roles.tsx
- // import { getUserPerm } from '@/services/menu';
- // import router from 'umi/router';
- import React from 'react';
- import Icon from '@ant-design/icons';
- import * as icons from '@ant-design/icons';
- import { dynamic, RunTimeLayoutConfig } from 'umi';
- import { SmileOutlined, HeartOutlined } from '@ant-design/icons'
-
-
- export function mergeRoutes(routes) {
- if (!Array.isArray(routes)) return [];
- return routes.map(route => {
- let module = route.component;
- if (route.component) {
- route.component = (component => {
- if (typeof component === 'object') {
- return component;
- }
- // 封装一个异步组件
- return dynamic({
- loader: () => import(`../pages/${module}/index.tsx`)
- });
- })(route.component);
- }
-
- if (route.routes) {
- route.routes = mergeRoutes(route.routes);
- }
- return route;
- });
- }
注意: 登陆子模块要 符合 /src/pages/ 模块名称 /index.tsx 的组合
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。