Commit ff30733f by zhanghaozhe

passport

parent 02660017
...@@ -3,43 +3,36 @@ import './clearable-input.scss' ...@@ -3,43 +3,36 @@ import './clearable-input.scss'
import classnames from 'classnames' import classnames from 'classnames'
class ClearableInput extends Component { class ClearableInput extends Component {
constructor(props) {
super(props);
this.state = {
value: ''
}
}
handleChange = (e) => {
let {onChange} = this.props
let val = e.target.value
this.setState({value: val})
onChange && onChange(val)
}
clearInput = () => {
this.setState({value: ''})
}
render() { render() {
let {wrapperClass, inputClass, placeholder, type = 'text', onChange, icon, ...rest} = this.props let {
value,
name,
wrapperClass,
inputClass,
type = 'text',
icon,
setValues,
...rest
} = this.props
let clearIconStyle = { let clearIconStyle = {
display: this.state.value.length ? 'block' : 'none' display: value && value.length ? 'block' : 'none'
} }
return ( return (
<div className={classnames('clearable-input-wrapper', wrapperClass)}> <div className={classnames('clearable-input-wrapper', wrapperClass)}>
<input <input
type={type} type={type}
value={value}
className={inputClass} className={inputClass}
value={this.state.value}
onChange={this.handleChange}
placeholder={placeholder}
{...rest} {...rest}
name={name}
/> />
{icon} {icon}
<i <i
className={'iconfont icondanseshixintubiao-3 clear'} className={'iconfont icondanseshixintubiao-3 clear'}
onClick={this.clearInput} onClick={() => {
setValues({[name]: ''})
}}
style={clearIconStyle} style={clearIconStyle}
/> />
</div> </div>
......
...@@ -4,3 +4,7 @@ export { default as Tag } from './CategoryTag' ...@@ -4,3 +4,7 @@ export { default as Tag } from './CategoryTag'
export { default as OrderItem } from './OrderList' export { default as OrderItem } from './OrderList'
export { default as HeaderBar } from './HeaderBar' export { default as HeaderBar } from './HeaderBar'
export { default as ToApp } from './ToApp' export { default as ToApp } from './ToApp'
export { default as Captcha } from './Captcha'
export { default as ClearableInput } from "./ClearableInput";
.custom-button { .custom-button {
width:300px; width: 300px;
height:44px; height: 44px;
border-radius:3px; border-radius: 3px;
-webkit-appearance: none; -webkit-appearance: none;
border: none; border: none;
font-size: $font_18; font-size: $font_18;
color: $white;
&.active {
background: $active;
color: $white;
}
} }
\ No newline at end of file
import React, { Component } from 'react'; import React, { Component } from 'react';
import './veri-code-input.scss' import './veri-code-input.scss'
import { http, api } from '@/utils'; import { http, api, validateEmail, validateTel } from '@/utils';
import { Toast } from "antd-mobile"; import { Toast } from "antd-mobile";
import { has } from 'lodash'
import classnames from 'classnames' import classnames from 'classnames'
...@@ -17,11 +18,16 @@ class VeriCodeInput extends Component { ...@@ -17,11 +18,16 @@ class VeriCodeInput extends Component {
} }
timer = null timer = null
componentDidMount() {
console.log(this.props);
}
countDown = () => { countDown = () => {
let {count} = this.state let {count} = this.state
if (!this.state.isFirst) { if (!this.state.isFirst) {
Toast.info('请重新进行滑块验证',2,null,false) Toast.info('请重新进行滑块验证', 2, null, false)
this.props.instance.refresh() this.props.instance.refresh()
this.setState({ this.setState({
isFirst: true isFirst: true
...@@ -45,8 +51,39 @@ class VeriCodeInput extends Component { ...@@ -45,8 +51,39 @@ class VeriCodeInput extends Component {
} }
} }
getType = () => {
const {value} = this.props
if (validateEmail(value)) {
return 'email'
}
}
sendCode = () => { sendCode = () => {
if (!this.validate()) return if (!this.validate()) return
this.getType() === 'email' ? this.sendEmail() : this.sendSMS();
return true;
}
sendEmail = () => {
const {value, challenge} = this.props
http.post(`${api['passport-api']}/send_email_code`, {
email: value,
challenge
}).then(res => {
if (res.data.errno === 0) {
Toast.info('验证码发送成功', 2, null, false)
} else {
Toast.info(res.data.msg, 2, null, false)
}
this.setState({
isFirst: false
})
})
}
sendSMS = () => {
const {action, tel, challenge} = this.props const {action, tel, challenge} = this.props
http.post(`${api['passport-api']}/quick_sms`, { http.post(`${api['passport-api']}/quick_sms`, {
phone_num: tel, phone_num: tel,
...@@ -62,15 +99,23 @@ class VeriCodeInput extends Component { ...@@ -62,15 +99,23 @@ class VeriCodeInput extends Component {
isFirst: false isFirst: false
}) })
}) })
return true
} }
validate = () => { validate = () => {
const {tel, challenge} = this.props const {tel, challenge, account} = this.props
if (!tel) { let hasTel = has(this.props, 'tel')
Toast.info('手机号码不能为空', 2, null, false) let content
if (hasTel) {
content = '手机号码不能为空'
} else {
content = '手机号或电子邮件不能为空'
}
if (hasTel && !tel || !hasTel && !account) {
Toast.info(content, 2, null, false)
return false return false
} }
if (!challenge) { if (!challenge) {
Toast.info('请进行滑块验证', 2, null, false) Toast.info('请进行滑块验证', 2, null, false)
return false return false
......
.forgot-password { .forgot-password {
height: 100%; height: 100%;
padding: 38px 36px;
.content {
padding: 38px 36px;
}
.place { .place {
width: 100%; width: 100%;
...@@ -13,12 +18,8 @@ ...@@ -13,12 +18,8 @@
margin-bottom: 21px; margin-bottom: 21px;
} }
.verify-code{ .verify-code {
margin-bottom: 21px; margin-bottom: 21px;
} }
.next {
background: $active;
color: $white;
}
} }
\ No newline at end of file
import React, { Component } from 'react' import React, { Component } from 'react'
import './forgot-password.scss' import './forgot-password.scss'
import VeriCodeInput from '../common/veriCodeInput'
import ClearableInput from '@common/ClearableInput'
import VeriCodeButton from '../common/veriCodeInput'
import Button from '../common/Button' import Button from '../common/Button'
import { withFormik, Form, Field } from 'formik';
import { connect } from 'react-redux';
import { compose } from 'redux';
import { Toast } from "antd-mobile";
import { HeaderBar, Captcha, ClearableInput } from "@/common";
import { validateTel, validateEmail } from "@/utils";
import { quickLogin } from '@/store/userAction';
import { isEmpty } from "lodash";
class ForgotPassword extends Component { class ForgotPassword extends Component {
constructor(props) { state = {
super(props); validate: null,
this.state = { captchaInstance: null
verificationCode: '',
password: ''
}
} }
setTel = (val) => {
this.setState({tel: val})
}
setVerificationCode = (val) => { getCaptchaInstance = instance => {
this.setState({verificationCode: val}); this.setState({
captchaInstance: instance
})
}
onVerify = (err, data) => {
if (err) {
console.log(err)
} else {
this.setState({
validate: data.validate
})
}
} }
render() { render() {
const {
values,
errors
} = this.props
return ( return (
<div className={'forgot-password'}> <div className={'forgot-password'}>
<ClearableInput <HeaderBar title='忘记密码'/>
type={'tel'} <div className="content">
placeholder={'请输入注册时的邮箱账号或手机号'} <Form className='forgot-password-form'>
onChange={this.setTel} <Field
wrapperClass={'tel-input'} name={'account'}
icon={<i className={'iconfont iconshouji'} render={({field, form}) => {
style={{fontSize: '22px', left: '11px'}} return (
/>} <ClearableInput
/> {...field}
<VeriCodeButton setValues={form.setValues}
className={'verify-code'} type={'tel'}
onChange={this.setVerificationCode} placeholder={'请输入注册时的邮箱账号或手机号'}
icon={<i className={'iconfont iconduanxin'} wrapperClass={'tel-input'}
style={{fontSize: '20px', left: '12px'}} icon={<i className={'iconfont iconshouji'}
/>} style={{fontSize: '22px', left: '11px'}}
/> />}
<div className="place"/> />)
<Button className={'next'}>下一步</Button> }}
/>
<Field
name='veriCode'
render={({field}) => {
return (
<VeriCodeInput
{...field}
className={'verify-code'}
icon={<i className={'iconfont iconduanxin'}
style={{fontSize: '20px', left: '12px'}}
/>}
/>
)
}}
/>
</Form>
<Captcha getInstance={this.getCaptchaInstance} onVerify={this.onVerify}/>
<Button active={values.account && values.veriCode && isEmpty(errors)}>下一步</Button>
</div>
</div> </div>
); );
} }
} }
export default ForgotPassword
\ No newline at end of file const formikConfig = {
mapPropsToValues: () => ({
account: '',
veriCode: ''
}),
validateOnchange: true,
validate: values => {
let errors = {}
if (!validateTel(values.account) && !validateEmail(values.account)) {
errors.account = '请输入正确的手机号或邮箱地址'
}
return errors
},
handleSubmit(values, {props}) {
props.quickLogin({
phone_num: values.account,
phone_code: values.veriCode
}).then(res => {
if (res.hasError) {
Toast.info(res.msg);
} else {
let state = props.location.state || {from: {pathname: '/'}}
props.history.replace(state.from)
}
})
},
}
export default compose(
withFormik(formikConfig),
connect(
null,
{quickLogin}
)
)(ForgotPassword)
\ No newline at end of file
...@@ -44,7 +44,6 @@ class Passport extends Component { ...@@ -44,7 +44,6 @@ class Passport extends Component {
render() { render() {
let {match, location} = this.props let {match, location} = this.props
console.log(location)
return ( return (
<div className="passport"> <div className="passport">
<Switch> <Switch>
......
...@@ -7,12 +7,12 @@ import Header from '../common/Header' ...@@ -7,12 +7,12 @@ import Header from '../common/Header'
import VeriCodeInput from '../common/veriCodeInput' import VeriCodeInput from '../common/veriCodeInput'
import { Form, Field, withFormik } from "formik" import { Form, Field, withFormik } from "formik"
import Captcha from '@/common/Captcha' import Captcha from '@/common/Captcha'
import { http, api } from '@/utils';
import { quickLogin } from '@/store/userAction'; import { quickLogin } from '@/store/userAction';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { compose } from 'redux'; import { compose } from 'redux';
import { isEmpty } from 'lodash' import { isEmpty } from 'lodash'
import { Toast } from 'antd-mobile'; import { Toast } from 'antd-mobile';
import {validateTel} from "@/utils";
class WechatLogin extends Component { class WechatLogin extends Component {
...@@ -124,7 +124,7 @@ const FormikConfig = { ...@@ -124,7 +124,7 @@ const FormikConfig = {
validateOnChange: true, validateOnChange: true,
validate: (values) => { validate: (values) => {
let errors = {} let errors = {}
if (!/^1[3-9](\d{9})$/.test(values.tel)) { if (!validateTel(values.tel)) {
errors.tel = '请填写正确格式的手机号' errors.tel = '请填写正确格式的手机号'
} }
if (!/[0-9]{6}/.test(values.veriCode)) { if (!/[0-9]{6}/.test(values.veriCode)) {
......
export { default as http } from './http' export { default as http } from './http'
export { default as api } from './api' export { default as api } from './api'
export { html, initCaptcha } export { html, initCaptcha, validateTel, validateEmail }
export const getParam = (key, str) => { export const getParam = (key, str) => {
...@@ -69,3 +69,12 @@ export const is_weixin = () => { ...@@ -69,3 +69,12 @@ export const is_weixin = () => {
} }
return false; return false;
} }
function validateTel(tel) {
return /^1[3-9](\d{9})$/.test(tel)
}
function validateEmail(email) {
var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(String(email).toLowerCase());
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment