BasicLayout.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. import React from 'react';
  2. import PropTypes from 'prop-types';
  3. import { Layout, Icon, message } from 'antd';
  4. import DocumentTitle from 'react-document-title';
  5. import { connect } from 'dva';
  6. import { Route, Redirect, Switch } from 'dva/router';
  7. import { ContainerQuery } from 'react-container-query';
  8. import classNames from 'classnames';
  9. import { enquireScreen } from 'enquire-js';
  10. import GlobalHeader from '../components/GlobalHeader';
  11. import GlobalFooter from '../components/GlobalFooter';
  12. import SiderMenu from '../components/SiderMenu';
  13. import NotFound from '../routes/Exception/404';
  14. import { getRoutes } from '../utils/utils';
  15. import Authorized from '../utils/Authorized';
  16. import { getMenuData } from '../common/menu';
  17. import logo from '../assets/logo.svg';
  18. const { Content } = Layout;
  19. const { AuthorizedRoute } = Authorized;
  20. /**
  21. * 根据菜单取得重定向地址.
  22. */
  23. const redirectData = [];
  24. const getRedirect = (item) => {
  25. if (item && item.children) {
  26. if (item.children[0] && item.children[0].path) {
  27. redirectData.push({
  28. from: `/${item.path}`,
  29. to: `/${item.children[0].path}`,
  30. });
  31. item.children.forEach((children) => {
  32. getRedirect(children);
  33. });
  34. }
  35. }
  36. };
  37. getMenuData().forEach(getRedirect);
  38. const query = {
  39. 'screen-xs': {
  40. maxWidth: 575,
  41. },
  42. 'screen-sm': {
  43. minWidth: 576,
  44. maxWidth: 767,
  45. },
  46. 'screen-md': {
  47. minWidth: 768,
  48. maxWidth: 991,
  49. },
  50. 'screen-lg': {
  51. minWidth: 992,
  52. maxWidth: 1199,
  53. },
  54. 'screen-xl': {
  55. minWidth: 1200,
  56. },
  57. };
  58. let isMobile;
  59. enquireScreen((b) => {
  60. isMobile = b;
  61. });
  62. class BasicLayout extends React.PureComponent {
  63. static childContextTypes = {
  64. location: PropTypes.object,
  65. breadcrumbNameMap: PropTypes.object,
  66. }
  67. state = {
  68. isMobile,
  69. };
  70. getChildContext() {
  71. const { location, routerData } = this.props;
  72. return {
  73. location,
  74. breadcrumbNameMap: routerData,
  75. };
  76. }
  77. componentDidMount() {
  78. enquireScreen((mobile) => {
  79. this.setState({
  80. isMobile: mobile,
  81. });
  82. });
  83. this.props.dispatch({
  84. type: 'user/fetchCurrent',
  85. });
  86. }
  87. getPageTitle() {
  88. const { routerData, location } = this.props;
  89. const { pathname } = location;
  90. let title = 'Ant Design Pro';
  91. if (routerData[pathname] && routerData[pathname].name) {
  92. title = `${routerData[pathname].name} - Ant Design Pro`;
  93. }
  94. return title;
  95. }
  96. handleMenuCollapse = (collapsed) => {
  97. this.props.dispatch({
  98. type: 'global/changeLayoutCollapsed',
  99. payload: collapsed,
  100. });
  101. }
  102. handleNoticeClear = (type) => {
  103. message.success(`清空了${type}`);
  104. this.props.dispatch({
  105. type: 'global/clearNotices',
  106. payload: type,
  107. });
  108. }
  109. handleMenuClick = ({ key }) => {
  110. if (key === 'logout') {
  111. this.props.dispatch({
  112. type: 'login/logout',
  113. });
  114. }
  115. }
  116. handleNoticeVisibleChange = (visible) => {
  117. if (visible) {
  118. this.props.dispatch({
  119. type: 'global/fetchNotices',
  120. });
  121. }
  122. }
  123. render() {
  124. const {
  125. currentUser, collapsed, fetchingNotices, notices, routerData, match, location,
  126. } = this.props;
  127. const layout = (
  128. <Layout>
  129. <SiderMenu
  130. logo={logo}
  131. // 不带Authorized参数的情况下如果没有权限,会强制跳到403界面
  132. // If you do not have the Authorized parameter
  133. // you will be forced to jump to the 403 interface without permission
  134. Authorized={Authorized}
  135. menuData={getMenuData()}
  136. collapsed={collapsed}
  137. location={location}
  138. isMobile={this.state.isMobile}
  139. onCollapse={this.handleMenuCollapse}
  140. />
  141. <Layout>
  142. <GlobalHeader
  143. logo={logo}
  144. currentUser={currentUser}
  145. fetchingNotices={fetchingNotices}
  146. notices={notices}
  147. collapsed={collapsed}
  148. isMobile={this.state.isMobile}
  149. onNoticeClear={this.handleNoticeClear}
  150. onCollapse={this.handleMenuCollapse}
  151. onMenuClick={this.handleMenuClick}
  152. onNoticeVisibleChange={this.handleNoticeVisibleChange}
  153. />
  154. <Content style={{ margin: '24px 24px 0', height: '100%' }}>
  155. <div style={{ minHeight: 'calc(100vh - 260px)' }}>
  156. <Switch>
  157. {
  158. getRoutes(match.path, routerData).map(item =>
  159. (
  160. <AuthorizedRoute
  161. key={item.key}
  162. path={item.path}
  163. component={item.component}
  164. exact={item.exact}
  165. authority={item.authority}
  166. redirectPath="/exception/403"
  167. />
  168. )
  169. )
  170. }
  171. {
  172. redirectData.map(item =>
  173. <Redirect key={item.from} exact from={item.from} to={item.to} />
  174. )
  175. }
  176. <Redirect exact from="/" to="/dashboard/analysis" />
  177. <Route render={NotFound} />
  178. </Switch>
  179. </div>
  180. <GlobalFooter
  181. links={[{
  182. title: 'Pro 首页',
  183. href: 'http://pro.ant.design',
  184. blankTarget: true,
  185. }, {
  186. title: 'GitHub',
  187. href: 'https://github.com/ant-design/ant-design-pro',
  188. blankTarget: true,
  189. }, {
  190. title: 'Ant Design',
  191. href: 'http://ant.design',
  192. blankTarget: true,
  193. }]}
  194. copyright={
  195. <div>
  196. Copyright <Icon type="copyright" /> 2017 蚂蚁金服体验技术部出品
  197. </div>
  198. }
  199. />
  200. </Content>
  201. </Layout>
  202. </Layout>
  203. );
  204. return (
  205. <DocumentTitle title={this.getPageTitle()}>
  206. <ContainerQuery query={query}>
  207. {params => <div className={classNames(params)}>{layout}</div>}
  208. </ContainerQuery>
  209. </DocumentTitle>
  210. );
  211. }
  212. }
  213. export default connect(state => ({
  214. currentUser: state.user.currentUser,
  215. collapsed: state.global.collapsed,
  216. fetchingNotices: state.global.fetchingNotices,
  217. notices: state.global.notices,
  218. }))(BasicLayout);