Header.tsx 4.93 KB
Newer Older
何乐's avatar
何乐 committed
1 2 3
import GlobalHeader, { GlobalHeaderProps } from '@/components/GlobalHeader';
import TopNavHeader, { TopNavHeaderProps } from '@/components/TopNavHeader';
import { ConnectProps, ConnectState, SettingModelState } from '@/models/connect';
陈帅's avatar
陈帅 committed
4
import React, { Component } from 'react';
陈小聪's avatar
陈小聪 committed
5
import { formatMessage } from 'umi-plugin-react/locale';
jim's avatar
jim committed
6
import { Layout, message } from 'antd';
何乐's avatar
何乐 committed
7
import { ClickParam } from 'antd/es/menu';
jim's avatar
jim committed
8
import { connect } from 'dva';
陈小聪's avatar
陈小聪 committed
9
import Animate from 'rc-animate';
zinkey's avatar
zinkey committed
10
import router from 'umi/router';
jim's avatar
jim committed
11 12 13 14
import styles from './Header.less';

const { Header } = Layout;

何乐's avatar
何乐 committed
15 16 17 18 19 20
export interface HeaderViewProps extends ConnectProps, TopNavHeaderProps, GlobalHeaderProps {
  isMobile?: boolean;
  collapsed?: boolean;
  setting?: SettingModelState;
  autoHideHeader?: boolean;
  handleMenuCollapse?: (collapse: boolean) => void;
陈小聪's avatar
陈小聪 committed
21 22 23 24 25
}

interface HeaderViewState {
  visible: boolean;
}
陈帅's avatar
陈帅 committed
26

陈小聪's avatar
陈小聪 committed
27 28
class HeaderView extends Component<HeaderViewProps, HeaderViewState> {
  static getDerivedStateFromProps(props: HeaderViewProps, state: HeaderViewState) {
29 30 31 32 33 34 35
    if (!props.autoHideHeader && !state.visible) {
      return {
        visible: true,
      };
    }
    return null;
  }
陈帅's avatar
陈帅 committed
36 37 38
  state = {
    visible: true,
  };
39

何乐's avatar
何乐 committed
40 41
  ticking: boolean = false;
  oldScrollTop: number = 0;
陈小聪's avatar
陈小聪 committed
42

jim's avatar
jim committed
43
  componentDidMount() {
44
    document.addEventListener('scroll', this.handScroll, { passive: true });
jim's avatar
jim committed
45
  }
陈帅's avatar
陈帅 committed
46

jim's avatar
jim committed
47
  componentWillUnmount() {
48
    document.removeEventListener('scroll', this.handScroll);
jim's avatar
jim committed
49
  }
陈帅's avatar
陈帅 committed
50

jim's avatar
jim committed
51
  getHeadWidth = () => {
柴茂源's avatar
柴茂源 committed
52
    const { isMobile, collapsed, setting } = this.props;
何乐's avatar
何乐 committed
53
    const { fixedHeader, layout } = setting!;
柴茂源's avatar
柴茂源 committed
54
    if (isMobile || !fixedHeader || layout === 'topmenu') {
jim's avatar
jim committed
55 56
      return '100%';
    }
柴茂源's avatar
柴茂源 committed
57
    return collapsed ? 'calc(100% - 80px)' : 'calc(100% - 256px)';
jim's avatar
jim committed
58
  };
陈帅's avatar
陈帅 committed
59

何乐's avatar
何乐 committed
60 61
  handleNoticeClear = (type: string) => {
    const { dispatch } = this.props;
Rayron Victor's avatar
Rayron Victor committed
62 63 64
    message.success(
      `${formatMessage({ id: 'component.noticeIcon.cleared' })} ${formatMessage({
        id: `component.globalHeader.${type}`,
何乐's avatar
何乐 committed
65
      })}`,
Rayron Victor's avatar
Rayron Victor committed
66
    );
何乐's avatar
何乐 committed
67
    dispatch!({
jim's avatar
jim committed
68 69 70 71
      type: 'global/clearNotices',
      payload: type,
    });
  };
陈帅's avatar
陈帅 committed
72

何乐's avatar
何乐 committed
73
  handleMenuClick = ({ key }: ClickParam) => {
陈帅's avatar
陈帅 committed
74
    const { dispatch } = this.props;
jim's avatar
jim committed
75
    if (key === 'userCenter') {
zinkey's avatar
zinkey committed
76
      router.push('/account/center');
jim's avatar
jim committed
77 78 79
      return;
    }
    if (key === 'triggerError') {
zinkey's avatar
zinkey committed
80
      router.push('/exception/trigger');
jim's avatar
jim committed
81 82 83
      return;
    }
    if (key === 'userinfo') {
zinkey's avatar
zinkey committed
84
      router.push('/account/settings/base');
jim's avatar
jim committed
85 86 87
      return;
    }
    if (key === 'logout') {
何乐's avatar
何乐 committed
88
      dispatch!({
jim's avatar
jim committed
89 90 91 92
        type: 'login/logout',
      });
    }
  };
陈帅's avatar
陈帅 committed
93

何乐's avatar
何乐 committed
94
  handleNoticeVisibleChange = (visible: boolean) => {
jim's avatar
jim committed
95
    if (visible) {
陈帅's avatar
陈帅 committed
96
      const { dispatch } = this.props;
何乐's avatar
何乐 committed
97
      dispatch!({
jim's avatar
jim committed
98 99 100 101
        type: 'global/fetchNotices',
      });
    }
  };
陈帅's avatar
陈帅 committed
102

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

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

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