vue3+Element plus实现登录功能

一、想要实现的效果

二、搭建登录静态

1、实现左边背景和右边登录栏的总体布局布局:

<el-row class="content">
    <!--el-col 列: -->
    <el-col :span="16" :xs="0" class="content-left"></el-col>
    <el-col :span="8" :xs="24" class="content-right">
<el-row>

2、账号密码登录和手机号码登录切换使用<el-tabs>组件实现:

3、其他省略

4、全部代码:

  <el-row class="content">
    <!--el-col 列: -->
    <el-col :span="16" :xs="0" class="content-left"></el-col>
    <el-col :span="8" :xs="24" class="content-right">
      <div class="loginContent">
        <div class="loginContentTop">
          <div class="header">
            <div class="logo">
              <img src="../assets/images/logo.png" alt="" class="image" />
            </div>
            <div class="fontSize">JinPiKa</div>
          </div>
          <span class="introduce">全球最大的代码托管平台</span>
        </div>
        <div class="loginContentForm">
          <div class="loginMethods">
            <el-tabs>
              <el-tab-pane
                label="账号密码登录"
                class="toLogin"
                :class="{ option: !option }"
                @click="toOption(0)"
              >
                <!-- loginForm: 表单数据对象-->
                <el-form
                  :model="loginForm"
                  :rules="loginFormRules"
                  style="width: 208px"
                >
                  <el-form-item label="" prop="username">
                    <el-input
                      :prefix-icon="User"
                      placeholder="用户名:user"
                      v-model="loginForm.username"
                      inline-message
                    ></el-input>
                  </el-form-item>
                  <el-form-item label="" prop="password">
                    <el-input
                      :prefix-icon="Lock"
                      placeholder="密码:user"
                      show-password
                      v-model="loginForm.password"
                      inline-message
                    ></el-input>
                  </el-form-item>
                </el-form>
              </el-tab-pane>
              <el-tab-pane
                label="手机号码登录"
                class="toLogin"
                :class="{ option: !option }"
                @click="toOption(0)"
              >
                <!-- loginForm: 表单数据对象-->
                <el-form
                  :model="loginFormPhone"
                  :rules="loginFormPhoneRules"
                  style="width: 208px"
                  prop="phone"
                >
                  <el-form-item label="">
                    <el-input
                      :prefix-icon="User"
                      placeholder="请输入手机号"
                      v-model="loginFormPhone.phone"
                      inline-message
                    ></el-input>
                  </el-form-item>
                  <el-form-item label="" prop="code">
                    <el-input
                      :prefix-icon="Lock"
                      placeholder="请输入验证码"
                      v-model="loginFormPhone.code"
                      inline-message
                    ></el-input>
                  </el-form-item>
                </el-form>
              </el-tab-pane>
            </el-tabs>
          </div>
        </div>
        <div class="loginContentButton">
          <div class="buttonTop">
            <el-checkbox v-model="checked" label="自动登录" size="small" />
            <el-link type="primary" :underline="false">
              <span style="font-size: 12px">忘记密码</span>
            </el-link>
          </div>
          <el-button type="primary" class="loginButton" @click="tologin">
            登录
          </el-button>
          <el-divider>
            <span class="fengexian">其他登录方式</span>
          </el-divider>
          <div class="svgItems">
            <div class="svgItem">
              <svg-icon
                name="zhifubao"
                width="18px"
                height="18px"
                color="pink"
              ></svg-icon>
            </div>
            <div class="svgItem">
              <svg-icon
                name="taobao"
                width="18px"
                height="18px"
                color="pink"
              ></svg-icon>
            </div>
            <div class="svgItem">
              <svg-icon
                name="weibo"
                width="18px"
                height="18px"
                color="pink"
              ></svg-icon>
            </div>
          </div>
        </div>
      </div>
    </el-col>
  </el-row>

三、封装接口

1、首先需要对axios进行一个二次封装,实现请求和响应拦截器,在utils文件夹(一般用于存放封装的文件)下创建一个request.ts文件,

