UniApp手机滑块验证组件代码生成器

简介: UniApp手机滑块验证组件代码生成器

DIY可视化实现UniApp手机滑块验证组件,支持自定义背景图片、成功提示、错误提示、划动提示等。

手机滑块验证组件是一种广泛应用于手机应用、网页等场景的用户验证机制,其主要目的是通过用户的滑动操作来验证用户的真实性和操作意图,从而增强系统的安全性。以下是对手机滑块验证组件的详细介绍:

用户的真实性和操作意图,从而增强系统的安全性。以下是对手机滑块验证组件的详细介绍:

一、工作原理

滑块验证组件的工作原理基于人机交互的思想,通过要求用户在屏幕上滑动指定的滑块到特定位置来完成验证。这一过程结合了用户的视觉和运动能力,使得验证过程更加难以被自动化程序绕过。

二、组成元素

手机滑块验证组件通常包含以下几个关键元素:


滑块:用户需要操作的对象,通常是一个可拖动的图标或图形。

背景图:滑块需要与之匹配或对齐的图像,背景图上通常包含有特定的图案或元素,用于引导用户找到正确的滑动位置。

指示信息:提示用户如何操作的文字或图形信息,如“拖动滑块完成验证”。

验证逻辑:后台的验证算法,用于判断用户的滑动操作是否符合预期,包括滑块的位置、滑动轨迹等。

三、操作流程

显示验证页面:当用户需要进行验证时,系统会生成一张包含滑块和背景图的验证码图片,并显示在用户的手机上。

用户操作:用户用手指按住滑块,并沿着屏幕指示的方向拖动,直到滑块到达背景图的指定位置。

验证结果:系统会根据用户的滑动操作进行验证,如果验证通过,用户将获得验证成功的反馈;如果验证失败,用户需要重新进行验证。

四、优势与应用

手机滑块验证组件具有以下优势:


提高安全性:通过结合用户的视觉和运动能力进行验证,增加了自动化程序绕过的难度。

提升用户体验:相比传统的验证码输入方式,滑块验证更加简单直观,用户只需进行简单的滑动操作即可完成验证。

适用范围广:可以灵活应用于各种手机应用、网页等场景,满足不同的验证需求。

手机滑块验证组件广泛应用于各类网站和移动应用中,如用户注册、登录、重置密码等场景。它通过简单的滑动操作,有效地保护了用户的账户安全,并提升了用户体验。

五、技术实现

手机滑块验证组件的实现通常涉及图像处理、机器学习等技术。系统需要能够生成复杂的背景图、随机放置滑块位置、捕捉用户的滑动轨迹等。同时,还需要具备高效的验证算法,以快速准确地判断用户的滑动操作是否符合预期。


综上所述,手机滑块验证组件是一种简单有效且广泛应用的用户验证机制,它通过结合用户的视觉和运动能力进行验证,提高了系统的安全性和用户体验。

六、UniApp组件库实现

<template>
  <view class="diy-verify" v-if="initShow" :class="isModal?'diy-verify-modal':''" :id="elid"  @touchmove.stop.prevent="stopMoveHandle" :style="verifyWidthStyle">
    <view class="diy-verify-close" @tap="close" v-if="isModal">
      <u-icon :size="50" color="#fff" name="close"></u-icon>
    </view>
    <view class="diy-verify-wrap"  v-if="isShow">
      <view class="diy-verify-box">
        <image class="diy-verify-img" v-if="verifyImg" :src="verifyImg" mode="scaleToFill"></image>
        <!-- 右侧用来验证的滑块 -->
        <view class="diy-verify-block-verify" :style="blockVerifyStyle"></view>
        <!-- 被css操控的滑块 -->
        <view class="diy-verify-block-move" :style="blockMoveStyle"></view>
        
        <view class="diy-verify-tips" v-if="!showBottomVerify">
          <text class="diy-verify-tips-text" :style="blockTipsStyle">{{ tips }}</text>
        </view>
        <!-- 手指触摸的滑块 -->
        <view class="diy-verify-block-touch" :style="blockTouchStyle" @touchstart="touchstartHandle"
          @touchmove="touchmoveHandle" @touchend="touchendHandle">
        </view>
        <view @tap="initVerify()" class="diy-verify-refresh">
          <u-icon :size="50" :color="refreshColor" name="reload"></u-icon>
        </view>
      </view>
      <view class="diy-verify-verify" v-if="showBottomVerify"  :style="verifyBottomStyle">
        <view   :class="(isSuccess?'diy-verify-success-text':'diy-verify-text')">{{tips}}</view>
        <!-- 被css操控的滑块 -->
        <view class="diy-verify-verify-move" :style="verifyMoveStyle">
          <u-icon :size="bottomSize-10" :name="isSuccess?'checkbox-mark':'arrow-right-double'"></u-icon>
        </view>
        <!-- 手指触摸的滑块 -->
        <view class="diy-verify-verify-touch" :style="verifyTouchStyle" @touchstart="touchstartHandle"  @touchmove="touchmoveHandle" @touchend="touchendHandle">
        </view>
      </view>
    </view>
  </view>
