menu.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. import memoizeOne from 'memoize-one';
  2. import isEqual from 'lodash/isEqual';
  3. import { formatMessage } from 'umi/locale';
  4. import Authorized from '@/utils/Authorized';
  5. import { menu } from '../defaultSettings';
  6. const { check } = Authorized;
  7. // Conversion router to menu.
  8. function formatter(data, parentAuthority, parentName) {
  9. return data
  10. .map(item => {
  11. if (!item.name || !item.path) {
  12. return null;
  13. }
  14. let locale = 'menu';
  15. if (parentName) {
  16. locale = `${parentName}.${item.name}`;
  17. } else {
  18. locale = `menu.${item.name}`;
  19. }
  20. // if enableMenuLocale use item.name,
  21. // close menu international
  22. const name = menu.disableLocal
  23. ? item.name
  24. : formatMessage({ id: locale, defaultMessage: item.name });
  25. const result = {
  26. ...item,
  27. name,
  28. locale,
  29. authority: item.authority || parentAuthority,
  30. };
  31. if (item.routes) {
  32. const children = formatter(item.routes, item.authority, locale);
  33. // Reduce memory usage
  34. result.children = children;
  35. }
  36. delete result.routes;
  37. return result;
  38. })
  39. .filter(item => item);
  40. }
  41. const memoizeOneFormatter = memoizeOne(formatter, isEqual);
  42. /**
  43. * get SubMenu or Item
  44. */
  45. const getSubMenu = item => {
  46. // doc: add hideChildrenInMenu
  47. if (item.children && !item.hideChildrenInMenu && item.children.some(child => child.name)) {
  48. return {
  49. ...item,
  50. children: filterMenuData(item.children), // eslint-disable-line
  51. };
  52. }
  53. return item;
  54. };
  55. /**
  56. * filter menuData
  57. */
  58. const filterMenuData = menuData => {
  59. if (!menuData) {
  60. return [];
  61. }
  62. return menuData
  63. .filter(item => item.name && !item.hideInMenu)
  64. .map(item => check(item.authority, getSubMenu(item)))
  65. .filter(item => item);
  66. };
  67. /**
  68. * 获取面包屑映射
  69. * @param {Object} menuData 菜单配置
  70. */
  71. const getBreadcrumbNameMap = menuData => {
  72. const routerMap = {};
  73. const flattenMenuData = data => {
  74. data.forEach(menuItem => {
  75. if (menuItem.children) {
  76. flattenMenuData(menuItem.children);
  77. }
  78. // Reduce memory usage
  79. routerMap[menuItem.path] = menuItem;
  80. });
  81. };
  82. flattenMenuData(menuData);
  83. return routerMap;
  84. };
  85. const memoizeOneGetBreadcrumbNameMap = memoizeOne(getBreadcrumbNameMap, isEqual);
  86. export default {
  87. namespace: 'menu',
  88. state: {
  89. menuData: [],
  90. routerData: [],
  91. breadcrumbNameMap: {},
  92. },
  93. effects: {
  94. *getMenuData({ payload }, { put }) {
  95. const { routes, authority } = payload;
  96. const originalMenuData = memoizeOneFormatter(routes, authority);
  97. const menuData = filterMenuData(originalMenuData);
  98. const breadcrumbNameMap = memoizeOneGetBreadcrumbNameMap(originalMenuData);
  99. yield put({
  100. type: 'save',
  101. payload: { menuData, breadcrumbNameMap, routerData: routes },
  102. });
  103. },
  104. },
  105. reducers: {
  106. save(state, action) {
  107. return {
  108. ...state,
  109. ...action.payload,
  110. };
  111. },
  112. },
  113. };