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

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 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=>{19if (ele.children && ele.children.length > 0) {20  menuInfo.push({this.getSubMenus(ele.children)});21} else {22  menuInfo.push({ele.title});23}24     });25     return menuInfo;26   };27 28   render() {29     return (3031  32    33      
34 .35
36 40 {this.state.menus}41 42 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,{20method: 'POST', 21body: JSON.stringify(body), 22headers: 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权限控制、动态菜单的生成