diff --git a/src/components/Layout/Bread.js b/src/components/Layout/Bread.js index 75e74f2..21aa00f 100644 --- a/src/components/Layout/Bread.js +++ b/src/components/Layout/Bread.js @@ -25,7 +25,11 @@ const Bread = ({ menu }) => { } if (!current) { - pathArray.push(menu[0]) + pathArray.push(menu[0] || { + id: 1, + icon: 'laptop', + name: 'Dashboard', + }) pathArray.push({ id: 404, name: 'Not Found', diff --git a/src/components/Layout/Menu.js b/src/components/Layout/Menu.js index 7ad8fe7..a6889e7 100644 --- a/src/components/Layout/Menu.js +++ b/src/components/Layout/Menu.js @@ -7,7 +7,7 @@ import pathToRegexp from 'path-to-regexp' const Menus = ({ siderFold, darkTheme, location, handleClickNavMenu, navOpenKeys, changeOpenKeys, menu }) => { // 生成树状 - const menuTree = arrayToTree(menu.filter(_ => _.mpid !== -1), 'id', 'mpid') + const menuTree = arrayToTree(menu.filter(_ => _.mpid !== '-1'), 'id', 'mpid') const levelMap = {} // 递归生成菜单 @@ -22,7 +22,7 @@ const Menus = ({ siderFold, darkTheme, location, handleClickNavMenu, navOpenKeys key={item.id} title={ {item.icon && } - {(!siderFoldN || menuTree.indexOf(item) < 0) && item.name} + {(!siderFoldN || !menuTree.includes(item)) && item.name} } > {getMenus(item.children, siderFoldN)} @@ -33,7 +33,7 @@ const Menus = ({ siderFold, darkTheme, location, handleClickNavMenu, navOpenKeys {item.icon && } - {(!siderFoldN || menuTree.indexOf(item) < 0) && item.name} + {(!siderFoldN || !menuTree.includes(item)) && item.name} ) @@ -60,8 +60,8 @@ const Menus = ({ siderFold, darkTheme, location, handleClickNavMenu, navOpenKeys } const onOpenChange = (openKeys) => { - const latestOpenKey = openKeys.find(key => !(navOpenKeys.indexOf(key) > -1)) - const latestCloseKey = navOpenKeys.find(key => !(openKeys.indexOf(key) > -1)) + const latestOpenKey = openKeys.find(key => !navOpenKeys.includes(key)) + const latestCloseKey = navOpenKeys.find(key => !openKeys.includes(key)) let nextOpenKeys = [] if (latestOpenKey) { nextOpenKeys = getAncestorKeys(latestOpenKey).concat(latestOpenKey) diff --git a/src/mock/menu.js b/src/mock/menu.js new file mode 100644 index 0000000..c839d84 --- /dev/null +++ b/src/mock/menu.js @@ -0,0 +1,164 @@ +const { config, posts } = require('./common') + +const { apiPrefix } = config +let database = [ + { + id: '1', + icon: 'laptop', + name: 'Dashboard', + router: '/dashboard', + }, + { + id: '2', + bpid: '1', + name: 'Users', + icon: 'user', + router: '/user', + }, + { + id: '7', + bpid: '1', + name: 'Posts', + icon: 'shopping-cart', + router: '/post', + }, + { + id: '21', + mpid: '-1', + bpid: '2', + name: 'User Detail', + router: '/user/:id', + }, + { + id: '3', + bpid: '1', + name: 'Request', + icon: 'api', + router: '/request', + }, + { + id: '4', + bpid: '1', + name: 'UI Element', + icon: 'camera-o', + }, + { + id: '41', + bpid: '4', + mpid: '4', + name: 'IconFont', + icon: 'heart-o', + router: '/UIElement/iconfont', + }, + { + id: '42', + bpid: '4', + mpid: '4', + name: 'DataTable', + icon: 'database', + router: '/UIElement/dataTable', + }, + { + id: '43', + bpid: '4', + mpid: '4', + name: 'DropOption', + icon: 'bars', + router: '/UIElement/dropOption', + }, + { + id: '44', + bpid: '4', + mpid: '4', + name: 'Search', + icon: 'search', + router: '/UIElement/search', + }, + { + id: '45', + bpid: '4', + mpid: '4', + name: 'Editor', + icon: 'edit', + router: '/UIElement/editor', + }, + { + id: '46', + bpid: '4', + mpid: '4', + name: 'layer (Function)', + icon: 'credit-card', + router: '/UIElement/layer', + }, + { + id: '5', + bpid: '1', + name: 'Recharts', + icon: 'code-o', + }, + { + id: '51', + bpid: '5', + mpid: '5', + name: 'LineChart', + icon: 'line-chart', + router: '/chart/lineChart', + }, + { + id: '52', + bpid: '5', + mpid: '5', + name: 'BarChart', + icon: 'bar-chart', + router: '/chart/barChart', + }, + { + id: '53', + bpid: '5', + mpid: '5', + name: 'AreaChart', + icon: 'area-chart', + router: '/chart/areaChart', + }, + { + id: '6', + bpid: '1', + name: 'Test Navigation', + icon: 'setting', + }, + { + id: '61', + bpid: '6', + mpid: '6', + name: 'Test Navigation1', + router: '/navigation/navigation1', + }, + { + id: '62', + bpid: '6', + mpid: '6', + name: 'Test Navigation2', + router: '/navigation/navigation2', + }, + { + id: '621', + bpid: '62', + mpid: '62', + name: 'Test Navigation21', + router: '/navigation/navigation2/navigation1', + }, + { + id: '622', + bpid: '62', + mpid: '62', + name: 'Test Navigation22', + router: '/navigation/navigation2/navigation2', + }, +] + +module.exports = { + + [`GET ${apiPrefix}/menus`] (req, res) { + res.status(200).json(database) + }, +} diff --git a/src/mock/user.js b/src/mock/user.js index 8f31411..21f7d08 100644 --- a/src/mock/user.js +++ b/src/mock/user.js @@ -26,13 +26,15 @@ let usersListData = Mock.mock({ let database = usersListData.data const userPermission = { - DEFAULT: [ - 'dashboard', 'chart', - ], - ADMIN: [ - 'dashboard', 'users', 'UIElement', 'UIElementIconfont', 'chart', - ], - DEVELOPER: ['dashboard', 'users', 'UIElement', 'UIElementIconfont', 'chart'], + DEFAULT: { + visit: ['1', '2', '21', '7', '5', '51', '52', '53'], + }, + ADMIN: { + visit: ['1', '2', '7', '21', '3', '4', '41', '42', '43', '44', '45', '46', '5', '51', '52', '53', '6', '61', '62', '621', '622'], + }, + DEVELOPER: { + visit: ['1', '2', '7', '21', '3', '4', '41', '42', '43', '44', '45', '46', '5', '51', '52', '53', '6', '61', '62', '621', '622'], + }, } const adminUsers = [ diff --git a/src/models/app.js b/src/models/app.js index 3ff0667..453f307 100644 --- a/src/models/app.js +++ b/src/models/app.js @@ -1,4 +1,5 @@ import { query, logout } from '../services/app' +import * as menusService from '../services/menus' import { routerRedux } from 'dva/router' import { parse } from 'qs' import { config } from 'utils' @@ -8,6 +9,17 @@ export default { namespace: 'app', state: { user: {}, + permissions: { + visit: [], + }, + menu: [ + { + id: 1, + icon: 'laptop', + name: 'Dashboard', + router: '/dashboard', + }, + ], menuPopoverVisible: false, siderFold: localStorage.getItem(`${prefix}siderFold`) === 'true', darkTheme: localStorage.getItem(`${prefix}darkTheme`) === 'true', @@ -33,11 +45,25 @@ export default { *query ({ payload, }, { call, put }) { - const data = yield call(query, parse(payload)) - if (data.success && data.user) { + const { success, user } = yield call(query, payload) + const { list } = yield call(menusService.query) + if (success && user) { + const { permissions } = user yield put({ - type: 'querySuccess', - payload: data.user, + type: 'updateState', + payload: { + user, + permissions, + menu: list.filter(item => { + const cases = [ + permissions.visit.includes(item.id), + item.mpid ? permissions.visit.includes(item.mpid) || item.mpid === '-1' : true, + item.bpid ? permissions.visit.includes(item.bpid) : true, + ] + return cases.every(_ => _) + } + ), + }, }) if (location.pathname === '/login') { yield put(routerRedux.push('/dashboard')) @@ -76,10 +102,10 @@ export default { }, reducers: { - querySuccess (state, { payload: user }) { + updateState (state, { payload }) { return { ...state, - user, + ...payload, } }, diff --git a/src/routes/app.js b/src/routes/app.js index 8acdbea..e3f7e26 100644 --- a/src/routes/app.js +++ b/src/routes/app.js @@ -2,7 +2,7 @@ import React from 'react' import PropTypes from 'prop-types' import { connect } from 'dva' import { Layout } from 'components' -import { classnames, config, menu } from 'utils' +import { classnames, config } from 'utils' import { Helmet } from 'react-helmet' import '../themes/index.less' import './app.less' @@ -13,7 +13,7 @@ const { Header, Bread, Footer, Sider, styles } = Layout let lastHref const App = ({ children, location, dispatch, app, loading }) => { - const { user, siderFold, darkTheme, isNavbar, menuPopoverVisible, navOpenKeys } = app + const { user, siderFold, darkTheme, isNavbar, menuPopoverVisible, navOpenKeys, menu } = app const href = window.location.href if (lastHref !== href) { diff --git a/src/services/menus.js b/src/services/menus.js new file mode 100644 index 0000000..eddd097 --- /dev/null +++ b/src/services/menus.js @@ -0,0 +1,11 @@ +import { request, config } from 'utils' +const { api } = config +const { menus } = api + +export async function query (params) { + return request({ + url: menus, + method: 'get', + data: params, + }) +} diff --git a/src/utils/config.js b/src/utils/config.js index cbf4c9c..9fee97e 100644 --- a/src/utils/config.js +++ b/src/utils/config.js @@ -9,7 +9,7 @@ module.exports = { iconFontCSS: '/iconfont.css', iconFontJS: '/iconfont.js', YQL: ['http://www.zuimeitianqi.com'], - CORS: ['http://localhost:7000'], + CORS: [], openPages: ['/login'], apiPrefix: '/api/v1', api: { @@ -20,6 +20,7 @@ module.exports = { posts: `${APIV1}/posts`, user: `${APIV1}/user/:id`, dashboard: `${APIV1}/dashboard`, + menus: `${APIV1}/menus`, v1test: `${APIV1}/test`, v2test: `${APIV2}/test`, }, diff --git a/src/utils/request.js b/src/utils/request.js index 8a8c853..7ffd2bd 100644 --- a/src/utils/request.js +++ b/src/utils/request.js @@ -89,6 +89,12 @@ export default function request (options) { return fetch(options).then((response) => { const { statusText, status } = response let data = options.fetchType === 'YQL' ? response.data.query.results.json : response.data + if (data instanceof Array) { + data = { + list: data, + } + } + return { success: true, message: statusText,