vue3:八、登录界面实现-忘记密码
一、页面效果

二、实现
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) returnawait formEl.validate((valid, fields) => {if (valid) {console.log('submit!');// 1、请求登录接口进行登录// 参数为ruleFormconsole.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();}//存入该账号的tokensetToken(res.data.token)// 4、跳转页面router.push('/')}else {ElMessage.error(res.msg || '登录失败')}})} else {console.log('error submit!', fields)}})
}
//重置表单
const resetForm = (formEl) => {if (!formEl) returnformEl.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));
}
相关文章:
vue3:八、登录界面实现-忘记密码
一、页面效果 二、实现 1、视图层 <el-form-item class"flex flex-between"><el-checkbox label"记住密码" v-model"remember" /> </el-form-item> 参考 Checkbox 多选框 | Element Plus 2、逻辑层 首先设置记住密码的变…...
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漏洞,对其进行升级
我们付出一些成本,时间的或者其他,最终总能收获一些什么。 升级背景: 近日,新华三盾山实验室监测到 Apache 官方修复了一个远程代码执行漏洞 (CVE-2025-24813) ,其CVSS3 漏洞评分为 7.5 。 影响范围 9.0.0.M1 ≤…...
工程实践:如何使用SU17无人机来实现室内巡检任务
阿木实验室最近发布了科研开发者版本的无人机SU17,该无人机上集成了四目视觉,三维激光雷达,云台吊舱,高算力的机载计算机,是一个非常合适的平台用于室内外巡检场景。同时阿木实验室维护了多个和无人机相关的开源项目。…...
时序优化学习笔记
0.代码对应的底层调用 if-else的判定条件需要LUT实现,累加器的进位需要靠CARRY实现。 1.逻辑级数的概念 简单来讲就是组合逻辑串联的个数 逻辑级数查询命令 report_design_analysis -logic_level_distribution -logic_level_dist_paths 5000 -name design_analy…...
OSPF-3 1类LSA Router LSA
前面两期我们介绍了OSPF的邻居与邻接建立的关系及失败因素和原因 这章我们来说说OSPF是如何通过不同的LSA去描述拓扑的信息以及路由信息 一、概述 OSPF通过不同的LSA来构成LSDB链路状态数据库,再通过SPF算法来计算出最优的最短路径 二、LSA的分类 类型名称描述传播范围1类…...
纳米压印技术制备AR眼镜的参考步骤
纳米压印技术(Nanoimprint Lithography, NIL)在 AR(增强现实)眼镜中的应用主要集中在光学元件的制造上,例如衍射光栅、波导和微透镜阵列等。以下是使用纳米压印技术制备 AR 眼镜光学元件的详细步骤: 1. 设…...
FX-std::list
std::list 是 C 标准库中的一个双向链表容器,定义在 <list> 头文件中。它支持在任意位置高效地插入和删除元素,但不支持随机访问。以下是 std::list 的基本用法和一些常见操作: 1. 包含头文件 #include <list> 2. 定义和初始化…...
【清华大学第七版】DeepSeek赋能家庭教育的实操案例(批改作文+辅助语文/数学/科学学习+制定学习计划)
我用夸克网盘分享了「DeepSeek完整资料合集」,点击链接即可保存。打开「夸克APP」,无需下载在线播放视频,畅享原画5倍速,支持电视投屏。 链接:https://pan.quark.cn/s/621259e4af15 近日,清华大学发布了《…...
HCIA-ACL实验
前提条件:实现底层互通 转发层面 1、基本ACL ①要求PC3不能访问网段192.168.2.0的网段,PC4和客户端能正常访问服务器 ②AR2配置 acl 2000 rule deny source 192.168.1.1 0 匹配流量 int g 0/0/0 traffic-filter inbound acl 2000 接口调用…...
【Gee】项目总结:模仿 GIN 实现简单的 Golang Web 框架
文章目录 Gee 项目回顾Gee 项目总结Golang 已经具备基础的 web 功能,为什么还需要 web 框架?作为 web 框架,Gee 框架完成了哪些功能?如何用 Gee 来构建 web 项目? Gee 项目回顾 上个月月末我按照 Geektutu 的教程&…...
DeepLabv3+改进10:在主干网络中添加LSKBlock|动态调整其大型空间感受野,助力小目标识别
🔥【DeepLabv3+改进专栏!探索语义分割新高度】 🌟 你是否在为图像分割的精度与效率发愁? 📢 本专栏重磅推出: ✅ 独家改进策略:融合注意力机制、轻量化设计与多尺度优化 ✅ 即插即用模块:ASPP+升级、解码器 PS:订阅专栏提供完整代码 目录 论文简介 步骤一 步骤二…...
词向量:优维大模型语义理解的深度引擎
★ 放闸溯源 优维大模型「骨架级」技术干货 第二篇 ⇓ 词向量是Transformer突破传统NLP技术瓶颈的核心,它通过稠密向量空间映射,将离散符号转化为连续语义表示。优维大模型基于词向量技术,构建了运维领域的“语义地图”,实现从…...
编译原理:语法分析程序【附源码和超详细注释】
目录 一 、实验目的 二 、实验内容及步骤 三、程序分析 1. 需求分析 2. 功能分析 1. LL(1)文法功能分析 2. 算符优先文法功能分析 3. 信创分析-主要针对能力提升中国产操作系统上开发内容。 四、源代码 1. LL(1)文法代码 2. 算符优先文法 五、测试结果 1. LL(1)文…...
Go vs Rust vs C++ vs Python vs Java:谁主后端沉浮
一、核心性能对比(基于TechEmpower基准测试) 语言单核QPS延迟(ms)内存消耗适用场景Rust650,0000.1245MB高频交易/区块链C++720,0000.0932MB游戏服务器/实时渲染Go230,0000.45110MB微服务/API网关Java180,0001.2450MB企业ERP/银行系统Python12,0008.5220MBAI接口/快速原型技术…...
使用Flask和OpenCV 实现树莓派与客户端的视频流传输与显示
使用 Python 和 OpenCV 实现树莓派与客户端的视频流传输与显示 在计算机视觉和物联网领域,经常需要将树莓派作为视频流服务器,通过网络将摄像头画面传输到客户端进行处理和显示。本文将详细介绍如何利用picamera2库、Flask 框架以及 OpenCV 库ÿ…...
fs的proxy_media模式失效
概述 freeswitch是一款简单好用的VOIP开源软交换平台。 在fs的使用过程中,某些场景只需要对rtp媒体做透传,又不需要任何处理。 在fs1.6的版本中,我们可以使用proxy_media来代理媒体的转发,媒体的协商由AB路端对端处理ÿ…...
Linux 命名管道
文章目录 🚀 深入理解命名管道(FIFO)及其C实现一、命名管道核心特性1.1 🧩 基本概念 二、💻 代码实现解析2.1 📁 公共头文件(common.hpp)2.2 🖥️ 服务器端(s…...
HDU 学数数导致的
题目解析 首先,数对是有序的,<1,2>和<2,1>被视为不同的两组数字。 其次,数对<p,q>的p和q可以相等。 子序列为 p 0 p q,观察到,中间要出现一个0。那么,我们只需要找到第一个 p 满足与前…...
pjsip pjsua_media_config 结构体说明
clock_rate 描述:设置会议桥(conference bridge)的时钟频率(采样率)。 默认值:0(使用默认值 PJSUA_DEFAULT_CLOCK_RATE,通常为 16kHz)。 作用:影响音频的采样率,常见值有 8000(8kHz)、16000(16kHz)、48000(48kHz)等。snd_clock_rate 描述:设置音频设备的时钟…...
软件/硬件I2C读写MPU6050
MPU6050简介 6轴:3轴加速度,3轴角速度 9轴:3轴加速度,3轴角速度和3轴磁场强度 10轴:3轴加速度,3轴角速度和3轴磁场强度和一个气压强度 加速度计具有静态稳定性,不具有动态稳定性 欧拉角&…...
c++ union使用笔记
c union使用笔记 一、联合的简单使用二、联合与枚举结合三、匿名联合(Anonymous Union)四、关键注意事项五、C17 扩展:std::variant C联合(union)是一种特殊的数据结构,允许在相同内存位置存储不同的数据类…...
Android中的Wifi框架系列
Android wifi框架图 Android WIFI系统引入了wpa_supplicant,它的整个WIFI系统以wpa_supplicant为核心来定义上层接口和下层驱动接口。 Android WIFI主要分为六大层,分别是WiFi Settings层,Wifi Framework层,Wifi JNI 层ÿ…...
react(一):特点-基本使用-JSX语法
初识React React是一个用于构建用户界面的 JavaScript 库,由 Facebook 开发和维护。 官网文档:React 官方中文文档 特点 1.声明式编程 2.组件化开发 3.多平台适配 开发依赖 开发React必须依赖三个库: 1.react:包含react所必…...
【Go】无法访问 proxy.golang.org 进行依赖下载
golang.org/x/net/context: golang.org/x/netv0.37.0: Get "https://proxy.golang.org/golang.org/x/net/v/v0.37.0.zip": dial tcp 142.251.215.241:443: connect: connection refused解决方案: 使用国内的 Go 代理,如 goproxy.cn 或 gopro…...
鸿蒙 @ohos.arkui.observer (无感监听)
鸿蒙 ohos.arkui.observer (无感监听) 在鸿蒙开发中,ohos.arkui.observer 模块提供了一种强大的无感监听机制,允许开发者监听组件的状态变化、滚动事件、页面切换等事件。这些功能对于实现复杂的交互逻辑和优化性能非常有帮助。本文将详细介绍 ohos.ark…...
一键爬取b站视频
同学们。废话不多说, b站视频素材多, 二次加工就归你, 三话不说爬起来, 犯法违纪咱不干 代码 import json import requests from bs4 import BeautifulSoup import re# 目标网址bvnane"BV1hUQEYCEyY" pp("0&q…...
【含文档+PPT+源码】基于Python的图书管理系统的设计与实现
项目介绍 本课程演示的是一款基于Python的图书管理系统的设计与实现,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 包含:项目源码、项目文档、数据库脚本、软件工具等所有资料 带你从零开始部署运行本套系统 该项目附…...
开源工具利器:Mermaid助力知识图谱可视化与分享
在现代 web 开发中,可视化工具对于展示流程、结构和数据关系至关重要。Mermaid 是一款强大的 JavaScript 工具,它使用基于 Markdown 的语法来呈现可定制的图表、图表和可视化。对于展示流程、结构和数据关系至关重要。通过简单的文本描述,你可…...
Mysql的utf8mb4_general_ci 与 utf8mb4_bin 的具体区别是什么?中文适合哪个?
1. utf8mb4_general_ci vs utf8mb4_bin 的具体区别 utf8mb4_general_ci 和 utf8mb4_bin 都是 utf8mb4 编码的排序规则(collation),它们主要在 排序(ORDER BY) 和 比较(WHERE) 时的行为不同&…...