import axios from 'axios'
const requeset=axios.create({
    baseURL: import.meta.env.BASE_URL,   //基础路径
    timeout:5000    //发请求超时时间为5s
})
//给request实例添加请求拦截器
request.interceptors.request.use((config)=>{
    // config:配置对象:里面有个headers属性请求头,经常给服务器端通过请求头携带公共参数
    return config
})
//配置响应拦截器
request.interceptors.response.use(
    //成功响应:返回服务端的数据    
    (response)=>{
        return response.data
    },
    //失败响应:会返回错误对象,用来处理http网络错误
    (error)=>{
    // 存储网络错误信息
    let message = ''
    // 根据http状态码判断网络错误
    const status = error.response.status
    switch (status) {
      case 401:
        message = '登录已过期,请重新登录'
        break
      case 403:
        message = '没有权限,请联系管理员'
        break
      case 404:
        message = '请求资源不存在'
        break
      case 500:
        message = '服务器内部错误'
        break
      default:
        // eslint-disable-next-line @typescript-eslint/no-unused-vars
        message = '网络错误'
        break
    }
    // 提示错误信息
    ElMessage({
      type: 'error',
      message,
    })
    // 返回一个失败的promise对象
    return Promise.reject(error)
    }

)

2、引入pinia

(1)在store文件夹下创建pinia仓库,
// 引入 pinia
import { createPinia } from 'pinia'
// 创建大仓库
const pinia = createPinia()
// 对外暴露
export default pinia
(2)在main.ts中,引入仓库并全局使用pinia
// 引入仓库
import pinia from './store'
// 全局使用 pinia
app.use(pinia)
3、在api文件夹下,封装登录接口,用于统一管理用户相关的接口
// 引入封装好的 request
import request from '@/plugins/request'
// 引入用户相关的 ts 类型检测
import { loginForm, loginResponseData } from './type'
//用户相关接口的请求地址
enum API{
    //用户登录的请求地址:在接口文档中,去掉默认请求地址baseURL后剩下的部分
    LOGIN='/admin/login'
}
//登录接口
export const reqLogin=(data:loginForm)=>{
    request.post<any,loginResponseData>(API.LOGIN,data)
}
或者第二种普通封装方式:
// 封装登录相关接口
import { loginForm } from '@/apis/user/type'
import request from '@/utils/request'
export function useLoginAPI(data: loginForm) {
  return request({
    url: 'http://monitor-spring.jinxinapp.cn/api/v1/admin/login',
    method: 'POST',
    data,
  })
}

3、在store文件夹下创建用户相关的小仓库

// 用户相关的小仓库
import { defineStore } from 'pinia'
//引入登录接口
import {reqLogin} from '@/api/user/index.ts'
const useUserStore=defineStore('user',{
    state:()=>{
        return{
            token:localStorage.getItem('token'),
        }
    },
    actions:{
        //用户登录的方法,data是登录时传入的账号密码
        async useLogin(data:loginForm){
            //登录请求
            const result=awiat reqLogin(data)
            if(result.code==200){
                this.token=result.data.token
                localStorage.getItem('token',result.data.token)
                   return 'ok'
            }else{
                return Promise.reject(new Error(result.data.message))
            }
        }
    },
    getters:{}
})
export default useUserStore

4、在登录页面,点击登录按钮调用tologin方法

const tologin=async ()=>{
    try{
        //调用仓库里的登录方法,传入的loginForm里面是账号密码
        await useStore.userLogin(loginForm)
        $router.push('/home')    //登录成功跳转首页,
        ElNotification({
              title: '成功',
              message: '登录成功',
              type: 'success',
        })
    }catch(error){
        ElNotification({
          message: (error as Error).message,
          type: 'error',
        })
    }
}


 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

司铭宇老师:电话销售心态培训:电话销售被拒绝怎么调整心态

