menu.js 3.0 KB

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