Vue 邮箱登录界面

功能

模拟了纯前端的邮箱登录逻辑
还没有连接后端的发送邮件的服务
后续计划,再做一个邮箱、密码登录的界面
然后把这两个一块连接上后端

技术介绍

主要介绍绘制图形人机验证乃个
使用的是canvas,在源码里就有

界面控制主要就是用 表格、表单(其实表单都没怎么用到)、v-if、文本输入框和按钮。

效果图

在这里插入图片描述

在这里插入图片描述

代码

Auth.vue

<template><div><form @submit.prevent="handleSubmit"><table><!-- 邮箱输入框 --><tr v-show="!showEmailVerification"><td><label for="email">邮箱</label></td><td colspan="2"><input type="email" id="email" v-model="formData.email" placeholder="请输入邮箱" required></td></tr><!-- 人机校验 --><tr v-show="!showEmailVerification"><td><button type="button" @click="refreshCaptcha"><canvas ref="myCanvas" width="90" height="25"></canvas></button></td><td><input type="text" id="captcha" v-model="userInputCaptchaText" placeholder="请输入验证码" required></td></tr><tr v-show="!showEmailVerification"><td></td><td><button type="button" @click="sendEmail">人机验证</button></td></tr><!-- 邮箱认证 --><tr v-show="showEmailVerification"><td><label for="emailVerificationCode">验证码</label></td><td colspan="2"><input type="text" id="emailVerificationCode" v-model="formData.emailVerificationCode" placeholder="请输入邮箱验证码" required></td></tr><tr v-show="showEmailVerification"><td></td><td colspan="2"><button type="button" @click="verifyEmailVerificationCode">提交验证码</button></td></tr><!-- 消息通知栏 --><tr><td colspan="2">{{ message }}</td></tr></table></form></div>
</template><script setup>
import { onMounted } from 'vue';
import useFormValidation from './formValidation';const {formData,userInputCaptchaText,showEmailVerification,message,refreshCaptcha,sendEmail,verifyEmailVerificationCode,
} = useFormValidation();// Initialize captcha on component mount
onMounted(refreshCaptcha);function handleSubmit() {// 可以在这里添加表单提交逻辑
}
</script><style scoped>
table, th, td {border: 1px solid black;border-collapse: collapse;
}
</style>

captcha.js

export function drawCaptcha(ctx, width, height) {// 填充背景色ctx.fillStyle = '#f2f2f2';ctx.fillRect(0, 0, width, height);// 设置字符集const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789';const charCount = 4; // 验证码字符数let captchaText = '';// 随机生成验证码文本for (let i = 0; i < charCount; i++) {captchaText += chars.charAt(Math.floor(Math.random() * chars.length));}// 设置字体样式ctx.font = '24px Arial';ctx.fillStyle = '#333';ctx.textBaseline = 'middle';// 绘制字符for (let i = 0; i < captchaText.length; i++) {const x =  i * 24;const y = height / 2;const angle = (Math.random() - 0.5) * 0.6; // 随机旋转角度ctx.save();ctx.translate(x, y);ctx.rotate(angle);ctx.fillText(captchaText.charAt(i), 0, 0);ctx.restore();}// 添加干扰线条for (let i = 0; i < 10; i++) {ctx.strokeStyle = getRandomColor();ctx.beginPath();ctx.moveTo(Math.random() * width, Math.random() * height);ctx.lineTo(Math.random() * width, Math.random() * height);ctx.stroke();}// 添加噪点for (let i = 0; i < 50; i++) {ctx.fillStyle = getRandomColor();ctx.beginPath();ctx.arc(Math.random() * width, Math.random() * height, 1, 0, Math.PI * 2);ctx.fill();}return captchaText;
}function getRandomColor() {const r = Math.floor(Math.random() * 256);const g = Math.floor(Math.random() * 256);const b = Math.floor(Math.random() * 256);return `rgb(${r},${g},${b})`;
}

formValidation.js

