,

React忘记密码功能实现

forgetPwd.jsx user/component/SmcodeLogin.jsx 发送验证码组件 sr…

forgetPwd.jsx

import React, { useState } from 'react';
import SmCodeLogin from './component/SmCodeLogin.jsx'
import { Form, Input, Button, Row, message } from 'antd';
import UpdatePassword from './component/UpdatePassword.jsx';
import './css/login.less';
import $http from 'api';
import { useSelector, history  } from 'umi';

const FormItem = Form.Item;
const ForgetPwd = () => {
    const [form] = Form.useForm();
    const [step, setStep] = useState(1);
    //console.log(form,'form');
    const submitSelect = (data) => {
       step === 1 ? checkCode(data) : updatePassword(data.confirmPassword);
    }

    const checkCode = async (params) => { 
        //console.log("params",params.code);
        const {data,msg} = await $http.checkedCode({smCode:params.code});
        // if(data.code === 0){
        //     setStep(2);
        // }else{
        //     message.error(msg);
        // }
        console.log("checkCode",code,data,msg);
        if(data){
            setStep(2);
        }else{
            message.error(msg);
        }
    }
    const updatePassword = async (newPassword) => { 
        console.log("updatePassword",newPassword);
        const {data,msg} = await $http.resetPassword({newPassword});
        if(data){
            message.success('密码重置成功');
            history.replace('/users/login');
        }else{
            message.error(msg);
        }
    }
    const ComponentSelector = (props) => step === 1 ? <SmCodeLogin {...props} /> : <UpdatePassword {...props} />;

    return (
        <div className="form-wrapper forget-pwd">
            <div className="forget-password-title">
                {step === 1 ? '忘记密码' : '重置密码'}
            </div>
            <Form form={form} onFinish={submitSelect}>
                {ComponentSelector({form, FormItem, Input, Button})}
                <Row>
                    <Button 
                    block={true} 
                    type="primary" 
                    htmlType="submit"
                    >{step===1 ? '下一步':'重置密码'}</Button>
                </Row>
            </Form>
        </div>
    );
};


export default ForgetPwd;

user/component/SmcodeLogin.jsx

发送验证码组件

import React from 'react';
import IconMap from 'components/IconMap.jsx';
import { LoginRule } from 'utils/rules';
import { Space } from 'antd';
const { Compact } = Space;
import { useState, useRef, useEffect, useDispatch } from 'react';
import $http from 'api';
import { message } from 'antd';

const SmCodeLogin = ({form, FormItem, Input, Button}) => {
    //const dispatch = useDispatch();
    const handleSendCode = async () => {
        //console.log('发送验证码');
        setCodeStatus(false);
        const mobile = form.getFieldValue('mobile');
        console.log(mobile,'mobile');
        const res  = await $http.getSmsCode({mobile});
        console.log(res,'res');
        message.success(res.msg);
        setDisabled(true);
        runTime();
    }
    const [disabled, setDisabled] = useState(true);
    const [leftTime, setLeftTime] = useState(60);
    const [codeStatus, setCodeStatus] = useState(true);
      const timerRef = useRef(null);
    const runTime = () => { 
        // 防止重复点击多次开启定时器
        if (timerRef.current) return;
        setCodeStatus(false);
        timerRef.current = setInterval(()=>{
            setLeftTime(prev=>{
                if(prev <= 1){
                    clearInterval(timerRef.current);
                    timerRef.current = null;
                    setCodeStatus(true);
                    setDisabled(false);
                    return 60;
                }   
                return prev-1;
            });
        },1000)
    }

    // 组件卸载强制清定时器
    useEffect(() => {
        return () => {
            if (timerRef.current) clearInterval(timerRef.current);
        };
    }, []);
    const checkMobile = async (e) => {
        console.log(e.target.value,'e.target.value');
        //const status = await form.validateFields(['mobile']);
        //因为返回的promise2种状态采用trycatch处理
        try{
            const data = await form.validateFields(['mobile']);
            console.log(data,'data');
            setDisabled(false);
        }catch(error){
            console.log(error,'error');
            setDisabled(true);
        }
    }
    return (
        <>
            <FormItem
                name="mobile"
                rules={LoginRule.mobileRule}
                hasFeedback={true}
            >
                <Input  onChange={checkMobile} prefix={IconMap.mobile} placeholder="请输入手机号" />
            </FormItem>
            <FormItem
                name="code"
                rules={LoginRule.codeRule}
                hasFeedback={true}
            >
                <Compact>
                    <Input   
                    prefix={IconMap.code} 
                    placeholder="请输入验证码"
                    // addonAfter={<Button onClick={handleSendCode}>发送验证码</Button>} 
                    />
                    <Button 
                        disabled={disabled} 
                        onClick={handleSendCode}
                    >
                        {codeStatus ? '发送验证码' : `${leftTime}秒后重新发送`}
                        
                    </Button>
                </Compact>
            </FormItem>
        </>
    );
}

