index.tsx 10.1 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 44 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 79 80 81 82 83 84 85
interface BLOCK_NAME_CAMEL_CASEProps extends FormComponentProps {
  dispatch: Dispatch;
  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'],
  })
)
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',
  };
92

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

100 101 102
  componentWillUnmount() {
    clearInterval(this.interval);
  }
陈帅's avatar
陈帅 committed
103
  interval: number | undefined;
104 105 106
  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 196 197 198 199 200 201
      <div className={styles[`progress-${passwordStatus}`]}>
        <Progress
          status={passwordProgressMap[passwordStatus]}
          className={styles.progress}
          strokeWidth={6}
          percent={value.length * 10 > 100 ? 100 : value.length * 10}
          showInfo={false}
        />
ddcat1115's avatar
ddcat1115 committed
202 203 204
      </div>
    ) : null;
  };
205 206

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

陈帅's avatar
陈帅 committed
369
export default Form.create()(PAGE_NAME_UPPER_CAMEL_CASE);