Header.tsx 4.74 KB
Newer Older
1 2 3
import GlobalHeader from '@/components/GlobalHeader';
import TopNavHeader from '@/components/TopNavHeader';
import { DefaultSettings } from '../../config/defaultSettings';
jim's avatar
jim committed
4 5
import { Layout, message } from 'antd';
import { connect } from 'dva';
6 7 8
import Animate from 'rc-animate';
import React, { Component } from 'react';
import { formatMessage } from 'umi-plugin-locale';
zinkey's avatar
zinkey committed
9
import router from 'umi/router';
jim's avatar
jim committed
10 11 12 13
import styles from './Header.less';

const { Header } = Layout;

14 15 16 17 18 19 20 21 22 23 24 25 26 27
export declare type SiderTheme = 'light' | 'dark';

interface HeaderViewProps {
  isMobile: boolean;
  collapsed: boolean;
  setting: DefaultSettings;
  dispatch: (args: any) => void;
  autoHideHeader: boolean;
  handleMenuCollapse: (args: boolean) => void;
}

interface HeaderViewState {
  visible: boolean;
}
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
28

29 30
class HeaderView extends Component<HeaderViewProps, HeaderViewState> {
  static getDerivedStateFromProps(props: HeaderViewProps, state: HeaderViewState) {
31 32 33 34 35 36 37 38
    if (!props.autoHideHeader && !state.visible) {
      return {
        visible: true,
      };
    }
    return null;
  }

39 40 41 42 43 44 45 46
  state = {
    visible: true,
  };

  ticking: boolean;

  oldScrollTop: number;

jim's avatar
jim committed
47
  componentDidMount() {
48
    document.addEventListener('scroll', this.handScroll, { passive: true });
jim's avatar
jim committed
49
  }
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
50

jim's avatar
jim committed
51
  componentWillUnmount() {
52
    document.removeEventListener('scroll', this.handScroll);
jim's avatar
jim committed
53
  }
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
54

jim's avatar
jim committed
55
  getHeadWidth = () => {
56 57 58
    const { isMobile, collapsed, setting } = this.props;
    const { fixedHeader, layout } = setting;
    if (isMobile || !fixedHeader || layout === 'topmenu') {
jim's avatar
jim committed
59 60
      return '100%';
    }
61
    return collapsed ? 'calc(100% - 80px)' : 'calc(100% - 256px)';
jim's avatar
jim committed
62
  };
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
63

jim's avatar
jim committed
64
  handleNoticeClear = type => {
Rayron Victor's avatar
Rayron Victor committed
65 66 67 68 69
    message.success(
      `${formatMessage({ id: 'component.noticeIcon.cleared' })} ${formatMessage({
        id: `component.globalHeader.${type}`,
      })}`
    );
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
70 71
    const { dispatch } = this.props;
    dispatch({
jim's avatar
jim committed
72 73 74 75
      type: 'global/clearNotices',
      payload: type,
    });
  };
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
76

jim's avatar
jim committed
77
  handleMenuClick = ({ key }) => {
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
78
    const { dispatch } = this.props;
jim's avatar
jim committed
79
    if (key === 'userCenter') {
zinkey's avatar
zinkey committed
80
      router.push('/account/center');
jim's avatar
jim committed
81 82 83
      return;
    }
    if (key === 'triggerError') {
zinkey's avatar
zinkey committed
84
      router.push('/exception/trigger');
jim's avatar
jim committed
85 86 87
      return;
    }
    if (key === 'userinfo') {
zinkey's avatar
zinkey committed
88
      router.push('/account/settings/base');
jim's avatar
jim committed
89 90 91
      return;
    }
    if (key === 'logout') {
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
92
      dispatch({
jim's avatar
jim committed
93 94 95 96
        type: 'login/logout',
      });
    }
  };
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
97

jim's avatar
jim committed
98
  handleNoticeVisibleChange = visible => {
jim's avatar
jim committed
99
    if (visible) {
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
100 101
      const { dispatch } = this.props;
      dispatch({
jim's avatar
jim committed
102 103 104 105
        type: 'global/fetchNotices',
      });
    }
  };
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
106

107
  handScroll = () => {
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
108 109 110
    const { autoHideHeader } = this.props;
    const { visible } = this.state;
    if (!autoHideHeader) {
jim's avatar
jim committed
111 112
      return;
    }
113
    const scrollTop = document.body.scrollTop + document.documentElement.scrollTop;
jim's avatar
jim committed
114
    if (!this.ticking) {
115
      this.ticking = true;
jim's avatar
jim committed
116
      requestAnimationFrame(() => {
117 118 119 120
        if (this.oldScrollTop > scrollTop) {
          this.setState({
            visible: true,
          });
121
        } else if (scrollTop > 300 && visible) {
jim's avatar
jim committed
122 123 124
          this.setState({
            visible: false,
          });
125
        } else if (scrollTop < 300 && !visible) {
jim's avatar
jim committed
126 127 128 129
          this.setState({
            visible: true,
          });
        }
130
        this.oldScrollTop = scrollTop;
jim's avatar
jim committed
131 132 133 134
        this.ticking = false;
      });
    }
  };
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
135

jim's avatar
jim committed
136
  render() {
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
137
    const { isMobile, handleMenuCollapse, setting } = this.props;
afc163's avatar
afc163 committed
138
    const { navTheme, layout, fixedHeader } = setting;
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
139
    const { visible } = this.state;
jim's avatar
jim committed
140
    const isTop = layout === 'topmenu';
141
    const width = this.getHeadWidth();
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
142
    const HeaderDom = visible ? (
143
      <Header style={{ padding: 0, width }} className={fixedHeader ? styles.fixedHeader : ''}>
jim's avatar
jim committed
144 145
        {isTop && !isMobile ? (
          <TopNavHeader
146
            theme={navTheme as SiderTheme}
jim's avatar
jim committed
147 148
            mode="horizontal"
            onCollapse={handleMenuCollapse}
jim's avatar
jim committed
149
            onNoticeClear={this.handleNoticeClear}
jim's avatar
jim committed
150 151 152 153 154 155 156
            onMenuClick={this.handleMenuClick}
            onNoticeVisibleChange={this.handleNoticeVisibleChange}
            {...this.props}
          />
        ) : (
          <GlobalHeader
            onCollapse={handleMenuCollapse}
jim's avatar
jim committed
157
            onNoticeClear={this.handleNoticeClear}
jim's avatar
jim committed
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
            onMenuClick={this.handleMenuClick}
            onNoticeVisibleChange={this.handleNoticeVisibleChange}
            {...this.props}
          />
        )}
      </Header>
    ) : null;
    return (
      <Animate component="" transitionName="fade">
        {HeaderDom}
      </Animate>
    );
  }
}

export default connect(({ user, global, setting, loading }) => ({
  currentUser: user.currentUser,
  collapsed: global.collapsed,
何乐's avatar
何乐 committed
176
  fetchingMoreNotices: loading.effects['global/fetchMoreNotices'],
jim's avatar
jim committed
177 178
  fetchingNotices: loading.effects['global/fetchNotices'],
  notices: global.notices,
jim's avatar
jim committed
179
  setting,
jim's avatar
jim committed
180
}))(HeaderView);