静态路由配置

Pro 中默认会读取 config/config.tsx 中的 routes 配置作为 ProLayout 的菜单数据来生成菜单,并且配合 plugin-access 还可以很方便的进行菜单的权限管理。
位置:/config/routers.ts
image.png

  1. export default [
  2. {
  3. path: '/',
  4. component: '../layouts/BlankLayout',
  5. routes: [
  6. {
  7. path: '/user',
  8. component: '../layouts/UserLayout',
  9. routes: [
  10. {
  11. name: 'login',
  12. path: '/user/login',
  13. component: './User/login',
  14. },
  15. ],
  16. },
  17. {
  18. path: '/',
  19. component: '../layouts/SecurityLayout',
  20. routes: [
  21. {
  22. path: '/',
  23. component: '../layouts/BasicLayout',
  24. authority: ['admin', 'user'],
  25. routes: [
  26. {
  27. path: '/',
  28. redirect: '/welcome',
  29. },
  30. {
  31. path: '/welcome',
  32. name: 'welcome',
  33. icon: 'smile',
  34. component: './Welcome',
  35. },
  36. {
  37. path: '/admin',
  38. name: 'admin',
  39. icon: 'crown',
  40. component: './Admin',
  41. authority: ['admin'],
  42. routes: [
  43. {
  44. path: '/admin/sub-page',
  45. name: 'sub-page',
  46. icon: 'smile',
  47. component: './Welcome',
  48. authority: ['admin'],
  49. },
  50. ],
  51. },
  52. {
  53. name: 'list.table-list',
  54. icon: 'table',
  55. path: '/list',
  56. component: './TableList',
  57. },
  58. {
  59. path: '/system',
  60. name: '系统管理',
  61. icon: 'crown',
  62. authority: ['admin'],
  63. routes: [
  64. {
  65. path: '/system/user',
  66. name: '用户管理',
  67. icon: 'smile',
  68. component: './system/user',
  69. authority: ['admin'],
  70. },{
  71. path: '/system/organize',
  72. name: '组织管理',
  73. icon: 'smile',
  74. component: './system/organize',
  75. authority: ['admin'],
  76. },
  77. {
  78. path: '/system/role',
  79. name: '角色管理',
  80. icon: 'smile',
  81. component: './system/role',
  82. authority: ['admin'],
  83. },
  84. {
  85. path: '/system/dictionary',
  86. name: '字典管理',
  87. icon: 'smile',
  88. component: './system/dictionary',
  89. authority: ['admin'],
  90. },
  91. {
  92. path: '/system/menu',
  93. name: '菜单管理',
  94. icon: 'smile',
  95. component: './system/menu',
  96. authority: ['admin'],
  97. },
  98. {
  99. path: '/system/area',
  100. name: '地区管理',
  101. icon: 'smile',
  102. component: './system/area',
  103. authority: ['admin'],
  104. },
  105. {
  106. path: '/system/group',
  107. name: '用户组管理',
  108. icon: 'smile',
  109. component: './system/group',
  110. authority: ['admin'],
  111. },
  112. {
  113. path: '/system/Gencode',
  114. name: '代码生成器',
  115. icon: 'crown',
  116. component: './system/Gencode',
  117. authority: ['admin']
  118. },
  119. ],
  120. },
  121. {
  122. path: '/quartz',
  123. name: 'quartz定时器',
  124. routes: [
  125. {
  126. path: '/quartz/Cron',
  127. name: 'cron表达式',
  128. component: './quartz/Cron',
  129. },{
  130. path: '/quartz/CronSelect',
  131. name: 'cron表达式',
  132. component: './quartz/CronSelect',
  133. },{
  134. path: '/quartz/TimTask',
  135. name: 'quartz任务管理',
  136. component: './quartz/TimTask',
  137. },{
  138. path: '/quartz/busTask',
  139. name: '业务任务案例',
  140. component: './quartz/busTask',
  141. }
  142. ],
  143. },
  144. {
  145. path: '/monitor',
  146. name: '监控管理',
  147. routes: [
  148. {
  149. path: '/monitor/server',
  150. name: '服务监控',
  151. component: './monitor/server',
  152. }
  153. ],
  154. },
  155. {
  156. path: '/example',
  157. name: '案例管理',
  158. icon: 'crown',
  159. authority: ['admin'],
  160. routes: [
  161. {
  162. path: '/example/userOrganize',
  163. name: '选择用户组织',
  164. icon: 'smile',
  165. component: './example/userOrganize',
  166. authority: ['admin']
  167. },{
  168. path: '/example/openHref',
  169. name: '外链跳转',
  170. icon: 'smile',
  171. component: './example/openHref',
  172. authority: ['admin']
  173. },{
  174. path: '/example/iframe',
  175. name: 'iframe嵌套',
  176. icon: 'smile',
  177. component: './example/iframe',
  178. authority: ['admin']
  179. },{
  180. path: '/example/richText',
  181. name: 'iframe嵌套',
  182. icon: 'smile',
  183. component: './example/richText',
  184. authority: ['admin']
  185. },{
  186. path: '/gencode/mycontent',
  187. name: '测试单表',
  188. icon: 'smile',
  189. component: './gencode/mycontent',
  190. authority: ['admin']
  191. },
  192. ],
  193. },
  194. {
  195. path: '/gencode',
  196. name: '代码生成',
  197. icon: 'crown',
  198. authority: ['admin'],
  199. routes: [
  200. {
  201. path: '/gencode/mycontent',
  202. name: '测试单表',
  203. icon: 'smile',
  204. component: './gencode/mycontent',
  205. authority: ['admin']
  206. },
  207. {
  208. path: '/gencode/mytree',
  209. name: '测试树表',
  210. icon: 'smile',
  211. component: './gencode/mytree',
  212. authority: ['admin']
  213. },
  214. ],
  215. },
  216. {
  217. component: './404',
  218. },
  219. ],
  220. },
  221. {
  222. component: './404',
  223. },
  224. ],
  225. },
  226. ],
  227. },
  228. {
  229. component: './404',
  230. },
  231. ];

