揭秘如何使用react 18 + antd (v5.3.0) 进行权限列表设置?

本文介绍了如何利用antd库在React应用中进行权限管理的实现,包括获取并渲染左侧导航数据,通过Table组件展示权限列表,以及添加自定义渲染功能,如Tag、Switch和Popover等。同时,详细讲述了编辑和删除权限的操作处理,包括确认对话框和状态更新。
摘要由CSDN通过智能技术生成

antd专门为react定制的中后台组件库,提供了大量的组件供开发者使用,

官网地址 点击跳转

在中后台中,权限管理是必不可少的,今天就使用react结合antd V5.0 处理一下权限管理.

此权限管理,分两部分: 权限列表角色管理

  • 权限列表即如何在页面中配置左侧导航栏显示列表
  • 角色管理即各种用户角色配置

本节主要是阐述如何配置权限列表

最终显示结果如下:

此部分,主要用到了antd的组件如下:

  • Space,
  • Switch,
  • Table,
  • Tag,
  • Button,
  • Modal,
  • Popover

实现步骤如下:

第一步,获取左侧导航数据用于渲染表格

此部分用到表格组件.

选用的是 树形数据展示 ,当然也可以选择其他。

获取数据

const [dataSource, setdataSource] = useState([]);

useEffect(() => {
  const fetchData = async () => {
    const menusListData = await fetchGetMenus(); // fetchGetMenus 为获取导航数据的api接口
    menusListData.forEach((element) => {
      if (element.children.length === 0) {
        element.children = ""; // 此处处理是为了防止有空数组显示
      }
    });

    setdataSource(menusListData);
  };
  fetchData();
}, []); 

渲染表格

// RightList.js
import { useState, useEffect } from 'react'
import {Table} from "antd";

export default function Redirect() {
  const [dataSource, setdataSource] = useState([]);

  useEffect(() => {
  const fetchData = async () => {
    const menusListData = await fetchGetMenus(); // fetchGetMenus 为获取导航数据的api接口
    menusListData.forEach((element) => {
      if (element.children.length === 0) {
        element.children = ""; // 此处处理是为了防止有空数组显示
      }
    });

    setdataSource(menusListData);
  };
  fetchData();
  }, []);

  const columns = [
    {
      title: "ID",
      dataIndex: "id",
    },
    {
      title: "权限名称",
      dataIndex: "title",
    },
    {
      title: "权限路径",
      dataIndex: "key" 
    }, 
  ];

  return (
    <div>Redirect</div>
  )
} 

页面显示如下

第二步,表格添加自定义渲染设置

列描述数据对象 – render,是 columns 中的一项,Column 使用相同的 API。

render 生成复杂数据的渲染函数,参数分别为当前行的值当前行数据行索引

使用方法: function(text, record, index) {}

改造columns数据

// RightList.js

const columns = [
  {
    title: "ID",
    dataIndex: "id",
  },
  {
    title: "权限名称",
    dataIndex: "title",
  },
  {
    title: "权限路径",
    dataIndex: "key",
    render: (key) => {
      return <Tag color="magenta">{key}</Tag>;
    },
  },
  {
    title: "操作",
    render: (item) => {  // 注意此处传值 item
      // item
      return (
        <Space>
          <Popover
            style={{ width: "100px" }}
            content={
              <div
                style={{
                  display: "flex",
                  alignItems: "center",
                  textAlign: "center",
                }}
              >
                <h5 style={{padding: '0 10px 0 0'}}>显示左侧导航栏</h5>{" "}
                <Switch
                  size="small"
                  checked={item.pagepermisson === 1 ? true : false}
                  onChange={() => switchChange(item)}
                />
              </div>
            }
            title="左侧导航栏权限配置"
            trigger={item.pagepermisson === undefined ? "" : "click"}
          >
            <Button
              icon={<EditOutlined style={{ fontSize: "12px" }} />}
              shape="circle"
              type="primary"
              size="small"
              disabled={item.pagepermisson === undefined}
            ></Button>
          </Popover>

          <Button
            icon={<DeleteOutlined style={{ fontSize: "12px" }} />}
            shape="circle"
            danger
            size="small"
            onClick={() => {
              confirmHandel(item); // 注意此处传值 item
            }}
          ></Button>
        </Space>
      );
    },
  },
];

页面展示如下

第三步,添加编辑和删除事件

删除操作

删除操作是一个比较危险的操作,所以,需要再次提醒用户是否确实需要删除操作。

此处使用了 弹出确认框组件

// 删除弹框事件
const confirmHandel = (item) => {
  confirm({
    title: "您确定要删除吗?",
    icon: <ExclamationCircleFilled />,
    content: "此处删除会删除掉左侧导航,请谨慎操作!",
    okText: "确认",
    cancelText: "取消",
    onOk() {
      console.log("OK");
      deleteRightMethod(item);
    },
    onCancel() {
      console.log("Cancel");
    },
  });
};

