前端自定义验证码,校验验证码,验证码时效

最近做的项目,不需要后端接口,只需要前端验证,如图

初始页面

获取验证码

验证码的文件,直接复制就行

<template>
    <div class="s-canvas">
      <canvas
        id="s-canvas"
        :width="contentWidth"
        :height="contentHeight"
      ></canvas>
    </div>
  </template>
  <script>
  export default {
    name: "SIdentify",
    props: {
      identifyCode: {
        // 默认注册码
        type: String,
        default: "1234",
      },
      fontSizeMin: {
        // 字体最小值
        type: Number,
        default: 25,
      },
      fontSizeMax: {
        // 字体最大值
        type: Number,
        default: 35,
      },
      backgroundColorMin: {
        // 验证码图片背景色最小值
        type: Number,
        default: 200,
      },
      backgroundColorMax: {
        // 验证码图片背景色最大值
        type: Number,
        default: 220,
      },
      dotColorMin: {
        // 背景干扰点最小值
        type: Number,
        default: 60,
      },
      dotColorMax: {
        // 背景干扰点最大值
        type: Number,
        default: 120,
      },
      contentWidth: {
        // 容器宽度
        type: Number,
        default: 90,
      },
      contentHeight: {
        // 容器高度
        type: Number,
        default: 38,
      },
    },
    methods: {
      // 生成一个随机数
      randomNum(min, max) {
        return Math.floor(Math.random() * (max - min) + min);
      },
  
      // 生成一个随机的颜色
      randomColor(min, max) {
        let r = this.randomNum(min, max);
        let g = this.randomNum(min, max);
        let b = this.randomNum(min, max);
        return "rgb(" + r + "," + g + "," + b + ")";
      },
      //画图
      drawPic() {
        let canvas = document.getElementById("s-canvas");
        //创建一个2D对象作为上下文。
        let ctx = canvas.getContext("2d");
        ctx.textBaseline = "bottom";
        // 绘制背景
        ctx.fillStyle = "#e6ecfd";
        ctx.fillRect(0, 0, this.contentWidth, this.contentHeight);
        // 绘制文字
        for (let i = 0; i < this.identifyCode.length; i++) {
          this.drawText(ctx, this.identifyCode[i], i);
        }
        this.drawLine(ctx);
        this.drawDot(ctx);
      },
      //在画布上显示数据
      drawText(ctx, txt, i) {
        ctx.fillStyle = this.randomColor(50, 160); // 随机生成字体颜色
        ctx.font =
          this.randomNum(this.fontSizeMin, this.fontSizeMax) + "px SimHei"; // 随机生成字体大小
        let x = (i + 1) * (this.contentWidth / (this.identifyCode.length + 1));
        let y = this.randomNum(this.fontSizeMax, this.contentHeight - 5);
        var deg = this.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);
      },
  
      // 绘制干扰线
      drawLine(ctx) {
        for (let i = 0; i < 4; i++) {
          ctx.strokeStyle = this.randomColor(100, 200);
          ctx.beginPath();
          ctx.moveTo(
            this.randomNum(0, this.contentWidth),
            this.randomNum(0, this.contentHeight)
          );
          ctx.lineTo(
            this.randomNum(0, this.contentWidth),
            this.randomNum(0, this.contentHeight)
          );
          ctx.stroke();
        }
      },
  
      // 绘制干扰点
      drawDot(ctx) {
        for (let i = 0; i < 30; i++) {
          ctx.fillStyle = this.randomColor(0, 255);
          ctx.beginPath();
          ctx.arc(
            this.randomNum(0, this.contentWidth),
            this.randomNum(0, this.contentHeight),
            1,
            0,
            2 * Math.PI
          );
          ctx.fill();
        }
      },
    },
    watch: {
      identifyCode() {
        this.drawPic();
      },
    },
    mounted() {
      this.drawPic();
    },
  };
  </script>
  
  

登录页面,运用验证码

<div style="position: relative;margin: 20px 0;">
   <el-input style="width: 100px;margin-right: 10px;" v-model="code" placeholder="验证码"> 
   </el-input>
   //组件       
   <dentify v-if="identifyCode" :identifyCode="identifyCode" style="width: 100px;height: 4 
     0px;display: inline-block;position: absolute;top: 0px;"></dentify>
   <el-button v-if="identifyCode" @click="refreshCode" style="margin-left: 100px;color: 
    #c4c4c4;">换一换</el-button>
   <el-button v-else  @click="refreshCode" style="color: #c4c4c4;">获取验证码</el-button>               
