Common front-end [mobile phone verification code] [picture verification code] function realization - front-end and back-end cooperation

People always like "sweet" and forget "bitter before sweet"

Generally, users need to verify the user's personal identity information on the registration, login, feedback and other pages of the system, and the [mobile phone verification code] and [picture verification code] functions are required.

Table of contents

1. Mobile phone verification code function 

1. Implementation ideas

2. Backend interface

3. Front-end implementation

2. Image verification code function

1. Implementation ideas

2. Backend interface

3. Front-end implementation


1. Mobile phone verification code function 

1. Implementation ideas

The page needs to implement the function of retrieving the password, click "Get Verification Code", call the interface provided by the backend, submit the request for retrieving the password within 60 seconds, send the data form and verification code to the backend, and check whether the backend is up to date The interface call success information is returned after the verification code.

2. Backend interface

3. Front-end implementation

(1) Page layout

<div className={styles.psw} style={
   
   { height: '540px' }}>
          <div className={styles.pswTitle}>找回密码</div>
          <div className={styles.line1}></div>
          <div className={styles.line2}></div>
          <div>
            <Form layout="inline">
              <div className={styles.inputW}>
                <div>
                  <div className={styles.iconPosition}>
                    <img
                      src={usericon}
                      alt=""
                      style={
   
   { width: '15px', height: '20px' }}
                    />
                    <span className={styles.inputText}>
                      <span style={
   
   { color: 'red' }}>*</span>用户名
                    </span>
                  </div>
                  <FormItem>
                    {getFieldDecorator('userName', {
                      rules: [
                        {
                          required: true,
                          message: '请输入用户名'
                        }
                      ]
                    })(<Input placeholder="请输入用户名" />)}
                  </FormItem>
                </div>
              </div>
              <div className={styles.inputW}>
                <div>
                  <div className={styles.iconPosition}>
                    <img
                      src={phoneIcon}
                      alt=""
                      style={
   
   { width: '15px', height: '20px' }}
                    />
                    <span className={styles.inputText}>
                      <span style={
   
   { color: 'red' }}>*</span>手机号
                    </span>
                  </div>
                  <FormItem>
                    {getFieldDecorator('mobile', {
                      rules: [
                        {
                          required: true,
                          pattern: /^1[34578]\d{9}$/,
                          message: '请输入正确的手机号码'
                        }
                      ]
                    })(<Input placeholder="请输入手机号" />)}
                  </FormItem>
                </div>
              </div>

              <div className={styles.inputW}>
                <div>
                  <div className={styles.iconPosition}>
                    <img
                      src={passwordIcon}
                      alt=""
                      style={
   
   { width: '15px', height: '20px' }}
                    />
                    <span
                      className={styles.inputText}
                      style={
   
   { width: '70px' }}
                    >
                      <span style={
   
   { color: 'red' }}>*</span>设置密码
                    </span>
                  </div>
                  <FormItem>
                    {getFieldDecorator('password', {
                      rules: [
                        {
                          required: true,
                          message: '请输入6-16位字符和数字组合,字符区分大小写',
                          // eslint-disable-next-line
                          pattern: /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,16}$/
                        },
                        { validator: validateToNextPassword }
                      ]
                    })(<Input.Password placeholder="请输入密码" />)}
                  </FormItem>
                </div>
              </div>
              <div className={styles.inputW}>
                <div>
                  <div className={styles.iconPosition}>
                    <img
                      src={passwordIcon}
                      alt=""
                      style={
   
   { width: '15px', height: '20px' }}
                    />
                    <span
                      className={styles.inputText}
                      style={
   
   { width: '70px' }}
                    >
                      <span style={
   
   { color: 'red' }}>*</span>确认密码
                    </span>
                  </div>
                  <FormItem>
                    {getFieldDecorator('comfirm', {
                      rules: [
                        { required: true, message: '请输入确认密码' },
                        { validator: compareToFirstPassword }
                      ]
                    })(
                      <Input.Password
                        onBlur={handleConfirmBlur}
                        placeholder="请再次输入密码"
                      />
                    )}
                  </FormItem>
                </div>
              </div>
              <div className={styles.inputW1} style={
   
   { position: 'relative' }}>
                <div>
                  <div className={styles.iconPosition}>
                    <img
                      src={check}
                      alt=""
                      style={
   
   { width: '15px', height: '20px' }}
                    />
                    <span
                      className={styles.inputText}
                      style={
   
   { width: '70px' }}
                    >
                      <span style={
   
   { color: 'red' }}>*</span>短信验证
                    </span>
                  </div>
                  <YZMButton
                    onClick={onclick}
                    time={time}
                    className={styles.yzmc}
                  />
                  <FormItem>
                    {getFieldDecorator('smsCode', {
                      rules: [
                        {
                          required: true,
                          message: '请输入'
                        }
                      ]
                    })(<Input placeholder="请输入验证码" />)}
                  </FormItem>
                </div>
              </div>

              <div className={styles.button} style={
   
   { margin: '30px 50px' }}>
                <Button
                  onClick={() => {
                    window.history.back()
                  }}
                  className={styles.backButton}
                >
                  返回
                </Button>
                <Button onClick={handlOnsave} className={styles.findButton}>
                  找回密码
                </Button>
              </div>
            </Form>
          </div>
        </div>

(2) Use the verification code component YZMButton

import React, { useCallback, useState, useRef } from 'react'
import styles from './index.less'
import classnames from 'classnames'
import { Button } from 'antd'
interface YZMButtonProps {
  onClick: (e: any) => any
  time: number
  text?: string
  className: any
}

