wya1
  • 课程
  • 书籍
  • 工具
  • 博客
  • 登录
  • 注册

小言_互联网的博客

小言_互联网的博客

个人资料

小言_互联网

  • 访问:8335991次
  • 积分:0
  • 等级:1

文章分类

  1. Java(577)
  2. Python(569)
  3. Linux(200)
  4. 笔记(181)
  5. 人工智能(180)
  6. 数据库(140)
  7. 算法(132)
  8. C++(130)
  9. MySQL(127)
  10. 机器学习(126)

文章存档

  1. 2023年03月(33)
  2. 2023年02月(699)
  3. 2023年01月(754)
  4. 2022年12月(936)
  5. 2022年11月(1064)
  6. 2022年07月(232)
  7. 2022年06月(171)
  8. 2022年03月(35)
  9. 2021年06月(233)
  10. 2021年05月(1243)
  11. 2021年04月(1215)
  12. 2021年03月(775)
  13. 2021年02月(837)
  14. 2021年01月(1158)
  15. 2020年12月(876)
  16. 2020年11月(289)
  17. 2020年10月(373)
  18. 2020年09月(627)
  19. 2020年08月(143)
  20. 2020年07月(71)
  21. 2020年06月(782)
  22. 2020年05月(887)
  23. 2020年04月(1911)
  24. 2020年03月(253)
  25. 2020年02月(179)
  26. 2019年10月(9)

阅读排行

  1. 20+个很棒的 Python 脚本的集合(迷你项目)(194672)
  2. 解决报错:org.springframework.web.client.HttpClientErrorException$Unauthorized: 401 : [no body](15302)
  3. 安装Photoshop时出现The installation cannot continue as the installer file may be damaged. Download the in(10788)
  4. STM32单片机之温湿度检测系统(DTH11、OLED、LCD1602)(10652)
  5. 误差分析计算公式及其 matlab 代码实现(mse、mape、rmse等)(9850)
  6. 【elementUI】关于el-input限制输入整数、数字范围以及在form表单验证中限制输入正整数(8380)
  7. 手把手教你配置linux下C++开发工具——vim+ycm(YouCompleteMe),支持基于语义的自动补全和第三方库补全(史上最简单、史上最透彻、史上最全的终极解决方案)(7503)
  8. 银河麒麟高级服务器操作系统V10上安装k8s单机集群(6562)
  9. 【Yolo3】一文掌握图像标注、训练、识别(Keras+TensorFlow-gpu)(5770)
  10. 基于STM32L431设计的云端绿化管理系统(ESP8266+阿里云物联网平台)(5464)

评论排行

  1. 了解Axios及其运用方式(0)
  2. Vue中 引入使用 babel-polyfill 兼容低版本浏览器(0)
  3. 1000亿数据、30W级qps如何架构?来一个天花板案例(0)
  4. STM32开发(16)----CubeMX配置DMA(0)
  5. Hadoop综合案例 - 聊天软件数据(0)
  6. 基于JWT实现用户身份认证(0)
  7. 【企业云端全栈开发实践-2】Spring Boot Controller(0)
  8. 使用手工特征提升模型性能(0)
  9. 《MySql学习》 Select 查询语句慢的非性能原因(0)
  10. 客户端攻击(溯源攻击,获取客户端信息)(0)

推荐文章

  1. 20+个很棒的 Python 脚本的集合(迷你项目)
  2. 又发现一个ChatGPT国内镜像站,无次数限制也无广告
  3. 解决报错:org.springframework.web.client.HttpClientErrorException$Unauthorized: 401 : [no body]
  4. 解决 eslint 的 Parsing error: Unexpected token 错误
  5. Proxy error: Could not proxy request
  6. 五、肺癌检测-数据集训练 training.py model.py
  7. 安装Photoshop时出现The installation cannot continue as the installer file may be damaged. Download the in
  8. STM32单片机之温湿度检测系统(DTH11、OLED、LCD1602)
  9. 误差分析计算公式及其 matlab 代码实现(mse、mape、rmse等)
  10. echarts——实现3D地图+3D柱状图 效果——粗糙代码记录——技能提升

vue3+ts 登陆页面,前端实现滑块验证

2022-11-21 08:19 1108人阅读  评论(0)
<template>
    <div class="login" @keyup.enter="clickLogin">
        <div class="loginModule" ref="formWrap">
            <div class="logo">
                <img src="@/assets/images/logo.png" alt="" />
            </div>
            <div class="form">
                <el-form ref="loginFormRef" :rules="loginRules" :model="loginForm">
                    <el-form-item prop="username">
                        <el-input
                            clearable
                            placeholder="用户名"
                            v-model="loginForm.username"
                        >
                        </el-input>
                    </el-form-item>
                    <el-form-item prop="password">
                        <el-input
                            clearable
                            show-password
                            placeholder="密码"
                            v-model="loginForm.password"
                        >
                        </el-input>
                    </el-form-item>
                    <div class="sliderValidate">
                        <div
                            class="validateWrap"
                            ref="sliderWrap"
                            :class="{
                                validatePass: validPass
                            }"
                        >
                            <div class="block" ref="slider">
                                <img
                                    v-show="validPass"
                                    src="@/assets/images/Login/slider-icon.png"
                                    alt="滑块"
                                />
                                <div class="sliderIcon" v-show="!validPass">
                                    <DArrowRight style="width: 1em; height: 1em; " />
                                </div>
                            </div>
                            <span v-show="validPass" class="validatePass">验证通过</span>
                            <span v-show="!validPass" class="noValidate">拖动滑块校验</span>
                        </div>
                    </div>
                    <div class="showResetPassword">
                        <p>
                            <span class="sliderValid" v-if="showSliderWarn">请拖动滑块完成校验</span>
                        </p>
                    </div>
                </el-form>
                <a-button class="loginButton" type="primary" @click="clickLogin">登录</a-button>
            </div>
        </div>
    </div>
