menu.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. const { AccessControl } = require('accesscontrol');
  2. const { buildAc } = require('./can');
  3. class Menu {
  4. ac;
  5. menuList;
  6. /**
  7. *
  8. * @param {AccessControl} ac
  9. * @param {*} menuList
  10. */
  11. constructor(menuList, ac) {
  12. this.ac = ac;
  13. this.menu = {
  14. name: 'ROOT',
  15. children: menuList,
  16. }
  17. }
  18. /*
  19. * 深度优先
  20. */
  21. travelDFS(menu, callback, depth) {
  22. depth = depth || 0;
  23. if (menu.children) {
  24. menu.children.forEach(c => this.travelDFS(c, callback, depth + 1))
  25. }
  26. callback(menu, depth);
  27. }
  28. /*
  29. * 广度优先
  30. */
  31. travelBFS(menu, callback, depth) {
  32. depth = depth || 0;
  33. callback(menu, depth);
  34. if (menu.children) {
  35. menu.children.forEach(c => this.travelBFS(c, callback, depth + 1))
  36. }
  37. }
  38. checkPermission(role, permission) {
  39. permission.role = role;
  40. return this.ac.permission(permission).granted;
  41. }
  42. /*
  43. * 根据角色获取菜单
  44. */
  45. getByRole(role) {
  46. let menu = this.dcopy(this.menu);
  47. this.travelDFS(menu, (item) => {
  48. let keep = item.permission ? this.checkPermission(role, item.permission) : true;
  49. item.keep = item.children ? item.children.some(c => c.keep) : keep;
  50. });
  51. this.travelBFS(menu, (item) => {
  52. if (item.children) item.children = item.children.filter(c => c.keep);
  53. });
  54. //移除无用信息
  55. this.travelBFS(menu, (item) => {
  56. delete item.permission;
  57. delete item.keep;
  58. });
  59. //this.print(menu);
  60. //console.log(JSON.stringify(menu, null, 2));
  61. return menu.children;
  62. }
  63. print(menu) {
  64. menu = menu || this.menu;
  65. this.travelBFS(menu, (item, depth) => {
  66. console.log(
  67. '\t\t\t\t\t\t\t\t\t'.substr(0, depth), depth, item.name, item.url);
  68. })
  69. }
  70. dcopy(obj) {
  71. return JSON.parse(JSON.stringify(obj));
  72. }
  73. }
  74. if (require.main === module) {
  75. (async () => {
  76. let username = 'chengen.test';
  77. let user = await require('../../models').User.findOne({ username });
  78. if (!user) throw new Error(`user ${username}`);
  79. let ac = await buildAc(user._id);
  80. const menu = new Menu(require('./menu-config'), ac);
  81. menu.print();
  82. let roleMenu = menu.getByRole('user');
  83. //let roleMenu = menu.getByRole('调解员');
  84. console.log(JSON.stringify(roleMenu, null, 2));
  85. })().catch(console.error)
  86. }
  87. module.exports = Menu;