Auth.js
import {session, stoage} from './util'
const NotLoginAuth = [
'/login',
'/register',
'/register/complete',
'/register/fail',
'/forgetpassword'
]
/**
* 分角色控制权限和菜单
*/
const RoleAssentPath = {
GUEST : [
...NotLoginAuth,
],
USER : [
...NotLoginAuth,
'/',
'/user',
],
COMPANY : [
...NotLoginAuth,
'/',
'/company',
'/user',
'/user/list',
'/user/add',
'/user/edit',
],
ADMIN : [
...NotLoginAuth,
'/',
'/channel',
'/channel/add',
'/channel/list',
'/company',
'/company/add',
'/company/list',
'/company/edit',
],
}
export const getRoute = () => { return RoleAssentPath[LoginInfo.role] }
let LoginInfo = {
logined : false,
username : null,
role : 'GUEST', // ADMIN | COMPANY | USER | GUEST
}
export const Login = (userInfo, remember) =>{
LoginInfo = {
...userInfo,
logined : true,
lastime : new Date().getTime(),
}
if(remember){
stoage.setStore('UserInfo', LoginInfo)
}
session.setStore('UserInfo', LoginInfo)
}
export const LoginOut = () =>{
LoginInfo = {
logined : false,
role : 'GUEST',
}
session.removeStore('UserInfo')
stoage.removeStore('UserInfo')
}
export const getUser = () =>{
if(LoginInfo.logined === false){
let storeUser = stoage.getStore('UserInfo')
if(storeUser && storeUser.logined){ Login(storeUser) }
}
return LoginInfo
}
export default (nextState, replace) => {
let path = nextState.location.pathname.toLocaleLowerCase()
if(path == '/loginout'){
LoginOut()
replace('/login')
}else if(NotLoginAuth.indexOf(path) == -1 && getUser().logined == false){
replace('/login')
}else if(getRoute().indexOf(path)==-1){
console.log('没有权限')
replace('/error/401')
}
}
route.js
/**
* 定义应用路由
*/
import React from 'react';
import { Router, hashHistory, } from 'react-router';
import auth from './auth';
// 路由配置规则参考: https://github.com/ReactTraining/react-router/blob/v3/docs/guides/RouteConfiguration.md#configuration-with-plain-routes
// 一下部分是由 ICE 相关工具自动生成的路由,请勿随意改变,否则可能会出现一些异常情况
// <!-- auto generated routes start -->
import ForgetPassword from "./pages/ForgetPassword";
import Login from "./pages/Login";
import HeaderAsideFooterResponsiveLayout from './layouts/HeaderAsideFooterResponsiveLayout';
import BlankLayout from './layouts/BlankLayout';
import Home from './pages/Home';
import HeaderFooterLayout from './layouts/HeaderFooterLayout';
import { NotFound, BasicException, NotPermission, EmptyContent } from './pages/ErrorPage';
import { Register, RegisterComplete, RegisterFail } from "./pages/Register";
import { Channel, AddChannel, EditChannel } from "./pages/Channel";
import { Company, AddCompany, EditCompany } from "./pages/Company";
import { User, AddUser } from "./pages/User";
const autoGeneratedRoutes = [{
path: "/company",
childRoutes: [{
path: "list",
component: Company,
onEnter: auth
}, {
path: "add",
component: AddCompany,
onEnter: auth
}, {
path: "edit/:id",
component: EditCompany,
onEnter: auth
}],
component: HeaderAsideFooterResponsiveLayout,
onEnter: auth
}, {
path: "/channel",
childRoutes: [{
path: "list",
component: Channel,
onEnter: auth
}, {
path: "add",
component: AddChannel,
onEnter: auth
}, {
path: "edit/:id",
component: EditChannel,
onEnter: auth
}],
component: HeaderAsideFooterResponsiveLayout,
onEnter: auth
}, {
path: "/user",
childRoutes: [{
path: "list",
component: User,
onEnter: auth
}, {
path: "add",
component: AddUser,
onEnter: auth
}],
component: HeaderAsideFooterResponsiveLayout,
onEnter: auth
}, {
path: "/error",
childRoutes: [{
path: "401",
component: NotPermission
}, {
path: "404",
component: NotFound
}, {
path: "500",
component: BasicException
}, {
path: "empty",
component: EmptyContent
}],
component: BlankLayout,
indexRoute: {
component: NotFound
}
}, {
path: "/forgetPassword",
childRoutes: [],
component: BlankLayout,
indexRoute: {
component: ForgetPassword
},
onEnter: auth
}, {
path: "/register",
childRoutes: [
{
path: "complete",
component: RegisterComplete
}, {
path: "fail",
component: RegisterFail
}
],
component: BlankLayout,
indexRoute: {
component: Register
},
onEnter: auth
}, {
path: "/login",
childRoutes: [],
component: BlankLayout,
indexRoute: {
component: Login
},
onEnter: auth
}, {
path: "/loginout",
childRoutes: [],
component: BlankLayout,
indexRoute: {
component: Login
},
onEnter: auth
}, {
path: '/',
childRoutes: [{
path: '*',
childRoutes: [],
component: NotFound
}],
component: HeaderAsideFooterResponsiveLayout,
indexRoute: {
component: Home
},
onEnter: auth
}];
// <!-- auto generated routes end -->
// 自定义路由,如果 path 相同则会覆盖自动生成部分的路由配置
const customRoutes = [];
export default (
<Router history={hashHistory} routes={[...autoGeneratedRoutes, ...customRoutes]} />
);
HeaderAsideFooterResponsiveLayout/Layout.js
/* eslint no-undef:0, no-unused-expressions:0, array-callback-return:0 */
import React, { Component } from 'react';
import cx from 'classnames';
import Layout from '@icedesign/layout';
import { Icon } from '@icedesign/base';
import Menu, { SubMenu, Item as MenuItem } from '@icedesign/menu';
import { Link } from 'react-router';
import FoundationSymbol from 'foundation-symbol';
import { enquire } from 'enquire-js';
import Header from './../../components/Header';
import Footer from './../../components/Footer';
import Logo from './../../components/Logo';
import { asideNavs } from './../../navs';
import './scss/light.scss';
import './scss/dark.scss';
import { getRoute } from '../../auth'
// 设置默认的皮肤配置,支持 dark 和 light 两套皮肤配置
const theme = typeof THEME === 'undefined' ? 'light' : THEME;
export default class HeaderAsideFooterResponsiveLayout extends Component {
static propTypes = {};
static defaultProps = {};
constructor(props) {
super(props);
const openKeys = this.getOpenKeys();
this.state = {
collapse: false,
openDrawer: false,
isScreen: undefined,
openKeys,
};
this.openKeysCache = openKeys;
}
getAsideNavs = () =>{
if(this.asideNavs == null){
let routes = getRoute()
let allMenu = asideNavs.filter(m=> routes.indexOf(m.to) != -1 )
allMenu.forEach(m=>{
if(m.children){
m.children = m.children.filter(m=> routes.indexOf(m.to) != -1)
}
})
this.asideNavs = allMenu
}
return this.asideNavs
}
componentDidMount() {
this.enquireScreenRegister();
}
/**
* 注册监听屏幕的变化,可根据不同分辨率做对应的处理
*/
enquireScreenRegister = () => {
const isMobile = 'screen and (max-width: 720px)';
const isTablet = 'screen and (min-width: 721px) and (max-width: 1199px)';
const isDesktop = 'screen and (min-width: 1200px)';
enquire.register(isMobile, this.enquireScreenHandle('isMobile'));
enquire.register(isTablet, this.enquireScreenHandle('isTablet'));
enquire.register(isDesktop, this.enquireScreenHandle('isDesktop'));
};
enquireScreenHandle = (type) => {
let collapse;
if (type === 'isMobile') {
collapse = false;
} else if (type === 'isTablet') {
collapse = true;
} else {
collapse = this.state.collapse;
}
const handler = {
match: () => {
this.setState({
isScreen: type,
collapse,
});
},
unmatch: () => {
// handler unmatched
},
};
return handler;
};
/**
* 左侧菜单收缩切换
*/
toggleCollapse = () => {
const { collapse } = this.state;
const openKeys = !collapse ? [] : this.openKeysCache;
this.setState({
collapse: !collapse,
openKeys,
});
};
/**
* 响应式通过抽屉形式切换菜单
*/
toggleMenu = () => {
const { openDrawer } = this.state;
this.setState({
openDrawer: !openDrawer,
});
};
/**
* 当前展开的菜单项
*/
onOpenChange = (openKeys) => {
this.setState({
openKeys,
});
this.openKeysCache = openKeys;
};
/**
* 响应式时点击菜单进行切换
*/
onMenuClick = () => {
this.toggleMenu();
};
/**
* 获取当前展开的菜单项
*/
getOpenKeys = () => {
const { routes } = this.props;
const matched = routes[0].path;
const asideNavs = this.getAsideNavs()
let openKeys = [];
asideNavs &&
asideNavs.length > 0 &&
asideNavs.map((item, index) => {
if (item.to === matched) {
openKeys = [`${index}`];
}
});
return openKeys;
};
render() {
const { location = {} } = this.props;
const { pathname } = location;
const asideNavs = this.getAsideNavs()
return (
<Layout
style={{ minHeight: '100vh' }}
className={cx(
`ice-design-header-aside-footer-responsive-layout-${theme}`,
{
'ice-design-layout': true,
}
)}
>
<Header
theme={theme}
isMobile={this.state.isScreen !== 'isDesktop' ? true : undefined}
/>
<Layout.Section>
{this.state.isScreen === 'isMobile' && (
<a className="menu-btn" onClick={this.toggleMenu}>
<Icon type="category" size="small" />
</a>
)}
{this.state.openDrawer && (
<div className="open-drawer-bg" onClick={this.toggleMenu} />
)}
<Layout.Aside
width="auto"
theme={theme}
className={cx('ice-design-layout-aside', {
'open-drawer': this.state.openDrawer,
})}
>
{/* 侧边菜单项 begin */}
{this.state.isScreen !== 'isMobile' && (
<a className="collapse-btn" onClick={this.toggleCollapse}>
<Icon
type={this.state.collapse ? 'arrow-right' : 'arrow-left'}
size="small"
/>
</a>
)}
{this.state.isScreen === 'isMobile' && <Logo />}
<Menu
style={{ width: this.state.collapse ? 60 : 200 }}
inlineCollapsed={this.state.collapse}
mode="inline"
selectedKeys={[pathname]}
openKeys={this.state.openKeys}
defaultSelectedKeys={[pathname]}
onOpenChange={this.onOpenChange}
onClick={this.onMenuClick}
>
{asideNavs &&
asideNavs.length > 0 &&
asideNavs.map((nav, index) => {
if (nav.children && nav.children.length > 0) {
return (
<SubMenu
key={index}
title={
<span>
{nav.icon ? (
<FoundationSymbol size="small" type={nav.icon} />
) : null}
<span className="ice-menu-collapse-hide">
{nav.text}
</span>
</span>
}
>
{nav.children.map((item) => {
const linkProps = {};
if (item.newWindow) {
linkProps.href = item.to;
linkProps.target = '_blank';
} else if (item.external) {
linkProps.href = item.to;
} else {
linkProps.to = item.to;
}
return (
<MenuItem key={item.to}>
<Link {...linkProps}>{item.text}</Link>
</MenuItem>
);
})}
</SubMenu>
);
}
const linkProps = {};
if (nav.newWindow) {
linkProps.href = nav.to;
linkProps.target = '_blank';
} else if (nav.external) {
linkProps.href = nav.to;
} else {
linkProps.to = nav.to;
}
return (
<MenuItem key={nav.to}>
<Link {...linkProps}>
<span>
{nav.icon ? (
<FoundationSymbol size="small" type={nav.icon} />
) : null}
<span className="ice-menu-collapse-hide">
{nav.text}
</span>
</span>
</Link>
</MenuItem>
);
})}
</Menu>
{/* 侧边菜单项 end */}
</Layout.Aside>
{/* 主体内容 */}
<Layout.Main>{this.props.children}</Layout.Main>
</Layout.Section>
<Footer />
</Layout>
);
}
}