</template>
<script lang="ts" setup>
// ref:用于声明基础类型响应式数据, reactive:用于声明复杂类型响应式数据。unref:如果参数是一个 ref 则返回它的 value,否则返回参数本身
import {
      reactive, ref, unref, onMounted, inject, getCurrentInstance } from "vue";
// 接口
import {
      login } from "@/api/User";
// 节流
import throttle from "@/utils/common"
// 提示信息
const Mes: any = inject('$message')
// 登陆密码加密
import {
      submitEncrypt } from '@/utils/jsencrypt';

// 对用户和密码进行类型限制
interface loginData {
     
    username: string;
    password: string;
}

//登录数据
let loginForm = reactive<loginData>({
     
    username: "",
    password: ""
});

// 检查用户名是否存在
const usernameCheck = async (rule: any, value: string, cb: any) => {
     
    if (!/^\w{5,20}$/g.test(value)) {
     
        return cb("用户名不合法");
    }
  
};
// 登录数据校验
let loginRules = reactive({
     
    username: [ {
      required: true, message: "请输入用户名", trigger: "blur" }, {
      validator: usernameCheck, trigger: 'blur' } ],
    password: [ {
      required: true, message: "请输入密码", trigger: "blur" } ]
});
// 表单校验结果
const loginFormRef = ref();

// 标示滑块校验是否通过
const validPass = ref(false)
// 显示滑块校验文字提示
const showSliderWarn = ref(false)
// 滑块 ref
const slider = ref()
// 滑块容器 ref
const sliderWrap = ref()
// 登陆模块 ref
const formWrap = ref()

/**
 * 为滑块添加事件
 */
function sliderEvent() {
     
    if (!slider.value || !sliderWrap.value) return null;
    // 滑块容器的宽度
    const sliderBoxWidth = sliderWrap.value.clientWidth;
    // 滑块宽度
    const sliderWidth = slider.value.clientWidth;
    // 最大可拖动距离
    const maxSlideX = sliderBoxWidth - sliderWidth;
    // 滑块容器距离屏幕左边的距离(通过父级元素的offsetLeft计算)
    const formClientX = formWrap.value.offsetLeft + 43;
    // 滑块划过的过程
    slider.value.onmousedown = function(e: any) {
     
        const offsetX = e.offsetX
        // 滑块校验已通过
        if (validPass.value) {
     
            return
        }
        // 鼠标在页面上进行移动
        document.onmousemove = function(e: any) {
     
            if (validPass.value) {
     
                document.onmousemove = null;
                document.onmouseup = null;
                return;
            }
            const x = e.clientX - formClientX - offsetX;
            if (x > 0 && x < maxSlideX) {
     
                slider.value.style.left = x + "px";
            }
            if (x < 0) {
     
                slider.value.style.left = "0px";
            }
            if (x > maxSlideX) {
     
                slider.value.style.left = maxSlideX + "px";
                validPass.value = true;
                showSliderWarn.value = false;
            }
            if (x === maxSlideX) {
     
                validPass.value = true;
                showSliderWarn.value = false;
            }
        }
        //鼠标按键被松开
        document.onmouseup = function(e: any) {
     
            const centerX = sliderBoxWidth / 2 - 23;
            let x = e.clientX - formClientX - offsetX;
            
            let timer: any = null;
            
            // 恢复到起始点
            if (x <= centerX && x > 0) {
     
                timer = setInterval(() => {
     
                    x -= 2;
                    if (x <= 0) {
     
                        clearInterval(timer);
                        slider.value.style.left = "0px";
                    }
                    
                    slider.value.style.left = x + "px";
                }, 1);
            } else if (x > centerX && x < maxSlideX) {
      // 终点
                timer = setInterval(() => {
     
                    x += 2;
                    if (x >= maxSlideX) {
     
                        clearInterval(timer);
                        slider.value.style.left = maxSlideX + "px";
                        validPass.value = true;
                        showSliderWarn.value = false;
                    }
                    slider.value.style.left = x + "px";
                }, 1);
            }
            document.onmousemove = null;
            document.onmouseup = null;
        }
    }
}

// 节流
const throttles = throttle(2000);
/**
 * 登陆
 */

const clickLogin = () => {
     
    throttles(async () => {
     
        const form: any = unref(loginFormRef)
        await form.validate()
        if (validPass.value) {
     
            showSliderWarn.value = false;
            // 登陆
            await isLogin();
        } else {
     
            showSliderWarn.value = true;
        }
    })
}



/**
 * 执行登陆
 */
async function isLogin() {
     
    try {
     
        const {
      data } = await login({
     
            username: loginForm.username,
            password: submitEncrypt(loginForm.password)
        })
        if (data.code) {
     
        	//登陆成功
        }else{
     
        	// 失败
        }
        
   
    } catch (err) {
     
        console.log('e', err)
        Mes.error('用户名或密码错误,请重试')
    }
}

onMounted(() => {
     
    // ref页面组件还没有挂载完成,需要在挂载完成之后才能使用refs
    sliderEvent()
});
</script>

<style lang="scss" scoped src="./Login.scss"></style>

 

转载:https://blog.csdn.net/weixin_44996782/article/details/127751280
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场

Copyright © 2016 wya1 wya1.com All Rights Reserved 鄂ICP备15022242号-2