Vue3+Vite+Pinia+Naive后台管理系统搭建之八:构建 login.vue 登录页

前言

如果对 vue3 的语法不熟悉的,可以移步Vue3.0 基础入门,快速入门。

项目所需要的图片,icon图标(推荐:阿里巴巴矢量图标库)自行获取,命名一致就行。

1. 构建 src/components/CopyRight.vue 版本号组件

<!-- src/components/CopyRight.vue  -->
<script setup>
const props = defineProps({color: {type: String,},
});
</script><template><p :style="{ color }">版权所有 © YLD科技有限公司,保留所有权利,川F3-20233308号</p>
</template><style lang="scss" scoped>
p {position: absolute;bottom: 15px;left: 0;right: 0;text-align: center;color: #fff;font-family: Arial;font-size: 12px;letter-spacing: 1px;
}
</style>

2. 构建 src/components/SvgIcon.vue 图标组件

参考在 vue3 中构建 SvgIcon 组件

3. 编辑 src/pages/login.vue

<!-- src/pages/login.vue -->
<script setup>
import cookie from "js-cookie";
import { ref, reactive } from "vue";
import { NButton, NInput, NForm, NFormItem, NCheckbox } from "naive-ui";
import router from "@/router/index.js";
import { useUserStore } from "@/store/user.js";
import { encrypt, decrypt } from "@/utils/jsencrypt";
import { getCodeImg } from "@/api/login.js";import CopeRight from "@/components/CopyRight.vue";// 用户状态管理
let userStore = useUserStore();// 是否需要验证码
let needCode = ref(false);
let codeUrl = ref("");
// 获取图形验证码
function getCode() {getCodeImg().then((res) => {needCode.value =res.captchaEnabled === undefined ? true : res.captchaEnabled;if (needCode.value) {codeUrl.value = "data:image/gif;base64," + res.img;form.uuid = res.uuid;}});
}
getCode();// 登录
let formRef = ref(null);
let form = reactive({username: "",password: "",code: "",uuid: "",
});
let rules = {username: {required: true,trigger: ["input", "blur"],message: "请输入用户名",},password: {required: true,trigger: ["input", "blur"],message: "请输入密码",},code: {required: true,trigger: ["input", "blur"],message: "请输入验证码",},
};
let rememberMe = ref(false);
let loginBtnState = ref(false);
let handleLogin = () => {loginBtnState.value = true;formRef.value?.validate((errors) => {if (!errors) {if (rememberMe.value) {cookie.set("username", form.username, { expires: 30 });cookie.set("password", encrypt(form.password), { expires: 30 });cookie.set("rememberMe", rememberMe.value, { expires: 30 });} else {cookie.remove("username");cookie.remove("password");cookie.remove("rememberMe");}userStore.login(form).then(() => {window.$msg.success("登录成功");router.push({ name: "home" });}).catch(() => {loginBtnState.value = false;getCode();});} else {loginBtnState.value = false;}});
};// 获取默认登录账号
function getCookie() {form.username = cookie.get("username") || "";form.password = decrypt(cookie.get("password")) || "";rememberMe.value = Boolean(cookie.get("rememberMe")) || false;
}
getCookie();
</script><template><div class="login-bg c-center"><div class="login__box"><div class="login-logo__box"><div class="login__title login-logo">登 录</div></div><n-formref="formRef"class="login-form__box":model="form":rules="rules"label-placement="left"><n-form-item path="username"><n-inputclass="login-input"v-model:value="form.username"placeholder="请输入用户名/手机号"@blur="validate"><template #prefix><svg-icon name="username" color="grey"></svg-icon></template></n-input></n-form-item><n-form-item path="password"><n-inputclass="login-input"v-model:value="form.password"placeholder="请输入密码"type="password"show-password-on="mousedown"@keyup.enter="handleLogin"><template #prefix><svg-icon name="password" color="grey"></svg-icon></template></n-input></n-form-item><n-form-item v-if="needCode" class="login-code" path="code"><n-inputv-model:value="form.code"class="login-input login-input_code"placeholder="验证码"@keyup.enter="handleLogin"><template #prefix><svg-icon name="code" color="grey"></svg-icon></template></n-input><img class="login-code-img" :src="codeUrl" @click="getCode" /></n-form-item><div class="login-checkbox_box"><n-checkboxclass="login-checkbox"v-model:checked="rememberMe"></n-checkbox><span>记住密码</span></div><n-buttonclass="login-btn_login"type="info"@click="handleLogin":loading="loginBtnState":disabled="loginBtnState">登录</n-button></n-form><!-- <div class="login-btn_forget" @click="handleForget">忘记密码 ?</div> --></div><cope-right></cope-right></div>
</template><style lang="scss">
.n-form-item {margin-top: -20px;
}
</style><style lang="scss" scoped>
.login-bg {width: 100vw;height: 100vh;background-image: url("@/assets/imgs/login_bg.png");background-size: cover;background-repeat: no-repeat;overflow: hidden;.login__box {width: 425px;padding: 20px 40px;border-radius: 10px;background: rgba(2, 57, 104, 0.7);box-shadow: 0 0 30px rgba(2, 57, 104, 0.7);box-sizing: border-box;.login__title {font-size: 24px;text-align: center;color: #fff;}}
}.login-title {margin-bottom: 15px;text-align: center;letter-spacing: 10px;font-size: 18px;color: #fff;opacity: 1;
}.login-logo__box {display: flex;justify-content: center;align-items: center;margin-bottom: 20px;text {display: flex;align-items: center;font-size: 16px;font-family: "Gill Sans", "Gill Sans MT", Calibri, "Trebuchet MS",sans-serif;color: #1d69a3;&::before {content: "";display: inline-block;margin: 0 5px;width: 5px;height: 5px;background: gray;border-radius: 50%;}}
}.login-logo {width: 55%;img {width: 100%;object-fit: cover;}
}.login-code {.login-input_code {width: 240px;}.login-btn_code {color: #fff;margin-left: 20px;}
}.login-btn_login {height: 40px;width: 100%;
}.login-input {margin-top: 20px;
}.login-checkbox_box {display: flex;align-items: center;justify-content: flex-end;margin: -16px 0 10px;color: #71a1c5;font-size: 12px;
}.login-checkbox {margin-right: 5px;
}.login-btn_forget {margin-top: 10px;text-align: center;font-size: 12px;color: #71a1c5;cursor: pointer;
}.login-code-img {margin-top: 20px;width: 30%;height: 35px;margin-left: 20px;object-fit: contain;cursor: pointer;
}
</style>

 

综上

login.vue 登录页构建完成。下一章:layout 动态路由布局

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL~索引的优缺点是什么?有哪些优化索引的方法?

1.索引的优缺点 优点&#xff1a;提高查询记录的速度。 缺点&#xff1a; 需要占用空间&#xff0c;索引是一种用空间换时间的做法创建索引和维护索引都需要消耗时间&#xff0c;会降低表的增删查改效率&#xff0c;因为每次进行增删查改&#xff0c;都需要对索引进行维护&a…

系统设计蓝图 / 备忘单

开发一个强大、可扩展和高效的系统可能会令人望而却步。然而&#xff0c;了解关键概念和组件可以使这个过程更可管理。在本博客文章中&#xff0c;我们将探讨系统设计的关键概念和组件&#xff0c;如DNS、负载均衡、API网关等&#xff0c;以及一个简明的备忘单&#xff0c;可以…

自定义类型详解

目录 一、结构体类型 1.认识结构体 2.如何使用结构体类型 2.1按顺序初始化结构体&#xff0c;并通过.符号访问 ​2.2无序初始化结构体&#xff0c;并用.符号访问 2.3通过地址的方式访问结构体变量成员 2.4结构体的自引用 2.4.1错误的自引用 2.4.2正确的自引用 3.结构体内存…

Ansible 自动化运维工具(完善版)

目录 Ansible概述 Ansible特点 Ansible应用 1、使用者 2、Ansible工具集合 3、作用对象 Ansible的搭建 环境 ansible主机 1、ansible 2、Ansible-doc Ansible模块 1.command模块 2.shell模块 3.raw模块 Ansible概述 Ansible是最近非常火的一款开源运维自动化工具…

最全的ubuntu20.04上安装nvidia和cuda

文章目录 一、环境要求二、查询推荐安装的驱动版本三、安装470四、查看显卡驱动是否成功五、安装对应版本的cuda 官方路径 一、环境要求 ubuntu20.04如果之前有过驱动应该先卸载 sudo apt-get --purge remove nvidia* sudo apt autoremove# 卸载cuda sudo apt-get --purge r…

Oracle通过函数调用dblink同步表数据方案(全量/增量)

创建对应的包&#xff0c;以方便触发调用 /*包声明*/ CREATE OR REPLACE PACKAGE yjb.pkg_scene_job AS /*创建同步任务*/FUNCTION F_SYNC_DRUG_STOCK RETURN NUMBER;/*同步*/PROCEDURE PRC_SYNC_DRUG_STOCK(RUNJOB VARCHAR2) ; END pkg_scene_job; /*包体*/ CREATE OR REPL…

Hudi基础知识讲解

Hudi概述 Hudi是一种数据湖的存储格式&#xff0c;在Hadoop文件系统之上提供了更新数据和删除数据的能力以及消费变化数据的能力。支持多种计算引擎&#xff0c;提供IUD接口&#xff0c;在 HDFS的数据集上提供了插入更新和增量拉取的流原语。 基础架构图 Hudi特性 ACID事务能…

用户案例 | Apache DolphinScheduler 离线调度在自如多业务场景下的应用与实践

用户案例 | 自如 随着自如业务的快速发展&#xff0c;不断增长的调度任务和历史逾万的存量任务对平台稳定性提出了更高的要求。同时&#xff0c;众多非专业开发人员也需要一种更为“亲民”的调度平台使用体验。 如何满足这些日渐凸显的需求对自如大数据平台的开发团队来说&am…

2023年最全最新的学习课程合集

WEB前端入门&#xff1a;从零开始做网站。 完成所有课堂练习就可以做出自己的作品&#xff0c;并掌握数据库和了解开源项目。 这些课程涵盖了HTML、CSS和JavaScript等前端技术&#xff0c;以及与之相关的设计原则和最佳实践。 前端课程的目标是培养学生在网页开发方面的技能…

冒泡排序模拟实现qsort()函数

冒泡排序模拟实现qsort函数 前言1. 分析2. 解决一&#xff0c;如何接受不同数据3. 解决二&#xff0c;如何实现不同数据的比较4. 解决三&#xff0c;如何实现不同数据交换5. 模拟bubble_sort&#xff08;&#xff09;函数排序整型所有代码实现6. 结构体排序实现7. 结尾 前言 要…

应急管理大屏助力暴雨天气下的水灾防范

随着气候变化和城市化进程的加剧&#xff0c;暴雨天气引发的水灾风险日益凸显。在面对这种自然灾害时&#xff0c;如何高效、及时地应对、减轻损失成为了当务之急。水灾应急管理平台的可视化大屏为相关部门和决策者提供了实时、全面的信息展示和决策支持&#xff0c;大大提升了…

逻辑(css)-背景网格制作(linear-gradient)

目录 linear-gradient需求实现 linear-gradient 语法&#xff1a;linear-gradient([direction], color-stop1, color-stop2, ...) 第一个参数为(可选)方向参数&#xff0c;可以是度数也可以是方位名词,方向与读书的关系如下&#xff1a; 角度方位文字说明示例0degto top从下…