export default function YZMButton({
  onClick,
  time,
  text,
  className
}: YZMButtonProps) {
  const [yzime, setYzime] = useState(time)
  const _yzime = useRef(yzime)
  _yzime.current = yzime
  const flag = yzime === time
  const handleClick = useCallback(
    (e: any) => {
      if (flag) {
        if (!onClick(e)) {
          return
        }
        let timer = setInterval(() => {
          if (_yzime.current === 0) {
            clearInterval(timer)
            setYzime(time)
          } else {
            setYzime(value => value - 1)
          }
        }, 1000)
      }
    },
    [flag, onClick, time]
  )

  return (
    <Button
      className={classnames(styles.content, className)}
      onClick={handleClick}
      disabled={!flag}
    >
      {flag ? text || '获取验证码' : `还剩${yzime}s`}
    </Button>
  )
}

After clicking the button, the button becomes unavailable, and at the same time the 60-second countdown starts.

(3) Call the interface to get the verification code

In the click method, call the method provided by the backend to obtain the SMS verification code

const onclick = useCallback(() => {
    let callbackRes = true
    validateFields(['mobile'], (err: any, fieldsValue: any) => {
      if (err) {
        callbackRes = false
      }
      let { mobile } = fieldsValue
      let res = {
        mobile: mobile,
        type: 'forget-password'
      }
      dispatch({
        type: 'login/getyzm',
        params: [res]
      }).then((v: any) => {
        if (v.code === -1) {
          message.error(v.message)
          callbackRes = false
        } else if (v.code === 500) {
          message.error(v.message)
          callbackRes = false
        } else {
          callbackRes = true
        }
      })
    })
    return callbackRes
  }, [dispatch, validateFields])

 (4) Submit the form to retrieve the password

  const handlOnsave = useCallback(() => {
    validateFields((err: any, fieldsValue: any) => {
      if (err) return
      let res = {
        userName: fieldsValue.userName,
        mobile: fieldsValue.mobile,
        // password: btoa(fieldsValue.password),
        newPassword: fieldsValue.password,
        code: fieldsValue.smsCode
      }
      dispatch({
        type: 'login/getback',
        params: [res]
      }).then((v: any) => {
        if (v.code === 200) {
          message.info(v.message)
          window.location.href = '/#/login/password'
        } else {
          message.info(v.message)
        }
      })
    })
  }, [dispatch, validateFields])

2. Image verification code function

1. Implementation ideas

 Enter the page, the front end sends a request to the back end (requires UUID), obtains a QR code, then submits the uuid and verification code at the same time when submitting the form, and the back end requests verification. The backend uses Ali's service for obtaining SMS verification codes.

2. Backend interface

The backend needs to get the uuid to generate it with the help of Ali's tool for generating image verification codes, and return the image verification codes to the front end. Finally, you need to compare the uuid and verification code information submitted by the front end to realize the submission function.

3. Front-end implementation

(1) Use uuid

UUID is a universally unique identifier.

Installation dependencies: npm install uuid

Import dependencies: import { v4 as uuidv4 } from "uuid

Generate uuid Usage: const id =uuidv4()
console.log(id)
e6a2f201-f720-4e98-8fea-7f473101acd3

(2) Enter the page to get the verification code picture

  const getCode = useCallback(() => {
    let id = uuidv4()
    setUuid(id)
    let result = dispatch({
      type: 'global/get1',
      params: ['/uaa/captcha.jpg', { uuid: id }]
    })
    console.log(result)
    return result
  }, [dispatch, setUuid])

  useEffect(() => {
    getCode().then((v: any) => {
      let a = window.URL.createObjectURL(v)
      setCode(a)
    })
  }, [getCode])

The request to generate an image needs to provide a uuid to the backend.

Note that the request here is /uaa/captcha.jpg You read that right.

(3) Process and display the pictures returned by the backend

After the request, the backend returns a picture. Note that it is a picture, not the url of the picture.

Visible on this page. The request to upload an attachment returns JSON data

But for the request for the image verification code, the image format is returned.

 

 Therefore, the get1 method needs to be used for processing.


Find the commonModal file. You can see that the get and post methods are used in the package.

get: async (
      {
        type,
        params: [url, remoteValue, options = {}]
      }: { type: string; params: [string, object, object | string] },
      { dispatch, getState }
    ) => {
      const { back = false, message: messageFlag = false } = options as any
      const res = await remote(url, remoteValue, 'get')
      const { success, message: _messagae } = res
      if (!success) {
        return
      }
      if (messageFlag) {
        message.success(_messagae || '操作成功!')
      }
      if (back) {
        history.go(-1)
      }
      return res
    },
get1: async (
      {
        type,
        params: [url, remoteValue, options = {}]
      }: { type: string; params: [string, object, object | string] },
      { dispatch, getState }
    ) => {
      const res = await remote(url, remoteValue, 'get1')
      return res
    },

And you need to use let a = window.URL.createObjectURL(v) to create a new URL object, set it, and finally bind it in the src of the image img

 

 At this point, the picture verification code is displayed.

 (4) Submit operation

//提交反馈
  const submit = useCallback(
    (data: any) => {
      validateFields((err: any, fieldsValue: any) => {
        if (err) return
        let data = {
          ...fieldsValue,
          uuid: uuid,
          fileId: file[0] && file[0].id
        }
        debugger
        let result = dispatch({
          type: 'global/post',
          params: ['/api/problemFeedback/create', { data }]
        })
        return result
      }).then((v: any) => {
        if (v.code === 200) {
          //setDetailData(v.data)
          message.success(v.message)
          toggleForm()
        }
      })
    },
    [dispatch, file, toggleForm, uuid, validateFields]
  )

 The submit function is unremarkable. Note that adding the unique uuid just generated can be handed over to the backend for processing.

Guess you like

Origin blog.csdn.net/Sabrina_cc/article/details/121098784