vue3:八、登录界面实现-忘记密码

news2025/3/15 6:50:46

一、页面效果

二、实现

1、视图层

<el-form-item class="flex flex-between">
    <el-checkbox label="记住密码" v-model="remember" />
</el-form-item>

参考

Checkbox 多选框 | Element Plus

2、逻辑层

首先设置记住密码的变量,默认值为否。

勾选后,在执行登录成功后,将记住的账号密码存入缓存。(密码的存取需要用到密码加密与解密)

如果记住密码,进入登录页面将账号密码自动显示到账号框和密码框,并且勾选记住密码

①设置变量

const remember = ref(false)

②封装解密加密方法

安装crypto-js 库

npm install crypto-js

这里使用AES(Advanced Encryption Standard)​ 加密算法

建立页面src/utils/encrypt.js

// 引入方法
import CryptoJS from 'crypto-js';

// 加密密钥(建议存储在环境变量中)
const SECRET_KEY = 'cmskey-QWERTYUIOPASDFGHJKLZXCVBNM';

// 加密函数
export function encryptData(data) {
  return CryptoJS.AES.encrypt(JSON.stringify(data), SECRET_KEY).toString();
}

// 解密函数
export function decryptData(encryptedData) {
  const bytes = CryptoJS.AES.decrypt(encryptedData, SECRET_KEY);
  return JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
}

③封装记住密码的本地存储管理

建立页面src/utils/logininfo.js

  • 存入缓存:正常传递的参数是一个对象{username:'',password:''},先对密码进行加密,然后转换为字符串进行存入缓存
  • 取出缓存:首先从缓存中获取,获取之后需要将字符串转换为对象,然后将加密的密码进行解密,将设置的新对象进行返回。如果没获取到,清除之前存储的数据
  • 删除缓存:根据名称清除记住密码的缓存
//引入加密和解密方法
import { encryptData,decryptData } from '@/utils/encrypt'; 
//设置变量
const rememberMeKey = 'rememberMe';

//将需要记住的账号密码存入本地缓存
export function setLoginInfo(loginInfo) {
  //密码加密
  loginInfo.password = encryptData(loginInfo.password);
  //将对象转换为字符串
  loginInfo = JSON.stringify(loginInfo);
  //设置到本地缓存
  localStorage.setItem(rememberMeKey, loginInfo);
}

//获取账号密码
export function getLoginInfo() {
  //获取账号密码
  const loginInfo = localStorage.getItem(rememberMeKey);
  //判断是否为空
  if (loginInfo) {
    //不为空,返回账号密码
    //转换为对象
    const LoginBase = JSON.parse(loginInfo);
    //对密码进行解密
    LoginBase.password = decryptData(LoginBase.password);
    return LoginBase;
  }
  else{
    //如果没有账号密码,清空之前存的,也就是返回空
    removeLoginInfo();
  }
}
//删除记住的账号密码
export function removeLoginInfo() {
  localStorage.removeItem(rememberMeKey);
}

④登录成功后,将记住的密码存入缓存

//勾选了记住密码
if(remember){
    setLoginInfo({
        username: ruleForm.username,
        password: ruleForm.password
    });
}
else{
    removeLoginInfo();
}

⑤ 记住密码的默认设置

//获取记住密码的数据
const rememberInfo = getLoginInfo();
if(remember){
    //将账号密码设置到页面,并勾选多选框
    ruleForm.username = rememberInfo.username;
    ruleForm.username = rememberInfo.username;
    remember.value = true;
}

三、测试效果

登录前记录缓存-没有账号密码信息

登录成功后,查询本地缓存

成功进入页面,查看是否记录到页面

取消勾选,查看缓存是否清空

发现已经清空缓存

重新进入登录页面,查看页面信息是否清除

四、完整代码

1、登录页面

LoginView.vue

<template>
    <div class="page_all flex flex-center">
        <div class="login_all flex flex-between">
            <div class="login_left flex flex-center"><img src="/svg/login.png"></div>
            <div class="login_right flex flex-center flex-column">
                <div class="form flex flex-center flex-column">
                    <div class="title flex flex-center">CMS管理系统</div>
                    <el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" class="el-form demo-ruleForm"
                        :size="formSize" status-icon>
                        <el-form-item prop="username">
                            <el-input v-model="ruleForm.username" placeholder="请输入账号" />
                        </el-form-item>
                        <el-form-item prop="password">
                            <el-input v-model="ruleForm.password" show-password placeholder="请输入密码" />
                        </el-form-item>
                        <el-form-item class="flex flex-between">
                            <el-checkbox label="记住密码" v-model="remember" />
                        </el-form-item>
                        <el-form-item class="btn-group">
                            <el-button type="primary" @click="submitForm(ruleFormRef)">
                                登录
                            </el-button>
                            <el-button @click="resetForm(ruleFormRef)">重置</el-button>
                        </el-form-item>
                    </el-form>
                </div>
            </div>
        </div>
    </div> 