动态路由配置

在某些情况下,写死的菜单数据可能满足不了我们的需求,Pro 也提供了相应的解决方案来进行远程的菜单数据请求。我们这里需要用到两个 API, menu.request 和 menu.params,request 需要传入一个 promise,它会自动托管 loading,params 修改会触发 request 方便重新请求菜单。
image.png
进入src/layouts/Basilayout.js在官网中直接复制该代码,将原文件替换。
现在正式进入正题。
image.png

查询菜单

  1. //查询菜单
  2. getTreeList({types: '0,1,3,4'}).then((res:any) =>{
  3. // console.log('--------------我进来查询菜单了。。。。')
  4. // console.log(res);
  5. const treeData = fommat(
  6. res.data,
  7. "parent_id"
  8. );
  9. const menu = menuAuthorized(treeData);
  10. setMenuData(menu);
  11. })

菜单数据格式化

  1. const fommat = (arrayList:any,pidStr = "parent_id",idStr = "id",childrenStr = "children") => {
  2. let listOjb = {}; // 用来储存{key: obj}格式的对象
  3. let treeList = []; // 用来储存最终树形结构数据的数组
  4. // 将数据变换成{key: obj}格式,方便下面处理数据
  5. // const responseDataLength = response?.data?.data?.length || 0;
  6. for (let i = 0; i < arrayList?.length || 0; i++) {
  7. var data = arrayList[i];
  8. data.key = data.id;
  9. data.icon = "";
  10. //处理菜单格式信息
  11. // if (data.type == '0') {//目录
  12. // } else if (data.type == '1') {
  13. // } else if (data.type == '4') {
  14. // }
  15. const authority = data.role_ids?.split(',')
  16. if (data.child_num > 0) {
  17. if (authority == undefined) {
  18. authority = ['system']
  19. } else {
  20. authority.push('system');
  21. }
  22. }
  23. data.authority = authority;
  24. if (data.type == '3') {
  25. data.target = '_black';
  26. }
  27. // console.log(data.meta)
  28. listOjb[arrayList[i][idStr]] = data;
  29. }
  30. // 根据pid来将数据进行格式化
  31. for (let j = 0; j < arrayList?.length || 0; j++) {
  32. // 判断父级是否存在
  33. let haveParent = listOjb[arrayList[j][pidStr]];
  34. if (haveParent) {
  35. // 如果有没有父级children字段,就创建一个children字段
  36. !haveParent[childrenStr] && (haveParent[childrenStr] = []);
  37. // 在父级里插入子项
  38. haveParent[childrenStr].push(arrayList[j]);
  39. } else {
  40. // 如果没有父级直接插入到最外层
  41. treeList.push(arrayList[j]);
  42. }
  43. }
  44. return treeList;
  45. }

注意:需要在router.config.js里面把你的菜单全集写出来。你动态拉取的必须是你router.config.js里面有的路由才能有效。

菜单权限控制

权限菜单的配置

在路由配置中,通过配置authority: [‘admin’, ‘user’],来控制权限,权限标识可以理解成通过角色进行控制,比如admin角色和user角色。
image.png

赋权控制

1、鉴权角色设置

image.png

2、鉴权角色管理

通过设置【authority】可以对权限角色进行控制,角色存储在本地:antd-pro-authority。
image.png

3、菜单权限鉴权

image.png

  1. /**
  2. * 通用权限检查方法 Common check permissions method
  3. *
  4. * @param { 权限判定 | Permission judgment } authority
  5. * @param { 你的权限 | Your permission description } currentAuthority
  6. * @param { 通过的组件 | Passing components } target
  7. * @param { 未通过的组件 | no pass components } Exception
  8. */
  9. const checkPermissions = <T, K>(
  10. authority: IAuthorityType,
  11. currentAuthority: string | string[],
  12. target: T,
  13. Exception: K,
  14. ): T | K | React.ReactNode => {
  15. // 没有判定权限.默认查看所有
  16. // Retirement authority, return target;
  17. if (!authority) {
  18. return target;
  19. }
  20. // 数组处理
  21. if (Array.isArray(authority)) {
  22. if (Array.isArray(currentAuthority)) {
  23. if (currentAuthority.some((item) => authority.includes(item))) {
  24. return target;
  25. }
  26. } else if (authority.includes(currentAuthority)) {
  27. return target;
  28. }
  29. return Exception;
  30. }
  31. // string 处理
  32. if (typeof authority === 'string') {
  33. if (Array.isArray(currentAuthority)) {
  34. if (currentAuthority.some((item) => authority === item)) {
  35. return target;
  36. }
  37. } else if (authority === currentAuthority) {
  38. return target;
  39. }
  40. return Exception;
  41. }
  42. // Promise 处理
  43. if (authority instanceof Promise) {
  44. return <PromiseRender<T, K> ok={target} error={Exception} promise={authority} />;
  45. }
  46. // Function 处理
  47. if (typeof authority === 'function') {
  48. const bool = authority(currentAuthority);
  49. // 函数执行后返回值是 Promise
  50. if (bool instanceof Promise) {
  51. return <PromiseRender<T, K> ok={target} error={Exception} promise={bool} />;
  52. }
  53. if (bool) {
  54. return target;
  55. }
  56. return Exception;
  57. }
  58. throw new Error('unsupported parameters');
  59. };