blob: 189abc0c7d7af2d8fcc1ef445605d89184490b86 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { Component } from 'react';
import { connect } from 'dva';
import { routerRedux, Link } from 'dva/router';
import { Form, Input, Button, Select, Row, Col, Popover, Progress } from 'antd';
import styles from './Register.less';
const FormItem = Form.Item;
const { Option } = Select;
const InputGroup = Input.Group;
const passwordStatusMap = {
ok: <div className={styles.success}>强度:强</div>,
pass: <div className={styles.warning}>强度:中</div>,
poor: <div className={styles.error}>强度:太短</div>,
};
const passwordProgressMap = {
ok: 'success',
pass: 'normal',
poor: 'exception',
};
@connect(({ register, loading }) => ({
register,
submitting: loading.effects['register/submit'],
}))
@Form.create()
export default class Register extends Component {
state = {
count: 0,
confirmDirty: false,
visible: false,
help: '',
prefix: '86',
};
componentWillReceiveProps(nextProps) {
const {...propsData} = this.props;
const account = propsData.form.getFieldValue('mail');
if (nextProps.register.status === 'ok') {
propsData.dispatch(routerRedux.push({
pathname: '/user/register-result',
state: {
account,
},
}));
}
}
componentWillUnmount() {
clearInterval(this.interval);
}
onGetCaptcha = () => {
let count = 59;
this.setState({ count });
this.interval = setInterval(() => {
count -= 1;
this.setState({ count });
if (count === 0) {
clearInterval(this.interval);
}
}, 1000);
};
getPasswordStatus = () => {
const { form } = this.props;
const value = form.getFieldValue('password');
if (value && value.length > 9) {
return 'ok';
}
if (value && value.length > 5) {
return 'pass';
}
return 'poor';
};
handleSubmit = (e) => {
e.preventDefault();
const {...propsData} = this.props;
const {...stateData} = this.state;
propsData.form.validateFields({ force: true }, (err, values) => {
if (!err) {
propsData.dispatch({
type: 'register/submit',
payload: {
...values,
prefix: stateData.prefix,
},
});
}
});
};
handleConfirmBlur = (e) => {
const { value } = e.target;
const {...stateData} = this.state;
this.setState({ confirmDirty: stateData.confirmDirty || !!value });
};
checkConfirm = (rule, value, callback) => {
const { form } = this.props;
if (value && value !== form.getFieldValue('password')) {
callback('两次输入的密码不匹配!');
} else {
callback();
}
};
checkPassword = (rule, value, callback) => {
const {...stateData} = this.state;
if (!value) {
this.setState({
help: '请输入密码!',
visible: !!value,
});
callback('error');
} else {
this.setState({
help: '',
});
if (!stateData.visible) {
this.setState({
visible: !!value,
});
}
if (value.length < 6) {
callback('error');
} else {
const { form } = this.props;
if (value && stateData.confirmDirty) {
form.validateFields(['confirm'], { force: true });
}
callback();
}
}
};
changePrefix = (value) => {
this.setState({
prefix: value,
});
};
renderPasswordProgress = () => {
const { form } = this.props;
const value = form.getFieldValue('password');
const passwordStatus = this.getPasswordStatus();
return value && value.length ? (
<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}
/>
</div>
) : null;
};
render() {
const { form, submitting } = this.props;
const { getFieldDecorator } = form;
const { help, count, prefix } = this.state;
const { stateData } = this.state;
return (
<div className={styles.main}>
<h3>注册</h3>
<Form onSubmit={this.handleSubmit}>
<FormItem>
{getFieldDecorator('mail', {
rules: [
{
required: true,
message: '请输入邮箱地址!',
},
{
type: 'email',
message: '邮箱地址格式错误!',
},
],
})(<Input size="large" placeholder="邮箱" />)}
</FormItem>
<FormItem help={help}>
<Popover
content={
<div style={{ padding: '4px 0' }}>
{passwordStatusMap[this.getPasswordStatus()]}
{this.renderPasswordProgress()}
<div style={{ marginTop: 10 }}>
请至少输入 6 个字符。请不要使用容易被猜到的密码。
</div>
</div>
}
overlayStyle={{ width: 240 }}
placement="right"
visible={stateData.visible}
>
{getFieldDecorator('password', {
rules: [
{
validator: this.checkPassword,
},
],
})(
<Input
size="large"
type="password"
placeholder="至少6位密码,区分大小写"
/>
)}
</Popover>
</FormItem>
<FormItem>
{getFieldDecorator('confirm', {
rules: [
{
required: true,
message: '请确认密码!',
},
{
validator: this.checkConfirm,
},
],
})(<Input size="large" type="password" placeholder="确认密码" />)}
</FormItem>
<FormItem>
<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,
message: '请输入手机号!',
},
{
pattern: /^1\d{10}$/,
message: '手机号格式错误!',
},
],
})(
<Input
size="large"
style={{ width: '80%' }}
placeholder="11位手机号"
/>
)}
</InputGroup>
</FormItem>
<FormItem>
<Row gutter={8}>
<Col span={16}>
{getFieldDecorator('captcha', {
rules: [
{
required: true,
message: '请输入验证码!',
},
],
})(<Input size="large" placeholder="验证码" />)}
</Col>
<Col span={8}>
<Button
size="large"
disabled={count}
className={styles.getCaptcha}
onClick={this.onGetCaptcha}
>
{count ? `${count} s` : '获取验证码'}
</Button>
</Col>
</Row>
</FormItem>
<FormItem>
<Button
size="large"
loading={submitting}
className={styles.submit}
type="primary"
htmlType="submit"
>
注册
</Button>
<Link className={styles.login} to="/user/login">
使用已有账户登录
</Link>
</FormItem>
</Form>
</div>
);
}
}