UNPKG

react-app-shell

Version:

react打包脚本和example, 这里的版本请忽略

442 lines (410 loc) 15.4 kB
import React from 'react'; import propTypes from 'prop-types'; import classNames from 'classnames'; import {message, myToast, monitor, localStore} from '../../utils'; import {authService} from '../../service'; import {REISTER_RESULT_CODE} from '../../constants/user'; import styles from './auth.less'; import image_close from '../../public/images/group/close.png'; import image_login_logo from '../../public/images/group/login-logo.png'; import image_phone from '../../public/images/group/phone.png'; import image_pwd from '../../public/images/group/pwd.png'; import image_code from '../../public/images/group/auth-code.png'; import image_p_code from '../../public/images/group/code.png'; import {appConfig} from '../../config'; const noop = () => { }; const phoneReg = /^1\d{10}$/; const passwordReg = /^[a-zA-Z0-9]{6,18}$/; /** * @author pssgo * @description 登录组件 */ export default class Auth extends React.Component { static propTypes = { visible: propTypes.bool, registerCallback: propTypes.func, // 注册成功的callback loginCallback: propTypes.func, // 登录成功的callback onClose: propTypes.func, // 点击关闭按钮触发的事件 initialMode: propTypes.oneOf(['login', 'register']), // 初始化的组件状态只触发一次 默认为登录组件 grf: propTypes.oneOfType([propTypes.string, propTypes.number]), // 团长的id 如果没有传给我空字符串或者-1 rf: propTypes.oneOfType([propTypes.string, propTypes.number]), // rf码 如果没有传给我空字符串或者 -1 }; static defaultProps = { visible: false, registerCallback: noop, loginCallback: noop, onClose: noop, initialMode: 'register', grf: -1, rf: -1, }; constructor(props) { super(...props); this.timer = null; this.allow = true; this.state = { mode: 'login', login: { phone: '', password: '', }, register: { needCaptcha: false, countdown: false, icode: '', code: '', endTime: 0, phone: '', password: '', } }; } componentDidMount() { if (this.props.initialMode) { this.setState({ mode: this.props.initialMode, }); } } /** * @description 切换 模式 */ switchMode = () => { this.allow = true; this.timer = null; this.setState(state => ({ mode: state.mode === 'login' ? 'register' : 'login' })); }; /** * @description 设置登录的state */ transferSetLoginState = field => event => { const value = event.target.value; this.setState(state => ({ login: { ...state.login, [field]: value, } })); }; /** * @description 设置注册的state */ transferSetRegisterState = field => event => { const value = event.target.value; this.setState(state => ({ register: { ...state.register, [field]: value } })); }; // 刷新验证码 handleChangeImageCode = () => { if (this.refs.captchaImg) { this.refs.captchaImg.src = '/captcha/get?t=' + Math.random(); } }; // 注册组件 renderRegisterComponent = () => { const {register: {countdown, endTime, phone, needCaptcha, icode, password, code}} = this.state; return ( <div className={styles.p_register}> <div className={styles.p_input_wrapper}> <div className={styles.icon}> <img src={image_phone} alt=""/> </div> <div className={styles.p_input}> <input placeholder={'手机账号'} value={phone} maxLength={11} onChange={this.transferSetRegisterState('phone')} /> </div> </div> { needCaptcha && <div className={classNames(styles.p_input_wrapper, styles.image_code_wrapper)}> {/* 图形验证码 */} <div className={styles.icon}> <img src={image_p_code} alt=""/> </div> <div className={styles.p_input}> <input type={'text'} maxLength={18} onChange={this.transferSetRegisterState('icode')} value={icode} placeholder={'请输入图片验证码'} /> </div> <div className={styles.image_code} onClick={this.handleChangeImageCode}> <img src={''} ref={'captchaImg'} alt={''}/> </div> </div> } <div className={classNames(styles.p_input_wrapper, styles.code)}> <div className={styles.icon}> <img src={image_code} alt=""/> </div> <div className={styles.p_input}> <input placeholder={'请输入验证码'} maxLength={6} onChange={this.transferSetRegisterState('code')} value={code} /> </div> <div className={classNames(styles.code_btn, { [styles.disable]: countdown })} onClick={this.handleSendCode} >{countdown ? `${endTime}秒后重新获取` : '获取验证码'}</div> </div> <div className={styles.p_input_wrapper}> <div className={styles.icon}> <img src={image_pwd} alt=""/> </div> <div className={styles.p_input}> <input type={'password'} maxLength={18} value={password} onChange={this.transferSetRegisterState('password')} placeholder={'6-18位数字或字母'} /> </div> </div> <div className={styles.padding_top_20}> <button className={styles.login_btn} onClick={this.handleRegister}>免费注册</button> </div> <button className={styles.register_btn} onClick={this.switchMode}>已有账号? 直接登录</button> <div className={styles.desc}> <a href={appConfig.resources.protocolUrl} target={'_blank'}>注册即视为同意《魔力耳朵用户注册协议》</a> </div> </div> ); }; // 登录组件 renderLoginComponent = () => { const {login: {phone, password}} = this.state; return ( <div className={styles.p_login}> <div className={styles.p_input_wrapper}> <div className={styles.icon}> <img src={image_phone} alt=""/> </div> <div className={styles.p_input}> <input placeholder={'手机账号'} value={phone} maxLength={11} onChange={this.transferSetLoginState('phone')} /> </div> </div> <div className={styles.p_input_wrapper}> <div className={styles.icon}> <img src={image_pwd} alt=""/> </div> <div className={styles.p_input}> <input type={'password'} maxLength={18} value={password} onChange={this.transferSetLoginState('password')} placeholder={'6-18位数字或字母'} /> </div> </div> <div className={styles.padding_top_20}> <button className={styles.login_btn} onClick={this.handleLogin}>登录</button> </div> <button className={styles.register_btn} onClick={this.switchMode}>免费注册</button> </div> ); }; /** * @description 校验 * @return {boolean} */ verifyLogin = () => { const {login: {phone, password}} = this.state; if (!phone) { message.info('请输入手机号码'); return false; } if (!phoneReg.test(phone)) { message.info('手机号格式错误'); return false; } if (!password) { message.info('请输入密码'); return false; } if (password.length < 6) { message.info('请输入正确的登录密码'); return false; } return true; }; /** * @description 校验注册 * @return {boolean} */ verifyRegister = () => { const {register: {phone, password, code}} = this.state; if (!phone) { message.info('手机号不能为空'); return false; } if (!phoneReg.test(phone)) { message.info('请输入正确的手机号'); return false; } if (!code) { message.info('验证码不能为空'); return false; } if (!password) { message.info('密码不能为空'); return false; } if (!passwordReg.test(password)) { message.info('请输入6-18位数字或字母'); return false; } return true; }; /** * @description 注册 */ handleRegister = () => { if (!this.verifyRegister()) return; this.allow = false; const {register: {phone, password, code}} = this.state; let grf = this.props.grf || -1; let rf = this.props.rf || -1; authService.register(phone, password, code, grf, rf).then(({data}) => { this.allow = true; localStore.setToken(data.userId, data.passToken); monitor.login(); this.props.registerCallback(); }).catch(e => { this.allow = true; message.error(e.msg || '注册失败'); }); }; handleSendCode = () => { if (!this.allow) return false; const {register: {phone, icode, needCaptcha}} = this.state; if (!phoneReg.test(phone)) { return message.info('请输入手机号码'); } if (needCaptcha && icode.length !== 4) { return message.info('请输入图片验证码'); } monitor.log(phone, '获取短信验证码'); this.allow = false; authService.sendCode(phone, icode).then(() => { this.allow = true; myToast.success('发送成功', 1500); this.setState(state => ({ register: { ...state.register, countdown: true, endTime: 30, } })); this.timer = setInterval(() => { this.setState(state => { if (state.register.endTime - 1 < 0) { clearInterval(this.timer); return { register: { ...state.register, countdown: false, } }; } else { return { register: { ...state.register, endTime: state.register.endTime - 1, } }; } }); }, 1000); }).catch(e => { this.allow = true; switch (e.code) { case REISTER_RESULT_CODE.EXCEED_MAX_COUNT: { monitor.log(phone, '超过获取手机验证码最大次数'); message.error('超过获取手机验证码最大次数'); break; } case REISTER_RESULT_CODE.PHONE_ALEARDY_REGISTED: { monitor.log(phone, '该手机号已注册'); message.error('该手机号已注册'); break; } case REISTER_RESULT_CODE.INVALID_CODE: { monitor.log(phone, '弹出图形验证码'); this.setState(state => ({ register: { ...state.register, needCaptcha: true, } }), this.handleChangeImageCode); message.error('请输入图片验证码'); break; } default: { // empty } } console.log('e', e); }); }; /** * @description 登录 */ handleLogin = () => { if (!this.allow) { return false; } if (!this.verifyLogin()) { return false; } const {login: {phone, password}} = this.state; this.allow = false; authService.login(phone, password).then(({userId, passToken}) => { localStore.setToken(userId, passToken); monitor.login(); console.log('登录成功'); this.props.loginCallback(); }).catch(e => { message.error(e.msg || '登录失败'); this.allow = true; }); }; render() { const {mode} = this.state; const {onClose} = this.props; return ( <div className={styles.p_auth}> <div className={classNames(styles.modal, { [styles.super_height]: mode !== 'login' })}> <div className={styles.header}> <img src={image_login_logo} alt={''}/> </div> <p className={styles.title}>{mode === 'login' ? '登录' : '注册'}魔力耳朵账号</p> <div className={styles.content}> {mode === 'login' ? this.renderLoginComponent() : this.renderRegisterComponent()} </div> <div className={styles.close} onClick={onClose}> <img src={image_close} alt={''}/> </div> </div> </div> ); } }