index.tsx 4.13 KB
Newer Older
陈帅's avatar
陈帅 committed
1 2 3
import React, { Component } from 'react';
import { Form, Tabs } from 'antd';
import classNames from 'classnames';
陈帅's avatar
陈帅 committed
4
import { FormComponentProps } from 'antd/es/form';
陈帅's avatar
陈帅 committed
5 6 7 8 9 10
import LoginItem, { LoginItemType, LoginItemProps } from './LoginItem';
import LoginTab from './LoginTab';
import styles from './index.less';
import LoginContext, { ILoginContext } from './LoginContext';
import LoginSubmit from './LoginSubmit';

陈帅's avatar
陈帅 committed
11
export interface LoginProps {
陈帅's avatar
陈帅 committed
12 13 14 15 16
  defaultActiveKey?: string;
  onTabChange?: (key: string) => void;
  style?: React.CSSProperties;
  onSubmit?: (error: any, values: any) => void;
  className?: string;
陈帅's avatar
陈帅 committed
17
  form: FormComponentProps['form'];
陈帅's avatar
陈帅 committed
18 19 20 21 22 23
  children: React.ReactElement<LoginTab>[];
}

interface LoginState {
  tabs?: string[];
  type?: string;
陈帅's avatar
陈帅 committed
24
  active?: { [key: string]: any[] };
陈帅's avatar
陈帅 committed
25 26 27 28
}

class Login extends Component<LoginProps, LoginState> {
  public static Tab = LoginTab;
陈帅's avatar
陈帅 committed
29

陈帅's avatar
陈帅 committed
30
  public static Submit = LoginSubmit;
陈帅's avatar
陈帅 committed
31

陈帅's avatar
陈帅 committed
32
  public static UserName: React.FunctionComponent<LoginItemProps>;
陈帅's avatar
陈帅 committed
33

陈帅's avatar
陈帅 committed
34
  public static Password: React.FunctionComponent<LoginItemProps>;
陈帅's avatar
陈帅 committed
35

陈帅's avatar
陈帅 committed
36
  public static Mobile: React.FunctionComponent<LoginItemProps>;
陈帅's avatar
陈帅 committed
37

陈帅's avatar
陈帅 committed
38
  public static Captcha: React.FunctionComponent<LoginItemProps>;
陈帅's avatar
陈帅 committed
39

陈帅's avatar
陈帅 committed
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
  static defaultProps = {
    className: '',
    defaultActiveKey: '',
    onTabChange: () => {},
    onSubmit: () => {},
  };

  constructor(props: LoginProps) {
    super(props);
    this.state = {
      type: props.defaultActiveKey,
      tabs: [],
      active: {},
    };
  }

  onSwitch = (type: string) => {
    this.setState(
      {
        type,
      },
      () => {
        const { onTabChange } = this.props;
        if (onTabChange) {
          onTabChange(type);
        }
陈帅's avatar
陈帅 committed
66
      },
陈帅's avatar
陈帅 committed
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
    );
  };

  getContext: () => ILoginContext = () => {
    const { form } = this.props;
    const { tabs = [] } = this.state;
    return {
      tabUtil: {
        addTab: id => {
          this.setState({
            tabs: [...tabs, id],
          });
        },
        removeTab: id => {
          this.setState({
            tabs: tabs.filter(currentId => currentId !== id),
          });
        },
      },
      form: { ...form },
      updateActive: activeItem => {
        const { type = '', active = {} } = this.state;
        if (active[type]) {
          active[type].push(activeItem);
        } else {
          active[type] = [activeItem];
        }
        this.setState({
          active,
        });
      },
    };
  };

  handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    const { active = {}, type = '' } = this.state;
    const { form, onSubmit } = this.props;
    const activeFields = active[type] || [];
陈帅's avatar
陈帅 committed
106
    if (form) {
陈帅's avatar
陈帅 committed
107
      form.validateFields(activeFields, { force: true }, (err, values) => {
陈帅's avatar
陈帅 committed
108 109 110
        if (onSubmit) {
          onSubmit(err, values);
        }
陈帅's avatar
陈帅 committed
111
      });
陈帅's avatar
陈帅 committed
112
    }
陈帅's avatar
陈帅 committed
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
  };

  render() {
    const { className, children } = this.props;
    const { type, tabs = [] } = this.state;
    const TabChildren: React.ReactComponentElement<LoginTab>[] = [];
    const otherChildren: React.ReactElement<any>[] = [];
    React.Children.forEach(
      children,
      (child: React.ReactComponentElement<LoginTab> | React.ReactElement<any>) => {
        if (!child) {
          return;
        }
        if (child.type.typeName === 'LoginTab') {
          TabChildren.push(child);
        } else {
          otherChildren.push(child);
        }
陈帅's avatar
陈帅 committed
131
      },
陈帅's avatar
陈帅 committed
132 133 134 135
    );
    return (
      <LoginContext.Provider value={this.getContext()}>
        <div className={classNames(className, styles.login)}>
136 137 138
          <Form onSubmit={this.handleSubmit}>
            {tabs.length ? (
              <React.Fragment>
陈帅's avatar
陈帅 committed
139 140 141 142 143 144 145 146 147
                <Tabs
                  animated={false}
                  className={styles.tabs}
                  activeKey={type}
                  onChange={this.onSwitch}
                >
                  {TabChildren}
                </Tabs>
                {otherChildren}
148 149 150 151 152
              </React.Fragment>
            ) : (
              children
            )}
          </Form>
陈帅's avatar
陈帅 committed
153 154 155 156 157
        </div>
      </LoginContext.Provider>
    );
  }
}
陈帅's avatar
陈帅 committed
158

陈帅's avatar
陈帅 committed
159
(Object.keys(LoginItem) as (keyof LoginItemType)[]).forEach(item => {
陈帅's avatar
陈帅 committed
160 161 162
  Login[item] = LoginItem[item];
});

陈帅's avatar
陈帅 committed
163
export default Form.create<LoginProps>()(Login);