Sword/src/models/menu.js

338 lines
7.9 KiB
JavaScript

import memoizeOne from 'memoize-one';
import isEqual from 'lodash/isEqual';
import { message } from 'antd';
import router from 'umi/router';
import { formatMessage } from 'umi/locale';
import Authorized from '../utils/Authorized';
import { menu } from '../defaultSettings';
import {
dynamicRoutes,
dynamicButtons,
list,
parentList,
submit,
detail,
remove,
tree,
dataScopeList,
} from '../services/menu';
import { dict } from '../services/dict';
import { getRoutes, setRoutes, getButtons, setButtons } from '../utils/authority';
import { MENU_NAMESPACE } from '../actions/menu';
import { formatRoutes, formatButtons } from '../utils/utils';
const { check } = Authorized;
// Conversion router to menu.
function formatter(data, parentAuthority, parentName) {
return data
.map(item => {
if (!item.name || !item.path) {
return null;
}
let locale = 'menu';
if (parentName) {
locale = `${parentName}.${item.name}`;
} else {
locale = `menu.${item.name}`;
}
// if enableMenuLocale use item.name,
// close menu international
const name = menu.disableLocal
? item.name
: formatMessage({ id: locale, defaultMessage: item.name });
const result = {
...item,
name,
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)
.map(item => check(item.authority, getSubMenu(item)))
.filter(item => item);
};
/**
* 获取面包屑映射
* @param {Object} menuData 菜单配置
*/
const getBreadcrumbNameMap = menuData => {
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);
export default {
namespace: MENU_NAMESPACE,
state: {
menuData: [],
breadcrumbNameMap: {},
data: {
list: [],
pagination: false,
},
init: {
tree: [],
},
dict: {
dataScopeType: [],
},
detail: {},
drawer: {
visible: false,
menuId: '',
menuName: '',
dataScope: {
list: [],
pagination: false,
},
},
},
effects: {
*fetchMenuData({ payload }, { call, put }) {
const { authority } = payload;
// 设置菜单数据
let routes = getRoutes();
if (routes.length === 0) {
const response = yield call(dynamicRoutes);
routes = formatRoutes(response.data);
setRoutes(routes);
}
// 设置按钮数据
let buttons = getButtons();
if (buttons.length === 0) {
const response = yield call(dynamicButtons);
buttons = formatButtons(response.data);
setButtons(buttons);
}
const menuData = filterMenuData(memoizeOneFormatter(routes, authority));
const breadcrumbNameMap = memoizeOneGetBreadcrumbNameMap(menuData);
yield put({
type: 'save',
payload: { menuData, breadcrumbNameMap },
});
},
*fetchList({ payload }, { call, put }) {
const response = yield call(list, payload);
if (response.success) {
yield put({
type: 'saveList',
payload: {
list: response.data,
pagination: false,
},
});
}
},
*fetchParentList({ payload }, { call, put }) {
const response = yield call(parentList, payload);
if (response.success) {
yield put({
type: 'saveList',
payload: {
list: response.data,
pagination: false,
},
});
}
},
*fetchInit({ payload }, { call, put }) {
const response = yield call(tree, payload);
if (response.success) {
yield put({
type: 'saveInit',
payload: {
tree: response.data,
},
});
}
},
*fetchDetail({ payload }, { call, put }) {
const response = yield call(detail, payload);
if (response.success) {
yield put({
type: 'saveDetail',
payload: {
detail: response.data,
},
});
}
},
*clearDetail({ payload }, { put }) {
yield put({
type: 'removeDetail',
payload: { payload },
});
},
*selectIcon({ payload }, { put }) {
yield put({
type: 'saveIcon',
payload: {
detail: payload,
},
});
},
*showDrawer({ payload }, { put }) {
yield put({
type: 'saveDrawer',
payload,
});
},
*loadDataScopeDrawer({ payload }, { call, put }) {
const response = yield call(dataScopeList, payload);
if (response.success) {
yield put({
type: 'saveLoadDataScopeDrawer',
payload: {
dataScope: {
list: response.data.records,
pagination: {
total: response.data.total,
current: response.data.current,
pageSize: response.data.size,
},
},
},
});
}
},
*loadDataScopeDict({ payload }, { call, put }) {
const response = yield call(dict, payload);
if (response.success) {
yield put({
type: 'saveDataScopeDict',
payload: {
dataScopeType: response.data,
},
});
}
},
*submit({ payload }, { call }) {
const response = yield call(submit, payload);
if (response.success) {
message.success('提交成功');
router.push('/system/menu');
}
},
*remove({ payload }, { call }) {
const {
data: { keys },
success,
} = payload;
const response = yield call(remove, { ids: keys });
if (response.success) {
success();
}
},
},
reducers: {
save(state, action) {
return {
...state,
...action.payload,
};
},
saveList(state, action) {
return {
...state,
data: action.payload,
};
},
saveInit(state, action) {
return {
...state,
init: action.payload,
};
},
saveDetail(state, action) {
return {
...state,
detail: action.payload.detail,
};
},
saveIcon(state, action) {
const newState = state;
newState.detail.source = action.payload.detail.source;
return {
...newState,
};
},
saveDrawer(state, action) {
return {
...state,
drawer: action.payload,
};
},
saveLoadDataScopeDrawer(state, action) {
const newState = state;
newState.drawer.dataScope = action.payload.dataScope;
return {
...newState,
};
},
saveDataScopeDict(state, action) {
const newState = state;
newState.dict.dataScopeType = action.payload.dataScopeType;
return {
...newState,
};
},
removeDetail(state) {
return {
...state,
detail: {},
};
},
},
};