</div>
<el-button @click="Submit" class="buton">登录 </el-button>
import dentify from "@/components/dentify.vue";
export default {
  components: {
    dentify,
  },
  data() {
    return {
      code:'',
      identifyCodes: "1234567890abcdefjhijklinopqrsduvwxyz", //随机串内容,从这里随机抽几个显示验证码
      identifyCode: "", //验证码图片内容
      timer: null, //设置计时器
      count:'',
    };
  },
  methods: {
//判断验证码并提交
    async Submit() {
      console.log(this.count,'count')
      if(this.identifyCode ==''){
        this.$message({
          message: '获取验证码',
          type: 'warning'
        });
      }else if(this.count == 0){
        this.$message.error("验证码失效");
      }else if(this.code == ''){
        this.$message.error("验证码不能为空");
      }else if(this.identifyCode == this.code){
        await GET_LOGIN(this.form).then((res) => {
        console.log(res, "ress");
        if (res.code == 200) {
          this.$message({
            message: "登陆成功",
            type: "success",
          });

        } else {
          this.$message.error(res.msg);
        }
      });
      }else{
        this.$message.error("验证码错误");
      }
     
    },
    // 重置验证码并倒计时
    refreshCode() {
      this.identifyCode = "";
      this.count = ""
      this.makeCode(this.identifyCodes, 4);
      let TIME_COUNT = 60;
      if (!this.timer) {
        this.count = TIME_COUNT;
        this.timer = setInterval(() => {
          if (this.count > 0 && this.count <= TIME_COUNT) { 
            this.count--;
          } else {
            clearInterval(this.timer);
            this.timer = null;
          }
        }, 1000);
      }
    },
    //获取验证码的值
    makeCode(o, l) {
      for (let i = 0; i < l; i++) {
        //通过循环获取字符串内随机几位
        this.identifyCode +=
          this.identifyCodes[this.randomNum(0, this.identifyCodes.length)];
      }
     
    },
    
    //随机数字:用于当角标拿字符串的值
    randomNum(min, max) {
      return Math.floor(Math.random() * (max - min) + min);
    },

   }
 }

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Axure RP9】的详细安装及Axure入门应用

目录 一 Axure入门安装 1.1 Axure是什么? 1.2 Axure应用场景 1.3 Axure安装 1.3.1 汉化 1.3.2 授权 二, Axure应用 1.1 Axure软件界面概述 1.2 Axure的应用 1.2.1备份 1.2.2 视图显示及网格设置 1.2.3 生成HTML文件 1.2.4 备注说明 一 Axure入门安装 1.1 Axure…

吉林省文旅厅联合高德地图上线自驾游精品线路指南

12月15日消息&#xff0c;今日&#xff0c;吉林省文化和旅游厅联合高德地图推出“吉林省自驾游精品线路指南”&#xff0c;依托全省冬夏两季特色资源&#xff0c;推出了基于位置的8条自驾游品牌路线、百余个吉林省重点旅游场景&#xff0c;游客可以根据季节、地理位置、资源类型…

SoC中跨时钟域的信号同步设计(单比特同步设计)

一、 亚稳态 在数字电路中&#xff0c;触发器是一种很常用的器件。对于任意一个触发器&#xff0c;都由其参数库文件规定了能正常使用的“建立时间”&#xff08;Setup time&#xff09;和“保持时间”&#xff08;Hold time &#xff09;两个参数。“建立时间”是指在时钟…

【C语言】C的面向对象

一、BREW接口实现 高通的BREW&#xff08;Binary Runtime Environment for Wireless&#xff09;是一个早期为手机设备开发的应用程序平台&#xff0c;用于开发在CDMA手机上运行的软件。尽管这个平台目前已经不太流行&#xff0c;但是在其使用高峰时期&#xff0c;开发者需要使…

【深度学习目标检测】七、基于深度学习的火灾烟雾识别(python,目标检测,yolov8)

YOLOv8是一种物体检测算法&#xff0c;是YOLO系列算法的最新版本。 YOLO&#xff08;You Only Look Once&#xff09;是一种实时物体检测算法&#xff0c;其优势在于快速且准确的检测结果。YOLOv8在之前的版本基础上进行了一系列改进和优化&#xff0c;提高了检测速度和准确性。…

C/C++ STL提供的序列式容器之deque

deque是双向开口的连续内存空间&#xff08;动态将多个连续空间通过指针数组接合在一起&#xff09;&#xff0c;随时可以增加一段新的空间。 deque 的最大任务就是在这些分段的连续空间上&#xff0c;维护其整体连续的假象&#xff0c;并提供随机存取的接口。 特点 1. 一…

v-show和v-if有什么区别?使用场景分别是什么?

一、v-show与v-if的共同点 我们都知道在 vue 中 v-show 与 v-if 的作用效果是相同的(不含v-else)&#xff0c;都能控制元素在页面是否显示 在用法上也是相同的 <Model v-show"isShow" /> <Model v-if"isShow" />1 2 当表达式为true的时候&…

RK3588安装TVM-CPU版本

1.背景 TVM是一个开源的机器学习编译器栈&#xff0c;用于优化和编译深度学习模型&#xff0c;以在各种硬件平台上实现高效性能。以下是关于TVM的详细介绍&#xff1a; TVM的目标是将深度学习模型的优化和编译过程自动化&#xff0c;以便开发人员可以轻松地将其模型部署到各种…

