vue3-滑动箭头完成安全验证--箭头

效果图

在登陆页面使用安全验证组件

<dragVerify v-model:value="form.isVerifyPass"></dragVerify>

点击登陆的时候,验证是否完成了安全验证

function doLogin() {
  proxy.$refs.loginRef.validate((valid) => {
    if (valid && form.isVerifyPass) {
      const password = proxy.sha256(form.password);
      const param = {
        userMobile: form.userMobile,
        password,
      };
      loading.value = true;
      userStore
        .login(param)
        .then((res) => {
          mobile.value = res.userInfo.userMobile;
          userId.value = res.userInfo.userId;
          const hasPwd = res && res.userInfo && res.userInfo.hasPwd;
            // visible.value = true;
            if (hasPwd === 1) {
                visible.value = true;
            } else {
              sessionStorage.setItem("token", res.token);
                const path = query && query.redirect ? query.redirect : '/';
                router.replace(path);
            }
        
        }).catch((err) =>{
          console.log(err,'====')
        })
        .finally(() => {
          loading.value = false;
        });
    } else {
      ElMessage.error('请完成表单验证和滑块验证!');
    }
  });
}

安全验证组件


<template>
    <div class="drag-verify">
      <div class="range" :class="verifyResult ? 'success' : ''">
        <div class="block" @mousedown="onStart" @touchstart="onStart">
          <i :class="verifyResult ? successIcon : startIcon"></i>
        </div>
        <span class="text">{{ verifyResult ? successText : startText }}</span>
      </div>
    </div>
  </template>
  <script lang="ts" setup>
  import { ref } from 'vue'
  
  const emit = defineEmits(['update:value'])
  defineProps({
    value: {
      type: Boolean,
      defalut: false,
    },
    // 成功图标
    successIcon: {
      type: String,
      default: 'iconfont icon-status-nor',
    },
    // 成功文字
    successText: {
      type: String,
      default: '验证成功',
    },
    // 开始的图标
    startIcon: {
      type: String,
      default: 'el-icon-right',
    },
    // 开始的文字
    startText: {
      type: String,
      default: '向右滑动完成验证',
    },
  })
  
  const verifyResult = ref(false) // 验证结果
  const isTouch = 'ontouchstart' in document.documentElement
  const moveEvent = isTouch ? 'touchmove' : 'mousemove'
  const upEvent = isTouch ? 'touchend' : 'mouseup'
  
  // 滑块触摸开始
  const onStart = (ev: MouseEvent | TouchEvent) => {
    let disX = 0 // 滑块移动距离
    const iconWidth = 40 // 滑动图标宽度
    const ele = document.querySelector('.drag-verify .block') as HTMLElement
    const startX = (ev as MouseEvent).clientX || (ev as TouchEvent).touches[0].pageX
    const parentWidth = ele.offsetWidth
    const MaxX = parentWidth - iconWidth
    if (verifyResult.value) {
      return false
    }
  
    // 滑块触摸移动
    const onMove = (e: MouseEvent | TouchEvent) => {
      const endX = (e as MouseEvent).clientX || (e as TouchEvent).touches[0].pageX
      disX = endX - startX
      if (disX <= 0) {
        disX = 0
      }
      if (disX >= MaxX - iconWidth) {
        disX = MaxX
      }
      ele.style.transition = '.1s all'
      ele.style.transform = `translateX(${disX}px)`
    }
  
    // 滑块触摸结束
    const onEnd = () => {
      if (disX !== MaxX) {
        ele.style.transition = '.5s all'
        ele.style.transform = 'translateX(0)'
      } else {
        // 执行成功
        verifyResult.value = true
        emit('update:value', verifyResult.value)
      }
  
      document.removeEventListener(moveEvent, onMove)
      document.removeEventListener(upEvent, onEnd)
    }
  
    document.addEventListener(moveEvent, onMove)
    document.addEventListener(upEvent, onEnd)
  }
  </script>
  <style lang="scss" scoped>
  $color-primary: #03c5e5;
  
  @mixin flex {
    display: flex;
    justify-content: center;
    align-items: center;
  }
  .drag-verify {
    width: 100%;
    .range {
      background-color: #ececee;
      position: relative;
      border-radius: 4px;
      transition: 1s all;
      user-select: none;
      color: #666;
      overflow: hidden;
      @include flex;
      height: 40px;
      &.success {
        background-color: $color-primary;
        color: #fff;
        .text {
          position: relative;
          z-index: 1;
        }
        .block i {
          color: $color-primary;
        }
      }
      .block {
        display: block;
        position: absolute;
        left: calc(-100% + 40px);
        width: 100%;
        height: 100%;
        background: $color-primary;
        border-radius: 4px;
        overflow: hidden;
        i {
          position: absolute;
          right: 0;
          width: 40px;
          height: 100%;
          font-size: 20px;
          color: #c8c9cc;
          background-color: #fff;
          border: 1px solid #e5e5e5;
          border-radius: 4px;
          cursor: pointer;
          @include flex;
        }
      }
    }
  }
  </style>
  

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值