// 删除事件
const deleteRightMethod = async (item) => {
  console.log(item);
  if (item.grade === 1) {
    setdataSource(dataSource.filter((data) => data.id != item.id));
    const menusListData = await fetchDeleteMenus(item.id); // 调用后端接口
  } else if (item.grade === 2) {
    let list = dataSource.filter((data) => data.id === item.rightId);
    list[0].children = list[0].children.filter((data) => data.id !== item.id);
    setdataSource([...dataSource]); 
    const menusListData = await fetchDeleteSubMenus(item.id); // 调用后端接口
  } else {
    return false;
  }
};

编辑操作

// 编辑事件
const switchChange = async (item) => {
  console.log(item);
  item.pagepermisson = item.pagepermisson === 1 ? 0 : 1;
  setdataSource([...dataSource]);
  if (item.grade === 1) {
    await fetchPatchMenus(item.id, { pagepermisson: item.pagepermisson }); // 调用后端接口
  } else if (item.grade === 2) { 
    await fetchPatchSubMenus(item.id, { pagepermisson: item.pagepermisson }); // 调用后端接口
  } else {
    return false;
  }
};

完整代码

import { useState, useEffect } from "react";
import { Space, Switch, Table, Tag, Button, Modal, Popover } from "antd";
import {
  DeleteOutlined,
  EditOutlined,
  ExclamationCircleFilled,
} from "@ant-design/icons";
import {
  fetchGetMenus,
  fetchDeleteMenus,
  fetchDeleteSubMenus,
  fetchPatchMenus,
  fetchPatchSubMenus,
} from "../../utils/api";
const { confirm } = Modal;
export default function RightList() {
  const [dataSource, setdataSource] = useState([]);

  useEffect(() => {
    const fetchData = async () => {
      const menusListData = await fetchGetMenus();
      menusListData.forEach((element) => {
        if (element.children.length === 0) {
          element.children = "";
        }
      });
      setdataSource(menusListData);
    };
    fetchData();
  }, []);

  // 删除弹框事件
  const confirmHandel = (item) => {
    confirm({
      title: "您确定要删除吗?",
      icon: <ExclamationCircleFilled />,
      content: "此处删除会删除掉左侧导航,请谨慎操作!",
      okText: "确认",
      cancelText: "取消",
      onOk() {
        console.log("OK");
        deleteRightMethod(item);
      },
      onCancel() {
        console.log("Cancel");
      },
    });
  };

  // 删除事件
  const deleteRightMethod = async (item) => {
    console.log(item);
    if (item.grade === 1) {
      setdataSource(dataSource.filter((data) => data.id != item.id));
      const menusListData = await fetchDeleteMenus(item.id);
    } else if (item.grade === 2) {
      let list = dataSource.filter((data) => data.id === item.rightId);
      list[0].children = list[0].children.filter((data) => data.id !== item.id);
      setdataSource([...dataSource]);
      const menusListData = await fetchDeleteSubMenus(item.id);
    } else {
      return false;
    }
  };

  // 编辑事件
  const switchChange = async (item) => {
    console.log(item);
    item.pagepermisson = item.pagepermisson === 1 ? 0 : 1;
    setdataSource([...dataSource]);
    if (item.grade === 1) {
      await fetchPatchMenus(item.id, { pagepermisson: item.pagepermisson });
    } else if (item.grade === 2) {
      await fetchPatchSubMenus(item.id, { pagepermisson: item.pagepermisson });
    } else {
      return false;
    }
  };

  const columns = [
    {
      title: "ID",
      dataIndex: "id",
    },
    {
      title: "权限名称",
      dataIndex: "title",
    },
    {
      title: "权限路径",
      dataIndex: "key",
      render: (key) => {
        return <Tag color="magenta">{key}</Tag>;
      },
    },
    {
      title: "操作",
      render: (item) => {
        // item
        return (
          <Space>
            <Popover
              style={{ width: "100px" }}
              content={
                <div
                  style={{
                    display: "flex",
                    alignItems: "center",
                    textAlign: "center",
                  }}
                >
                  <h5 style={{padding: '0 10px 0 0'}}>显示左侧导航栏</h5>{" "}
                  <Switch
                    size="small"
                    checked={item.pagepermisson === 1 ? true : false}
                    onChange={() => switchChange(item)}
                  />
                </div>
              }
              title="左侧导航栏权限配置"
              trigger={item.pagepermisson === undefined ? "" : "click"}
            >
              <Button
                icon={<EditOutlined style={{ fontSize: "12px" }} />}
                shape="circle"
                type="primary"
                size="small"
                disabled={item.pagepermisson === undefined}
              ></Button>
            </Popover>

            <Button
              icon={<DeleteOutlined style={{ fontSize: "12px" }} />}
              shape="circle"
              danger
              size="small"
              onClick={() => {
                confirmHandel(item);
              }}
            ></Button>
          </Space>
        );
      },
    },
  ];

  return (
    <div>
      <Table columns={columns} dataSource={dataSource} />
    </div>
  );
}

需要思考问题

  • 如何自定义渲染表格,即添加操作一列?
  • 是否所有的权限都可以编辑?
  • 为什么需要刷新页面,左侧导航呈现修改状态?
  • 是否还有需要完善部分?肯定有。如何完善?

此问题,下部分在做回答。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端布道人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值