HACON error #2453:

问题&#xff1a;HALCON handle is NULL in operator grab_image_async" 分析&#xff1a;句柄为空&#xff0c;因为提前hv_AcqHandle.Dispose();将句柄释放掉了 解决方案&#xff1a;屏蔽此语句

【Spring】06 生命周期之销毁回调

文章目录 1. 回调是什么2. 销毁回调2.1 实现 DisposableBean 接口2.2 配置 destroy-method 3. 执行顺序4. 应用场景总结 在 Spring 框架中&#xff0c;生命周期回调&#xff08;Lifecycle Callbacks&#xff09;是一种强大的机制&#xff0c;它允许我们在 Spring 容器中的 Bean…

【Vue】日期格式化(全局)

系列文章 【Vue】vue增加导航标签 本文链接&#xff1a;https://blog.csdn.net/youcheng_ge/article/details/134965353 【Vue】Element开发笔记 本文链接&#xff1a;https://blog.csdn.net/youcheng_ge/article/details/133947977 【Vue】vue&#xff0c;在Windows IIS平台…

基于若依搭建微服务nacos版本(ruoyi-Cloud前后端分离)

说明&#xff1a;本文介绍基于Ruoyi-Cloud前后端分离nacos版本的微服务从0到1的搭建过程&#xff0c;同时新增一个新的微服务模块。是基于官方文档的补充说明&#xff0c;需要结合Ruoyi-Cloud的官方文档 https://doc.ruoyi.vip/ruoyi-cloud/ 如果直接查看官方文档便可成功部署&…

Linux Conda 安装 Jupyter

在Linux服务器Conda环境上安装Jupyter过程中遇到了无数的报错&#xff0c;特此记录。 目录 步骤一&#xff1a;安装Anaconda3 步骤二&#xff1a;配置Conda源 步骤三&#xff1a;安装Jupyter 安装报错&#xff1a;simplejson.errors.JSONDecodeError 安装报错&#xff1a;…

Linux---重定向命令

1. 重定向命令的介绍 重定向也称为输出重定向&#xff0c;把在终端执行命令的结果保存到目标文件。 2. 重定向命令的使用 命令说明>如果文件存在会覆盖原有文件内容&#xff0c;相当于文件操作中的‘w’模式>>如果文件存在会追加写入文件末尾&#xff0c;相当于文件…

DevOps云原生创建devops流水线(微服务项目上传git,打包镜像,部署k8s)

开发和运维人员的解决方案 一、中间件的部署&#xff08;Sentinel/MongoDB/MySQL&#xff09; 二、创建DevOps工程 邀请成员 三、创建流水线 四、编辑流水线 ①、拉取代码&#xff08;若失败&#xff0c;则将制定容器改为maven&#xff09; 若失败&#xff0c;则将命令改…

P1789 【Mc生存】插火把

题目描述 话说有一天 linyorson 在“我的世界”开了一个 nn 的方阵&#xff0c;现在他有 m 个火把和 k 个萤石&#xff0c;分别放在 (x1​,y1​)∼(xm​,ym​) 和 (o1​,p1​)∼(ok​,pk​) 的位置&#xff0c;没有光并且没放东西的地方会生成怪物。请问在这个方阵中有几个点会…

Python 实现:OCR在图片中提取文字(基于Gradio实现)

Paddle OCR PaddleOCR 基于深度学习技术实现的&#xff0c;使用十分简单。 先看效果 可以看出来识别效果还是不错的&#xff0c;里面的“湿”字识别成了繁体字。如果不是连体字&#xff0c;就不会出现这个问题。 1.测试环境 操作系统&#xff1a;Win10 Python&#xff1a;3…

KVM虚拟机console使用

注意这些设置都在你要进入虚拟机里设置&#xff0c;不是在你的物理机设置 首先debian12 需要设置 grep ttyS0 /etc/securetty #没有则加上 echo ttyS0 >> /etc/securetty #启动 systemctl start serial-gettyttyS0 systemctl enable serial-gettyttyS0#CentOS Stream …

广西开放大学形成性考核 平时作业 统一资料 参考

试卷代号&#xff1a;1293 心理学 参考试题 一、选择题&#xff08;每个3分&#xff0c;共30分&#xff0c;含单选和多选&#xff0c;请将正确答案的字母序号填入括号中&#xff09; 1.人们通常把下列图形知觉为一个连续、完整的形状&#xff0c;说明图形知觉遵循( )。…

转载:TableView性能优化

转载&#xff1a;TableView性能优化 原文链接&#xff1a;https://juejin.cn/post/6955731915672387592 tableView性能优化 Cell重用、标识重用 使用 static 修饰重用标识名称能够保证这个标识只会创建一次&#xff0c;提高性能。接着调用dequeueReusableCellWithIdentifie…