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,
    },
    ],
    }

相关推荐
光影少年9 小时前
如果 React 组件的属性没有传值,它的默认值是什么?
前端·javascript·react.js
Fate_I_C11 小时前
Capacitor 应用鸿蒙化实战:用 hionic 把 React 应用跑在 OpenHarmony 上
react.js·华为·harmonyos
liangshanbo121512 小时前
面试题:React.memo 和 useMemo 的区别
前端·react.js·前端框架
太子釢1 天前
React 函数组件与 Hook 实践指南
前端·react.js
liangshanbo12151 天前
面试题:React 中 Lane 和 Scheduler 是怎么配合的?
前端·react.js·前端框架
liangshanbo12151 天前
React面试题:Hooks 为什么不能在分支和循环里面写?
前端·javascript·react.js
FungLeo1 天前
成为全栈·Next.js 网站前台篇·响应式、可访问性与错误状态:内容站不能只验桌面首页
react.js·响应式设计·next.js·移动端适配·成为全栈·web 可访问性
ss2731 天前
AI全栈实战 | 3.5-01 Python 全栈前端最小集:不会 React 也能做出能看的后台,关键就一条线
前端·python·react.js
记得开心一点嘛2 天前
Trellora:基于 Electron、React 和本地知识库的 AI 知识工作台
人工智能·react.js·electron
500842 天前
React Native for OpenHarmony 实战:三方库 react-native-url-polyfill 的鸿蒙化适配指南
javascript·react native·react.js·性能优化·electron·harmonyos