diff --git a/admin-web/mock/admin.js b/admin-web/mock/admin.js new file mode 100644 index 000000000..1a201cff3 --- /dev/null +++ b/admin-web/mock/admin.js @@ -0,0 +1,21 @@ +import adminMenu from './geographic/admin-menu.json'; +import adminMenuAll from './geographic/admin-menu-all.json'; +import adminUrls from './geographic/admin-urls'; + +/* eslint-disable */ +function getAdminMenu(req, res) { + return res.json(adminMenu); +} + +function getAdminMenuAll(req, res) { + return res.json(adminMenuAll); +} + +function getAdminUrls(req, res) { + return res.json(adminUrls); +} + +export default { + 'GET /admin-api/admin/resource/admin_menu_tree': getAdminMenuAll, + 'GET /admin-api/admin/resource/admin_url_list': getAdminUrls, +}; diff --git a/admin-web/mock/geographic/admin-menu-all.json b/admin-web/mock/geographic/admin-menu-all.json new file mode 100644 index 000000000..e3329c0af --- /dev/null +++ b/admin-web/mock/geographic/admin-menu-all.json @@ -0,0 +1,5 @@ +{ + "code": 0, + "message": "", + "data": "all" +} diff --git a/admin-web/mock/geographic/admin-menu.json b/admin-web/mock/geographic/admin-menu.json new file mode 100644 index 000000000..ac5db246e --- /dev/null +++ b/admin-web/mock/geographic/admin-menu.json @@ -0,0 +1,26 @@ +{ + "code": 0, + "message": "", + "data": [ + { + "children": [ + { + "handler": "/order/list1", + "id": 1, + "name": "商品管理1", + "pid": 1 + }, + { + "handler": "/order/list2", + "id": 1, + "name": "商品管理2", + "pid": 1 + } + ], + "handler": "/home", + "id": 1, + "name": "商品管理", + "pid": 1 + } + ] +} diff --git a/admin-web/mock/geographic/admin-urls.json b/admin-web/mock/geographic/admin-urls.json new file mode 100644 index 000000000..7b89eeb09 --- /dev/null +++ b/admin-web/mock/geographic/admin-urls.json @@ -0,0 +1,5 @@ +{ + "code": 0, + "data": ["/admin/source/add", "/admin/source/delete"], + "message": "string" +} diff --git a/admin-web/src/components/AuthorityControl/index.js b/admin-web/src/components/AuthorityControl/index.js index 0fa6eec89..107aad504 100644 --- a/admin-web/src/components/AuthorityControl/index.js +++ b/admin-web/src/components/AuthorityControl/index.js @@ -1,17 +1,17 @@ import React, { PureComponent } from 'react'; -import GlobalAuthority from '../../layouts/GlobalAuthorityContext'; +import UrlsContext from '../../layouts/UrlsContext'; // 用于控制权限 class AuthorityControl extends PureComponent { render() { const { authKey, children } = this.props; return ( - + {context => { const { authList } = context; return {authList[authKey] ? children : '无权限'}; }} - + ); } } diff --git a/admin-web/src/components/SiderMenu/index.js b/admin-web/src/components/SiderMenu/index.js index 0be273314..58ce4b457 100644 --- a/admin-web/src/components/SiderMenu/index.js +++ b/admin-web/src/components/SiderMenu/index.js @@ -6,6 +6,7 @@ import { getFlatMenuKeys } from './SiderMenuUtils'; const SiderMenuWrapper = React.memo(props => { const { isMobile, menuData, collapsed, onCollapse } = props; const flatMenuKeys = getFlatMenuKeys(menuData); + return isMobile ? ( { const routes = routeData.slice(); // clone @@ -166,7 +178,7 @@ class BasicLayout extends React.Component { /> }> - {children} + {children} @@ -194,6 +206,7 @@ export default connect(({ global, setting, menu: menuModel }) => ({ collapsed: global.collapsed, layout: setting.layout, menuData: menuModel.menuData, + urlsData: menuModel.urlsData, breadcrumbNameMap: menuModel.breadcrumbNameMap, ...setting, }))(props => ( diff --git a/admin-web/src/layouts/GlobalAuthorityContext.js b/admin-web/src/layouts/GlobalAuthorityContext.js deleted file mode 100644 index e0ee5ec51..000000000 --- a/admin-web/src/layouts/GlobalAuthorityContext.js +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; - -// 创建全局的权限控制 context,方便在所有页面使用 -const GlobalAuthorityContext = React.createContext({ - theme: 'dark', - toggle: () => {}, -}); - -export default GlobalAuthorityContext; diff --git a/admin-web/src/layouts/UrlsContext.js b/admin-web/src/layouts/UrlsContext.js new file mode 100644 index 000000000..3f597d4de --- /dev/null +++ b/admin-web/src/layouts/UrlsContext.js @@ -0,0 +1,6 @@ +import React from 'react'; + +// 创建全局的权限控制 context,方便在所有页面使用 +const UrlsContext = React.createContext({}); + +export default UrlsContext; diff --git a/admin-web/src/models/menu.js b/admin-web/src/models/menu.jsx similarity index 62% rename from admin-web/src/models/menu.js rename to admin-web/src/models/menu.jsx index 218c70651..becae1d44 100644 --- a/admin-web/src/models/menu.js +++ b/admin-web/src/models/menu.jsx @@ -3,6 +3,7 @@ import isEqual from 'lodash/isEqual'; import { formatMessage } from 'umi/locale'; import Authorized from '@/utils/Authorized'; import { menu } from '../defaultSettings'; +import { getAdminMenus, getAdminUrls } from '../services/admin'; const { check } = Authorized; @@ -70,6 +71,26 @@ const filterMenuData = menuData => { .map(item => check(item.authority, getSubMenu(item))) .filter(item => item); }; + +/** + * 递归构建服务端,配置的菜单 + * @param resultMenuData + */ +const recursionBuildResultMenu = resultMenuData => { + const res = {}; + for (let i = 0; i < resultMenuData.length; i += 1) { + const menuItem = resultMenuData[i]; + // 存在子节点 + res[menuItem.handler] = { + ...menuItem, + }; + if (menuItem.children) { + res[menuItem.handler].children = recursionBuildResultMenu(menuItem.children); + } + } + return res; +}; + /** * 获取面包屑映射 * @param {Object} menuData 菜单配置 @@ -97,26 +118,59 @@ export default { state: { menuData: [], + urlsData: {}, breadcrumbNameMap: {}, }, effects: { - *getMenuData({ payload }, { put }) { + *getMenuData({ payload }, { put, call }) { + const { data } = yield call(getAdminMenus); const { routes, authority } = payload; - const menuData = filterMenuData(memoizeOneFormatter(routes, authority)); + // authority 已经不适用 + const antMenuData = filterMenuData(memoizeOneFormatter(routes, authority)); + + let menuData = antMenuData; + const resultMenuData = data; + if (data !== 'all') { + // 处理后台数据结构 + const buildResultMenu = recursionBuildResultMenu(resultMenuData); + // 过滤没有权限的菜单 + menuData = antMenuData.filter(item => { + if (buildResultMenu[item.path]) { + return item; + } + return false; + }); + } + + // 生成 menu 和 router mapping const breadcrumbNameMap = memoizeOneGetBreadcrumbNameMap(menuData); yield put({ type: 'save', payload: { menuData, breadcrumbNameMap }, }); }, + *getUrlsData(state, { put, call }) { + const { data } = yield call(getAdminUrls); + + // 构建 {'/user': true} 这种 map 结构方便取数据、 + const urlsData = {}; + data.forEach(item => { + urlsData[item] = true; + }); + + yield put({ + type: 'save', + payload: { urlsData }, + }); + }, }, reducers: { - save(state, action) { + save(state, { payload }) { return { ...state, - ...action.payload, + ...payload, }; }, }, diff --git a/admin-web/src/pages/Home/Home.js b/admin-web/src/pages/Home/Home.js index f334d7ebb..7e1096aa2 100644 --- a/admin-web/src/pages/Home/Home.js +++ b/admin-web/src/pages/Home/Home.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import { Button } from 'antd'; import AuthorityControl from '../../components/AuthorityControl'; -import GlobalAuthority from '../../layouts/GlobalAuthorityContext'; +import UrlsContext from '../../layouts/UrlsContext'; export default class Home extends Component { state = {}; @@ -17,12 +17,12 @@ export default class Home extends Component { }; return ( - + 按钮 控制 home... - + ); } } diff --git a/admin-web/src/services/admin.js b/admin-web/src/services/admin.js new file mode 100644 index 000000000..c4a28d167 --- /dev/null +++ b/admin-web/src/services/admin.js @@ -0,0 +1,10 @@ +import { stringify } from 'qs'; +import request from '@/utils/request'; + +export async function getAdminMenus() { + return request('/admin-api/admin/resource/admin_menu_tree'); +} + +export async function getAdminUrls(params) { + return request(`/admin-api/admin/resource/admin_url_list?${stringify(params)}`); +} diff --git a/admin-web/src/utils/request.js b/admin-web/src/utils/request.js index 398b787f1..78aa4635c 100644 --- a/admin-web/src/utils/request.js +++ b/admin-web/src/utils/request.js @@ -22,20 +22,21 @@ const codeMessage = { 504: '网关超时。', }; -const checkStatus = response => { +function checkStatus(response) { if (response.status >= 200 && response.status < 300) { return response; } const errortext = codeMessage[response.status] || response.statusText; - notification.error({ + notification.warning({ message: `请求错误 ${response.status}: ${response.url}`, description: errortext, }); + const error = new Error(errortext); error.name = response.status; error.response = response; throw error; -}; +} const cachedSave = (response, hashcode) => { /** diff --git a/admin-web/笔记 b/admin-web/笔记 new file mode 100644 index 000000000..23b4ec1a7 --- /dev/null +++ b/admin-web/笔记 @@ -0,0 +1,4 @@ + +登陆账号 +admin +nicai