</template>
<script setup>
//引入方法
import { reactive, ref } from 'vue' //引入vue响应式
import { login } from '@/api/logininfo' //引入登录接口
import { useRouter } from 'vue-router'  //引入路由
import { ElMessage } from 'element-plus' //引入提示框
import { setToken } from '@/utils/token' //引入token设置
import { getLoginInfo, removeLoginInfo, setLoginInfo } from '@/utils/logininfo'

//设置表单大小
const formSize = ref('default')
//设置表单数据
const ruleFormRef = ref()
const ruleForm = reactive({
    username: '',
    password: '',
})
//设置路由
const router = useRouter();

//设置验证规则
const rules = reactive({
    username: [
        { required: true, message: '请输入账号', trigger: 'blur' },
        { min: 3, max: 10, message: '长度请在3-10之间', trigger: 'blur' },
    ],
    password: [
        { required: true, message: '请输入密码', trigger: 'blur' },
        { min: 6, max: 20, message: '长度请在6-20之间', trigger: 'blur' },
        {
            validator: (rule, value, callback) => {
                const passwordPattern = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]+$/;
                if (!passwordPattern.test(value)) {
                    callback(new Error('密码必须包含大写字母、小写字母、数字和特殊字符'));
                } else {
                    callback();
                }
            }, trigger: 'blur'
        },
        // 或者
        // {pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]+$/, message: '密码必须包含大写字母、小写字母、数字和特殊字符', trigger: 'blur'}
    ],
})
//设置记住密码
const remember = ref(false)
//获取记住密码的数据
const rememberInfo = getLoginInfo();
if(remember){
    //将账号密码设置到页面,并勾选多选框
    ruleForm.username = rememberInfo.username;
    ruleForm.username = rememberInfo.username;
    remember.value = true;
}
//表单提交
const submitForm = async (formEl) => {
    if (!formEl) return
    await formEl.validate((valid, fields) => {
        if (valid) {
            console.log('submit!');
            // 1、请求登录接口进行登录
            // 参数为ruleForm
            console.log(ruleForm)
            // 2、请求登录接口进行登录
            login( ruleForm ).then(res => {
                console.log('res:', res)
                if (res.code == 1) {
                    // 3、提示成功信息
                    ElMessage.success(res.msg || '登录成功')
                    //记住密码勾选
                    if(remember){
                        setLoginInfo({
                            username: ruleForm.username,
                            password: ruleForm.password
                        });
                    }
                    else{
                        removeLoginInfo();
                    }
                    //存入该账号的token
                    setToken(res.data.token)
                    // 4、跳转页面
                    router.push('/')
                }
                else {
                    ElMessage.error(res.msg || '登录失败')
                }
            })
        } else {
            console.log('error submit!', fields)
        }
    })
}
//重置表单
const resetForm = (formEl) => {
    if (!formEl) return
    formEl.resetFields()
}

</script>
<style>
.page_all {
    width: 100%;
    height: 100vh;
    background-color: #808cdd;
}

.login_all {
    width: 50%;
    height: 60%;
    background-color: white;
}

.login_left {
    width: 50%;
    height: 98%;
}

.login_left img {
    width: 95%;
    height: 80%;
    object-fit: contain;
}

.login_right {
    width: 50%;
    height: 100%;
}

.title {
    font-size: 25px;
    color: #646cff;
    letter-spacing: 3px;
    height: 20%;
}

.form {
    flex: 1;
    width: 90%;
}

.el-form {
    width: 60%;
}

.el-input__inner {
    font-size: 12px;
}

.btn-group {
    width: 100%;
    margin-top: 30px;
}

.btn-group button {
    width: 45%;
}

.el-form-item__content {
    justify-content: space-between;
}
</style>

2、记住密码的本地存储管理

src/utils/logininfo

import { encryptData,decryptData } from '@/utils/encrypt'; 
//设置变量
const rememberMeKey = 'rememberMe';

//将需要记住的账号密码存入本地缓存
export function setLoginInfo(loginInfo) {
  //密码加密
  loginInfo.password = encryptData(loginInfo.password);
  //将对象转换为字符串
  loginInfo = JSON.stringify(loginInfo);
  //设置到本地缓存
  localStorage.setItem(rememberMeKey, loginInfo);
}

