第二章🚦登录页面

726 阅读2分钟

🧑‍🎓 个人主页:SilenceLamb

📖 本章内容:【vue登录页面

image.png

🌳Gitee仓库地址:👉🏽vue登录页面


image.png

一、路由配置

// 公共路由
export const constantRoutes = [
    {
        path: '/login',
        name: 'Login',
        component: () => import('@/views/login/login.vue')
    },
    {
        path: '/',
        name: 'Index',
        redirect: '/index',
        component: () => import('@/views/index/index.vue')
    },

]

二、API统一管理

🍎 获取验证码

// 获取验证码
export function getCodeImage() {
    return request({
        url: '/captchaImage',
        method: 'get'
    })
}

🍎 用户登录

//用户登录
export function login(data) {
    return request({
        url: '/login',
        headers: {
            isToken: false
        },
        method: 'post',
        data: data
    })
}

三、 登录页面布局

🍒 页面布局

<template>
  <div class="login">
    <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form">
      <h3 class="title">后台管理系统</h3>
      <el-form-item prop="username">
        <el-input
            v-model="loginForm.username"
            type="text"
            auto-complete="off"
            placeholder="账号"
        >
          <svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon"/>
        </el-input>
      </el-form-item>
      <el-form-item prop="password">
        <el-input
            v-model="loginForm.password"
            :type="passwordType"
            auto-complete="off"
            placeholder="密码"
            @keyup.enter.native="handleLogin"
        >
          <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon"/>

          <span slot="suffix" @click="showPassword()">
            <svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'"
                      class="el-input__icon input-icon"
            ></svg-icon>
        </span>

        </el-input>
      </el-form-item>
      <el-form-item prop="code" v-if="captchaEnabled">
        <el-input
            v-model="loginForm.code"
            auto-complete="off"
            placeholder="验证码"
            style="width: 63%"
            @keyup.enter.native="handleLogin"
        >
          <svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon"/>
        </el-input>
        <div class="login-code">
          <img :src="codeUrl" @click="getCode" class="login-code-img"/>
        </div>
      </el-form-item>
      <el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;">记住密码</el-checkbox>
      <el-form-item style="width:100%;">
        <el-button
            :loading="loading"
            size="medium"
            type="primary"
            style="width:100%;"
            @click.native.prevent="handleLogin"
        >
          <span v-if="!loading">登 录</span>
          <span v-else>登 录 中...</span>
        </el-button>
        <div style="float: right;" v-if="register">
          <router-link class="link-type" :to="'/register'">立即注册</router-link>
        </div>
      </el-form-item>
    </el-form>
    <!--  底部  -->
    <div class="el-login-footer">
    </div>
  </div>
</template>
  • 🌳src/views/logindata封装的数据
