我们知道,当下最火的前端框架,非蚂蚁金服的AntDesign莫属,这个框架不仅在国内非常有名,在国外GitHub上React前端框架也排名第一。而且这个框架涵盖了React、Vue、Angular等多种语言,甚至有人结合.net Core 5的新特性WebAssembly做了Ant Design Blazor,在此为国人点赞!

公司的新平台,用户前端界面当仁不让地使用了AntDesign for React,可以使用最新版本的特性(目前版本为4.10.1);至于为什么不使用Ant Design Pro,是因为Pro封装的控件太多,不利于我们自定义页面。

SAAS系统,页面上首先就是权限,我们后台采用中等复杂度的RBAC控制,如图所示:

在界面上表示,就是程序左侧的树状菜单,参照AntdPro的官方文档,路由和菜单,需要在菜单的ts文档中写清楚各种权限组和相应菜单,显然不符合我们前后端分离使用动态菜单的方法。

因此,我研究一段时间,终于找到完全在后端生成动态菜单并且在前端的使用方法,特此分享给大家。

传递到前端的菜单实体类:

1     public class 菜单实体类
2 {
3 public string key { get; set; }
4 public string icon { get; set; }
5 public string title { get; set; }
6 public string link { get; set; }
7 public IEnumerable<PortalMenu> children { get; set; }
8 }

