Commit b41c453e by zhanghaozhe

忘记密码

parent 983b183b
...@@ -10,7 +10,7 @@ export const delCountryNum = () => ({ ...@@ -10,7 +10,7 @@ export const delCountryNum = () => ({
type: 'DEL_COUNTRY_NUM' type: 'DEL_COUNTRY_NUM'
}); });
export default (state = {}, action) => { export default (state = {num: 86, code: null}, action) => {
const { type, payload } = action; const { type, payload } = action;
switch (type) { switch (type) {
case ADD_COUNTRY_NUM: case ADD_COUNTRY_NUM:
......
...@@ -53,7 +53,8 @@ class Country extends Component { ...@@ -53,7 +53,8 @@ class Country extends Component {
num, num,
code: getParam('share_code') code: getParam('share_code')
}); });
history.push(`/detail?id=${getParam('id')}`); // history.push(`/detail?id=${getParam('id')}`);
history.go(-1)
e.preventDefault(); e.preventDefault();
} }
......
...@@ -6,13 +6,8 @@ import more from '../../icons/more.png' ...@@ -6,13 +6,8 @@ import more from '../../icons/more.png'
class LoginWays extends PureComponent { class LoginWays extends PureComponent {
state = { state = {
ways: browser.isWeixin ? this.props.loginWays.slice(0, 2) : this.props.loginWays.slice(0, 1) ways: browser.isWeixin ? this.props.loginWays.slice(0, 2) : this.props.loginWays.slice(0, 1),
} showMore: true
componentDidMount() {
this.setState({
ways: this.filterWays()
})
} }
...@@ -21,12 +16,13 @@ class LoginWays extends PureComponent { ...@@ -21,12 +16,13 @@ class LoginWays extends PureComponent {
} }
filterWays = () => { filterWays = () => {
return browser.isWeixin ? this.props.loginWays : this.state.ways.filter(item => item.id !== 'wechat') return browser.isWeixin ? this.props.loginWays : this.props.loginWays.filter(item => item.id !== 'wechat')
} }
showMore = () => { showMore = () => {
this.setState({ this.setState({
ways: this.props.loginWays ways: this.filterWays(),
showMore: false
}) })
} }
...@@ -46,7 +42,7 @@ class LoginWays extends PureComponent { ...@@ -46,7 +42,7 @@ class LoginWays extends PureComponent {
}) })
} }
{ {
this.state.ways.length !== this.props.loginWays.length && this.state.showMore &&
<li className={'more'} onClick={this.showMore}> <li className={'more'} onClick={this.showMore}>
<img src={more} alt="更多"/> <img src={more} alt="更多"/>
<p>更多</p> <p>更多</p>
......
import React, { Component } from 'react';
import ClearableInput from '@common/ClearableInput'
import './index.scss'
import { Link } from "react-router-dom";
class ClearableInputWithCountryCodes extends Component {
render() {
const {country, ...rest} = this.props
return (
<div className={'clearable-input-with-country-codes'}>
<div className="country-code">
<Link to={'/country'}>
+{country && country.num || 86}
<i className={'iconfont iconiconfront-69'}/>
</Link>
</div>
<ClearableInput {...rest}/>
</div>
);
}
}
export default ClearableInputWithCountryCodes;
\ No newline at end of file
.clearable-input-with-country-codes {
display: flex;
border: 1px solid #ccc;
border-radius: 3px;
margin-bottom: 24px;
.clearable-input-wrapper {
margin-bottom: 0;
flex: 1 1 auto;
input {
padding-left: 10px;
border: none;
width: 100%;
padding-right: 34px;
}
}
.country-code {
flex-shrink: 0;
display: flex;
justify-content: center;
align-items: center;
font-size: 15px;
color: #333;
width: 63px;
text-align: center;
border-right: 1px solid #ccc;
.iconfont {
margin-left: 3px;
}
}
}
\ No newline at end of file
...@@ -3,13 +3,19 @@ import './index.scss' ...@@ -3,13 +3,19 @@ import './index.scss'
import Input from '../Input' import Input from '../Input'
class InputWithCountryCodes extends Component { class InputWithCountryCodes extends Component {
static defaultProps = {
countryCode: '86'
}
render() { render() {
const {countryCode, ...rest} = this.props
return ( return (
<div className={'input-with-country-codes'}> <div className={'input-with-country-codes'}>
<div className="country-codes"> <div className="country-codes">
<i className={'iconfont iconiconfront-69'}></i> +{countryCode}
<i className={'iconfont iconiconfront-69'}/>
</div> </div>
<Input/> <Input {...rest}/>
</div> </div>
); );
} }
......
.input-with-country-codes{ .input-with-country-codes {
.input-wrapper{ display: flex;
.input{ border: 1px solid #ccc;
border-radius: 3px;
margin-bottom: 24px;
.tel-input {
margin-bottom: 0;
.input {
padding-left: 10px; padding-left: 10px;
border: none;
} }
} }
.country-codes{
font-size: 10px; .country-codes {
flex-shrink: 0;
display: flex;
justify-content: center;
align-items: center;
font-size: 15px;
color: #333;
width: 63px;
text-align: center;
border-right: 1px solid #ccc;
} }
} }
\ 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, validateEmail, validateTel } from '@/utils'; import { http, validateEmail } from '@/utils';
import { Toast } from "antd-mobile"; import { Toast } from "antd-mobile";
import { has } from 'lodash' import { has } from 'lodash'
...@@ -47,8 +47,8 @@ class VeriCodeInput extends Component { ...@@ -47,8 +47,8 @@ class VeriCodeInput extends Component {
} }
getType = () => { getType = () => {
const {account} = this.props const {email} = this.props
if (validateEmail(account)) { if (validateEmail(email)) {
return 'email' return 'email'
} }
} }
...@@ -61,9 +61,9 @@ class VeriCodeInput extends Component { ...@@ -61,9 +61,9 @@ class VeriCodeInput extends Component {
} }
sendEmail = () => { sendEmail = () => {
const {account, challenge} = this.props const {email, challenge} = this.props
http.post(`${API['passport-api']}/send_email_code`, { http.post(`${API['passport-api']}/send_email_code`, {
email: account, email,
challenge challenge
}).then(res => { }).then(res => {
if (res.data.errno === 0) { if (res.data.errno === 0) {
...@@ -79,14 +79,15 @@ class VeriCodeInput extends Component { ...@@ -79,14 +79,15 @@ class VeriCodeInput extends Component {
} }
sendSMS = () => { sendSMS = () => {
const {action, tel, account, challenge, checking} = this.props const {action, tel, account, challenge, checking, country} = this.props
if (!tel && !account) { if (!tel) {
Toast.info('请输入手机号或邮箱地址') Toast.info('请输入手机号')
return return
} }
http.post(`${API['passport-api']}/quick_sms`, { http.post(`${API['passport-api']}/quick_sms`, {
phone_num: tel || account, phone_num: tel || account,
action: action || 'login', action: action || 'login',
area_code: country.num,
challenge, challenge,
checking checking
}).then(res => { }).then(res => {
...@@ -103,7 +104,7 @@ class VeriCodeInput extends Component { ...@@ -103,7 +104,7 @@ class VeriCodeInput extends Component {
validate = () => { validate = () => {
const {tel, challenge, account} = this.props const {tel, challenge, email} = this.props
let hasTel = has(this.props, 'tel') let hasTel = has(this.props, 'tel')
let content let content
...@@ -111,15 +112,15 @@ class VeriCodeInput extends Component { ...@@ -111,15 +112,15 @@ class VeriCodeInput extends Component {
if (!tel) { if (!tel) {
content = '手机号码不能为空' content = '手机号码不能为空'
} }
if (!validateTel(tel)) { if (!/\d/.test(tel)) {
content = '请输入正确格式的手机号码' content = '请输入正确格式的手机号码'
} }
} else { } else {
if (!account) { if (!email) {
content = '手机号或电子邮件不能为空' content = '电子邮件不能为空'
} }
if (!validateTel(account) && !validateEmail(account)) { if (!validateEmail(email)) {
content = '请输入正确格式的手机号或电子邮件' content = '请输入正确格式的电子邮件'
} }
} }
......
...@@ -4,6 +4,13 @@ ...@@ -4,6 +4,13 @@
.content { .content {
padding: 38px 36px; padding: 38px 36px;
text-align: center;
.to-email{
line-height: 55px;
font-size: 15px;
color: #666;
}
} }
...@@ -14,10 +21,6 @@ ...@@ -14,10 +21,6 @@
background: #56abff; background: #56abff;
} }
.tel-input {
margin-bottom: 21px;
}
.verify-code { .verify-code {
margin-bottom: 21px; margin-bottom: 21px;
} }
...@@ -25,4 +28,5 @@ ...@@ -25,4 +28,5 @@
.next_step { .next_step {
margin-top: 32px; margin-top: 32px;
} }
} }
\ No newline at end of file
...@@ -6,10 +6,12 @@ import { withFormik, Form, Field } from 'formik'; ...@@ -6,10 +6,12 @@ import { withFormik, Form, Field } from 'formik';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { compose } from 'redux'; import { compose } from 'redux';
import { Toast } from "antd-mobile"; import { Toast } from "antd-mobile";
import { HeaderBar, Captcha, ClearableInput } from "@/common"; import { HeaderBar, Captcha } from "@/common";
import { validateTel, validateEmail, http, api } from "@/utils"; import ClearableInput from '../common/clearableInputWithCountryCodes'
import { validateTel, http, api } from "@/utils";
import { quickLogin } from '@/store/userAction'; import { quickLogin } from '@/store/userAction';
import OnSubmissionError from '../common/OnSubmissionError' import OnSubmissionError from '../common/OnSubmissionError'
import { Link } from "react-router-dom";
class ForgotPassword extends Component { class ForgotPassword extends Component {
...@@ -42,7 +44,8 @@ class ForgotPassword extends Component { ...@@ -42,7 +44,8 @@ class ForgotPassword extends Component {
render() { render() {
const { const {
values, values,
isValid isValid,
country
} = this.props } = this.props
return ( return (
<div className={'forgot-password'}> <div className={'forgot-password'}>
...@@ -50,18 +53,16 @@ class ForgotPassword extends Component { ...@@ -50,18 +53,16 @@ class ForgotPassword extends Component {
<div className="content"> <div className="content">
<Form className='forgot-password-form'> <Form className='forgot-password-form'>
<Field <Field
name={'account'} name={'tel'}
render={({field, form}) => { render={({field, form}) => {
return ( return (
<ClearableInput <ClearableInput
{...field} {...field}
type={'tel'} type={'tel'}
placeholder={'请输入注册时的邮箱账号或手机号'} placeholder={'请输入注册时的手机号'}
wrapperClass={'tel-input'} wrapperClass={'tel-input'}
setFieldValue={form.setFieldValue} setFieldValue={form.setFieldValue}
icon={<i className={'iconfont iconshouji'} country={country}
style={{fontSize: '22px', left: '11px'}}
/>}
/>) />)
}} }}
/> />
...@@ -77,11 +78,12 @@ class ForgotPassword extends Component { ...@@ -77,11 +78,12 @@ class ForgotPassword extends Component {
icon={<i className={'iconfont iconduanxin'} icon={<i className={'iconfont iconduanxin'}
style={{fontSize: '20px', left: '12px'}} style={{fontSize: '20px', left: '12px'}}
/>} />}
account={values.account} tel={values.tel}
challenge={this.state.validate} challenge={this.state.validate}
instance={this.state.captchaInstance} instance={this.state.captchaInstance}
action={'auth'} action={'auth'}
checking={1} checking={1}
country={country}
/> />
) )
}} }}
...@@ -90,6 +92,7 @@ class ForgotPassword extends Component { ...@@ -90,6 +92,7 @@ class ForgotPassword extends Component {
<OnSubmissionError callback={this.onSubmissionError}/> <OnSubmissionError callback={this.onSubmissionError}/>
<Captcha getInstance={this.getCaptchaInstance} onVerify={this.onVerify}/> <Captcha getInstance={this.getCaptchaInstance} onVerify={this.onVerify}/>
<Button className={'next_step'} active={isValid}>下一步</Button> <Button className={'next_step'} active={isValid}>下一步</Button>
<Link className={'to-email'} to={`/passport/forgot-password-email`} replace>邮箱找回</Link>
</Form> </Form>
</div> </div>
</div> </div>
...@@ -101,37 +104,26 @@ class ForgotPassword extends Component { ...@@ -101,37 +104,26 @@ class ForgotPassword extends Component {
const formikConfig = { const formikConfig = {
mapPropsToValues: () => ({ mapPropsToValues: () => ({
account: '', tel: '',
veriCode: '' veriCode: ''
}), }),
validateOnChange: true, validateOnChange: true,
validateOnBlur: true, validateOnBlur: true,
validate: values => { validate: values => {
let errors = {} let errors = {}
if (!validateTel(values.account) && !validateEmail(values.account)) { if (!validateTel(values.tel)) {
errors.account = '请输入正确的手机号或邮箱地址' errors.tel = '请输入正确的手机号'
} }
values.veriCode.toString().length !== 6 && (errors.veriCode = '验证码格式不正确') values.veriCode.toString().length !== 6 && (errors.veriCode = '验证码格式不正确')
return errors return errors
}, },
handleSubmit(values, {props}) { handleSubmit(values, {props}) {
let account, address sessionStorage.setItem('r_type', 'phone')
sessionStorage.setItem('tel', values.tel)
if (validateEmail(values.account)) { http.post(`${API['passport-api']}/check_phone_code`, {
account = 'email' phone: values.tel,
address = 'check_email_code' code: values.veriCode,
sessionStorage.setItem('r_type', 'email') area_code: props.country.num
sessionStorage.setItem('email', values.account)
} else {
account = 'phone'
address = 'check_phone_code'
sessionStorage.setItem('r_type', 'phone')
sessionStorage.setItem('tel', values.account)
}
http.post(`${API['passport-api']}/${address}`, {
[account]: values.account,
code: values.veriCode
}).then(res => { }).then(res => {
if (res.data.errno == 0) { if (res.data.errno == 0) {
props.history.push('/passport/set-password', {from: props.location}) props.history.push('/passport/set-password', {from: props.location})
...@@ -145,7 +137,7 @@ const formikConfig = { ...@@ -145,7 +137,7 @@ const formikConfig = {
export default compose( export default compose(
connect( connect(
null, state => ({country: state.country}),
{quickLogin} {quickLogin}
), ),
withFormik(formikConfig) withFormik(formikConfig)
......
import React, { Component } from 'react'
import './index.scss'
import VeriCodeInput from '../common/veriCodeInput'
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 { validateEmail, http, api } from "@/utils";
import { quickLogin } from '@/store/userAction';
import OnSubmissionError from '../common/OnSubmissionError'
import { Link } from "react-router-dom";
class ForgotPassword extends Component {
state = {
validate: null,
captchaInstance: null
}
getCaptchaInstance = instance => {
this.setState({
captchaInstance: instance
})
}
onVerify = (err, data) => {
if (err) {
console.log(err)
} else {
this.setState({
validate: data.validate
})
}
}
onSubmissionError = () => {
const errors = Object.values(this.props.errors);
errors.length && Toast.info(errors[0], 2, null, false)
}
render() {
const {
values,
isValid
} = this.props
return (
<div className={'forgot-password-email'}>
<HeaderBar title='忘记密码' arrow={true}/>
<div className="content">
<Form className='forgot-password-form'>
<Field
name={'email'}
render={({field, form}) => {
return (
<ClearableInput
{...field}
type={'email'}
placeholder={'请输入注册时的邮箱账号'}
wrapperClass={'email-input'}
setFieldValue={form.setFieldValue}
/>)
}}
/>
{
this.state.validate &&
<Field
name='veriCode'
render={({field}) => {
return (
<VeriCodeInput
{...field}
className={'verify-code'}
icon={<i className={'iconfont iconduanxin'}
style={{fontSize: '20px', left: '12px'}}
/>}
email={values.email}
challenge={this.state.validate}
instance={this.state.captchaInstance}
action={'auth'}
checking={1}
/>
)
}}
/>
}
<OnSubmissionError callback={this.onSubmissionError}/>
<Captcha getInstance={this.getCaptchaInstance} onVerify={this.onVerify}/>
<Button className={'next_step'} active={isValid}>下一步</Button>
<Link className={'to-phone'} to={'/passport/forgot-password'} replace>手机号找回</Link>
</Form>
</div>
</div>
);
}
}
const formikConfig = {
mapPropsToValues: () => ({
email: '',
veriCode: ''
}),
validateOnChange: true,
validateOnBlur: true,
validate: values => {
let errors = {}
if (!validateEmail(values.email)) {
errors.email = '请输入正确的邮箱地址'
}
values.veriCode.toString().length !== 6 && (errors.veriCode = '验证码格式不正确')
return errors
},
handleSubmit(values, {props}) {
sessionStorage.setItem('r_type', 'email')
sessionStorage.setItem('email', values.email)
http.post(`${API['passport-api']}/check_email_code`, {
email: values.email,
code: values.veriCode
}).then(res => {
if (res.data.errno == 0) {
props.history.push('/passport/set-password', {from: props.location})
} else {
Toast.info(res.data.msg, 2, null, false)
}
})
},
}
export default compose(
connect(
null,
{quickLogin}
),
withFormik(formikConfig)
)(ForgotPassword)
\ No newline at end of file
.forgot-password-email {
height: 100%;
.content {
padding: 38px 36px;
text-align: center;
.to-phone{
line-height: 55px;
font-size: 15px;
color: #666;
}
.email-input{
margin-bottom: 21px;
input{
padding-left: 10px;
}
}
}
.place {
width: 100%;
height: 39px;
margin-bottom: 33px;
background: #56abff;
}
.verify-code {
margin-bottom: 21px;
}
.next_step {
margin-top: 32px;
}
}
\ No newline at end of file
...@@ -8,8 +8,10 @@ import AccountLogin from './accountLogin' ...@@ -8,8 +8,10 @@ import AccountLogin from './accountLogin'
import ForgotPassword from './forgotPassword' import ForgotPassword from './forgotPassword'
import SetPassword from './setPassword' import SetPassword from './setPassword'
import BindingTel from './bindingTel' import BindingTel from './bindingTel'
import ForgotPasswordEmail from './forgotPasswordEmail'
import { connect } from "react-redux"; import { connect } from "react-redux";
import { compose } from "redux"; import { compose } from "redux";
import {getParam} from "@/utils";
import account from './icons/account.png' import account from './icons/account.png'
import qq from './icons/qq.png' import qq from './icons/qq.png'
...@@ -96,6 +98,7 @@ class Passport extends Component { ...@@ -96,6 +98,7 @@ class Passport extends Component {
}}/> }}/>
<Route path={match.url + '/account-login'} component={AccountLogin}/> <Route path={match.url + '/account-login'} component={AccountLogin}/>
<Route path={match.url + '/forgot-password'} component={ForgotPassword}/> <Route path={match.url + '/forgot-password'} component={ForgotPassword}/>
<Route path={match.url + '/forgot-password-email'} component={ForgotPasswordEmail}/>
<Route path={match.url + '/set-password'} component={SetPassword}/> <Route path={match.url + '/set-password'} component={SetPassword}/>
<Route path={match.url + '/binding-tel'} component={BindingTel}/> <Route path={match.url + '/binding-tel'} component={BindingTel}/>
</Switch> </Switch>
......
...@@ -85,9 +85,9 @@ class Login extends Component { ...@@ -85,9 +85,9 @@ class Login extends Component {
type={'tel'} type={'tel'}
placeholder={'手机号快捷登录(免注册)'} placeholder={'手机号快捷登录(免注册)'}
wrapperClass={'tel-input'} wrapperClass={'tel-input'}
icon={<i className={'iconfont iconshouji'} /*icon={<i className={'iconfont iconshouji'}
style={{fontSize: '22px', left: '10px'}} style={{fontSize: '22px', left: '10px'}}
/>} />}*/
/> />
)} )}
> >
......
...@@ -8,9 +8,9 @@ ...@@ -8,9 +8,9 @@
padding: 0 38px; padding: 0 38px;
flex: 1 0 auto; flex: 1 0 auto;
.tel-input { /*.tel-input {
margin-bottom: 24px; margin-bottom: 24px;
} }*/
.verification{ .verification{
margin-bottom: 24px; margin-bottom: 24px;
......
...@@ -16,10 +16,6 @@ import { connect } from "react-redux"; ...@@ -16,10 +16,6 @@ import { connect } from "react-redux";
class SetPassword extends Component { class SetPassword extends Component {
componentDidMount() {
// console.log(this.props.location);
}
render() { render() {
let {values, errors, location} = this.props let {values, errors, location} = this.props
......
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