1.若依后台提供了获取当前登录用户菜单路由的方法,在SysLoginController中
    image.png
    java方法代码如下:

    1. @GetMapping("getRouters")
    2. public AjaxResult getRouters()
    3. {
    4. Long userId = SecurityUtils.getUserId();
    5. List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
    6. return AjaxResult.success(menuService.buildMenus(menus));
    7. }

    代码逻辑是得到当前登录用户userId,根据当前登录用户Id,到sys_menu表中递归遍历用户有权访问的所有菜单,并返回一个JSON结果。

    2.我们查一下sys_menu表中的数据,parent_id为0的是第一级菜单,菜单是个树状设计,可以根据parent_id查找子菜单
    image.png

    3.下一步我们想先了解下getRouters接口生成的JSON数据格式,再确定怎么跟我们的菜单格式做匹配,这里有个问题就是getRouters接口是不能在浏览器中直接访问测试的,要先登录,拿到当前用户登录userId,然后按照JWT规范,在Header中加入Token才能正常访问到getRouters接口,我们没法在浏览器中直接调用getRouters接口的,这个问题如何解决呢,有两个方案,方案一是按swagger规范写接口,用swagger方式来做测试,具体可以参考https://doc.ruoyi.vip/ruoyi-cloud/cloud/swagger.html(这个版本是微服务版,仅供参考),方案二是使用postman之类的工具来做测试,方案一要改代码,繁琐一点,我们采用方案二

    4.Postman的调用方式,我们用截图稍作说明,我们先实现登录,url地址里面填http://localhost:8080/login
    Headers Content-Type选application/json,
    image.png
    image.png
    body中参数格式如下

    1. {
    2. "username":"admin",
    3. "password":"admin123"
    4. }

    点发送时,正常登录的话会返回token值,我们要拿这个token只来测试/getRouters接口,这次测试登录我们拿到的token值是(每次调用的时候token值会不一样):eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6ImM1OGNjMTI5LWZjMzctNDc0YS04OTkyLTIyYmM2ZTEwZDI0ZiJ9.Jed5Kf6c-HiewxeJY44enCWJbuDkqOfXorAtq4oUCk-yDPQgHexd-OhK-rSRz3l4evAZ9zO_tLE2ELn8n_RQ

    5.我们在postman中新建一个Tab栏,来测试/getRouters接口,请求方法改为Get,请求地址填写http://localhost:8080/getRouters,Headers Content-Type选application/json,
    image.png
    Header中新增一行,key中输入”Authorization”,value中输入Bearer+空格+刚才拿到的Token即eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6ImM1OGNjMTI5LWZjMzctNDc0YS04OTkyLTIyYmM2ZTEwZDI0ZiJ9.Jed5Kf6c-HiewxeJY44enCWJbuDkqOfXorAtq4oUCk-yDPQgHexd-OhK-rSRz3l4evAZ9zOtLE2ELn8n_RQ,完整的value值为:
    Bearer eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6ImM1OGNjMTI5LWZjMzctNDc0YS04OTkyLTIyYmM2ZTEwZDI0ZiJ9.Jed5Kf6c-HiewxeJY44enCWJbuDkqOfXorAt_q4oUCk
    -yDPQgHexd-OhK-rSRz3l4evAZ9zO_tLE2ELn8n_RQ
    然后点发送,如下图所示:
    image.png

    6.顺利的话应该可以拿到admin用户可以访问的所有菜单JSON数据,最终拿到的JSON数据如下:

    1. {
    2. "msg":"操作成功",
    3. "code":200,
    4. "data":[
    5. {
    6. "name":"System",
    7. "path":"/system",
    8. "hidden":false,
    9. "redirect":"noRedirect",
    10. "component":"Layout",
    11. "alwaysShow":true,
    12. "meta":{
    13. "title":"系统管理",
    14. "icon":"system",
    15. "noCache":false,
    16. "link":null
    17. },
    18. "children":[
    19. {
    20. "name":"User",
    21. "path":"user",
    22. "hidden":false,
    23. "component":"system/user/index",
    24. "meta":{
    25. "title":"用户管理",
    26. "icon":"user",
    27. "noCache":false,
    28. "link":null
    29. }
    30. },
    31. {
    32. "name":"Role",
    33. "path":"role",
    34. "hidden":false,
    35. "component":"system/role/index",
    36. "meta":{
    37. "title":"角色管理",
    38. "icon":"peoples",
    39. "noCache":false,
    40. "link":null
    41. }
    42. },
    43. {
    44. "name":"Menu",
    45. "path":"menu",
    46. "hidden":false,
    47. "component":"system/menu/index",
    48. "meta":{
    49. "title":"菜单管理",
    50. "icon":"tree-table",
    51. "noCache":false,
    52. "link":null
    53. }
    54. },
    55. {
    56. "name":"Dept",
    57. "path":"dept",
    58. "hidden":false,
    59. "component":"system/dept/index",
    60. "meta":{
    61. "title":"部门管理",
    62. "icon":"tree",
    63. "noCache":false,
    64. "link":null
    65. }
    66. },
    67. {
    68. "name":"Post",
    69. "path":"post",
    70. "hidden":false,
    71. "component":"system/post/index",
    72. "meta":{
    73. "title":"岗位管理",
    74. "icon":"post",
    75. "noCache":false,
    76. "link":null
    77. }
    78. },
    79. {
    80. "name":"Dict",
    81. "path":"dict",
    82. "hidden":false,
    83. "component":"system/dict/index",
    84. "meta":{
    85. "title":"字典管理",
    86. "icon":"dict",
    87. "noCache":false,
    88. "link":null
    89. }
    90. },
    91. {
    92. "name":"Config",
    93. "path":"config",
    94. "hidden":false,
    95. "component":"system/config/index",
    96. "meta":{
    97. "title":"参数设置",
    98. "icon":"edit",
    99. "noCache":false,
    100. "link":null
    101. }
    102. },
    103. {
    104. "name":"Notice",
    105. "path":"notice",
    106. "hidden":false,
    107. "component":"system/notice/index",
    108. "meta":{
    109. "title":"通知公告",
    110. "icon":"message",
    111. "noCache":false,
    112. "link":null
    113. }
    114. },
    115. {
    116. "name":"Log",
    117. "path":"log",
    118. "hidden":false,
    119. "redirect":"noRedirect",
    120. "component":"ParentView",
    121. "alwaysShow":true,
    122. "meta":{
    123. "title":"日志管理",
    124. "icon":"log",
    125. "noCache":false,
    126. "link":null
    127. },
    128. "children":[
    129. {
    130. "name":"Operlog",
    131. "path":"operlog",
    132. "hidden":false,
    133. "component":"monitor/operlog/index",
    134. "meta":{
    135. "title":"操作日志",
    136. "icon":"form",
    137. "noCache":false,
    138. "link":null
    139. }
    140. },
    141. {
    142. "name":"Logininfor",
    143. "path":"logininfor",
    144. "hidden":false,
    145. "component":"monitor/logininfor/index",
    146. "meta":{
    147. "title":"登录日志",
    148. "icon":"logininfor",
    149. "noCache":false,
    150. "link":null
    151. }
    152. }
    153. ]
    154. }
    155. ]
    156. },
    157. {
    158. "name":"Monitor",
    159. "path":"/monitor",
    160. "hidden":false,
    161. "redirect":"noRedirect",
    162. "component":"Layout",
    163. "alwaysShow":true,
    164. "meta":{
    165. "title":"系统监控",
    166. "icon":"monitor",
    167. "noCache":false,
    168. "link":null
    169. },
    170. "children":[
    171. {
    172. "name":"Online",
    173. "path":"online",
    174. "hidden":false,
    175. "component":"monitor/online/index",
    176. "meta":{
    177. "title":"在线用户",
    178. "icon":"online",
    179. "noCache":false,
    180. "link":null
    181. }
    182. },
    183. {
    184. "name":"Job",
    185. "path":"job",
    186. "hidden":false,
    187. "component":"monitor/job/index",
    188. "meta":{
    189. "title":"定时任务",
    190. "icon":"job",
    191. "noCache":false,
    192. "link":null
    193. }
    194. },
    195. {
    196. "name":"Druid",
    197. "path":"druid",
    198. "hidden":false,
    199. "component":"monitor/druid/index",
    200. "meta":{
    201. "title":"数据监控",
    202. "icon":"druid",
    203. "noCache":false,
    204. "link":null
    205. }
    206. },
    207. {
    208. "name":"Server",
    209. "path":"server",
    210. "hidden":false,
    211. "component":"monitor/server/index",
    212. "meta":{
    213. "title":"服务监控",
    214. "icon":"server",
    215. "noCache":false,
    216. "link":null
    217. }
    218. },
    219. {
    220. "name":"Cache",
    221. "path":"cache",
    222. "hidden":false,
    223. "component":"monitor/cache/index",
    224. "meta":{
    225. "title":"缓存监控",
    226. "icon":"redis",
    227. "noCache":false,
    228. "link":null
    229. }
    230. }
    231. ]
    232. },
    233. {
    234. "name":"Tool",
    235. "path":"/tool",
    236. "hidden":false,
    237. "redirect":"noRedirect",
    238. "component":"Layout",
    239. "alwaysShow":true,
    240. "meta":{
    241. "title":"系统工具",
    242. "icon":"tool",
    243. "noCache":false,
    244. "link":null
    245. },
    246. "children":[
    247. {
    248. "name":"Build",
    249. "path":"build",
    250. "hidden":false,
    251. "component":"tool/build/index",
    252. "meta":{
    253. "title":"表单构建",
    254. "icon":"build",
    255. "noCache":false,
    256. "link":null
    257. }
    258. },
    259. {
    260. "name":"Gen",
    261. "path":"gen",
    262. "hidden":false,
    263. "component":"tool/gen/index",
    264. "meta":{
    265. "title":"代码生成",
    266. "icon":"code",
    267. "noCache":false,
    268. "link":null
    269. }
    270. },
    271. {
    272. "name":"Swagger",
    273. "path":"swagger",
    274. "hidden":false,
    275. "component":"tool/swagger/index",
    276. "meta":{
    277. "title":"系统接口",
    278. "icon":"swagger",
    279. "noCache":false,
    280. "link":null
    281. }
    282. }
    283. ]
    284. },
    285. {
    286. "name":"Http://ruoyi.vip",
    287. "path":"http://ruoyi.vip",
    288. "hidden":false,
    289. "component":"Layout",
    290. "meta":{
    291. "title":"若依官网",
    292. "icon":"guide",
    293. "noCache":false,
    294. "link":"http://ruoyi.vip"
    295. }
    296. }
    297. ]
    298. }

    7.以一个菜单为例,我们稍微分析下拿到的JSON数据

    1. "name":"System",
    2. "path":"/system",
    3. "hidden":false,
    4. "redirect":"noRedirect",
    5. "component":"Layout",
    6. "alwaysShow":true,
    7. "meta":
    8. {
    9. "title":"系统管理",
    10. "icon":"system",
    11. "noCache":false,
    12. "link":null
    13. },
    14. "children":[...]

    name菜单英文名, path 路由位置,hidden是否隐藏,redirect默认跳转路由,component使用组件,
    meta.title菜单中文名称,meta.icon:菜单图标,children[]子菜单数组。

    8.对比下我们现在从config/config.js中拿到的菜单格式

    1. {
    2. name: 'table-list',
    3. icon: 'smile',
    4. path: '/list/table-list',
    5. component: './list/table-list',
    6. },

    config.js中的菜单只有4个属性,name,icon,path,component,跟我们从数据库中拿到的菜单有部分不太一样,我们的icon在meta.icon中,我们的name要取中文显示,应该用meta.title,这个属性值的转换我们就不改后台的代码了,直接在前台做转换,不过由于是一个树状结构,要用到递归,有一点点麻烦,下一步我们先封装请求菜单的service方法。