menu.js 3.06 KB
Newer Older
陈小聪's avatar
陈小聪 committed
1 2 3 4
import memoizeOne from 'memoize-one';
import isEqual from 'lodash/isEqual';
import { formatMessage } from 'umi/locale';
import Authorized from '@/utils/Authorized';
5
import { menu } from '../defaultSettings';
陈小聪's avatar
陈小聪 committed
6 7 8 9 10

const { check } = Authorized;

// Conversion router to menu.
function formatter(data, parentAuthority, parentName) {
11 12 13
  if (!data) {
    return undefined;
  }
陈小聪's avatar
陈小聪 committed
14 15 16 17 18 19 20
  return data
    .map(item => {
      if (!item.name || !item.path) {
        return null;
      }

      let locale = 'menu';
chen shuai's avatar
chen shuai committed
21
      if (parentName && parentName !== '/') {
陈小聪's avatar
陈小聪 committed
22 23 24 25
        locale = `${parentName}.${item.name}`;
      } else {
        locale = `menu.${item.name}`;
      }
26 27 28 29 30
      // if enableMenuLocale use item.name,
      // close menu international
      const name = menu.disableLocal
        ? item.name
        : formatMessage({ id: locale, defaultMessage: item.name });
陈小聪's avatar
陈小聪 committed
31 32
      const result = {
        ...item,
33
        name,
陈小聪's avatar
陈小聪 committed
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
        locale,
        authority: item.authority || parentAuthority,
      };
      if (item.routes) {
        const children = formatter(item.routes, item.authority, locale);
        // Reduce memory usage
        result.children = children;
      }
      delete result.routes;
      return result;
    })
    .filter(item => item);
}

const memoizeOneFormatter = memoizeOne(formatter, isEqual);

/**
 * get SubMenu or Item
 */
const getSubMenu = item => {
  // doc: add hideChildrenInMenu
  if (item.children && !item.hideChildrenInMenu && item.children.some(child => child.name)) {
    return {
      ...item,
      children: filterMenuData(item.children), // eslint-disable-line
    };
  }
  return item;
};

/**
 * filter menuData
 */
const filterMenuData = menuData => {
  if (!menuData) {
    return [];
  }
  return menuData
    .filter(item => item.name && !item.hideInMenu)
73
    .map(item => check(item.authority, getSubMenu(item)))
陈小聪's avatar
陈小聪 committed
74 75
    .filter(item => item);
};
76 77 78 79 80
/**
 * 获取面包屑映射
 * @param {Object} menuData 菜单配置
 */
const getBreadcrumbNameMap = menuData => {
81 82 83
  if (!menuData) {
    return {};
  }
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
  const routerMap = {};

  const flattenMenuData = data => {
    data.forEach(menuItem => {
      if (menuItem.children) {
        flattenMenuData(menuItem.children);
      }
      // Reduce memory usage
      routerMap[menuItem.path] = menuItem;
    });
  };
  flattenMenuData(menuData);
  return routerMap;
};

const memoizeOneGetBreadcrumbNameMap = memoizeOne(getBreadcrumbNameMap, isEqual);
陈小聪's avatar
陈小聪 committed
100 101 102 103 104 105

export default {
  namespace: 'menu',

  state: {
    menuData: [],
陈小聪's avatar
陈小聪 committed
106
    routerData: [],
107
    breadcrumbNameMap: {},
陈小聪's avatar
陈小聪 committed
108 109 110 111
  },

  effects: {
    *getMenuData({ payload }, { put }) {
陈小聪's avatar
陈小聪 committed
112 113
      const { routes, authority, path } = payload;
      const originalMenuData = memoizeOneFormatter(routes, authority, path);
114 115
      const menuData = filterMenuData(originalMenuData);
      const breadcrumbNameMap = memoizeOneGetBreadcrumbNameMap(originalMenuData);
陈小聪's avatar
陈小聪 committed
116 117
      yield put({
        type: 'save',
陈小聪's avatar
陈小聪 committed
118
        payload: { menuData, breadcrumbNameMap, routerData: routes },
陈小聪's avatar
陈小聪 committed
119 120 121 122 123 124 125 126
      });
    },
  },

  reducers: {
    save(state, action) {
      return {
        ...state,
127
        ...action.payload,
陈小聪's avatar
陈小聪 committed
128 129 130 131
      };
    },
  },
};