首页 前端知识 Vue3后台通用管理系统(三):用户登录与跳转、全局路由守卫

Vue3后台通用管理系统(三):用户登录与跳转、全局路由守卫

2024-05-12 17:05:34 前端知识 前端哥 221 145 我要收藏

(一)用户登录页面的实现

1.登录页面静态页面

<div class="login">
        <div class="loginFlat">
            <h1>用户登录</h1>
            <el-form>
                <el-form-item label="账号:">
                    <el-input></el-input>
                </el-form-item>
                <el-form-item label="密码:">
                    <el-input></el-input>
                </el-form-item>
            </el-form>
            <el-button>登录 </el-button>
        </div>
    </div>

配置路由

在router/index中:
    {
      path: '/login',
      name: 'login',
      component: () => import('@/views/Login.vue')
    }

2.登录跳转

点击发送登录请求,将账号密码传给mock

在login中:
import { usePermitStore } from '@/stores/Permit';
const router = useRouter()
let loginForm = reactive({
    name: '',
    password: ''
})
const permitStore = usePermitStore()
async function handleLogin() {
    // 发送登录请求
    await login(loginForm).then((res: any) => {
        if (res.code == 200) {
            // 将登录token和menulist传给store
            permitStore.setToken(res.data.token)
            permitStore.setMenu(res.data.menuList)
            router.push('/')
        } else {
            alert(res.data.message)
        }

    })
}

<el-button @click="handleLogin">登录</el-button>

mock请求根据不同账号发送不同的菜单list给login

import Mock from "mockjs";
import { nanoid } from "nanoid";
// 用于标志用户
let token = nanoid()
// 管理员
const adminUser = {
    name: 'admin',
    password: '123123'
}
// 一般用户
const normalUser = {
    name: 'dogegg',
    password: '12345'
}
// 管理员看到的菜单
const admiMenuListData = [
    {
        path: "/",
        name: "home",
        label: "首页",
        icon: "house",
        url: "Home/Home",
    },
    {
        path: "/mall",
        name: "mall",
        label: "商品管理",
        icon: "video-play",
        url: "MallManage/MallManage",
    },
    {
        path: "/user",
        name: "user",
        label: "用户管理",
        icon: "user",
        url: "UserManage/UserManage",
    },
    {
        label: "其他",
        icon: "location",
        children: [
            {
                path: "/page1",
                name: "page1",
                label: "Page1",
                icon: "setting",
                url: "Other/PageOne",
            },
            {
                path: "/page2",
                name: "page2",
                label: "Page2",
                icon: "setting",
                url: "Other/PageTwo",
            },
        ],
    },
]
// 普通用户看到的菜单
const normalMenuListData = [
    {
        path: "/",
        name: "home",
        label: "首页",
        icon: "house",
        url: "Home/Home",
    },
    {
        path: "/user",
        name: "user",
        label: "用户管理",
        icon: "user",
        url: "UserManage/UserManage",
    },
]
let menu = []
Mock.mock('/mock/permit/login', 'post', (config) => {
    let { name, password } = JSON.parse(config.body)

    if (name == adminUser.name && password == adminUser.password) {
        menu = admiMenuListData
    } else if (name == normalUser.name && password == normalUser.password) {
        menu = normalMenuListData
    } else { // 密码账号错误
        return {
            code: 201,
            data: {
                message: '账号或密码错误!'
            }
        }
    }
    // 成功就返回token和菜单
    return {
        code: 200,
        data: {
            token,
            menuList: menu
        }
    }
})

新建usePermitStore用于存储跟登录有关的数据和方法

import { defineStore } from 'pinia'
import { ref } from 'vue'
import Cookies from 'js-cookie'
import { useRouter } from 'vue-router'
import { useMenuStore } from './Menu'
export const usePermitStore = defineStore('Permit', () => {
    const router = useRouter()

    let menuList: any = ref([])

    function setToken(token: string) {
        Cookies.set('token', token)
    }
    // 登录后存储menu在localStorage
    function setMenu(menu: any) {
        menuList.value = menu
        // 菜单存储到本地
        localStorage.setItem('menu', JSON.stringify(menu))
    }

    return {
        setToken, setMenu,  menuList, 
    }
})

获取对应的menulist后存储到store中,通过本地存储实现持久化处理,一刷新就重新获取menulist

在store/permit中:
// 获取menulist 实现持久化
function getMenu() {
    if (!localStorage.getItem('menu')) return
    menuList.value = JSON.parse(localStorage.getItem('menu') as string)
}

在commonAside中:
import { usePermitStore } from '@/stores/Permit';
const permitStore = usePermitStore()
// 从本地获取menu 每次刷新都重新获取在本地存储的menulist
permitStore.getMenu()

3.退出登录

点击commonHeader里的退出退出登录,返回到登录页

退出登录即删除token、删除本地存储的menulist、删除tagsList(存储在menuStore中,需要引入再操作)

在store/Permit中:
import { useMenuStore } from './Menu'
// 退出登录
    function deleteMenu() {
        localStorage.removeItem('menu')
        Cookies.remove('token')
        useMenuStore().clearTags()
        router.push('/login')
    }

在store/Menu中:
// 退出登录后清除tags
  function clearTags() {
    tagsList.value = [{
      path: "/",
      name: "home",
      label: "首页",
      icon: "house",
      url: "Home/Home",
    }]
  }

(二)路由守卫

这个项目比较简单,只需要全局前置路由守卫

需要使用到cookie,若cookie存在即为登录状态

下载js-cookie(两个都需要下,否则报错)

npm i js-cookie

npm i @types/js-cookie

使用方法

import Cookies from 'js-cookie'
Cookies.set('token', token)
Cookies.get('token')
Cookies.remove('token')

实现功能:

未登录时不能跳转到除登录页以外的页面;

登录后不能再跳转到登录页;

不能跳转到不存在的路由;

// 全局前置路由守卫 
router.beforeEach((to, from, next) => {
  // 判断是否为存在的路径 不是则回到主页路由
  let check = router.getRoutes().filter((item) => {
    return item.path == to.path
  }).length
  if (!check) {
    next('/')
  }

  // 已登录
  if (Cookies.get('token')) {
    // 不能再跳转到login
    if (to.fullPath == '/login') {
      next(from.path)
    } else {
      next()
    }
  } else { // 未登录
    if (to.path != '/login') {
      // 不能访问登录页以外的页面
      next('/login')
    } else {
      next()
    }
  }
})

(三)结束

搞完了。。这个项目功能感觉好少。。后面想把后端部分重新用node和mysql实现一下 加油

转载请注明出处或者链接地址:https://www.qianduange.cn//article/8406.html
标签
评论
会员中心 联系我 留言建议 回顶部
复制成功!