忘记密码

This commit is contained in:
saplf
2019-09-06 16:15:08 +08:00
parent 8d6cd7a46f
commit 61810d9db4
11 changed files with 163 additions and 14 deletions

View File

@@ -41,6 +41,7 @@ export default {
'check.setPwd': '设置登录密码', 'check.setPwd': '设置登录密码',
'check.confirmPwd': '确认登录密码', 'check.confirmPwd': '确认登录密码',
'check.invite': '邀请码', 'check.invite': '邀请码',
'check.resetSuccess': '密码已成功重置,请使用新密码登录。',
'home.tabHome': 'Home', 'home.tabHome': 'Home',
'home.tabEstate': '矿场', 'home.tabEstate': '矿场',

View File

@@ -41,6 +41,7 @@ export default {
'check.setPwd': '设置登录密码', 'check.setPwd': '设置登录密码',
'check.confirmPwd': '确认登录密码', 'check.confirmPwd': '确认登录密码',
'check.invite': '邀请码', 'check.invite': '邀请码',
'check.resetSuccess': '密码已成功重置,请使用新密码登录。',
'home.tabHome': '首页', 'home.tabHome': '首页',
'home.tabEstate': '矿场', 'home.tabEstate': '矿场',

View File

@@ -14,6 +14,7 @@ import styles from './style.less';
import CheckPage from './check'; import CheckPage from './check';
import LoginPage from './login'; import LoginPage from './login';
import RegisterPage from './register'; import RegisterPage from './register';
import ResetPage from './reset';
import { formatMessage } from 'umi-plugin-locale'; import { formatMessage } from 'umi-plugin-locale';
const Page: React.FC<DispatchProp & CheckModelState> = ({ const Page: React.FC<DispatchProp & CheckModelState> = ({
@@ -74,7 +75,7 @@ const Page: React.FC<DispatchProp & CheckModelState> = ({
[PageStep.Check]: <CheckPage />, [PageStep.Check]: <CheckPage />,
[PageStep.Login]: <LoginPage />, [PageStep.Login]: <LoginPage />,
[PageStep.Register]: <RegisterPage />, [PageStep.Register]: <RegisterPage />,
[PageStep.Reset]: null, [PageStep.Reset]: <ResetPage />,
[PageStep.ResetSuccess]: null, [PageStep.ResetSuccess]: null,
}[pageStep]} }[pageStep]}
</div> </div>

View File

@@ -2,7 +2,7 @@ import React from 'react';
import { Button, Input } from 'antd'; import { Button, Input } from 'antd';
import { connect, DispatchProp } from 'dva'; import { connect, DispatchProp } from 'dva';
import { formatMessage } from 'umi-plugin-locale'; import { formatMessage } from 'umi-plugin-locale';
import { CheckModelState } from './model'; import { CheckModelState, PageStep } from './model';
const LoginPage: React.FC<DispatchProp & CheckModelState> = ({ const LoginPage: React.FC<DispatchProp & CheckModelState> = ({
password, password,
@@ -20,6 +20,14 @@ const LoginPage: React.FC<DispatchProp & CheckModelState> = ({
type="password" type="password"
/> />
<div
className="item"
style={{ textAlign: 'right' }}
onClick={() => dispatch({ type: 'check/onUpdateState', pageStep: PageStep.Reset })}
>
{formatMessage({ id: 'check.forget' })}
</div>
<Button <Button
className="item gradient submit" className="item gradient submit"
type="primary" type="primary"

View File

@@ -1,12 +1,13 @@
import { Model } from "dva"; import { Model } from "dva";
import _ from 'lodash'; import _ from 'lodash';
import { message } from 'antd'; import { message, Modal } from 'antd';
import { delay } from 'dva/saga'; import { delay } from 'dva/saga';
import { PageState, AreaCode, AreaCodes } from '@/types/common'; import { PageState, AreaCode, AreaCodes } from '@/types/common';
import { getAreaCodes, getUserInfo } from '@/services/common'; import { getAreaCodes, getUserInfo } from '@/services/common';
import { validPhoneInput, validPwdInput, validPhone, validPwd } from '@/utils/validate'; import { validPhoneInput, validPwdInput, validPhone, validPwd } from '@/utils/validate';
import { checkExistence, CheckResult, signIn, signUp, sendCode } from './service'; import { checkExistence, CheckResult, signIn, signUp, sendCode, reset } from './service';
import { formatMessage } from 'umi-plugin-locale'; import { formatMessage } from 'umi-plugin-locale';
import { dispatch } from '@/utils/utils';
export enum PageStep { export enum PageStep {
Check = 'check', Check = 'check',
@@ -121,7 +122,7 @@ const model: Model = {
try { try {
const token = yield call(signIn, areacode, phone, password); const token = yield call(signIn, areacode, phone, password);
yield put({ type: 'user/updateToken', payload: token }); yield put({ type: 'user/updateToken', payload: token });
yield delay(0); yield delay(10);
const user = yield call(getUserInfo, true); const user = yield call(getUserInfo, true);
yield put({ type: 'user/updateUser', payload: user }); yield put({ type: 'user/updateUser', payload: user });
} catch(e) { } catch(e) {
@@ -145,7 +146,7 @@ const model: Model = {
try { try {
const token = yield call(signUp, areacode, phone, password, verifyCode, inviter); const token = yield call(signUp, areacode, phone, password, verifyCode, inviter);
yield put({ type: 'user/updateToken', payload: token }); yield put({ type: 'user/updateToken', payload: token });
yield delay(0); yield delay(10);
const user = yield call(getUserInfo, true); const user = yield call(getUserInfo, true);
yield put({ type: 'user/updateUser', payload: user }); yield put({ type: 'user/updateUser', payload: user });
} catch(e) { } catch(e) {
@@ -156,14 +157,38 @@ const model: Model = {
} }
}, },
*sendCode(_, { select, put, call }) { *submitReset(_, { put, select, call }) {
const { areacode, phone, password, verifyCode, pwdConfirm } = yield select((state: any) => state.check);
if (!areacode) return message.warn(formatMessage({ id: 'check.msgArea' }));
if (!validPhone(phone)) return message.warn(formatMessage({ id: 'check.msgPhone' }));
if (!verifyCode) return message.warn(formatMessage({ id: 'check.msgCode' }));
if (!validPwd(password)) return message.warn(formatMessage({ id: 'check.msgPwd' }));
if (password !== pwdConfirm) return message.warn(formatMessage({ id: 'check.msgConfirm' }));
yield put({ type: 'onUpdateState', submitting: true });
try {
yield call(reset, areacode, phone, password, verifyCode);
Modal.success({
okText: formatMessage({ id: 'common.iknow' }),
title: formatMessage({ id: 'common.prompt' }),
content: formatMessage({ id: 'check.resetSuccess' }),
onOk: () => dispatch({ type: 'check/back' }),
});
} catch(e) {
message.error(e.message);
} finally {
yield put({ type: 'onUpdateState', submitting: false });
}
},
*sendCode({ payload }, { select, put, call }) {
const { areacode, phone } = yield select((state: any) => state.check); const { areacode, phone } = yield select((state: any) => state.check);
if (!areacode) return message.warn(formatMessage({ id: 'check.msgArea' })); if (!areacode) return message.warn(formatMessage({ id: 'check.msgArea' }));
if (!validPhone(phone)) return message.warn(formatMessage({ id: 'check.msgPhone' })); if (!validPhone(phone)) return message.warn(formatMessage({ id: 'check.msgPhone' }));
yield put({ type: 'onUpdateState', sendingCode: true }); yield put({ type: 'onUpdateState', sendingCode: true });
try { try {
yield call(sendCode, areacode, phone); yield call(sendCode, areacode, phone, payload);
yield put({ type: 'timer', payload: 60 }); yield put({ type: 'timer', payload: 60 });
} catch(e) { } catch(e) {
message.error(e.message); message.error(e.message);

View File

@@ -5,6 +5,7 @@ import { formatMessage } from 'umi-plugin-locale';
import { CheckModelState } from './model'; import { CheckModelState } from './model';
import styles from './style.less'; import styles from './style.less';
import { SendCodeType } from '@/types/common';
const RegisterPage: React.FC<DispatchProp & CheckModelState> = ({ const RegisterPage: React.FC<DispatchProp & CheckModelState> = ({
password, password,
@@ -43,7 +44,7 @@ const RegisterPage: React.FC<DispatchProp & CheckModelState> = ({
size="large" size="large"
loading={sendingCode} loading={sendingCode}
disabled={codeTimer > 0} disabled={codeTimer > 0}
onClick={() => dispatch({ type: 'check/sendCode' })} onClick={() => dispatch({ type: 'check/sendCode', payload: SendCodeType.SignUp })}
>{btnText}</Button> >{btnText}</Button>
</Input.Group> </Input.Group>

82
src/pages/check/reset.tsx Normal file
View File

@@ -0,0 +1,82 @@
import React from 'react';
import { Button, Input } from 'antd';
import { connect, DispatchProp } from 'dva';
import { formatMessage } from 'umi-plugin-locale';
import { CheckModelState } from './model';
import styles from './style.less';
import { SendCodeType } from '@/types/common';
const ResetPage: React.FC<DispatchProp & CheckModelState> = ({
password,
inviter,
pwdConfirm,
verifyCode,
submitting,
dispatch,
codeTimer,
sendingCode,
}) => {
let btnText;
if (codeTimer < 0) {
btnText = formatMessage({ id: 'check.getCode1' });
} else if (codeTimer === 0) {
btnText = formatMessage({ id: 'check.getCode3' });
} else {
btnText = formatMessage({ id: 'check.getCode2' }, { time: codeTimer })
}
return (
<div className={styles.reset}>
<Input.Group
className="item"
compact={true}
size="large"
>
<Input
style={{ width: '40%' }}
placeholder={formatMessage({ id: 'common.codeHolder' })}
value={verifyCode}
onChange={e => dispatch({ type: 'check/onUpdateState', verifyCode: e.target.value })}
/>
<Button
style={{ width: '60%' }}
size="large"
loading={sendingCode}
disabled={codeTimer > 0}
onClick={() => dispatch({ type: 'check/sendCode', payload: SendCodeType.ForgetPwd })}
>{btnText}</Button>
</Input.Group>
<Input
className="item"
placeholder={formatMessage({ id: 'check.setPwd' })}
value={password}
onChange={e => dispatch({ type: 'check/onUpdatePassword', payload: e.target.value })}
size="large"
type="password"
/>
<Input
className="item"
placeholder={formatMessage({ id: 'check.confirmPwd' })}
value={pwdConfirm}
onChange={e => dispatch({ type: 'check/onUpdateState', pwdConfirm: e.target.value })}
size="large"
type="password"
/>
<Button
className="item gradient submit"
type="primary"
loading={submitting}
onClick={() => dispatch({ type: 'check/submitReset' })}
size="large"
>{formatMessage({ id: 'check.reset' })}</Button>
</div>
);
}
export default connect(
({ check } : any) => ({ ...check })
)(ResetPage) as any;

View File

@@ -1,5 +1,5 @@
import http from '@/utils/http'; import http from '@/utils/http';
import { AreaCode } from '@/types/common'; import { AreaCode, SendCodeType } from '@/types/common';
import { encodePhone } from '@/utils/transform'; import { encodePhone } from '@/utils/transform';
export enum CheckResult { export enum CheckResult {
@@ -45,12 +45,26 @@ export async function signUp(areacode: AreaCode, phone: string, password: string
return data.token; return data.token;
} }
export async function sendCode(areacode: AreaCode, phone: string) { export async function reset(areacode: AreaCode, phone: string, password: string, code: string): Promise<void> {
const { ok, msg, data } = await http.post(
'/sign/forget',
{
phone: encodePhone(areacode, phone),
password,
code,
},
);
if (!ok) {
throw Error(msg);
}
}
export async function sendCode(areacode: AreaCode, phone: string, type: SendCodeType) {
const { ok, msg } = await http.post( const { ok, msg } = await http.post(
'/sign/send', '/sign/send',
{ {
phone: encodePhone(areacode, phone), phone: encodePhone(areacode, phone),
type: 'signUp', type,
}, },
); );
if (ok) { if (ok) {

View File

@@ -1,3 +1,4 @@
@import '../../global.less';
.check { .check {
position: relative; position: relative;
@@ -57,7 +58,14 @@
.register { .register {
height: 100%; height: 100%;
padding-top: 160px; padding-top: @header-height;
display: flex;
flex-direction: column;
}
.reset {
height: 100%;
padding-top: @header-height;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }

View File

@@ -14,6 +14,11 @@ export interface User {
inviteCode: string; inviteCode: string;
} }
export enum SendCodeType {
SignUp = 'signUp',
ForgetPwd = 'forgetPasswd',
}
export interface AreaCode { export interface AreaCode {
id: string; id: string;
areacode: string; areacode: string;

View File

@@ -2,7 +2,7 @@ import axios, { AxiosRequestConfig, AxiosResponse, AxiosInstance } from 'axios';
import { formatMessage } from 'umi-plugin-locale'; import { formatMessage } from 'umi-plugin-locale';
import _ from 'lodash'; import _ from 'lodash';
import { globalState } from '@/services/common'; import { globalState } from '@/services/common';
import { isDev } from './utils'; import { isDev, dispatch } from './utils';
export interface AppResp<T = any> { export interface AppResp<T = any> {
ok: boolean, ok: boolean,
@@ -55,6 +55,9 @@ async function filter<T>(
} }
const { status, data } = await (instance[method] as (...args: any[]) => Promise<AxiosResponse<AppResp>>)(...args); const { status, data } = await (instance[method] as (...args: any[]) => Promise<AxiosResponse<AppResp>>)(...args);
replaceId(data); replaceId(data);
if (data && data.code === 401) {
dispatch({ type: 'user/logout' });
}
ret = { ret = {
ok: status >= 200 && status < 300 && data && data.code === 0, ok: status >= 200 && status < 300 && data && data.code === 0,
code: data && data.code, code: data && data.code,