index.tsx 10.2 KB
Newer Older
1 2
import React, { Component } from 'react';
import { connect } from 'dva';
陈帅's avatar
陈帅 committed
3
import { formatMessage, FormattedMessage } from 'umi-plugin-react/locale';
zinkey's avatar
zinkey committed
4
import Link from 'umi/link';
陈帅's avatar
陈帅 committed
5
import { Form, Input, message, Button, Select, Row, Col, Popover, Progress } from 'antd';
6
import styles from './style.less';
陈帅's avatar
陈帅 committed
7 8 9
import { Dispatch } from 'redux';
import { IStateType } from './model';
import { FormComponentProps } from 'antd/lib/form';
10 11

const FormItem = Form.Item;
afc163's avatar
afc163 committed
12
const { Option } = Select;
13 14 15
const InputGroup = Input.Group;

const passwordStatusMap = {
16 17
  ok: (
    <div className={styles.success}>
18
      <FormattedMessage id="BLOCK_NAME.strength.strong" />
19 20 21 22
    </div>
  ),
  pass: (
    <div className={styles.warning}>
23
      <FormattedMessage id="BLOCK_NAME.strength.medium" />
24 25 26 27
    </div>
  ),
  poor: (
    <div className={styles.error}>
28
      <FormattedMessage id="BLOCK_NAME.strength.short" />
29 30
    </div>
  ),
31 32
};

陈帅's avatar
陈帅 committed
33 34 35 36 37
const passwordProgressMap: {
  ok: 'success';
  pass: 'normal';
  poor: 'exception';
} = {
38 39
  ok: 'success',
  pass: 'normal',
jim's avatar
jim committed
40
  poor: 'exception',
41 42
};

陈帅's avatar
陈帅 committed
43
interface BLOCK_NAME_CAMEL_CASEProps extends FormComponentProps {
陈帅's avatar
陈帅 committed
44
  dispatch: Dispatch<any>;
陈帅's avatar
陈帅 committed
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
  BLOCK_NAME_CAMEL_CASE: IStateType;
  submitting: boolean;
}
interface BLOCK_NAME_CAMEL_CASEState {
  count: number;
  confirmDirty: boolean;
  visible: boolean;
  help: string;
  prefix: string;
}

export interface IUserRegisterParams {
  mail: string;
  password: string;
  confirm: string;
  mobile: string;
  captcha: string;
  prefix: string;
}

@connect(
  ({
    BLOCK_NAME_CAMEL_CASE,
    loading,
  }: {
    BLOCK_NAME_CAMEL_CASE: IStateType;
    loading: {
      effects: {
        [key: string]: string;
      };
    };
  }) => ({
    BLOCK_NAME_CAMEL_CASE,
    submitting: loading.effects['BLOCK_NAME_CAMEL_CASE/submit'],
陈帅's avatar
陈帅 committed
79
  }),
陈帅's avatar
陈帅 committed
80 81 82 83 84 85
)
class PAGE_NAME_UPPER_CAMEL_CASE extends Component<
  BLOCK_NAME_CAMEL_CASEProps,
  BLOCK_NAME_CAMEL_CASEState
