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
2. Image verification code function
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.