实际上是一个递归结构的json字符串:

  1 {
2 "returnCode": 0,
3 "errorMsg": null,
4 "data": {
5 "portalMenus": [{
6 "key": "R0HGQWqTzE9gzg",
7 "icon": "DashboardOutlined",
8 "title": "查询",
9 "link": "/Wuire",
10 "children": []
11 }, {
12 "key": "g9asSJsw9yx6w",
13 "icon": "HomeOutlined",
14 "title": "管理",
15 "children": [{
16 "key": "GBvD0rfpsYa6w",
17 "title": "设定",
18 "link": "/Willage",
19 "children": []
20 }, {
21 "key": "L3LD2SrK84g",
22 "title": "管理",
23 "link": "/Wuse",
24 "children": []
25 }, {
26 "key": "Wdvue6w",
27 "title": "管理",
28 "link": "/Wner",
29 "children": []
30 }]
31 }, {
32 "key": "R3JvXJWQk6d6A",
33 "icon": "ContactsOutlined",
34 "title": "",
35 "children": [{
36 "key": "IIJCXkQfPyzg",
37 "title": "群发",
38 "children": [{
39 "key": "hnhrfYWq29w",
40 "title": "邮件",
41 "link": "/Wend",
42 "children": []
43 }, {
44 "key": "gF7a1XnHQ",
45 "title": "群板",
46 "link": "/Wdule",
47 "children": []
48 }, {
49 "key": "a8yaA-u6PNQ",
50 "title": "历史",
51 "link": "/Wtory",
52 "children": []
53 }]
54 }, {
55 "key": "CI03foxpw",
56 "title": "群发",
57 "children": [{
58 "key": "giaPpeiEoY1Rg",
59 "title": "短信",
60 "link": "/Wend",
61 "children": []
62 }, {
63 "key": "ewpJBHTcZLjutGQ",
64 "title": "模板",
65 "link": "/Wuodule",
66 "children": []
67 }, {
68 "key": "0B3qVuvVXpA",
69 "title": "历史",
70 "link": "/Wtory",
71 "children": []
72 }]
73 }, {
74 "key": "7foEYA",
75 "title": "信印",
76 "link": "/Wurint",
77 "children": []
78 }]
79 }, {
80 "key": "f3l981rYVQ",
81 "icon": "PayCircleOutlined",
82 "title": "费",
83 "children": [{
84 "key": "DIw69fx0d3Q",
85 "title": "每",
86 "link": "/Wufei",
87 "children": []
88 }, {
89 "key": "PBLCWp73mUV8kA",
90 "title": "收定",
91 "link": "/WMonth",
92 "children": []
93 }, {
94 "key": "jT8bbGMc5EVIw",
95 "title": "定",
96 "link": "/Wting/ShowfeiXiangmu",
97 "children": []
98 }, {
99 "key": "eUsfeeeOzbw",
100 "title": "表",
101 "link": "/Wufei/Daily",
102 "children": []
103 }]
104 }, {
105 "key": "RsLTvHziej3eeg",
106 "icon": "ToolOutlined",
107 "title": "理",
108 "children": [{
109 "key": "jTqs3ne_FJSxqg",
110 "title": "报",
111 "link": "/WuAdd",
112 "children": []
113 }, {
114 "key": "GTJetl8mFEQ",
115 "title": "馈",
116 "link": "/Wudback",
117 "children": []
118 }, {
119 "key": "MFtdebYGvg",
120 "title": "询",
121 "link": "/Wuyu/Inquire",
122 "children": []
123 }]
124 }, {
125 "key": "OTzJmw",
126 "icon": "MailOutlined",
127 "title": "理",
128 "children": [{
129 "key": "5x9__uzbmQ",
130 "title": "发息",
131 "link": "/Managend",
132 "children": []
133 }, {
134 "key": "D6dGz0J-u98iGXw",
135 "title": "盒",
136 "link": "/Manage/Inbox",
137 "children": []
138 }, {
139 "key": "xNE-jOp4khOHQ",
140 "title": "群发",
141 "link": "/ManagpSend",
142 "children": []
143 }, {
144 "key": "DbIxzw6Q",
145 "title": "群发",
146 "link": "/ManaSend",
147 "children": []
148 }, {
149 "key": "JRO7RUL54zaQ",
150 "title": "群发",
151 "link": "/ManaoupSend",
152 "children": []
153 }]
154 }, {
155 "key": "rKYgJZdxqQ",
156 "icon": "TeamOutlined",
157 "title": "用理",
158 "children": [{
159 "key": "VpTCpsvOsFyUZQ",
160 "icon": "UserOutlined",
161 "title": "管理",
162 "link": "/Mar/List",
163 "children": []
164 }, {
165 "key": "YVaswUMx3g",
166 "icon": "ClusterOutlined",
167 "title": "部管理",
168 "link": "/Manist",
169 "children": []
170 }, {
171 "key": "nYIdFQ9K0fiNiw",
172 "icon": "TeamOutlined",
173 "title": "用管理",
174 "link": "/MapList",
175 "children": []
176 }, {
177 "key": "5cFzOGcLIQ",
178 "icon": "KeyOutlined",
179 "title": "用管理",
180 "link": "/Manage/UsAuthority",
181 "children": []
182 }]
183 }, {
184 "key": "ab6MCJ9hNUOIfC5ofROgOw",
185 "icon": "SettingOutlined",
186 "title": "系统设置",
187 "children": [{
188 "key": "PUGYrEbEZ6Q",
189 "title": "基本设置",
190 "link": "/Manaasic",
191 "children": []
192 }, {
193 "key": "ueve6vGuOGKD8w",
194 "title": "域名设置",
195 "link": "/Manas/Domain",
196 "children": []
197 }]
198 }, {
199 "key": "46lZGOCDyk6saVYzZwdsJA",
200 "icon": "FileTextOutlined",
201 "title": "日志管理",
202 "children": [{
203 "key": "ZPi2io3l_EGATyr-9KFk2A",
204 "title": "系统日志",
205 "link": "/Manage/Log/Sys",
206 "children": []
207 }, {
208 "key": "Ze8mGMsbmkKTXtPQ",
209 "title": "操作日志",
210 "link": "/Manage/Log/Operate",
211 "children": []
212 }]
213 }],
214 "defaultMenuId": "RTzE9gzg"
215 }
216 }

前端页面接收后,处理下一二三级菜单,加上图标,就可以渲染出来了:

 1 ......