</template>
 
<script>
  export default {
    name: 'zmmVerifyVerify',
    emits: ["update:modelValue",'close',"change"],
    props: {
      // 通过双向绑定控制组件的弹出与收起
      modelValue: {
        type: Boolean,
        default: false
      },
      //是否弹窗验证
      isModal:{
        type:Boolean,
        default: false
      },
      //提醒
      tip: {
        type: String,
        default: '请将左侧透明滑块拖进白色框内'
      },
      successTip: {
           type: String,
           default: "验证通过"
      },
      failTip:{
        type: String,
        default: "验证失败"
      },
      //滑块大小
      verifySize: {
        type: Number,
        default: 50
      },
      //滑块颜色
      verifyColor: {
        type: String,
        default: 'rgba(0,0,0,0.4)'
      },
      //图片验证高度
      verifyHeight:{
        type: Number,
        default: 170
      },
      // 图片
      verifyImg: {
        type: String,
        default: ''
      },
      //刷新颜色
      refreshColor: {
        type: String,
        default: '#ffffff'
      },
      //校验正负差值区间像素
      between: {
        type: Number,
        default: 10
      },
      //如果不显示底部滑动条时提示字段颜色
      tipColor:{
        type: String,
        default: '#ffff00'
      },
      // 是否显示底部滑动条
      showBottomVerify: {
        type: Boolean,
        default: false
      },
      //底部滑块大小
      bottomSize: {
        type: Number,
        default: 40
      },
      bottomBarColor: {
        type: String,
        default: '#eee'
      },
      bottomSuccessColor: {
        type: String,
        default: '#19be6b'
      },
      //底部滑块颜色
      bottomBgColor: {
            type: String,
            default: '#ffffff'
      },
      bottomColor: {
        type: String,
        default: '#bbbbbb'
      },
      bottomBorderColor: {
        type: String,
        default: '#bbbbbb'
      },
    },
    data() {
      return {
        elid: this.$u.guid(),
        verifyWidth:280,
        initShow:!this.isModal,
        tips:this.tip,
        startPageX: 0, //开始距离
        moveLeft: 0, //滑动距离
        isSuccess: false, //是否成功
        autoLeft: 80, //验证滑块随机的像素
        autoTop: 80, //验证滑块随机的top像素
        isShow: false
      };
    }, 
        watch: {
      verifyImg: {
        immediate: true,
        handler(){
          this.init()
        }
      }
    },
    computed: {
      verifyWidthStyle(){
        return `--diy-verify-width:${this.verifyWidth}px;--diy-verify-height:${this.verifyHeight}px`
      },
      blockVerifyStyle() {
        return `top:${this.autoTop}px;left:${this.autoLeft}px;height:${this.verifySize}px;width:${this.verifySize}px;background-color:${this.verifyColor};`
      },
      blockMoveStyle() {
        let moveLeft = this.isSuccess?this.autoLeft:this.moveLeft;
        return `top:${this.autoTop}px;left:${moveLeft}px;height:${this.verifySize}px;width:${this.verifySize}px;background-color: ${this.verifyColor};`
      },
      blockTipsStyle(){
        return `color:${this.tipColor}`
      },
      blockTouchStyle() {
        return `top:${this.autoTop}px;height:${this.verifySize}px;width:${this.verifySize}px;`
      },
      verifyMoveStyle() {
        let moveLeft = this.isSuccess?this.autoLeft:this.moveLeft;
        return `border:1px solid ${this.bottomBorderColor};left:${moveLeft}px;height:${this.bottomSize}px;width:${this.bottomSize}px;color:${this.bottomColor};background-color: ${this.bottomBgColor};`
      },
      verifyTouchStyle() {
        return `height:${this.bottomSize}px;width:${this.bottomSize}px;`
      },
      verifyBottomStyle() {
        return `font-size:${this.bottomSize-26}px;line-height:${this.bottomSize}px;height:${this.bottomSize}px;background-color:${this.isSuccess?this.bottomSuccessColor:this.bottomBarColor}`
      }
    },
    mounted() {
      this.init()
    },
    methods: {
      // 初始化
      init() {
        if(this.initShow){
          this.$nextTick(()=>{
            this.$uGetRect('#' + this.elid).then((res) => {
              this.verifyWidth = this.isModal?res.width-20:res.width;
              this.initVerify()
            });
          })
        }
      },
      initVerify(){
        this.isShow = true
        this.moveLeft = 0;
        this.isSuccess = false;
        this.autoTop = this.randPostion(0, this.verifyHeight - this.verifySize);
        this.autoLeft = this.randPostion(this.verifySize + 20, this.verifyWidth - this.verifySize);
      },
      show(){
        this.initShow = true;
        this.init();
      },
      close(){
        if(this.isModal){
          this.initShow = false;
          this.$emit("close");
        }
      },
      // 拦截其他触摸事件防止nvue下input等元素层级问题
      stopMoveHandle(e) {
        if (e.preventDefault) {
          // 阻止页面滚动
          e.preventDefault()
        }
      },
      // 随机数
      randPostion(min, max) {
        //返回包括最大/小值
        return Math.floor(Math.random() * (max - min + 1)) + min;
      },
      //按下
      touchstartHandle(e) {
        if (this.isSuccess) {
          return;
        }
        this.startPageX = e.changedTouches[0].pageX;
      },
      // 滑动
      touchmoveHandle(e) {
        // 滑动分两个块来操作不然会有数据抖动
        if (this.isSuccess) {
          return;
        }
        var left = e.changedTouches[0].pageX - this.startPageX; //补偿起始位置
        this.moveLeft = left;
      },
      // 滑动离开(最终)
      touchendHandle(e) {
        var endLeft = e.changedTouches[0].pageX;
        var verifyLeft = this.autoLeft + this.startPageX; //补偿起始位置
        var chazhi = verifyLeft - endLeft; //最终差值
        // 判断是否在正负差值区间
        if (chazhi >= 0 - this.between && chazhi <= this.between) {
          this.isSuccess = true;
          // 通过会执行成功和关闭
          this.tips = this.successTip
          this.$emit("update:modelValue", true);
          this.$emit("change", true);
          uni.showToast({
            icon:'none',
            title:this.successTip?this.successTip:'验证通过'
          })
          this.close()
        } else {
          this.tips = this.failTip?this.failTip:'验证失败';
          setTimeout(()=>{
            this.tips = this.tip;
          })
          // 失败会执行失败并重新初始化
          this.show();
          uni.showToast({
            title: this.failTip?this.failTip:'验证失败',
            icon: 'none'
          });
          this.$emit("update:modelValue", false);
          this.$emit("change", false);
        }
      }
    }
  };