电话销售心态培训&#xff1a;电话销售被拒绝怎么调整心态 在电话销售这个行业中&#xff0c;遭遇拒绝是家常便饭。无论你如何努力&#xff0c;总有那么些时候&#xff0c;客户会对你的产品或服务说“不”。然而&#xff0c;这并不意味着你的努力白费。关键在于如何调整心态&am…

洗内裤的小洗衣机买啥牌子的?四款家用小洗衣机推荐

随着内衣洗衣机的流行&#xff0c;很多小伙伴在纠结该不该入手一款内衣洗衣机&#xff0c;专门来洗一些贴身衣物&#xff0c;答案是非常有必要的&#xff0c;因为我们现在市面上的大型洗衣机只能做清洁&#xff0c;无法对我们的贴身衣物进行一个高强度的清洁&#xff0c;而小小…

Java|IDEA 运行和打包报错解决

IDEA 运行和打包报错解决 java.lang.NoSuchFieldError&#xff1a;com.sun.tools.javac.tree.JCTree$JCImport 报错信息 环境&#xff1a;JDK 21 java: java.lang.NoSuchFieldError: Class com.sun.tools.javac.tree.JCTree$JCImport does not have member field com.sun.t…

Messari发布重磅研报,波场TRON 2023 Q4期间实现多项突破

近日,顶级加密数据研究机构Messari发布了波场TRON 2023 Q4调研报告,报告从网络数据、生态、稳定币和RWA等多个方面对波场TRON进行了细致研究,并给与了波场TRON极大的肯定。这份调研报告帮助投资者和社区更好地了解波场TRON的发展前景和竞争优势。同时,这些数据和见解可以提高投…

嵌入式学习五

使用circuit JS模拟器讲解 一&#xff1a;欧姆定律 演示电压电阻的关系 欧姆定律 二&#xff1a;电阻 计算电阻串并联的阻值 电阻 电阻越串越大&#xff0c;越并越小 并联电路增加通路 三&#xff1a;电容器 观察电容的充放电 电容器 电容就是一个临时存储电量的容器 当电…

Unity_使用Image和脚本生成虚线段

生成如图样式的虚线段 原理&#xff1a;使用Image做一条线段&#xff0c;这个方法的原理就是给固定的片元长度&#xff0c;对Image进行分割&#xff0c;把片元添加到一个列表中&#xff0c;然后循环对列表中的偶数位进行隐藏&#xff0c;也可以调整线段的宽度 缺陷&#xff1…

力扣hot100 LRU 缓存 有序Map

Problem: 146. LRU 缓存 文章目录 思路&#x1f496; Code 思路 &#x1f468;‍&#x1f3eb; 参考题解 &#x1f469;‍&#x1f3eb; 参考图解 &#x1f496; Code ⏰ 两操作 时间复杂度: O ( 1 ) O(1) O(1) class LRUCache {int cap;LinkedHashMap<Integer, In…

【并发】什么是 AQS

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;JAVA ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 AQS的主要特征和方法包括&#xff1a; 状态管理&#xff1a; 等待队列&#xff1a; 独占模式&#xff1a; 共享模式&#xff1…

提高塑料制品的塑料透光率测量仪

塑料透光率检测仪是一种用于测量塑料材料透光率的仪器。透光率是指光线通过材料后&#xff0c;被吸收、反射和散射的量与总光线量的比例。塑料透光率检测仪在塑料制品的研发、生产和质量控制等方面具有广泛的应用。 塑料透光率检测仪的原理是使用光束通过待测塑料样品&#xff…

PageHelper学习使用

基于mybatis源码和PageHelper源码进行的测试 版本 mybatis3.5.0&#xff0c;pageHelper6.0.0 测试用例 依赖 <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.15</version> &…

STM 32 SPI 调试的问题

问题&#xff1a;STM32G0 系列 SPI单线与AD7694通信采集数据&#xff0c;使用stm32cube 生成的HAL库编写 刚开始HAL_SPI_Receive&#xff0c;执行到这句时&#xff0c;一直卡在这里不在往下执行。 最终发现&#xff0c;我使用正点原子的 sysytick 延时函数delay_us, 与这里用…