data() {
  return {
    codeUrl: "",
    loginForm: {
      username: "admin",
      password: "michale",
      rememberMe: false,
      code: "",
      uuid: ""
    },
    loginRules: {
      username: [
        {required: true, trigger: "blur", message: "请输入您的账号"}
      ],
      password: [
        {required: true, trigger: "blur", message: "请输入您的密码"}
      ],
      code: [{required: true, trigger: "change", message: "请输入验证码"}]
    },
    passwordType: 'password',
    loading: false,
    // 验证码开关
    captchaEnabled: true,
    // 注册开关
    register: false,
    redirect: undefined
  };
  • 🌳src/views/login:🕰️可以导入其他文件
  • 例如:import 《组件名称》 from '《组件路径》';

🍒相关方法定义

import {getCodeImage} from "@/api/common/captchaImage";
import {encrypt, decrypt} from "@/utils/jsencrypt";
import Cookies from "js-cookie";
  • 🍏获取验证码
//获取验证码
getCode() {
  getCodeImage().then(res => {
    this.captchaEnabled = res.data.captchaEnabled === undefined ? true : res.data.captchaEnabled;
    if (this.captchaEnabled) {
      this.codeUrl = "data:image/gif;base64," + res.data.img;
      this.loginForm.uuid = res.data.uuid;
    }
  });
},
  • 🍏从cookie中获取信息
//从cookie中获取信息
getCookie() {
  const username = Cookies.get("username");
  const password = Cookies.get("password");
  const rememberMe = Cookies.get('rememberMe')
  this.loginForm = {
    username: username === undefined ? this.loginForm.username : username,
    password: password === undefined ? this.loginForm.password : decrypt(password),
    rememberMe: rememberMe === undefined ? false : Boolean(rememberMe)
  };
},
  • 🍑登陆处理
//登陆处理
handleLogin() {
  this.$refs.loginForm.validate(valid => {
    if (valid) {
      this.loading = true;
      if (this.loginForm.rememberMe) {
        Cookies.set("username", this.loginForm.username, {expires: 30});
        Cookies.set("password", encrypt(this.loginForm.password), {expires: 30});
        Cookies.set('rememberMe', this.loginForm.rememberMe, {expires: 30});
      } else {
        Cookies.remove("username");
        Cookies.remove("password");
        Cookies.remove('rememberMe');
      }
      this.$store.dispatch('user/Login', this.loginForm).then(() => {
        this.$router.push({path: this.redirect || "/"});
      })
    }
  })
},
  • 👑密码显示和隐藏
//密码显示和隐藏
showPassword() {
  if (this.passwordType === 'password') {
    this.passwordType = ''
  } else {
    this.passwordType = 'password'
  }
},

🍒 登录页面样式

<style rel="stylesheet/scss" lang="scss">
//@import url(); 引入公共 css 类
@import url("@/views/login/login.scss");
</style>

四、登录操作

image.png

  • 🌳src/store/modules/user.js
import {login} from '@/api/common/login'
import {getToken, setToken, removeToken} from '@/utils/token'

🍬 初始化Token的state

//状态
state: {
    token: getToken(),
},

🍬 提供修改token的mutations

//修改状态
mutations: {
    SET_TOKEN: (state, token) => {
        state.token = token
    },
},

🍬 封装登录的Action

//异步执行
actions: {
    // 登录
    Login({commit}, loginForm) {
        return new Promise((resolve, reject) => {
            login(loginForm).then(res => {
                setToken(res.data)
                commit('SET_TOKEN', res.data)
                resolve()
            }).catch(error => {
                reject(error)
            })
        })
    },
}

🍬 对state属性进行计算

  • 🌳src/store/getters.js
const getters = {
    token: state => state.user.token,
}
export default getters
  • 🌳src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'

Vue.use(Vuex)


const store = new Vuex.Store({
    state: {},
    getters: {},
    mutations: {},
    actions: {},
    modules: {
        user
    }
})

export default store

五、获取用户信息

🍬 初始化用户信息的state

const state = {
    userName: "",
    identity: "",
    avatar: "",
    roles: [],
    permissions: [],
    title: "",
    logo: "",
}

🍬 提供修改token的mutations

const mutations = {
    SET_NAME: (state, name) => {
        state.userName = name
    },
    SET_AVATAR: (state, avatar) => {
        state.avatar = avatar
    },
    SET_ROLES: (state, roles) => {
        state.roles = roles
    },
    SET_PERMISSIONS: (state, permissions) => {
        state.permissions = permissions
    },
    SET_TITLE: (state, title) => {
        state.title = title
    },
    SET_LOGO: (state, logo) => {
        state.logo = logo
    },
    SET_IDENTITY: (state, identity) => {
        state.identity = identity
    },
}

🍬 封装登录的action

 // 获取用户信息
    GetInfo({commit}) {
        return new Promise((resolve, reject) => {
            getInfo().then(res => {
                const avatar = (res.data.sysUser.avatar === "" || res.data.sysUser.avatar == null) ? require("@/assets/images/login.gif") : res.data.user.avatar;
                if (res.data.roles && res.data.roles.length > 0) { // 验证返回的roles是否是一个非空数组
                    commit('SET_ROLES', res.data.roles)
                    commit('SET_PERMISSIONS', res.data.permissions)
                } else {
                    commit('SET_ROLES', ['ROLE_DEFAULT'])
                }
                commit('SET_NAME', res.data.sysUser.userName)
                commit('SET_IDENTITY', res.data.sysUser.identity)
                commit('SET_AVATAR', avatar)
                commit('SET_LOGO', res.data.logo)
                commit('SET_TITLE', res.data.title)
                resolve(res)
            }).catch(error => {
                reject(error)
            })
        })
    },

🍬 对state属性进行计算

const getters = {
    avatar: state => state.user.avatar,
    userName: state => state.user.userName,
    identity: state => state.user.identity,
    roles: state => state.user.roles,
    permissions: state => state.user.permissions,
    title: state => state.user.title,
    logo: state => state.user.logo,
}
export default getters

扫码_搜索联合传播样式-标准色版.png

📢🌥️如果文章对你有帮助【关注👍点赞❤️收藏⭐】