SAAS云平台搭建札记: (三) AntDesign + .Net Core WebAPI权限控制、动态菜单的生成
我们知道,当下最火的前端框架,非蚂蚁金服的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权限控制、动态菜单的生成的更多相关文章
- SAAS云平台搭建札记: (四) AntD For React使用react-router-dom路由接收不同参数页面不刷新的问题
在.net开发员眼里,如果使用MVC,根据路由匹配原则,可以通过各种方式接收参数,比如 /Post/List/1, /Post/List/2,或者 /Post/List?id=1,/Post/List ...
- SAAS云平台搭建札记: (一) 浅论SAAS多租户自助云服务平台的产品、服务和订单
最近在做一个多租户的云SAAS软件自助服务平台,途中遇到很多问题,我会将一些心得.体会逐渐分享出来,和大家一起探讨.这是本系列的第一篇文章. 大家知道,要做一个全自助服务的SAAS云平台是比较复杂的, ...
- SAAS云平台搭建札记: (二) Linux Ubutu下.Net Core整套运行环境的搭建
最近做的项目,由于预算有限,公司决定不采购Windows服务器,而采购基于Linux的服务器. 一般的VPS服务器,如果使用Windows系统,那么Windows Server2012\2016安装好 ...
- Redis之高可用、集群、云平台搭建
原文:Redis之高可用.集群.云平台搭建 文章大纲 一.基础知识学习二.Redis常见的几种架构及优缺点总结三.Redis之Redis Sentinel(哨兵)实战四.Redis之Redis Clu ...
- Docker系列——InfluxDB+Grafana+Jmeter性能监控平台搭建(三)
在之前系列博文中,已经介绍完了数据采集和数据存储,那数据如何展示呢?所以今天就专门来讲下数据如何展示的问题. 以前博文参考: Docker系列--InfluxDB+Grafana+Jmeter性能监控 ...
- Redis之高可用、集群、云平台搭建(非原创)
文章大纲 一.基础知识学习二.Redis常见的几种架构及优缺点总结三.Redis之Redis Sentinel(哨兵)实战四.Redis之Redis Cluster(分布式集群)实战五.Java之Je ...
- 三种SpringSecurity方法级别权限控制
一 JSR-250注解 1.在pom.xml添加 <dependency> <groupId>javax.annotation</groupId> <arti ...
- .net core3.1 abp动态菜单和动态权限(动态菜单实现和动态权限添加) (三)
我们来创建动态菜单吧 首先,先对动态菜单的概念.操作.流程进行约束:1.Host和各个Tenant有自己的自定义菜单2.Host和各个Tenant的权限与自定义菜单相关联2.Tenant有一套默认的菜 ...
- Jmeter+ant+jenkins接口自动化测试 平台搭建(三)
四.报告优化 Jmeter 默认生成报告不是很详细,因此我们需要进行优化.这里我们使用新的报告模板:默认的报告模板是 jmeter-results-detail-report_21.xsl 先上效果图 ...
随机推荐
- buu学习记录(上)
前言:菜鸡误入buu,差点被打吐.不过学到了好多东西. 题目名称: (1)随便注 (2)高明的黑客 (3)CheckIn (4)Hack World (5)SSRF Me (6)piapiapia ( ...
- john快速破解各种散列hash
0x01 john工具安装: kali系统自带的有,也可以自己安装在其他linux和windows系统上,关于安装步骤网上都有可自行百度. 0x02 john常用选项 具体的其他选项可通过john - ...
- 二、Linux文件系统结构
为了方便管理文件和目录,Linux 系统将它们组织成一个以根目录 / 开始的倒置的树状结构.Linux 中的目录,和 Windows 系统中的文件夹类似,不同之处在于,Linux 系统中的目录也被当做 ...
- JavaSE14-集合·其一
1.Collection集合 1.1 集合体系结构 集合 (接口)Collection:单列 (接口)List:可重复 (实现类)ArrayList (实现类)LinkedList (接口)Set:不 ...
- TLS 协议
一.背景 参与了一个Sofa-RPC开源项目,认领了TLS的任务,记录下这次宝贵的经历,并感谢章哥的信任以及在整个过程中对我的帮助. 负责的部分不难,主要是使用h2(HTTP 2加密)协议,完成RPC ...
- Docker(五):Docker安装Elasticsearch
查找ElasticSearch镜像 镜像仓库 https://hub.docker.com/ 下拉镜像 docker pull elasticsearch:7.7.0 查看镜像 docker imag ...
- db2常用操作
1. db2建立远程节点编目及删除 db2 catalog tcpip node nodeName remote remoteIp server remotePort db2 list node di ...
- Application Data in Docker 笔记
Application Data in Docker By default all files created inside a container are stored on a writable ...
- 深入理解MySQL系列之索引
索引 查找一条数据的过程 先看下InnoDB的逻辑存储结构: 表空间:可以看做是InnoDB存储引擎逻辑结构的最高层,所有的数据都存放在表空间中.默认有个共享表空间ibdata1.如果启用innodb ...
- C盘满了删除C盘文件
还有很多文件在C:\Users\lock\AppData 比如C:\Users\lock\AppData\Local\Temp 临时文件 C:\Users\lock\AppData\Roaming\ ...