2
3 state = {
4 collapsed: false,
5 openKeys: [],
6 menus: null,
7 defaultMenuId: null,
8 };
9
10 async componentDidMount() {
11 var menus = await getUserMenus();
12 var allMenus = await this.getSubMenus(menus.portalMenus);
13 this.setState({ menus: allMenus, defaultMenuId: menus.defaultMenuId });
14 }
15
16 getSubMenus = (children) =>{
17 let menuInfo = [];
18 children.forEach(ele=>{
19 if (ele.children && ele.children.length > 0) {
20 menuInfo.push(<SubMenu key={ele.key} title={ele.title} icon={GetIconByName(ele.icon)}>{this.getSubMenus(ele.children)}</SubMenu>);
21 } else {
22 menuInfo.push(<Menu.Item key={ele.key} icon={GetIconByName(ele.icon)}><Link to={ele.link}>{ele.title}</Link></Menu.Item>);
23 }
24 });
25 return menuInfo;
26 };
27
28 render() {
29 return (
30 <Router>
31 <Layout>
32 <Sider trigger={null} collapsible collapsed={this.state.collapsed}>
33 <div className="logo">
34 .
35 </div>
36 <Menu theme="dark" mode="inline"
37 defaultSelectedKeys = {[this.state.defaultMenuId]}
38 openKeys={this.state.openKeys}
39 onOpenChange={this.onOpenChange}>
40 {this.state.menus}
41 </Menu>
42 </Sider>
43 ......

至此,左边的菜单就按照每个人的不同权限渲染出来了。

附:前端的getUserMenus和Comm方法:

 1 //用户取菜单
2 async function getUserMenus() {
3 var result = await Comm(....);
4 return result.data;
5 }
6
7 async function Comm(code, ...){
8 var body = {};
9 body.Code = code;
10 body.data = ...;
11
12 var cookie = getCookie(global.......);
13 var headers = {};
14 headers["Content-Type"] = 'application/json';
15 if(cookie){
16 headers.token = cookie;
17 }
18
19 const response = await fetch(global.webApiUrl,{
20 method: 'POST',
21 body: JSON.stringify(body),
22 headers: new Headers(headers)
23 });
24 const rep = await response.json();
25 return rep;
26 }

SAAS云平台搭建札记系列文章:

SAAS云平台搭建札记: (一)浅论SAAS多租户自助云服务平台的产品、服务和订单

SAAS云平台搭建札记: (二)Linux Unbutu下.Net Core整套运行环境的搭建

SAAS云平台搭建札记: (三) AntDesign + .Net Core WebAPI权限控制、动态菜单的生成

SAAS云平台搭建札记: (三) AntDesign + .Net Core WebAPI权限控制、动态菜单的生成的更多相关文章

  1. SAAS云平台搭建札记: (四) AntD For React使用react-router-dom路由接收不同参数页面不刷新的问题

    在.net开发员眼里,如果使用MVC,根据路由匹配原则,可以通过各种方式接收参数,比如 /Post/List/1, /Post/List/2,或者 /Post/List?id=1,/Post/List ...

  2. SAAS云平台搭建札记: (一) 浅论SAAS多租户自助云服务平台的产品、服务和订单

    最近在做一个多租户的云SAAS软件自助服务平台,途中遇到很多问题,我会将一些心得.体会逐渐分享出来,和大家一起探讨.这是本系列的第一篇文章. 大家知道,要做一个全自助服务的SAAS云平台是比较复杂的, ...

  3. SAAS云平台搭建札记: (二) Linux Ubutu下.Net Core整套运行环境的搭建

    最近做的项目,由于预算有限,公司决定不采购Windows服务器,而采购基于Linux的服务器. 一般的VPS服务器,如果使用Windows系统,那么Windows Server2012\2016安装好 ...

  4. Redis之高可用、集群、云平台搭建

    原文:Redis之高可用.集群.云平台搭建 文章大纲 一.基础知识学习二.Redis常见的几种架构及优缺点总结三.Redis之Redis Sentinel(哨兵)实战四.Redis之Redis Clu ...

  5. Docker系列——InfluxDB+Grafana+Jmeter性能监控平台搭建(三)

    在之前系列博文中,已经介绍完了数据采集和数据存储,那数据如何展示呢?所以今天就专门来讲下数据如何展示的问题. 以前博文参考: Docker系列--InfluxDB+Grafana+Jmeter性能监控 ...

  6. Redis之高可用、集群、云平台搭建(非原创)

    文章大纲 一.基础知识学习二.Redis常见的几种架构及优缺点总结三.Redis之Redis Sentinel(哨兵)实战四.Redis之Redis Cluster(分布式集群)实战五.Java之Je ...

  7. 三种SpringSecurity方法级别权限控制

    一 JSR-250注解 1.在pom.xml添加 <dependency> <groupId>javax.annotation</groupId> <arti ...

  8. .net core3.1 abp动态菜单和动态权限(动态菜单实现和动态权限添加) (三)

    我们来创建动态菜单吧 首先,先对动态菜单的概念.操作.流程进行约束:1.Host和各个Tenant有自己的自定义菜单2.Host和各个Tenant的权限与自定义菜单相关联2.Tenant有一套默认的菜 ...

  9. Jmeter+ant+jenkins接口自动化测试 平台搭建(三)

    四.报告优化 Jmeter 默认生成报告不是很详细,因此我们需要进行优化.这里我们使用新的报告模板:默认的报告模板是 jmeter-results-detail-report_21.xsl 先上效果图 ...

随机推荐

  1. buu学习记录(上)

    前言:菜鸡误入buu,差点被打吐.不过学到了好多东西. 题目名称: (1)随便注 (2)高明的黑客 (3)CheckIn (4)Hack World (5)SSRF Me (6)piapiapia ( ...

  2. john快速破解各种散列hash

    0x01 john工具安装: kali系统自带的有,也可以自己安装在其他linux和windows系统上,关于安装步骤网上都有可自行百度. 0x02 john常用选项 具体的其他选项可通过john - ...

  3. 二、Linux文件系统结构

    为了方便管理文件和目录,Linux 系统将它们组织成一个以根目录 / 开始的倒置的树状结构.Linux 中的目录,和 Windows 系统中的文件夹类似,不同之处在于,Linux 系统中的目录也被当做 ...

  4. JavaSE14-集合·其一

    1.Collection集合 1.1 集合体系结构 集合 (接口)Collection:单列 (接口)List:可重复 (实现类)ArrayList (实现类)LinkedList (接口)Set:不 ...

  5. TLS 协议

    一.背景 参与了一个Sofa-RPC开源项目,认领了TLS的任务,记录下这次宝贵的经历,并感谢章哥的信任以及在整个过程中对我的帮助. 负责的部分不难,主要是使用h2(HTTP 2加密)协议,完成RPC ...

  6. Docker(五):Docker安装Elasticsearch

    查找ElasticSearch镜像 镜像仓库 https://hub.docker.com/ 下拉镜像 docker pull elasticsearch:7.7.0 查看镜像 docker imag ...

  7. db2常用操作

    1. db2建立远程节点编目及删除 db2 catalog tcpip node nodeName remote remoteIp server remotePort db2 list node di ...

  8. Application Data in Docker 笔记

    Application Data in Docker By default all files created inside a container are stored on a writable ...

  9. 深入理解MySQL系列之索引

    索引 查找一条数据的过程 先看下InnoDB的逻辑存储结构: 表空间:可以看做是InnoDB存储引擎逻辑结构的最高层,所有的数据都存放在表空间中.默认有个共享表空间ibdata1.如果启用innodb ...

  10. C盘满了删除C盘文件

    还有很多文件在C:\Users\lock\AppData 比如C:\Users\lock\AppData\Local\Temp  临时文件 C:\Users\lock\AppData\Roaming\ ...