【数据类型转换】C语言中的数据类型转换

1.定义 数据类型转换&#xff0c;听这个名字你就懂了&#xff0c;就是将数据从一种类型转换为另一种类型。 2.自动类型转换 自动类型转换就是编译器默默地、隐式地、偷偷地进行的数据类型转换&#xff0c;这种转换不需要程序员干预&#xff0c;会自动发生。比如说&#xff1a…

链表/双向循环链表(C/C++)

本篇将给出双向循环链表的有关操作&#xff0c;以及对应的一些解释&#xff0c;大多都以注释给出。本篇给出的双向循环链表全称为带头双向循环链表。即如下图所示&#xff1a; 在本篇中一共包含三个代码片段&#xff0c;分别为&#xff1a;双向链表需要实现的内容、双向链表函数…

JS进阶-解构赋值(一)

扩展&#xff1a;解构赋值时Js特有的一种处理数据的方式&#xff0c;在Java中没有处理数据的方式 知识引入&#xff1a; 思考&#xff1a;在js中&#xff0c;在没有学习解构赋值之前&#xff0c;我们是如何获取数组的内容的&#xff1f; 以上要么不好记忆&#xff0c;要么书写麻…

gitlab备份-迁移-升级方案9.2.7升级到15版本最佳实践

背景 了解官方提供的版本的升级方案 - GitLab 8: 8.11.Z 8.12.0 8.17.7 - GitLab 9: 9.0.13 9.5.10 9.2.7 - GitLab 10: 10.0.7 10.8.7 - GitLab 11: 11.0.6 11.11.8 - GitLab 12: 12.0.12 12.1.17 12.10.14 - GitLab 13: 13.0.14 13.1.11 13.8.8 13.12.15 - G…

利用nginx宝塔免费防火墙实现禁止国外IP访问网站

本章教程&#xff0c;主要介绍&#xff0c;如何利用nginx宝塔面板中的插件免费防火墙&#xff0c;实现一键禁止国外IP访问网站。 目录 一、安装宝塔插件 二、 开启防火墙 一、安装宝塔插件 在宝塔面板中的软件商店&#xff0c;搜索防火墙关键词&#xff0c;找到Nginx免费防火…

详解STP生成树

华子目录 前沿导入二层环路导致问题&#xff1a; 生成树802.1D 角色选举根网桥根端口指定端口非指定端口&#xff08;阻塞端口&#xff09; cost值接口状态down侦听学习转发阻塞 收敛时间当结构发生变化时 802.1D缺点802.1D配置命令PVSTPVST快速生成树RSTP基于组的快速生成树MS…

Docker数据管理

管理 Docker 容器中数据主要有两种方式&#xff1a;数据卷&#xff08;Data Volumes&#xff09;和数据卷容器&#xff08;DataVolumes Containers&#xff09;。 在生成容器的同时&#xff0c;加上 -v 选项&#xff0c;指定把当前服务器的目录映射到容器中&#xff0c;实现do…

单核QPS近6000S,陌陌基于OceanBase的持久化缓存探索与实践

挚文集团于 2011 年 8 月推出了陌陌&#xff0c;这款立足地理位置服务的开放式移动视频社交应用在中国社交平台领域内独树一帜。陌陌和探探作为陌生人社交领域的主流应用&#xff0c;涵盖了多种核心业务模块&#xff0c;包括直播服务、附近动态功能、即时通讯&#xff08;IM&am…

亚马逊测评:自养号测评的深度解析与策略

亚马逊测评对于卖家来说至关重要&#xff0c;特别是在当今竞争激烈的电商环境中。然而&#xff0c;许多人对亚马逊测评的理解仅停留在刷销量和积累好评的层面&#xff0c;忽视了自养号测评的其他重要功能。本文将深入探讨自养号测评的多种功能&#xff0c;以及如何建立稳定、高…
最新文章