export default SmCodeLogin;

src\pages\users\component\UpdatePassword.jsx

第二步重置密码组件

import React from 'react';
import IconMap from 'components/IconMap.jsx';
import { LoginRule } from 'utils/rules';
const UpdatePassword = ({form, FormItem, Input}) => {
    return (
        <>
        <FormItem
            name="newPassword"
            rules={LoginRule.passwordRule}
            hasFeedback={true}
        >
            <Input    type="password" prefix={IconMap.lock} placeholder="新密码" />
        </FormItem>
        <FormItem
            name="confirmPassword"
            rules={LoginRule.confirmPasswordRule(form)}
            hasFeedback={true}
        >
            <Input type="password" prefix={IconMap.lock} placeholder="确认新密码" />
        </FormItem>
        </>
    );
}

export default UpdatePassword;

src\servicer\interface\user.js

api接口

import ajax from '../http';

export const userLogin = (params) => ajax.post('/api/login', params);

//手机验证码
export const getSmsCode = (params) => ajax.get('/api/getCode', params);
export const checkedCode = (params) => ajax.get('/api/checkSmCode', params);

export const resetPassword = (params) => ajax.post('/api/resetPassword', params);

规则校验

export const LoginRule = {
  userRule :[
    { required: true, message: '请输入用户名' },
    { max: 16, message: '用户名长度不合法'},
    { min: 4, message: '用户名长度不合法'},
  ],
  passwordRule :[
    { required: true, message: '请输入密码' },
    { max: 32, message: '密码长度不合法'},
    { min: 4, message: '密码长度不合法'},
  ],
  mobileRule :[
    // { required: true, message: '请输入手机号' },
    // { pattern: /^1[3456789]\d{9}$/, message: '手机号格式错误'},
    {
      validator: (rule, value, callback) => {
        const mobileReg = /^1[3|4|5|6|7|8][0-9]\d{8}$/;
        switch (true) {
          case !Boolean(value):
            return Promise.reject('手机号不能为空');
          case !mobileReg.test(value):
            return Promise.reject('手机号格式错误');
          default:
            return Promise.resolve();
        }
      }
    }
  ],
  codeRule :[
    { required: true, message: '请输入验证码' },
    { len: 6, message: '验证码长度错误'},
  ],
  confirmPasswordRule:(form)=>{
    return [
      {
        validator: (rule, value, callback) => {
          switch (true) {
            case !Boolean(value):
              return Promise.reject('请输入确认密码');
            case value !== form.getFieldValue('newPassword'):
                return Promise.reject('两次输入的密码不一致');
            default:
              return Promise.resolve();
          }
        }
      }
    ]
  }
}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

About the Author

每个人都有自己得时区,在自己得时区里,一切都是准时的。

BlockSpare — News, Magazine and Blog Addons for (Gutenberg) Block Editor