ANTD react 手机号(验证码)登陆 + 账号登陆(图形验证码)

article/2025/10/20 13:00:40

                  

这种页面可能是大家常用的,但重写比较费时间,之前没有搜到完整的,在这里自己总结一下,方面复用

代码:

     <LoginFormformRef={formRef}initialValues={{autoLogin: false}}onFinish={async values => {await handleSubmit(values as LoginParams)}}><Tabs activeKey={type} onChange={setType} style={{ color: '#999999', fontSize: '16px' }}><Tabs.TabPane key='account' tab={'账号登陆'} /><Tabs.TabPane key='mobile' tab={'手机登陆'} /></Tabs>

账号登陆:

  {type === 'account' && (<><ProFormTextstyle={{ width: '60%' }}name='account'fieldProps={{size: 'large',prefix: <UserOutlined className={styles.prefixIcon} />}}placeholder={'用户名:admin'}rules={[{required: true,message: '请输入用户名'}]}/><ProFormText.Passwordname='password'fieldProps={{size: 'large',prefix: <LockOutlined className={styles.prefixIcon} />}}placeholder={'输入密码'}rules={[{required: true,message: '请输入密码'}]}/><div style={{ display: 'flex' }} className={styles.inputThree}><ProForm.Itemname='captimg'rules={[{required: true,message: '验证码不能为空!'},{validator(_, value) {if (!value) {return new Promise((resolve, reject) => {reject('')})} else {const status = childRef.current.validate(value)return status? Promise.resolve(): Promise.reject(new Error('验证码不正确'))}}}]}><Inputstyle={{ width: '200px', height: '40px', paddingLeft: '30px' }}width='xs'placeholder={'请输入验证码'}className='site-form-item-icon'/></ProForm.Item><CaptchaInput cRef={childRef} />// 验证码画布组件,注意不能写到ProForm组件内,会有影响<IconFont type='icon-yanzhengma' className={styles.verify} /></div></>)}

验证码画布组件:

import * as React from 'react'const size = 4
const verifycode = {width: '32%',height: '40px',marginLeft: '5%',display: 'inline-block',top: '0',right: '0'
}export default ({ cRef }) => {const [options, setOptions] = React.useState({id: 'verifycode', // 容器IdcanvasId: 'verifyCanvas', // canvas的IDwidth: 150, // 默认canvas宽度height: 47, // 默认canvas高度type: 'blend', // 图形验证码默认类型blend:数字字母混合类型、number:纯数字、letter:纯字母code: '',numArr: '0,1,2,3,4,5,6,7,8,9'.split(','),letterArr: getAllLetter() })React.useImperativeHandle(cRef, () => ({validate: (value: any) => {const vcode = value?.toLowerCase()const v_code = options.code?.toLowerCase()if (vcode === v_code) {return true} else {return false}}}))React.useEffect(() => {_init()refresh()})function _init() {const con = document.getElementById(options.id)const canvas: any = document.createElement('canvas')options.width = con.offsetWidth > 0 ? con.offsetWidth : 150options.height = con.offsetHeight > 0 ? con.offsetHeight : 47canvas.id = options.canvasIdcanvas.width = options.widthcanvas.height = options.heightcanvas.style.cursor = 'pointer'canvas.innerHTML = '您的浏览器版本不支持canvas'con.appendChild(canvas)canvas.onclick = function() {refresh()}}function refresh() {options.code = ''const canvas: any = document.getElementById(options.canvasId)let ctx = nullif (canvas.getContext) {ctx = canvas.getContext('2d')} else {return}ctx.clearRect(0, 0, options.width, options.height)ctx.textBaseline = 'middle'ctx.fillStyle = randomColor(180, 240)ctx.fillStyle = 'rgba(206, 244, 196)'// 背景色ctx.fillRect(0, 0, options.width, options.height)if (options.type == 'blend') { // 判断验证码类型var txtArr = options.numArr.concat(options.letterArr)} else if (options.type == 'number') {var txtArr = options.numArr} else {var txtArr = options.letterArr}for (let i = 1; i <= size; i++) {const txt = txtArr[randomNum(0, txtArr.length)]options.code += txtctx.font = randomNum(options.height / 2, options.height) + 'px SimHei' // 随机生成字体大小ctx.fillStyle = randomColor(50, 160) // 随机生成字体颜色// ctx.fillStyle = "rgb(46, 137, 255)";//固定字体颜色ctx.shadowOffsetX = randomNum(-3, 3)ctx.shadowOffsetY = randomNum(-3, 3)ctx.shadowBlur = randomNum(-3, 3)ctx.shadowColor = 'rgba(0, 0, 0, 0.3)'const x = options.width / (size + 1) * iconst y = options.height / 2const deg = randomNum(-30, 30)/** 设置旋转角度和坐标原点**/ctx.translate(x, y)ctx.rotate(deg * Math.PI / 180)ctx.fillText(txt, 0, 0)/** 恢复旋转角度和坐标原点**/ctx.rotate(-deg * Math.PI / 180)ctx.translate(-x, -y)}/** 绘制干扰线**/for (let i = 0; i < 4; i++) {ctx.strokeStyle = randomColor(40, 180)ctx.beginPath()ctx.moveTo(randomNum(0, options.width), randomNum(0, options.height))ctx.lineTo(randomNum(0, options.width), randomNum(0, options.height))ctx.stroke()}// 绘制干扰点// for (let i = 0; i < 100; i++) {//   ctx.fillStyle = randomColor(0, 255)//   ctx.beginPath()//   ctx.arc(randomNum(0, options.width), randomNum(0, options.height), 1, 0, 2 * Math.PI)//   ctx.fill()// }}/** 生成字母数组**/function getAllLetter() {const letterStr = 'a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z'return letterStr.split(',')}/** 生成一个随机数**/function randomNum(min: number, max: number) {return Math.floor(Math.random() * (max - min) + min)}/** 生成一个随机色**/function randomColor(min: number, max: number) {const r = randomNum(min, max)const g = randomNum(min, max)const b = randomNum(min, max)return 'rgb(' + r + ',' + g + ',' + b + ')'}return (<div id='verifycode' style={verifycode} />)
}

手机号登陆

方法:const sendFn = () => {(formRef.current as any).validateFields(['mobile']).then((value) => {pchildref.current._childFn()loginCodeRun.run({mobile: value.mobile,event: 'admin:login_by_mobile'})}).catch(() => {return})}渲染:   {type === 'mobile' && (<><ProFormTextfieldProps={{size: 'large',prefix: <MobileOutlined className={styles.prefixIcon} />}}name='mobile'placeholder={'请输入手机号'}rules={[{required: true,message: '请输入手机号'},{pattern: /^1\d{10}$/,message: '手机号格式错误'}]}/><div style={{ display: 'flex' }} className={styles.inputThree}><ProForm.Itemname='captcha'rules={[{required: true,message: '请输入验证码'}]}><Inputstyle={{ width: '200px', height: '40px', paddingLeft: '30px' }}width='xs'placeholder={'请输入验证码'}className='site-form-item-icon'/></ProForm.Item><div onClick={sendFn}><CountDown ref={pchildref} codeStyle={codeStyle} />  // 倒计时计数器组件</div><IconFont type='icon-yanzhengma' className={styles.verify} /></div><ProForm.Item /></>)}

倒计时计数器组件


import React, { useState, useEffect, useRef, forwardRef, useImperativeHandle } from 'react'
import { Button } from 'antd'type selfProps = {codeStyle: object;
};const CountDown: React.FC<selfProps> = (props, ref) => {const intervalRef = useRef<any>(null)const [count, changeCount] = useState(0)const { codeStyle } = props // 样式// 组件卸载时清除计时器useEffect(() => {return () => {clearInterval(intervalRef.current)}}, [])useEffect(() => {if (count === 59) {intervalRef.current = setInterval(() => {changeCount((preCount) => preCount - 1)}, 1000)} else if (count === 0) {clearInterval(intervalRef.current)}}, [count])// 暴露的子组件方法,给父组件调用useImperativeHandle(ref, () => {return {_childFn() {changeCount(59)}}})return (<Button disabled={!!count} style={ codeStyle }>{count ? `${count} s后重新发送` : '发送验证码'}</Button>)
}export default forwardRef(CountDown)


http://chatgpt.dhexx.cn/article/LaL6aQaM.shtml

相关文章

Springboot+axios+vue使用VerifyCodeUtils工具类实现验证码图片功能

一、环境准备 ideajava 1.8maven 3.6.3操作系统&#xff1a;window10vue.min.jsaxios.min.js 二、VerifyCodeUtils工具类 import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import ja…

Identity and Authentication - Common Authentication Methods

Username and Passwords This is the most common method of identifying users in the age of Software as a Service (SaaS) 解释上面的图中的步骤&#xff1a; Login Request: POST /login postuser {username: users,password: pws }Find users: SELECT * FROM databa…

iOS code signing identity 配置

PROJECT 和 TARGET 中都要选:code signing identity: 调试统一都选 developer, 发布统一都选 distribution provisioning Profile 也要选. 过期和无效的证书及时删除, 避免 ambiguous 警告. 选择正确的证书配置后仍然报错, clean 一下重启 xcode 还不行~~~重启电脑

Invalid CAPTCHA response. Please try again. (Code: 1201)

项目场景&#xff1a; Invalid CAPTCHA response. Please try again. (Code: 1201) 解决方案&#xff1a; 直接使用隐私浏览器打开即可。

经典的Embedding方法Word2vec

提起Embedding,就不得不提Word2vec,它不仅让词向量在自然语言处理领域再度流行&#xff0c;更为关键的是&#xff0c;自2013年谷歌提出Word2vec以来&#xff0c;Embedding 技术从自然语言处理领域推广到广告、搜索、图像、推荐等深度学习应用领域&#xff0c; 成了深度学习知识…

embedding表示方法及原理

目录 1.前言2.embedding表示方法2.1 word2vec embedding2.2 neural network embedding2.3 graph embedding 3.参考文献 1.前言 近几年embedding的使用及优化在各种比赛、论文中都有很多的应用&#xff0c;使用embedding表示特征的空间表示也在各种应用中确定是一种很有效的特征…

深度学习:词嵌入Embedding

http://blog.csdn.net/pipisorry/article/details/76095118 词嵌入 词嵌入其实就是将数据的原始表示表示成模型可处理的或者是更dense的低维表示&#xff08;lz&#xff09;。 One-hot Embedding 假设一共有个物体&#xff0c;每个物体有自己唯一的id&#xff0c;那么从物体…

什么是embedding(把物体编码为一个低维稠密向量),pytorch中nn.Embedding原理及使用

文章目录 使embedding空前流行的word2vec句子的表达训练样本损失函数输入向量表达和输出向量表达 v w v_{w} vw​ 从word2vec到item2vec讨论环节pytorch中nn.Embedding原理及使用pytorch中nn.Embedding原理及使用一些注意的点 参考 简单来说&#xff0c;embedding就是用一个低维…

讲清楚embedding到底在干什么

要搞清楚embeding先要弄明白他和one hot encoding的区别&#xff0c;以及他解决了什么one hot encoding不能解决的问题&#xff0c;带着这两个问题去思考&#xff0c;在看一个简单的计算例子 以下引用 YJango的Word Embedding–介绍 https://zhuanlan.zhihu.com/p/27830489 On…

一文读懂Embedding

文章目录 一、**什么是Embedding&#xff1f;**二、One-Hot编码三、**怎么理解Embedding****四、Word Embedding** 一、什么是Embedding&#xff1f; “Embedding”直译是嵌入式、嵌入层。 简单来说&#xff0c;我们常见的地图就是对于现实地理的Embedding&#xff0c;现实的…

Embedding的理解

Embedding 嵌入&#xff0c;我们可以将其理解为一种降维行为。可以将高维数据映射到低维空间来解决稀疏输入数据的问题。 它主要有以下三个目的&#xff1a; 在 embedding 空间中查找最近邻&#xff0c;这可以很好的用于根据用户的兴趣来进行推荐。作为监督性学习任务的输…

BERT的三个Embedding详解

BERT将输入文本中的每一个词&#xff08;token)送入token embedding层从而将每一个词转换成向量形式 两个嵌入层&#xff0c;segment embeddings和 position embeddings token embedding token embedding 层是要将各个词转换成固定维度的向量。在BERT中&#xff0c;每个词会被…

Embedding层的理解

Embedding层的理解 转载自&#xff1a;原文&#xff1a;深入理解 Embedding层的本质_罗小丰同学的博客-CSDN博客_embedding层 首先&#xff0c;我们有一个one-hot编码的概念。 假设&#xff0c;我们中文&#xff0c;一共只有10个字。。。只是假设啊&#xff0c;那么我们用0-…

Embedding理解与代码实现

Embedding 字面理解是 “嵌入”&#xff0c;实质是一种映射&#xff0c;从语义空间到向量空间的映射&#xff0c;同时尽可能在向量空间保持原样本在语义空间的关系&#xff0c;如语义接近的两个词汇在向量空间中的位置也比较接近。 下面以一个基于Keras的简单的文本情感分类问…

深度学习中Embedding层有什么用?

2019年03月24日15:23:32更新&#xff1a; 由于CSDN图片经常显示不出来&#xff0c;本文最新链接请点击&#xff1a;https://fuhailin.github.io/Embedding/ 博主所有博客写作平台已迁移至&#xff1a;https://fuhailin.github.io/ &#xff0c;欢迎收藏关注。 这篇博客翻译自国…

pytorch nn.Embedding的用法和理解

&#xff08;2021.05.26补充&#xff09;nn.Embedding.from_pretrained()的使用&#xff1a; >>> # FloatTensor containing pretrained weights >>> weight torch.FloatTensor([[1, 2.3, 3], [4, 5.1, 6.3]]) >>> embedding nn.Embedding.from…

EMBEDDING层作用

embedding层作用&#xff1a;①降维②对低维的数据进行升维时&#xff0c;可能把一些其他特征给放大了&#xff0c;或者把笼统的特征给分开了。 Embedding其实就是一个映射&#xff0c;从原先所属的空间映射到新的多维空间中&#xff0c;也就是把原先所在空间嵌入到一个新的空…

彻底理解embedding

本文转载自https://blog.csdn.net/weixin_42078618/article/details/84553940&#xff0c;版权问题请联系博主删除 首先&#xff0c;我们有一个one-hot编码的概念。 假设&#xff0c;我们中文&#xff0c;一共只有10个字。。。只是假设啊&#xff0c;那么我们用0-9就可以表示…

深度学习中的embedding

整理翻译自google developer的机器学习入门课程&#xff0c;介绍了embedding的应用方式和如何计算embedding&#xff0c;后面还配有通过tensorflow DNN训练embedding练习加深理解。 分类输入数据(Categorical Input Data) 分类数据是指表示来自有限选择集的一个或多个离散项的…

【文本分类】深入理解embedding层的模型、结构与文本表示

[1] 名词理解 embedding层&#xff1a;嵌入层&#xff0c;神经网络结构中的一层&#xff0c;由embedding_size个神经元组成&#xff0c;[可调整的模型参数]。是input输入层的输出。 词嵌入&#xff1a;也就是word embedding…根据维基百科&#xff0c;被定义为自然语言处理NLP中…