</script>
 
<style lang="scss" scoped>
  .diy-verify {
    --diy-verify-width:280px;
    --diy-verify-height:170px;
    --textColor:#4d4d4d;
    width: 100%;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    &.diy-verify-modal{
      position: fixed;
      top:0px;
      left:0px;
      width: 100%;
      height: 100%;
      background: rgba(0, 0, 0, 0.6);
      z-index: 99999999;
      transition: all 0.3s ease-in-out 0s;
      
      .diy-verify-close{
        position: absolute;
        top:10px;
        right: 10px;
      }
      .diy-verify-wrap {
        opacity: 1;
        transition-duration: 0.3s;
        -ms-transform: scale(1);
        transform: scale(1);
        overflow-x: hidden;
        overflow-y: auto;
        pointer-events: auto;
      }
    }
 
    .diy-verify-wrap {
      display: flex;
      flex-direction: column;
      position: relative;
      margin: 0 auto;
      width: var(--diy-verify-width); 
      background-color: #ffffff;
 
      .diy-verify-tips {
        position: absolute;
        left:0;
        bottom: 0;
        width: 100%;
        background: rgba(0, 0, 0, .6);
        font-size: 12px;
        line-height: 20px;
        text-align: center;
 
        .diy-verify-tips-text {
          color: #ff0;
        }
      }
      .diy-verify-refresh{
        position: absolute;
        right: 10px;
        top: 10px;
      }
 
      .diy-verify-text{
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
        color: #FFFFFF;
        text-align: center;
        background: -webkit-gradient(linear,left top,right top,color-stop(0,var(--textColor)),color-stop(.4,var(--textColor)),color-stop(.5,#fff),color-stop(.6,var(--textColor)),color-stop(1,var(--textColor)));
        animation: slidetounlock 3s infinite;
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
      }
      .diy-verify-success-text{
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        text-align: center;
        color: #FFFFFF;
      }
 
      @keyframes slidetounlock{
        0% {
          background-position: -200rpx 0;
        }
        100% {
          background-position: 200rpx 0;
        }
      }
      .diy-verify-box {
        position: relative;
        width: var(--diy-verify-width);
        height: var(--diy-verify-height);
        overflow: hidden;
 
        .diy-verify-img {
          width: var(--diy-verify-width);
          height: var(--diy-verify-height);
          border-radius: 0px;
        }
 
        .diy-verify-block-verify,
        .diy-verify-block-move,
        .diy-verify-block-touch {
          position: absolute;
          left: 0px;
          top: 0;
          border-radius: 0px;
        }
 
        .diy-verify-block-verify {
          border:1px solid #fff;
        }
      }
 
      .diy-verify-verify {
        height:40px;
        width: var(--diy-verify-width);
        background-color: rgba(0,0,0,0.07);
        position: relative;
        overflow: hidden;
        .diy-verify-verify-move{
          display: flex;
          align-items: center;
          justify-content: center;
        }
        .diy-verify-verify-move,
        .diy-verify-verify-touch {
          border-radius: 0px;
        }
  
        .diy-verify-verify-move,.diy-verify-verify-touch {
          position: absolute;
          left: 0px;
          top: 0px;
        }
      }
    }
  }
</style>

七、组件使用

<template>
  <view class="container container23285">
    <view class="diygw-col-24">
      <diy-verify v-model="verify" successBarColor="#ff3d0c"></diy-verify>
    </view>
    <view class="diygw-col-24">
      <diy-verifyimg class="diygw-col-24" v-model="verifyimg" :verifySize="50" verifyImg="/static/pic1.jpg" :showBottomVerify="true"></diy-verifyimg>
    </view>
    <view class="clearfix"></view>
  </view>
</template>
 
<script>
  export default {
    data() {
      return {
        //用户全局信息
        userInfo: {},
        //页面传参
        globalOption: {},
        //自定义全局变量
        globalData: { logintype: '0', agree: '0' },
        verify: false,
        verifyimg: false
      };
    },
    onShow() {
      this.setCurrentPage(this);
    },
    onLoad(option) {
      this.setCurrentPage(this);
      if (option) {
        this.setData({
          globalOption: this.getOption(option)
        });
      }
 
      this.init();
    },
    methods: {
      async init() {}
    }
  };
</script>
 
<style lang="scss" scoped>
  .container23285 {
  }
</style>
目录
相关文章
|
25天前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
17天前
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了如何使用PolarDB、通义千问和LangChain搭建GraphRAG系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图+向量联合搜索增强了问答准确性。PolarDB支持AGE图引擎和pgvector插件,实现图数据和向量数据的统一存储与检索,提升了RAG系统的性能和效果。
|
4天前
|
JSON 自然语言处理 数据管理
阿里云百炼产品月刊【2024年9月】
阿里云百炼产品月刊【2024年9月】,涵盖本月产品和功能发布、活动,应用实践等内容,帮助您快速了解阿里云百炼产品的最新动态。
阿里云百炼产品月刊【2024年9月】
|
1天前
|
人工智能 Rust Java
10月更文挑战赛火热启动,坚持热爱坚持创作!
开发者社区10月更文挑战,寻找热爱技术内容创作的你,欢迎来创作!
256 12
|
19天前
|
人工智能 IDE 程序员
期盼已久!通义灵码 AI 程序员开启邀测,全流程开发仅用几分钟
在云栖大会上,阿里云云原生应用平台负责人丁宇宣布,「通义灵码」完成全面升级,并正式发布 AI 程序员。
|
21天前
|
机器学习/深度学习 算法 大数据
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
2024“华为杯”数学建模竞赛,对ABCDEF每个题进行详细的分析,涵盖风电场功率优化、WLAN网络吞吐量、磁性元件损耗建模、地理环境问题、高速公路应急车道启用和X射线脉冲星建模等多领域问题,解析了问题类型、专业和技能的需要。
2582 22
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
|
3天前
|
存储 人工智能 搜索推荐
数据治理,是时候打破刻板印象了
瓴羊智能数据建设与治理产品Datapin全面升级,可演进扩展的数据架构体系为企业数据治理预留发展空间,推出敏捷版用以解决企业数据量不大但需构建数据的场景问题,基于大模型打造的DataAgent更是为企业用好数据资产提供了便利。
169 2
|
1天前
|
编译器 C#
C#多态概述:通过继承实现的不同对象调用相同的方法,表现出不同的行为
C#多态概述:通过继承实现的不同对象调用相同的方法,表现出不同的行为
101 65
|
21天前
|
机器学习/深度学习 算法 数据可视化
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
2024年中国研究生数学建模竞赛C题聚焦磁性元件磁芯损耗建模。题目背景介绍了电能变换技术的发展与应用,强调磁性元件在功率变换器中的重要性。磁芯损耗受多种因素影响,现有模型难以精确预测。题目要求通过数据分析建立高精度磁芯损耗模型。具体任务包括励磁波形分类、修正斯坦麦茨方程、分析影响因素、构建预测模型及优化设计条件。涉及数据预处理、特征提取、机器学习及优化算法等技术。适合电气、材料、计算机等多个专业学生参与。
1578 16
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
|
5天前
|
Linux 虚拟化 开发者
一键将CentOs的yum源更换为国内阿里yum源
一键将CentOs的yum源更换为国内阿里yum源
257 2