umi6.x + react + antd的项目增加403(无权限页面拦截),404,错误处理页面

  1. 首先在src/pages下创建403,404,ErrorBoundary

    403
    import { Button, Result } from 'antd';
    import { history } from '@umijs/max';

    const UnAccessible = () => (
    <Result
    status="403"
    title="403"
    subTitle="抱歉,您无权限访问当前页面"
    extra={<Button type="primary" onClick={()=>{
    history.push('/')
    }}>返回主页}
    />
    );
    export default UnAccessible;

    404
    import { Button, Result } from 'antd';
    import { history } from '@umijs/max';

    const NotFound = () => (
    <Result
    status="404"
    title="404"
    subTitle="抱歉,无法找到你需要的页面"
    extra={<Button type="primary" onClick={()=>{
    history.push('/')
    }}>返回主页}
    />
    );
    export default NotFound;

    ErrorBoundary(错误边界)
    import { Result, Button, Tooltip, Typography } from 'antd';
    import React from 'react';
    // eslint-disable-next-line @typescript-eslint/ban-types
    export default class ErrorBoundary extends React.Component {
    state = { hasError: false, errorInfo: '' };
    static getDerivedStateFromError(error) {
    return { hasError: true, errorInfo: error.message };
    }

    componentDidCatch(error, errorInfo) {
    // You can also log the error to an error reporting service
    // eslint-disable-next-line no-console
    console.log(error, errorInfo);
    }

    render() {
    if (this.state.hasError) {
    // You can render any custom fallback UI
    return (
    <Result
    status="500"
    title={抱歉,服务发生错误!请刷新页面}
    subTitle={
    <Typography.Paragraph copyable={{
    text:this.state.errorInfo
    }}>错误信息</Typography.Paragraph>
    }
    extra={
    <Button
    type="primary"
    onClick={() => {
    window.location.reload();
    }}
    >
    刷新页面

    }
    />
    );
    }
    return this.props.children;
    }
    }

  2. 在app.js配置

  3. 对于没有权限的页面,在浏览器输入地址,前端拦截,需要access.js方法拦截,src/access.js
    4中routes.js中配置的access就是作为key(accessObj获取的key要和routes.js中配置的access一致)

    /* eslint-disable array-callback-return */
    import allData from '../config/routes';

    //获取权限 key 根据 path 生成
    function convertToAccessArray(data) {
    let accessArray = [];
    data.map(obj => {
    if (obj.path && obj.path !== '/' && obj.path !== '/home') {
    // 去掉路径中的斜杠,并且将首字母大写
    const access = obj.path.replace(///g, '').charAt(0).toUpperCase() + obj.path.replace(///g, '').slice(1);
    accessArray.push(access);
    }
    if (obj.routes) {
    const childAccessArray = convertToAccessArray(obj.routes);
    accessArray = accessArray.concat(childAccessArray);
    }
    });

    return accessArray;
    }

    export default (initialState) => {

    const {menuData} = initialState;
    //后端返回的页面(路由)
    const AccessList = convertToAccessArray(menuData?.routes??[]);
    //全部页面
    const AllList = convertToAccessArray(allData?.routes);
    //结果对象 accessKey 对应配置的 routes 里面的 access
    // {
    // accessKey: true or false
    // }
    const accessObj = {};

    //添加权限
    AllList?.map(it=>{
    accessObj[it] = AccessList.includes(it);
    })

    return accessObj;
    };

//后端返回的页面(路由)格式类似:

复制代码
[
    {
        "name": "首页",
        "key": "2024042410100000000",
        "path": "/home",
        "icon": null,
        "routes": []
    },
    {
        "name": "IoT管理",
        "key": "2024042410200000000",
        "path": "/iot",
        "icon": null,
        "routes": [
            {
                "name": "设备管理",
                "key": "2024042410200200000",
                "path": "/iot/device",
                "icon": "icon-shebeiguanli",
                "routes": [
                    {
                        "name": "设备台账",
                        "key": "2024042410200201000",
                        "path": "/iot/device/account",
                        "icon": null,
                        "routes": []
                    }
                ]
            }
        ]
    }
]
  1. 如果要对没有权限的页面进行拦截,还需要在routes.js配置access

    {
    path: '/',
    routes: [
    {
    path: '/',
    redirect: '/home',
    },
    {
    name: '首页',
    path: '/home',
    component: './Home',
    },
    {
    name: 'IoT管理',
    path: '/iot',
    access: 'Iot',
    routes: [
    {
    name: '设备清单',
    path: '/iot/devicelist',
    icon: 'icon-zhiduguifan',
    component: './Iot/DeviceList',
    access: 'Iotdevicelist',
    }
    ],
    },
    {
    path:'/*',
    name: '404',
    component: './404',
    hideInMenu: true,
    },
    ],
    }

相关推荐
牛仔只喝牛奶15 小时前
多端跨端技术选型:小程序 + H5 + App 的两栈拆分落地
react native·react.js
wear工程师19 小时前
setState 到底是不是异步的?这题从 React 16 问到 18,标准答案早就变了
react.js·面试
wanghowie21 小时前
LangGraph4j 落地(二)— ReAct 多步工具与 trace 扩展
前端·react.js·前端框架
csj501 天前
前端基础之《React(11)—state声明式》
前端·react.js
张元清1 天前
React useLocalStorage Hook:SSR 安全的持久化状态(2026)
javascript·react.js
析数塔1 天前
2026前端框架深度解析:React Compiler、Angular Zoneless、Vue 3.5重写游戏规则
前端·vue.js·react.js
杖雍皓1 天前
没有服务器如何构建现代 Web 应用:平台选型与组合策略
运维·服务器·前端·react.js·github·netlify·vercel
sun_weitao1 天前
微前端框架之qiankun 怎么用?vue3+vite+qiankun 和 react + qiankun
前端·react.js·前端框架
名字还没想好☜2 天前
React useEffect 依赖数组踩坑:闭包陷阱与清理函数
前端·javascript·react.js·react·useeffect
我是大卫2 天前
【图】React源码解析-第四部分:事件与跨层传递
react.js·源码