react-app-shell
Version:
react打包脚本和example, 这里的版本请忽略
329 lines (301 loc) • 10.1 kB
JavaScript
import React, {PureComponent} from 'react';
import classNames from 'classnames';
import PropTypes from 'prop-types';
import {userService} from '../../service';
import {localStore, message, monitor, myToast} from '../../utils';
import styles from './login.less';
const phoneReg = /^1\d{10}$/;
const maxNumber = 60;
// 默认账号
let defaultAccount = {
phone: '',
code: '',
};
/**
* 发送短信接口响应CODE码
*/
const SMG_RESULT_CODE = {
OK: 'OK', // 成功
INVALID_CODE: 'INVALID_CODE', // 需要输入图文验证码
PHONE_ALEARDY_REGISTED: 'PHONE_ALEARDY_REGISTED', // 手机号已经注册
EXCEED_MAX_COUNT: 'EXCEED_MAX_COUNT', // 超过获取手机验证码最大次数
};
/**
* 本地开发环境默认账号
*/
if (process.env.NODE_ENV === 'development') {
defaultAccount = {
phone: '18910210381',
code: '',
};
}
/**
* 登录页面
*/
class Login extends PureComponent {
static propTypes = {
onOk: PropTypes.func, // 登录成功的callback
onCancel: PropTypes.func,
grf: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), // 团长的id 如果没有传给我空字符串或者-1
rf: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), // rf码 如果没有传给我空字符串或者 -1
};
static defaultProps = {
onOk: () => {
console.log('您点击了确定');
},
onCancel: () => {
console.log('您点击了取消');
},
grf: -1,
rf: -1
};
constructor(props) {
super(props);
this.allow = true; // 请接口状态
this.state = {
captchaVisible: false, // 是否显示验证码
countDown: 0,
phone: defaultAccount.phone,
code: defaultAccount.code,
icode: '',
loadAnimation: false,
};
}
componentDidMount() {
setTimeout(() => {
this.setState({
loadAnimation: true
});
}, 200);
}
componentWillUnmount() {
if (this.countTimer) {
clearInterval(this.countTimer);
}
}
handleInputChange = (key, e) => {
this.setState({
[key]: e.target.value
});
};
handleLogin = () => {
if (!this.allow) {
return false;
}
const {phone, code} = this.state;
if (!this.verifyLogin(phone, code)) {
return false;
}
const {grf, rf} = this.props;
this.allow = false;
userService.login(phone, code, grf, rf)
.then(({userId, passToken}) => {
localStore.setToken(userId, passToken);
this.allow = true;
monitor.login();
this.loginSucceed();
})
.catch(error => {
message.error(error.msg || '登录失败');
this.allow = true;
});
};
/**
* 发送验证码短信
*/
handleSendCode = () => {
if (!this.allow) return false;
let {phone, captchaVisible, icode} = this.state;
if (captchaVisible && !icode) {
message.info('请输入图片验证码');
return false;
}
this.setState({loading: true});
this.allow = false;
userService.sendMessageCode(phone, icode)
.then(data => {
this.allow = true;
myToast.success('发送成功', 1500);
this.startCountDown();
})
.catch(error => {
this.allow = true;
let {loading} = this.state;
loading = false;
// 需要图片验证码验证
switch (error.code) {
// 超过获取手机验证码最大次数
case SMG_RESULT_CODE.EXCEED_MAX_COUNT:
monitor.log(phone, '超过获取手机验证码最大次数');
message.error('超过获取手机验证码最大次数');
break;
// 该手机号已注册
case SMG_RESULT_CODE.PHONE_ALEARDY_REGISTED:
monitor.log(phone, '该手机号已注册');
message.error('该手机号已注册');
break;
// 需要输入图文验证码
case SMG_RESULT_CODE.INVALID_CODE:
if (captchaVisible) {
message.info('验证码错误');
} else {
captchaVisible = true;
}
break;
default:
message.error(error.msg || '获取验证码失败');
break;
}
this.setState({
loading,
captchaVisible
}, this.handleRefreshCode);
});
};
/**
* 开始验证码倒计时
*/
startCountDown = () => {
this.setState({
loading: false,
countDown: maxNumber,
});
// 倒计时
this.countTimer = setInterval(() => {
const {countDown} = this.state;
if (countDown === 1) {
clearInterval(this.countTimer);
}
this.setState({
countDown: countDown - 1
});
}, 1000);
};
/**
* 登录成功后执行
*/
loginSucceed = () => {
const {onOk} = this.props;
message.info('登录成功');
this.setState({
loadAnimation: false
});
setTimeout(() => {
onOk && onOk();
}, 300);
};
/**
* 关闭登录
*/
handleCancel = () => {
const {onCancel} = this.props;
this.setState({
loadAnimation: false
});
setTimeout(() => {
onCancel && onCancel();
}, 300);
}
/**
* 校验用户输入
*/
verifyLogin = (phone, code) => {
if (!phone) {
message.info('请输入手机号码');
return false;
}
if (!phoneReg.test(phone)) {
message.info('手机号格式错误');
return false;
}
if (!code) {
message.info('请输入验证码');
return false;
}
if (code.length < 4) {
message.info('请输入正确的验证码');
return false;
}
return true;
};
/**
* 刷新图片验证码
*/
handleRefreshCode = () => {
const {captchaVisible} = this.state;
if (captchaVisible) {
this.refs.captchaImg.src = '/captcha/get?t=' + Math.random();
}
};
/**
* render发送验证码按钮
*/
renderSendMsgBtn = () => {
const {phone, countDown} = this.state;
let sendMsgText = countDown < 1 ? '获取验证码' : '秒后重新获取';
if (phoneReg.test(phone) && countDown < 1) {
return (
<div className={classNames(styles.sendMsgBtn, styles.active)}
onClick={this.handleSendCode}>{sendMsgText}</div>
);
}
return <div className={styles.sendMsgBtn}>{countDown ? (countDown + sendMsgText) : sendMsgText}</div>;
};
/**
* render图片验证码
*/
renderCaptchaCode = () => {
let {icode, captchaVisible} = this.state;
if (!captchaVisible) return null;
return (
<div className={classNames(styles.setItem, styles.icodeWrap, 'clearfix')}>
<label/>
<input
type="text" maxLength="4" value={icode}
onChange={this.handleInputChange.bind(null, 'icode')} placeholder="请输入图片验证码"
autoComplete="off"
/>
<div className={styles['captchaImg']} onClick={this.handleRefreshCode}>
<img src={''} ref="captchaImg" alt=""/>
</div>
</div>
);
}
render() {
const {phone, code, loadAnimation} = this.state;
return (
<div className={classNames(styles.loginWrapper, loadAnimation ? styles.animation : '')}>
<div className={styles.content}>
<div className={styles.section}>
<div className={classNames(styles.setItem, styles.phoneWarp, 'clearfix')}>
<label/>
<input
type="tel"
maxLength="11"
value={phone}
onChange={this.handleInputChange.bind(null, 'phone')}
placeholder="手机号码"
autoComplete="off"
/>
</div>
{this.renderCaptchaCode()}
<div className={classNames(styles.setItem, styles.codeWrap, 'clearfix')}>
<label/>
<input
type="text" maxLength="4" value={code} pattern="[0-9]*"
onChange={this.handleInputChange.bind(null, 'code')} placeholder="验证码"
autoComplete="off"
/>
{this.renderSendMsgBtn()}
</div>
</div>
<div className={styles.function}>
<div className={styles.closeBtn} onClick={this.handleCancel}>关闭</div>
<div className={styles.loginBtn} onClick={this.handleLogin}>登录</div>
</div>
</div>
</div>
);
}
}
export default Login;