import { Model } from "dva"; import _ from 'lodash'; import { message } from 'antd'; import { delay } from 'dva/saga'; import { PageState, AreaCode, AreaCodes } from '@/types/common'; import { getAreaCodes, getUserInfo } from '@/services/common'; import { validPhoneInput, validPwdInput, validPhone, validPwd } from '@/utils/validate'; import { checkExistence, CheckResult, signIn, signUp, sendCode } from './service'; import { formatMessage } from 'umi-plugin-locale'; export enum PageStep { Check = 'check', Login = 'login', Register = 'register', Reset = 'reset', ResetSuccess = 'resetSuccess', } export interface CheckModelState { pageState: PageState, pageStep: PageStep, areacodes: AreaCodes, areacode: AreaCode | undefined, // 选中的地区 phone: string; password: string; pwdConfirm: string; inviter: string; verifyCode: string; submitting: boolean; sendingCode: boolean; codeTimer: number; } const model: Model = { namespace: 'check', state: { pageState: PageState.Pending, pageStep: PageStep.Check, areacodes: [], areacode: undefined, phone: '', password: '', pwdConfirm: '', inviter: '', verifyCode: '', submitting: false, sendingCode: false, codeTimer: -1, } as CheckModelState, effects: { *back(_, { select, put }) { const { pageStep: prev } = yield select((state: any) => state.check); let pageStep = PageStep.Check; switch (prev) { case PageStep.Login: case PageStep.Register: case PageStep.ResetSuccess: pageStep = PageStep.Check; break; case PageStep.Reset: pageStep = PageStep.Login; break; } yield put({ type: 'onUpdateState', pageStep }); }, *load(_, { call, put, all }) { yield put({ type: 'onUpdatePageState', payload: PageState.Pending }); try { const areacodes = yield call(getAreaCodes); yield all([ put({ type: 'onUpdatePageState', payload: PageState.Success }), put({ type: 'onUpdateAreaCodes', payload: areacodes }), ]); } catch(e) { yield put({ type: 'onUpdatePageState', payload: PageState.Failure }); } }, *timer({ payload }: any, { put }) { yield put({ type: 'onUpdateState', codeTimer: payload }); yield delay(1000); const next = payload - 1; if (next >= 0) { yield put({ type: 'timer', payload: next }); } }, *submitCheck(_, { put, call, select }) { const { areacode, phone } = 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' })); yield put({ type: 'onUpdateState', submitting: true }); try { const checkResult: CheckResult = yield call(checkExistence, areacode, phone); yield put({ type: 'onUpdateState', pageStep: { [CheckResult.Login]: PageStep.Login, [CheckResult.Register]: PageStep.Register, }[checkResult], }); } catch(e) { message.error(e.message); } finally { yield put({ type: 'onUpdateState', submitting: false }); } }, *submitLogin(_, { put, call, select }) { const { areacode, phone, password } = 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 (!validPwd(password)) return message.warn(formatMessage({ id: 'check.msgPwd' })); yield put({ type: 'onUpdateState', submitting: true }); try { const token = yield call(signIn, areacode, phone, password); yield put({ type: 'user/updateToken', payload: token }); yield delay(0); const user = yield call(getUserInfo, true); yield put({ type: 'user/updateUser', payload: user }); } catch(e) { message.error(e.message); yield put({ type: 'user/logout' }); } finally { yield put({ type: 'onUpdateState', submitting: false }); } }, *submitRegister(_, { put, select, call }) { const { areacode, phone, password, verifyCode, inviter, 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' })); // if (!inviter) return message.warn(formatMessage({ id: 'check.msgInviter' })); yield put({ type: 'onUpdateState', submitting: true }); try { const token = yield call(signUp, areacode, phone, password, verifyCode, inviter); yield put({ type: 'user/updateToken', payload: token }); yield delay(0); const user = yield call(getUserInfo, true); yield put({ type: 'user/updateUser', payload: user }); } catch(e) { message.error(e.message); yield put({ type: 'user/logout' }); } finally { yield put({ type: 'onUpdateState', submitting: false }); } }, *sendCode(_, { select, put, call }) { const { areacode, phone } = 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' })); yield put({ type: 'onUpdateState', sendingCode: true }); try { yield call(sendCode, areacode, phone); yield put({ type: 'timer', payload: 60 }); } catch(e) { message.error(e.message); } finally { yield put({ type: 'onUpdateState', sendingCode: false }); } }, }, reducers: { onUpdatePageState(state, { payload: pageState } : any) { return { ...state, pageState, }; }, onUpdateAreaCodes(state, { payload: areacodes } : any) { return { ...state, areacodes, areacode: areacodes[0], }; }, onUpdatePhone(state, { payload } : any) { const phone = validPhoneInput(payload) ? payload : state.phone; return { ...state, phone, }; }, onUpdatePassword(state, { payload } : any) { const password = validPwdInput(payload) ? payload : state.password; return { ...state, password, }; }, onUpdateState(state, newState) { return { ...state, ...newState, }; }, }, }; export default model;