vue3 纯前端 验证码功能

子组件代码

<template>
  <div class="code">
    <div class="transfer_dia">
      <div class="title">
        <span class="icon_class">
          <el-icon color="#faad14"><InfoFilled /></el-icon>
        </span>
        仅限完成企业的已认证已签约才能申请账期,你已完成个人认证签约,
        <br />
        需先解除绑定后完成企业认证签约~
      </div>
    </div>
    <div class="confirm_box">
      <strong>确认需要解除认证?将右图中看到的验证码填入下方输入框中。 </strong>
    </div>
    <div class="input_box" style="display: flex">
      <el-form :model="cancelForm" :rules="cancelRules" ref="ruleFormRef2" class="form">
        <el-form-item label="" prop="number">
          <el-input
            style="width: 214px; height: 40px"
            placeholder="请输入验证码 (不区分大小写)"
            v-model="cancelForm.number"
            clearable />&nbsp;
        </el-form-item>
      </el-form>
      <canvas ref="canvas" width="120" height="43" @click="refreshCaptcha"></canvas>
    </div>
  </div>
</template>

<script setup>
  import { ref, onMounted } from 'vue'
  import black3 from '../../../../assets/home/bac_yanzhengma.png'
  const showNum = ref([])
  const ruleFormRef2 = ref('')
  const canvas = ref(null)
  const cancelForm = ref({
    number: ''
  })
  const cancelRules = ref({
    number: [
      { required: true, message: '必填项', trigger: 'blur' },
      {
        validator: (rule, value, callback) => {
          console.log('showNum:', showNum.value.join('').toLowerCase())
          console.log('value:', value.toLowerCase())
          const num = showNum.value.join('').toLowerCase()
          if (value.toLowerCase() === num) {
            callback()
          } else {
            callback(new Error('您输入的验证码错误!请重新输入!'))
          }
        },
        trigger: 'blur'
      }
    ]
  })

  onMounted(() => {
    const img = new Image()
    img.src = black3 // 图片的URL,注意路径应适配你的项目结构
    img.onload = () => {
      draw(showNum, img)
    }
  })

  // 绘制验证码图像
  function draw (showNum, img) {
    const aCode = 'A,B,C,E,F,G,H,J,K,L,M,N,P,Q,R,S,T,W,X,Y,Z,1,2,3,4,5,6,7,8,9,0'.split(',')
    const aLength = aCode.length // 验证码字符数组的长度

    const context = canvas.value.getContext('2d')
    context.drawImage(img, 0, 0, canvas.value.width, canvas.value.height)

    // 绘制验证码文本
    for (let i = 0; i <= 3; i++) {
      const j = Math.floor(Math.random() * aLength)
      const deg = (Math.random() * 30 * Math.PI) / 180
      const txt = aCode[j]
      showNum.value[i] = txt.toLowerCase()
      const x = 10 + i * 20
      const y = 20 + Math.random() * 8
      context.font = 'bold 23px 微软雅黑'
      context.translate(x, y)
      context.rotate(deg)
      context.fillStyle = randomColor()
      context.fillText(txt, 0, 0)
      context.rotate(-deg)
      context.translate(-x, -y)
    }

    // 绘制验证码的干扰线
    for (let i = 0; i <= 5; i++) {
      context.strokeStyle = randomColor()
      context.beginPath()
      context.moveTo(Math.random() * canvas.value.width, Math.random() * canvas.value.height)
      context.lineTo(Math.random() * canvas.value.width, Math.random() * canvas.value.height)
      context.stroke()
    }

    // 绘制验证码的干扰点
    for (let i = 0; i <= 30; i++) {
      context.strokeStyle = randomColor()
      context.beginPath()
      const x = Math.random() * canvas.value.width
      const y = Math.random() * canvas.value.height
      context.moveTo(x, y)
      context.lineTo(x + 1, y + 1)
      context.stroke()
    }
  }

  // 生成随机颜色
  function randomColor () {
    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})`
  }

  function refreshCaptcha () {
    const img = new Image()
    img.src = black3
    img.onload = () => {
      draw(showNum, img)
    }
  }

  const checkCaptcha = () => {
    return new Promise((resolve, reject) => {
      ruleFormRef2.value.validate(async (valid, fields) => {
        if (valid) {
          resolve(valid)
        } else {
          reject(valid)
        }
      })
    })
  }

  const reset = () => {
    ruleFormRef2.value.resetFields()
  }

  defineExpose({
    checkCaptcha,
    reset
  })
</script>

<style lang="scss" scoped>
  .code {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin: 0 auto;
    text-align: center;
    .transfer_dia {
      .title {
        width: 100%;
        padding: 10px;
        background-color: #fffbe6;
        line-height: 28px;
        // padding-left: 20px;
        border: 1px solid #faad14;
        display: flex;
        // align-items: center;
        .icon_class {
          margin-right: 10px;
        }
      }
      .el_transfer {
        text-align: left;
        display: inline-block;
      }
      .left_icon {
        position: absolute;
        left: 195px;
        top: 113px;
        &.right {
          left: 768px;
        }
      }
      ::v-deep .el-transfer-panel {
        width: 260px;
      }
    }
    .confirm_box {
      margin-top: 20px;
      margin-bottom: 10px;
    }
    .input_box {
      display: flex;
      margin-bottom: 30px;
      .form {
        margin-right: 20px;
      }
    }

    #canvas {
      float: right;
      display: inline-block;
      border: 1px solid #ccc;
      border-radius: 5px;
      cursor: pointer;
    }
  }
</style>

父组件 代码

 <!-- 解除认证 -->
    <MyDialog title="解除认证" width="600px" top="20vh" v-model="removeShow">
      <div class="remove_content">
        <CancelCertify ref="CancelCertifyRef"></CancelCertify>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="removeClose()">关闭</el-button>
          <el-button @click="removeSubmit()" type="primary"> 确定 </el-button>
        </div>
      </template>
    </MyDialog>


  // 解除认证  确定
  const removeSubmit = async () => {
    const res = await CancelCertifyRef.value.checkCaptcha()
    if (res) {
      const res = await accountUserUnbind()
      ElMessage.success('操作成功,即将进行跳转')
      removeClose()
      setTimeout(() => {
        toCertify()
      }, 1200)
    }
  }


  // 解除认证 关闭
  const removeClose = () => {
    CancelCertifyRef.value.reset()
    removeShow.value = false
  }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值