> {
  state: BLOCK_NAME_CAMEL_CASEState = {
86 87 88 89
    count: 0,
    confirmDirty: false,
    visible: false,
    help: '',
ddcat1115's avatar
ddcat1115 committed
90 91
    prefix: '86',
  };
陈帅's avatar
陈帅 committed
92
  interval: number | undefined;
93

jim's avatar
jim committed
94
  componentDidUpdate() {
陈帅's avatar
陈帅 committed
95
    const { BLOCK_NAME_CAMEL_CASE } = this.props;
96
    if (BLOCK_NAME_CAMEL_CASE.status === 'ok') {
陈帅's avatar
陈帅 committed
97
      message.success('注册成功!');
98 99
    }
  }
陈帅's avatar
陈帅 committed
100

101 102 103 104 105 106
  componentWillUnmount() {
    clearInterval(this.interval);
  }
  onGetCaptcha = () => {
    let count = 59;
    this.setState({ count });
陈帅's avatar
陈帅 committed
107
    this.interval = window.setInterval(() => {
108 109 110 111 112 113
      count -= 1;
      this.setState({ count });
      if (count === 0) {
        clearInterval(this.interval);
      }
    }, 1000);
ddcat1115's avatar
ddcat1115 committed
114
  };
115 116

  getPasswordStatus = () => {
afc163's avatar
afc163 committed
117
    const { form } = this.props;
118 119 120 121 122 123 124
    const value = form.getFieldValue('password');
    if (value && value.length > 9) {
      return 'ok';
    }
    if (value && value.length > 5) {
      return 'pass';
    }
jim's avatar
jim committed
125
    return 'poor';
ddcat1115's avatar
ddcat1115 committed
126
  };
127

陈帅's avatar
陈帅 committed
128
  handleSubmit = (e: React.FormEvent) => {
129
    e.preventDefault();
陈帅's avatar
陈帅 committed
130 131
    const { form, dispatch } = this.props;
    form.validateFields({ force: true }, (err, values) => {
ddcat1115's avatar
ddcat1115 committed
132
      if (!err) {
陈帅's avatar
陈帅 committed
133 134
        const { prefix } = this.state;
        dispatch({
135
          type: 'BLOCK_NAME_CAMEL_CASE/submit',
ddcat1115's avatar
ddcat1115 committed
136 137
          payload: {
            ...values,
陈帅's avatar
陈帅 committed
138
            prefix,
ddcat1115's avatar
ddcat1115 committed
139 140
          },
        });
141
      }
ddcat1115's avatar
ddcat1115 committed
142 143
    });
  };
144

陈帅's avatar
陈帅 committed
145
  checkConfirm = (rule: any, value: string, callback: (messgae?: string) => void) => {
afc163's avatar
afc163 committed
146
    const { form } = this.props;
147
    if (value && value !== form.getFieldValue('password')) {
148
      callback(formatMessage({ id: 'BLOCK_NAME.password.twice' }));
149 150 151
    } else {
      callback();
    }
ddcat1115's avatar
ddcat1115 committed
152
  };
153

陈帅's avatar
陈帅 committed
154
  checkPassword = (rule: any, value: string, callback: (messgae?: string) => void) => {
陈帅's avatar
陈帅 committed
155
    const { visible, confirmDirty } = this.state;
156 157
    if (!value) {
      this.setState({
158
        help: formatMessage({ id: 'BLOCK_NAME.password.required' }),
159 160 161 162 163 164 165
        visible: !!value,
      });
      callback('error');
    } else {
      this.setState({
        help: '',
      });
陈帅's avatar
陈帅 committed
166
      if (!visible) {
167 168 169 170 171 172 173
        this.setState({
          visible: !!value,
        });
      }
      if (value.length < 6) {
        callback('error');
      } else {
afc163's avatar
afc163 committed
174
        const { form } = this.props;
陈帅's avatar
陈帅 committed
175
        if (value && confirmDirty) {
176 177 178 179 180
          form.validateFields(['confirm'], { force: true });
        }
        callback();
      }
    }
ddcat1115's avatar
ddcat1115 committed
181 182
  };

陈帅's avatar
陈帅 committed
183
  changePrefix = (value: string) => {
ddcat1115's avatar
ddcat1115 committed
184 185 186 187
    this.setState({
      prefix: value,
    });
  };
188 189

  renderPasswordProgress = () => {
afc163's avatar
afc163 committed
190
    const { form } = this.props;
191 192
    const value = form.getFieldValue('password');
    const passwordStatus = this.getPasswordStatus();
ddcat1115's avatar
ddcat1115 committed
193
    return value && value.length ? (
194 195
      <div className={styles[`progress-${passwordStatus}`]}>
        <Progress
陈帅's avatar
陈帅 committed
196
          default={passwordProgressMap[passwordStatus]}
197 198 199 200 201 202
          status={passwordProgressMap[passwordStatus]}
          className={styles.progress}
          strokeWidth={6}
          percent={value.length * 10 > 100 ? 100 : value.length * 10}
          showInfo={false}
        />
ddcat1115's avatar
ddcat1115 committed
203 204 205
      </div>
    ) : null;
  };
206 207

  render() {
Andreas Cederström's avatar
Andreas Cederström committed
208
    const { form, submitting } = this.props;
209
    const { getFieldDecorator } = form;
陈帅's avatar
陈帅 committed
210
    const { count, prefix, help, visible } = this.state;
211 212
    return (
      <div className={styles.main}>
213
        <h3>
214
          <FormattedMessage id="BLOCK_NAME.register.register" />
215
        </h3>
216 217 218
        <Form onSubmit={this.handleSubmit}>
          <FormItem>
            {getFieldDecorator('mail', {
ddcat1115's avatar
ddcat1115 committed
219 220 221
              rules: [
                {
                  required: true,
222
                  message: formatMessage({ id: 'BLOCK_NAME.email.required' }),
ddcat1115's avatar
ddcat1115 committed
223 224 225
                },
                {
                  type: 'email',
226
                  message: formatMessage({ id: 'BLOCK_NAME.email.wrong-format' }),
ddcat1115's avatar
ddcat1115 committed
227 228
                },
              ],
229
            })(
xiaohuoni's avatar
xiaohuoni committed
230 231 232
              <Input
                size="large"
                placeholder={formatMessage({ id: 'BLOCK_NAME.email.placeholder' })}
陈帅's avatar
陈帅 committed
233
              />,
234
            )}
235
          </FormItem>
陈帅's avatar
陈帅 committed
236
          <FormItem help={help}>
237
            <Popover
陈帅's avatar
陈帅 committed
238 239 240
              getPopupContainer={node =>
                node && node.parentNode ? (node.parentNode as HTMLElement) : node
              }
241
              content={
ddcat1115's avatar
ddcat1115 committed
242
                <div style={{ padding: '4px 0' }}>
243 244
                  {passwordStatusMap[this.getPasswordStatus()]}
                  {this.renderPasswordProgress()}
ddcat1115's avatar
ddcat1115 committed
245
                  <div style={{ marginTop: 10 }}>
246
                    <FormattedMessage id="BLOCK_NAME.strength.msg" />
ddcat1115's avatar
ddcat1115 committed
247
                  </div>
248 249 250 251
                </div>
              }
              overlayStyle={{ width: 240 }}
              placement="right"
陈帅's avatar
陈帅 committed
252
              visible={visible}
253 254
            >
              {getFieldDecorator('password', {
ddcat1115's avatar
ddcat1115 committed
255 256 257 258 259
                rules: [
                  {
                    validator: this.checkPassword,
                  },
                ],
260 261 262 263
              })(
                <Input
                  size="large"
                  type="password"
264
                  placeholder={formatMessage({ id: 'BLOCK_NAME.password.placeholder' })}
陈帅's avatar
陈帅 committed
265
                />,
266
              )}
267 268 269 270
            </Popover>
          </FormItem>
          <FormItem>
            {getFieldDecorator('confirm', {
ddcat1115's avatar
ddcat1115 committed
271 272 273
              rules: [
                {
                  required: true,
274
                  message: formatMessage({ id: 'BLOCK_NAME.confirm-password.required' }),
ddcat1115's avatar
ddcat1115 committed
275 276 277 278 279
                },
                {
                  validator: this.checkConfirm,
                },
              ],
280 281 282 283
            })(
              <Input
                size="large"
                type="password"
284
                placeholder={formatMessage({ id: 'BLOCK_NAME.confirm-password.placeholder' })}
陈帅's avatar
陈帅 committed
285
              />,
286
            )}
287 288
          </FormItem>
          <FormItem>
ddcat1115's avatar
ddcat1115 committed
289 290 291 292 293 294 295 296 297 298 299 300 301 302
            <InputGroup compact>
              <Select
                size="large"
                value={prefix}
                onChange={this.changePrefix}
                style={{ width: '20%' }}
              >
                <Option value="86">+86</Option>
                <Option value="87">+87</Option>
              </Select>
              {getFieldDecorator('mobile', {
                rules: [
                  {
                    required: true,
303
                    message: formatMessage({ id: 'BLOCK_NAME.phone-number.required' }),
ddcat1115's avatar
ddcat1115 committed
304 305
                  },
                  {
306
                    pattern: /^\d{11}$/,
307
                    message: formatMessage({ id: 'BLOCK_NAME.phone-number.wrong-format' }),
ddcat1115's avatar
ddcat1115 committed
308 309
                  },
                ],
310 311 312 313
              })(
                <Input
                  size="large"
                  style={{ width: '80%' }}
314
                  placeholder={formatMessage({ id: 'BLOCK_NAME.phone-number.placeholder' })}
陈帅's avatar
陈帅 committed
315
                />,
316
              )}
317 318 319 320 321 322
            </InputGroup>
          </FormItem>
          <FormItem>
            <Row gutter={8}>
              <Col span={16}>
                {getFieldDecorator('captcha', {
ddcat1115's avatar
ddcat1115 committed
323 324 325
                  rules: [
                    {
                      required: true,
326
                      message: formatMessage({ id: 'BLOCK_NAME.verification-code.required' }),
ddcat1115's avatar
ddcat1115 committed
327 328
                    },
                  ],
329 330 331
                })(
                  <Input
                    size="large"
332
                    placeholder={formatMessage({ id: 'BLOCK_NAME.verification-code.placeholder' })}
陈帅's avatar
陈帅 committed
333
                  />,
334
                )}
335 336 337
              </Col>
              <Col span={8}>
                <Button
ddcat1115's avatar
ddcat1115 committed
338
                  size="large"
陈帅's avatar
陈帅 committed
339
                  disabled={!!count}
340 341 342
                  className={styles.getCaptcha}
                  onClick={this.onGetCaptcha}
                >
343 344
                  {count
                    ? `${count} s`
345
                    : formatMessage({ id: 'BLOCK_NAME.register.get-verification-code' })}
346 347 348 349 350
                </Button>
              </Col>
            </Row>
          </FormItem>
          <FormItem>
ddcat1115's avatar
ddcat1115 committed
351 352
            <Button
              size="large"
Andreas Cederström's avatar
Andreas Cederström committed
353
              loading={submitting}
ddcat1115's avatar
ddcat1115 committed
354 355 356 357
              className={styles.submit}
              type="primary"
              htmlType="submit"
            >
358
              <FormattedMessage id="BLOCK_NAME.register.register" />
359
            </Button>
360
            <Link className={styles.login} to="/user/login">
361
              <FormattedMessage id="BLOCK_NAME.register.sign-in" />
ddcat1115's avatar
ddcat1115 committed
362
            </Link>
363 364 365 366 367 368
          </FormItem>
        </Form>
      </div>
    );
  }
}
lijiehua's avatar
lijiehua committed
369

陈帅's avatar
陈帅 committed
370
export default Form.create<BLOCK_NAME_CAMEL_CASEProps>()(PAGE_NAME_UPPER_CAMEL_CASE);