React中实战入手实现菜单管理
【摘要】 React中实战入手实现菜单管理
❤ React-菜单管理
使用场景
使用背景 有时候我们需要给不同的用户赋予不同的权限进行系统的访问,这个时候我们就需要用到角色权限,通过角色来控制角色可以访问哪些菜单和路由
先来看一下我们最后搭建的效果
1、接口封装
封装相关的接口,还是跟我们之前差不多,但是这次我们新建文件src\api\system\role.js
import request from '@/utils/request.js'
const apiTypeurl='/api/menu';
// 查询菜单列表
export function getMenuList (n) {
return request({
url: apiTypeurl,
method: 'get',
params:n
})
}
// 添加菜单
export function addMenu (n) {
return request({
url: apiTypeurl,
method: 'post',
data:n
})
}
// 删除菜单
export function delMenu (id) {
return request({
url:apiTypeurl+ '/'+id,
method: 'delete'
})
}
// 修改菜单
export function editMenu(n) {
return request({
url: apiTypeurl,
method: 'put',
data:n
})
}
// 获取菜单详情
export function getMenu(id) {
return request({
url:apiTypeurl+ '/'+id,
method: 'get'
})
}
// 修改菜单状态
export function editMenuStatus (MenuId,status) {
return request({
url: apiTypeurl+'/status/'+MenuId,
method: 'put',
data:status
})
}
2、页面路由的增加
在页面的路由之中添加相关页面的路由部分src\router\index.tsx
// 权限部分
const PermissionMenu = lazy(() => import('@/views/system/permission/menu'));
{
key: '7',
path: "/admin/permission/menu",
element: <PermissionMenu/>,
label: '菜单管理',
// 该路由不出现在左侧菜单栏
meta: {
hidden: true
}
},
3、查询和页面搭建
整个页面的部分我们都写到这个里面 src\views\system\permission\menu.tsx
先来搭建一个简单的页面列表
👉表格部分搭建
表单引入,这里的表单以及结构的搭建还和我们之前角色的部分差不多
//引入我们相关的接口
import {getMenuList, addMenu, delMenu, editMenu, getMenu, editMenuStatus} from '@/api/system/menu'; //菜单接口
useEffect(() => {
handleQuery();
}, [queryParams]);
const handleQuery = () => {
console.log('handleQuery');
getList();
}
查看一下我们的查询接口
// 获取列表
const getList = async () => {
try {
const res:any = await getMenuList(queryForm); // 假设getUser函数能够正确返回Promise对象
if(res.code == 200){
message.success('查询成功!');
setDatatable(res.data);
}else{
console.log('查询失败,请重试!',res, 'getUser');
message.error(res.message);
}
} catch (error) {
console.log('查询失败,请重试!');
}
}
查看一下我们返回的数据
查询已经完整了证明!
接下来完善一下我们的表单部分
表单部分我们增加一下
const [data, setData] = useState([]);
const columns = [
{
title: '菜单编号',
dataIndex: 'menu_id',
key: 'menu_id',
render: (_: any, row) => {return (<> {row?.menu_id|| '--'}</>)},
},
{
title: '菜单名称',
dataIndex: 'menu_name',
key: 'menu_id',
render: (_: any, row) => {return (<> {row?.menu_name|| '--'}</>)},
},
{
title: '图标',
dataIndex: 'icon',
key: 'icon',
render: (_: any, row) => {return (<> {row?.icon|| '--'}</>)},
},
// <svg-icon :icon-class="scope.row.icon" />
{
title: '排序',
dataIndex: 'order_num',
key: 'order_num',
render: (_: any, row) => {return (<> {row?.order_num|| '--'}</>)},
},
{
title: '权限标识',
dataIndex: 'perms',
key: 'perms',
render: (_: any, row) => {return (<> {row?.perms|| '--'}</>)},
},
{
title: '组件路径',
dataIndex: 'component',
key: 'component',
render: (_: any, row) => {return (<> {row?.component|| '--'}</>)},
},
{
title: '可见',
dataIndex: 'visible',
key: 'visible',
render: (_: any, row) => {return (<> {row?.visible|| '--'}</>)},
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
render: (_: any, row) => {return (<> {row?.createTime|| '--'}</>)},
},
{
title: '操作',
key: 'action',
render: (_, row) => {
return (
<Flex gap="middle" wrap>
<Button type="dashed"
onClick={() => handleEdit(row)}
autoInsertSpace={false}>
修改
</Button>
<Button type="dashed"
onClick={() => handleEnable(row)}
autoInsertSpace={false} style={{color:row.state == 1 ? 'red' : "green"}}>
新增
</Button>
<Popconfirm
title="确定要删除吗?"
onConfirm={() => handleDelete(row)}
okText="确定"
cancelText="取消"
>
<Button style={{ marginLeft: 8 }} type="dashed" autoInsertSpace>
删除
</Button>
</Popconfirm>
</Flex>
)
},
},
];
<div className='comback' style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Table rowKey="id" dataSource={data} columns={columns} />
</div>
👉核对表单参数
其实也就是更改表单的这部分
页面搭建部分先看看
4、antd table 树形数据展示
这里我们需要注意的就是我们想要的不是普通的这种表格样式数据,其实是antd table 树形数据展示
接下来我们就把写一下这种树形数据
现在我们的数据是这样子的,也就是我们需要自己手动转化一下
为了使table能显示子节点 所以要重新数据处理
// import Menu from "@/services/menu"
import { map } from "lodash"
function getMenuData(data) {
console.log(data);
if (data[0].level === undefined) {
const rows = map(data, (item, index) => ({
key: "key" + index,
item
}))
return rows
}
var result = [], len = 0
data.forEach(item => {
if (item.id > len)
len = item.id
return len
})
const rows = map(data, (item, index) => ({
key: "row" + item.name,
item,
children: []
}))
for (let i = 0; i < len; i++) {
for (let j = 0; j < len; j++) {
if (rows[i] && rows[j] && rows[i].item.parent_id && rows[i].item.parent_id === rows[j].item.id) {
rows[j].children.push(rows[i])
}
}
}
rows.forEach(e=>{
if(e.children.length===0){
delete e.children
}
})
rows.forEach(elem => {
if (elem.item.parent_id === null) {
result.push(elem)
}
})
return result
}
export default getMenuData
5、新增功能部分
接下来搭建我们的新增部分,这里还是跟我们之前用户部分的搭建弹窗差不多!
我们先来简单的写一些参数然后看看我们的效果是什么样子的
我们的接口部分请求的地址部分方面是这样子的
这里我们可以先增加一个数据试试
直接就成功了,看一下我们的参数部分
完善一下我们的角色方面的逻辑
增加逻辑还是我们之前的那一部分,成功!
5、修改部分
const handleEdit = async (row) => {
setTitle("编辑");
try {
setLoading(true);
let data = await handleDetail(row); // 接口的方式查询
form.setFieldsValue(data); // 填充数据到表单中
} catch (error) {
message.error('获取数据详情失败,请重试!');
} finally {
setLoading(false);
}
setVisible(true);
};
/**
* 处理详情
*
* @param row 表格行数据
* @returns 返回获取到的详情数据
*/
const handleDetail = async (row) => {
try {
const response = await getDictType(row.dict_id);
const data = response.data;
return data;
} catch (error) {
message.error('获取数据详情失败,请重试!');
}
}
这边修改部分我们可以看到已经好了,完善一下功能就可以了,注意这部分我们稍后也是进行抽离的!
6、删除部分
<Button
type="link"
size="small"
danger
key="batchRemove"
// hidden={!access.hasPerms('system:dictType:remove')}
onClick={async () => {
console.log(row,'row--1');
Modal.confirm({
title: '删除',
content: '确定删除该项吗?',
okText: '确认',
cancelText: '取消',
onOk: () => {
handleDelete(row);
},
});
}}
>
删除
</Button>
const handleDelete = async (record) => {
try {
await delMenu(record.menu_id);
message.success('删除成功');
handleSearch();
} catch (error) {
message.error('删除失败,请重试!');
}
};
这边我们尝试一下,我们的删除已经成功了 !
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)