//获取账号密码
export function getLoginInfo() {
  //获取账号密码
  const loginInfo = localStorage.getItem(rememberMeKey);
  //判断是否为空
  if (loginInfo) {
    //不为空,返回账号密码
    //转换为对象
    const LoginBase = JSON.parse(loginInfo);
    //对密码进行解密
    LoginBase.password = decryptData(LoginBase.password);
    return LoginBase;
  }
  else{
    //如果没有账号密码,清空之前存的,也就是返回空
    removeLoginInfo();
  }
}

export function removeLoginInfo() {
  localStorage.removeItem(rememberMeKey);
}

3、加密解密

// src/utils/encrypt.js
import CryptoJS from 'crypto-js';

// 加密密钥(建议存储在环境变量中)
const SECRET_KEY = 'cmskey-QWERTYUIOPASDFGHJKLZXCVBNM';

// 加密函数
export function encryptData(data) {
  return CryptoJS.AES.encrypt(JSON.stringify(data), SECRET_KEY).toString();
}

// 解密函数
export function decryptData(encryptedData) {
  const bytes = CryptoJS.AES.decrypt(encryptedData, SECRET_KEY);
  return JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

el-table树形表格合并相同的值

el-table树形表格合并相同的值 el-table树形表格合并相同的值让Ai进行优化后的代码 el-table树形表格合并相同的值 <style lang"scss" scoped> .tableBox {/deep/ &.el-table th:first-child,/deep/ &.el-table td:first-child {padding-left: 0;} } …

Apache Tomcat漏洞,对其进行升级

我们付出一些成本&#xff0c;时间的或者其他&#xff0c;最终总能收获一些什么。 升级背景&#xff1a; 近日&#xff0c;新华三盾山实验室监测到 Apache 官方修复了一个远程代码执行漏洞 (CVE-2025-24813) &#xff0c;其CVSS3 漏洞评分为 7.5 。 影响范围 9.0.0.M1 ≤…

工程实践:如何使用SU17无人机来实现室内巡检任务

阿木实验室最近发布了科研开发者版本的无人机SU17&#xff0c;该无人机上集成了四目视觉&#xff0c;三维激光雷达&#xff0c;云台吊舱&#xff0c;高算力的机载计算机&#xff0c;是一个非常合适的平台用于室内外巡检场景。同时阿木实验室维护了多个和无人机相关的开源项目。…

OSPF-3 1类LSA Router LSA

前面两期我们介绍了OSPF的邻居与邻接建立的关系及失败因素和原因 这章我们来说说OSPF是如何通过不同的LSA去描述拓扑的信息以及路由信息 一、概述 OSPF通过不同的LSA来构成LSDB链路状态数据库,再通过SPF算法来计算出最优的最短路径 二、LSA的分类 类型名称描述传播范围1类…

【清华大学第七版】DeepSeek赋能家庭教育的实操案例(批改作文+辅助语文/数学/科学学习+制定学习计划)

我用夸克网盘分享了「DeepSeek完整资料合集」&#xff0c;点击链接即可保存。打开「夸克APP」&#xff0c;无需下载在线播放视频&#xff0c;畅享原画5倍速&#xff0c;支持电视投屏。 链接&#xff1a;https://pan.quark.cn/s/621259e4af15 近日&#xff0c;清华大学发布了《…

HCIA-ACL实验

前提条件&#xff1a;实现底层互通 转发层面 1、基本ACL ①要求PC3不能访问网段192.168.2.0的网段&#xff0c;PC4和客户端能正常访问服务器 ②AR2配置 acl 2000 rule deny source 192.168.1.1 0 匹配流量 int g 0/0/0 traffic-filter inbound acl 2000 接口调用…

DeepLabv3+改进10:在主干网络中添加LSKBlock|动态调整其大型空间感受野,助力小目标识别

🔥【DeepLabv3+改进专栏!探索语义分割新高度】 🌟 你是否在为图像分割的精度与效率发愁? 📢 本专栏重磅推出: ✅ 独家改进策略:融合注意力机制、轻量化设计与多尺度优化 ✅ 即插即用模块:ASPP+升级、解码器 PS:订阅专栏提供完整代码 目录 论文简介 步骤一 步骤二…

词向量:优维大模型语义理解的深度引擎

★ 放闸溯源 优维大模型「骨架级」技术干货 第二篇 ⇓ 词向量是Transformer突破传统NLP技术瓶颈的核心&#xff0c;它通过稠密向量空间映射&#xff0c;将离散符号转化为连续语义表示。优维大模型基于词向量技术&#xff0c;构建了运维领域的“语义地图”&#xff0c;实现从…

编译原理:语法分析程序【附源码和超详细注释】

目录 一 、实验目的 二 、实验内容及步骤 三、程序分析 1. 需求分析 2. 功能分析 1. LL(1)文法功能分析 2. 算符优先文法功能分析 3. 信创分析-主要针对能力提升中国产操作系统上开发内容。 四、源代码 1. LL(1)文法代码 2. 算符优先文法 五、测试结果 1. LL(1)文…

使用Flask和OpenCV 实现树莓派与客户端的视频流传输与显示

使用 Python 和 OpenCV 实现树莓派与客户端的视频流传输与显示 在计算机视觉和物联网领域&#xff0c;经常需要将树莓派作为视频流服务器&#xff0c;通过网络将摄像头画面传输到客户端进行处理和显示。本文将详细介绍如何利用picamera2库、Flask 框架以及 OpenCV 库&#xff…

fs的proxy_media模式失效

概述 freeswitch是一款简单好用的VOIP开源软交换平台。 在fs的使用过程中&#xff0c;某些场景只需要对rtp媒体做透传&#xff0c;又不需要任何处理。 在fs1.6的版本中&#xff0c;我们可以使用proxy_media来代理媒体的转发&#xff0c;媒体的协商由AB路端对端处理&#xff…

Linux 命名管道

文章目录 &#x1f680; 深入理解命名管道&#xff08;FIFO&#xff09;及其C实现一、命名管道核心特性1.1 &#x1f9e9; 基本概念 二、&#x1f4bb; 代码实现解析2.1 &#x1f4c1; 公共头文件&#xff08;common.hpp&#xff09;2.2 &#x1f5a5;️ 服务器端&#xff08;s…

HDU 学数数导致的

题目解析 首先&#xff0c;数对是有序的&#xff0c;<1,2>和<2,1>被视为不同的两组数字。 其次&#xff0c;数对<p,q>的p和q可以相等。 子序列为 p 0 p q&#xff0c;观察到&#xff0c;中间要出现一个0。那么&#xff0c;我们只需要找到第一个 p 满足与前…

软件/硬件I2C读写MPU6050

MPU6050简介 6轴&#xff1a;3轴加速度&#xff0c;3轴角速度 9轴&#xff1a;3轴加速度&#xff0c;3轴角速度和3轴磁场强度 10轴&#xff1a;3轴加速度&#xff0c;3轴角速度和3轴磁场强度和一个气压强度 加速度计具有静态稳定性&#xff0c;不具有动态稳定性 欧拉角&…

Android中的Wifi框架系列

Android wifi框架图 Android WIFI系统引入了wpa_supplicant&#xff0c;它的整个WIFI系统以wpa_supplicant为核心来定义上层接口和下层驱动接口。 Android WIFI主要分为六大层&#xff0c;分别是WiFi Settings层&#xff0c;Wifi Framework层&#xff0c;Wifi JNI 层&#xff…

【含文档+PPT+源码】基于Python的图书管理系统的设计与实现

项目介绍 本课程演示的是一款基于Python的图书管理系统的设计与实现&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 包含&#xff1a;项目源码、项目文档、数据库脚本、软件工具等所有资料 带你从零开始部署运行本套系统 该项目附…

开源工具利器:Mermaid助力知识图谱可视化与分享

在现代 web 开发中&#xff0c;可视化工具对于展示流程、结构和数据关系至关重要。Mermaid 是一款强大的 JavaScript 工具&#xff0c;它使用基于 Markdown 的语法来呈现可定制的图表、图表和可视化。对于展示流程、结构和数据关系至关重要。通过简单的文本描述&#xff0c;你可…

茂捷M1001电感式编码器芯片TSSOP28管脚,国产电感式编码器IC

简述&#xff1a; M1001 电感式编码器芯片是一款专为高精度位置检测而设计的芯片产品&#xff0c;采用先进的电感技术&#xff0c;能够精确测量旋转物体的位置和角度。芯片具有 SIN/COS、模拟、PWM、SENT、SPI、I2C等多种角度输出功能&#xff0c;具有高分辨率、宽工作温度范围…

LeetCode-跳跃游戏 II

方法一&#xff1a;反向查找出发位置 我们的目标是到达数组的最后一个位置&#xff0c;因此我们可以考虑最后一步跳跃前所在的位置&#xff0c;该位置通过跳跃能够到达最后一个位置。 如果有多个位置通过跳跃都能够到达最后一个位置&#xff0c;那么我们应该如何进行选择呢&a…

数据结构——双向链表dlist

前言&#xff1a;大家好&#x1f60d;&#xff0c;本文主要介绍了数据结构——双向链表dlist 一 双向链表定义 1. 双向链表的节点结构 二 双向链表操作 2.1 定义 2.2 初始化 2.3 插入 2.3.1 头插 2.3.2 尾插 2.3.3 按位置插 2.4 删除 2.4.1 头删 2.4.2 尾删 2.4.3 按…