import { ref } from 'vue';
import { drawCaptcha } from './captcha';
import axios from 'axios';export default function useFormValidation() {const formData = ref({email: '',emailVerificationCode: ''});const userInputCaptchaText = ref('');let captchaText = '';const isValid = ref(false);const showEmailVerification = ref(false);const loginSuccess = ref(false);const message = ref('');function refreshCaptcha() {const canvas = document.querySelector('canvas');const ctx = canvas.getContext('2d');captchaText = drawCaptcha(ctx, canvas.width, canvas.height);}function sendEmail() {if (!isValidEmail(formData.value.email)) {message.value = '请输入有效的邮箱地址';return;}if (isValidCaptcha(userInputCaptchaText.value, captchaText)) {isValid.value = true;showEmailVerification.value = true;message.value = '请查收邮箱验证码';// 发送邮件验证码的逻辑可以放在这里sendVerificationCode(formData.value.email);} else {message.value = '验证码错误,请重新输入';refreshCaptcha();userInputCaptchaText.value = '';isValid.value = false;showEmailVerification.value = false;}}const sendVerificationCode = async (email) => {try {const response = await axios.post('http://localhost:8080/api/register', { email }, {headers: {'Content-Type': 'application/json'}});console.log('Verification code sent successfully:', response.data);} catch (error) {console.error('Error sending verification code:', error);}};// 校验邮箱验证码function verifyEmailVerificationCode() {if (isValidEmailVerificationCode(formData.value.emailVerificationCode)) {loginSuccess.value = true;message.value = '邮箱验证码校验通过,登录成功!';} else {message.value = '邮箱验证码错误,请重新输入';}}const isValidEmailVerificationCode = async (code) => {console.log(code);try {const response = await axios.post('http://localhost:8080/api/checkEmail', { code }, {headers: {'Content-Type': 'application/json'}});console.log('Verification code check result:', response.data);return response.data;} catch (error) {console.error('Error checking verification code:', error);message.value = '校验邮箱验证码时发生错误';return false;}}return {formData,userInputCaptchaText,isValid,showEmailVerification,loginSuccess,message,refreshCaptcha,sendEmail,verifyEmailVerificationCode};
}function isValidEmail(email) {const emailRegex = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;return emailRegex.test(email);
}function isValidCaptcha(inputCaptcha, generatedCaptcha) {return inputCaptcha.toLowerCase() === generatedCaptcha.toLowerCase();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/371441.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SLF4J的介绍与使用(有logback和log4j2的具体实现案例)

目录 1.日志门面的介绍 常见的日志门面 &#xff1a; 常见的日志实现&#xff1a; 日志门面和日志实现的关系&#xff1a; 2.SLF4J 的介绍 业务场景&#xff08;问题&#xff09;&#xff1a; SLF4J的作用 SLF4J 的基本介绍 日志框架的绑定&#xff08;重点&#xff09…

GIT - 一条命令把项目更新到远程仓库

前言 阅读本文大概需要1分钟 说明 更新项目到远程仓库只需要执行一条命令&#xff0c;相当的简便 步骤 第一步 编辑配置文件 vim ~/.bash_profile第二步 写入配置文件 gsh() {local msg"${1:-ADD COMMIT PUSH}"git add . && git commit -m "$m…

elementUI 年份范围选择器实现

elementUI 不支持年份范围的选择器&#xff0c;依照下面的文章进行修改和完善 el-year-picker&#xff1b; element日期选择范围、选择年份范围_elemet 两个日期 选择的年份范围必须在三年之内-CSDN博客 el-year-picker 组件&#xff1a; 依赖包&#xff1a;moment 属性&…

Win11 Python3.10 安装pytorch3d

0&#xff0c;背景 Python3.10、cuda 11.7、pytorch 2.0.1 阅读【深度学习】【三维重建】windows10环境配置PyTorch3d详细教程-CSDN博客 1&#xff0c;解决方法 本来想尝试&#xff0c;结果发现CUB安装配置对照表里没有cuda 11.7对应的版本&#xff0c;不敢轻举妄动&#x…

Web前端开发——HTML快速入门

HTML&#xff1a;控制网页的结构CSS&#xff1a;控制网页的表现 一、什么是HTML、CSS &#xff08;1&#xff09;HTML &#xff08;HyperText Markup Languaqe&#xff1a;超文本标记语言&#xff09; 超文本&#xff1a;超越了文本的限制&#xff0c;比普通文本更强大。除了…

Android 如何通过代码实时设置EditTextView光标

背景&#xff1a;换肤框架下&#xff0c;QA进行深色浅色切换说输入框光标颜色没有改变&#xff0c;转UI结果UI说需要修改&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 本来有方法可以设置&#xff0c;但是 设置后未生效。重新进入该页面才生效&#xff01;&a…

AcWing 1260:二叉树输出

【题目来源】https://www.acwing.com/problem/content/1262/【题目描述】 树的凹入表示法主要用于树的屏幕或打印输出&#xff0c;其表示的基本思想是兄弟间等长&#xff0c;一个结点的长度要不小于其子结点的长度。 二叉树也可以这样表示&#xff0c;假设叶结点的长度为 1&…

人工智能、机器学习、神经网络、深度学习和卷积神经网络的概念和关系

人工智能&#xff08;Artificial Intelligence&#xff0c;缩写为AI&#xff09;--又称为机器智能&#xff0c;是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。 人工智能是智能学科重要的组成部分&#xff0c;它企图了解智能的实质…

[数据结构] --- 线性数据结构(数组/链表/栈/队列)

1 线性结构和非线性结构的理解 1.1 线性结构 线性结构是什么&#xff1f; 数据结构中线性结构指的是数据元素之间存在着“一对一”的线性关系的数据结构。线性结构是一个有序数据元素的集合。 线性结构特点&#xff1a; 线性结构有唯一的首元素&#xff08;第一个元素&#…

服务器本地部署文件服务器minio

minio类似于阿里云的OSS&#xff0c;为不方便把图、文、日志等形式的文件保存在公有云上的&#xff0c;可以在自己的服务器上部署文件服务器 看过本人前几个文章的&#xff0c;使用docker就会很快上手部署&#xff0c;直接上所有代码 #添加镜像 docker search minio docker p…

Okhttp hostnameVerifier详解

hostnameVerifier 方法简介核心原理参考资料 方法简介 本篇博文以Okhttp 4.6.0来解析hostnameVerfier的作用&#xff0c;顾名思义&#xff0c;该方法的主要作用就是鉴定hostnname的合法性。Okhttp在初始化的时候我们可以自己配置hostnameVerfier&#xff1a; new OkHttpClien…

【做一道算一道】和为 K 的子数组

给你一个整数数组 nums 和一个整数 k &#xff0c;请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 示例 1&#xff1a; 输入&#xff1a;nums [1,1,1], k 2 输出&#xff1a;2 示例 2&#xff1a; 输入&#xff1a;nums [1,2,3],…

(详细版)学生管理系统(姓名、成绩、学号)---顺序表

//1:创建顺序表 //2:判满 //3:判空 //4:插入学生信息 //5:输出学生信息 //6:按位置插入学生信息 //7:按位置删除学生信息 //8:按位置修改学生信息 //9:按学号查找学生信息 //10:顺序表去重 //11:销毁顺序表 main.c&#xff1a; int main(int argc, const char *argv[]) {seq_p…

Maven一键配置阿里云远程仓库,让你的项目依赖飞起来!

文章目录 引言一、为什么选择阿里云Maven仓库&#xff1f;二、如何设置Maven阿里云远程仓库&#xff1f;三、使用阿里云Maven仓库的注意事项总结 引言 在软件开发的世界里&#xff0c;Maven无疑是一个强大的项目管理工具&#xff0c;它能够帮助我们自动化构建、依赖管理和项目…

Flutter集成高德导航SDK(Android篇)(JAVA语法)

先上flutter doctor&#xff1a; flutter sdk版本为&#xff1a;3.19.4 引入依赖&#xff1a; 在app的build.gradle下&#xff0c;添加如下依赖&#xff1a; implementation com.amap.api:navi-3dmap:10.0.700_3dmap10.0.700navi-3dmap里面包含了定位功能&#xff0c;地图功能…

计数排序的实现

原理 对一个数组进行遍历&#xff0c;再创建一个count数组 每找到一个值则在count数组中对应的位置加一&#xff0c;再在count数组中找到数字上方的count值&#xff0c;count值为几&#xff0c;则打印几次数组中的值. 开空间 相对映射 排序的实现 void CountSort(int* a, i…

鸿蒙开发:Universal Keystore Kit(密钥管理服务)【明文导入密钥(C/C++)】

明文导入密钥(C/C) 以明文导入ECC密钥为例。具体的场景介绍及支持的算法规格 在CMake脚本中链接相关动态库 target_link_libraries(entry PUBLIC libhuks_ndk.z.so)开发步骤 指定密钥别名keyAlias。 密钥别名的最大长度为64字节。 封装密钥属性集和密钥材料。通过[OH_Huks_I…

读人工智能全传05专家系统

1. 知识就是力量 1.1. 人工智能领域此前存在的问题是过度关注搜索和解决问题这种通用法则 1.2. “弱”方法缺少一个关键的要素&#xff0c;而这一要素才是在所有智能行为中起决定性作用的组成部分&#xff1a;知识 1.3. 一种基于知识的人工智能系统&#xff1a;专家系统开始…

weblogic加入第三方数据库代理驱动jar包(Oracle为例)

做的是国企项目&#xff0c;项目本身业务并不复杂&#xff0c;最复杂的却是服务器部署问题&#xff0c;对方给提供的服务器分内网、外网交换网&#xff0c;应用在交换网&#xff0c;数据库在内网&#xff0c;应用不能直接访问内网数据库&#xff0c;只能通过安全隔离网闸访问内…