Header.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. import React, { PureComponent } from 'react';
  2. import { formatMessage } from 'umi/locale';
  3. import { Layout, message } from 'antd';
  4. import Animate from 'rc-animate';
  5. import { connect } from 'dva';
  6. import router from 'umi/router';
  7. import GlobalHeader from '@/components/GlobalHeader';
  8. import TopNavHeader from '@/components/TopNavHeader';
  9. import styles from './Header.less';
  10. const { Header } = Layout;
  11. class HeaderView extends PureComponent {
  12. state = {
  13. visible: true,
  14. };
  15. static getDerivedStateFromProps(props, state) {
  16. if (!props.autoHideHeader && !state.visible) {
  17. return {
  18. visible: true,
  19. };
  20. }
  21. return null;
  22. }
  23. componentDidMount() {
  24. document.addEventListener('scroll', this.handScroll, { passive: true });
  25. }
  26. componentWillUnmount() {
  27. document.removeEventListener('scroll', this.handScroll);
  28. }
  29. getHeadWidth = () => {
  30. const { isMobile, collapsed, setting } = this.props;
  31. const { fixedHeader, layout } = setting;
  32. if (isMobile || !fixedHeader || layout === 'topmenu') {
  33. return '100%';
  34. }
  35. return collapsed ? 'calc(100% - 80px)' : 'calc(100% - 256px)';
  36. };
  37. handleNoticeClear = type => {
  38. message.success(
  39. `${formatMessage({ id: 'component.noticeIcon.cleared' })} ${formatMessage({
  40. id: `component.globalHeader.${type}`,
  41. })}`
  42. );
  43. const { dispatch } = this.props;
  44. dispatch({
  45. type: 'global/clearNotices',
  46. payload: type,
  47. });
  48. };
  49. handleMenuClick = ({ key }) => {
  50. const { dispatch } = this.props;
  51. if (key === 'userCenter') {
  52. router.push('/account/center');
  53. return;
  54. }
  55. if (key === 'triggerError') {
  56. router.push('/exception/trigger');
  57. return;
  58. }
  59. if (key === 'userinfo') {
  60. router.push('/account/settings/base');
  61. return;
  62. }
  63. if (key === 'logout') {
  64. dispatch({
  65. type: 'login/logout',
  66. });
  67. }
  68. };
  69. handleNoticeVisibleChange = visible => {
  70. if (visible) {
  71. const { dispatch } = this.props;
  72. dispatch({
  73. type: 'global/fetchNotices',
  74. });
  75. }
  76. };
  77. handScroll = () => {
  78. const { autoHideHeader } = this.props;
  79. const { visible } = this.state;
  80. if (!autoHideHeader) {
  81. return;
  82. }
  83. const scrollTop = document.body.scrollTop + document.documentElement.scrollTop;
  84. if (!this.ticking) {
  85. this.ticking = true;
  86. requestAnimationFrame(() => {
  87. if (this.oldScrollTop > scrollTop) {
  88. this.setState({
  89. visible: true,
  90. });
  91. }
  92. else if (scrollTop > 300 && visible) {
  93. this.setState({
  94. visible: false,
  95. });
  96. }
  97. else if (scrollTop < 300 && !visible) {
  98. this.setState({
  99. visible: true,
  100. });
  101. }
  102. this.oldScrollTop = scrollTop;
  103. this.ticking = false;
  104. });
  105. }
  106. };
  107. render() {
  108. const { isMobile, handleMenuCollapse, setting } = this.props;
  109. const { navTheme, layout, fixedHeader } = setting;
  110. const { visible } = this.state;
  111. const isTop = layout === 'topmenu';
  112. const width = this.getHeadWidth();
  113. const HeaderDom = visible ? (
  114. <Header style={{ padding: 0, width }} className={fixedHeader ? styles.fixedHeader : ''}>
  115. {isTop && !isMobile ? (
  116. <TopNavHeader
  117. theme={navTheme}
  118. mode="horizontal"
  119. onCollapse={handleMenuCollapse}
  120. onNoticeClear={this.handleNoticeClear}
  121. onMenuClick={this.handleMenuClick}
  122. onNoticeVisibleChange={this.handleNoticeVisibleChange}
  123. {...this.props}
  124. />
  125. ) : (
  126. <GlobalHeader
  127. onCollapse={handleMenuCollapse}
  128. onNoticeClear={this.handleNoticeClear}
  129. onMenuClick={this.handleMenuClick}
  130. onNoticeVisibleChange={this.handleNoticeVisibleChange}
  131. {...this.props}
  132. />
  133. )}
  134. </Header>
  135. ) : null;
  136. return (
  137. <Animate component="" transitionName="fade">
  138. {HeaderDom}
  139. </Animate>
  140. );
  141. }
  142. }
  143. export default connect(({ user, global, setting, loading }) => ({
  144. currentUser: user.currentUser,
  145. collapsed: global.collapsed,
  146. fetchingNotices: loading.effects['global/fetchNotices'],
  147. notices: global.notices,
  148. setting,
  149. }))(HeaderView);