业务需求:
不同的登录用户进入系统后可以查看不同的菜单权限
比如:admin用户进入系统有四个权限:预报产品、预警产品、防灾减灾、系统管理,如下图:
而aaaa用户进入系统只有三个查看权限:预报产品、预警产品、系统管理,如下图:
具体实现:
1.postman提供的接口数据形式如下。当然期间我也参考了其他的项目,在别的项目中是单独写了一个接口,在这个项目中是把该用户所拥有的权限直接和登录接口写一起了。
2.简要介绍下项目的结构情况,导航栏部分我写在了header.vue里,用户登录以及发送登录请求我写在了login.vue里,下面介绍下思路:
- login.vue页面
用户在点击“登录”按钮时发送网络请求,若请求成功的同时需要把存放在menuInfos里的该用户对应的权限暂时用window.sessionStorage.setItem()保存起来
// 一开始写的是下面这个代码,后来在header.vue取数据的时候打印出来的一直是[object object]
// window.sessionStorage.setItem('menuInfos', res.data.menuInfos)
// 后来修改成下面两行代码了
window.sessionStorage.setItem('menuInfos', JSON.stringify(res.data))
let hh = JSON.parse(window.sessionStorage.getItem('menuInfos')).menuInfos
补充:
这里说明下为啥上面的一行代码改成下面两行代码就能成功获取到值了?
解释:
是因为sessionStorage存储的数据只能是字符串,对于常用的对象和数组是存储不了的,因此可以通过JSON对象提供的parse和stringify将其他数据类型转化成字符串,再存储到storage中
举栗:
存入数据:
this.queryParams={name:'lisi',id:'222'};
sessionStorage.setItem('queryParam',JSON.stringify(this.queryParams))
读取数据:
this.queryParams = JSON.parse(sessionStorage.getItem('queryParam'));
- header.vue页面
需要拿到在登录时候所存入的值
// 一开始写的是下面这个代码,后来在header.vue取数据的时候打印出来的一直是[object object]
// this.menuArray = window.sessionStorage.getItem('menuInfos') //获取当前用户拥有的权限
// console.log(this.menuArray)
// console.log(JSON.parse(window.sessionStorage.getItem('menuInfos')))
// 后来修改的部分是下面两行
let menuMap = new Map()
let hh = JSON.parse(window.sessionStorage.getItem('menuInfos')).menuInfos
console.log(hh)
3.获取到数据后将该数组的menuName,menuCode放入一个Map对象menuMap里,一一对应;
if (hh && hh.length > 0) {
for (let i = 0; i < hh.length; i++) {
menuMap.set(hh[i].menuName, hh[i].menuCode)
}
}
然后开始判断该Map对象中是否有该指定的元素,若有则将该导航的name和path值存入headerMenu数组中。(注意这里不能将componet也写进去)
get方法读取key对应的键值, 如果找不到key, 返回undefined。
// 刚开始我写的是!== '',在调试的过程中发现若用户没有这个权限时,仍然会把该权限给
// 追加到数据headerMenu中去,最后发现get()方法在找不到key值时是返回undefined的
// if (menuMap.get('预报产品') !== '') {
if (menuMap.get('预报产品') !== undefined) {
this.headerMenu.push({
path: '/main/forecastProducts',
// component: Forecastspro,
name: '预报产品'
})
console.log(this.headerMenu)
}
最后在页面中用headerMenu数组中的值去遍历元素
<ul class="nav">
<!-- <li @click="changeMunu(index)" v-for="(item, index) in routerName" :key="index" -->
<li @click="changeMunu(index)" v-for="(item, index) in this.headerMenu" :key="index"
:class="currentIndex == index ? 'active' : ''">
<router-link :to="item.path">
<!-- 渲染头部导航栏 -->
<span>{{ item.name }}</span>
</router-link>
</li>
</ul>
补充:
get() 方法用来获取一个 Map 对象中指定的元素。
set() 方法为Map对象添加一个指定键(key)和值(value)的新元素。
4.源码
login.vue
<template>
<div id="login">
<div class="loginTitle">
<span>江苏海域海浪精细化数值预报系统</span>
</div>
<div class="content">
<div class="login-contain">
<div class="head">
<span>用户登录</span>
</div>
<div class="form-login">
<a-form-model ref="ruleForm" :model="form" :rules="rules" :label-col="labelCol"
:wrapper-col="wrapperCol">
<div class="userText">
<span class="userIcon">
<a-icon type="user" />
</span>
<a-form-model-item ref="username" has-feedback prop="username" class="login-item-width">
<a-input v-model="form.username" placeholder="请输入管理员姓名" />
</a-form-model-item>
</div>
<div class="pwdText">
<span class="userIcon">
<a-icon type="lock" />
</span>
<a-form-model-item ref="password" has-feedback prop="password" type="password"
class="login-item-width">
<a-input @keyup.enter="onSubmit" type="password" v-model="form.password"
placeholder="请输入登录密码" />
</a-form-model-item>
</div>
<!-- <div class="loginTip">
<span>{{this.loginInformation}}</span>
</div> -->
<a-form-model-item :wrapper-col="{ span: 300, offset: 4 }">
<a-button class="login-item" type="primary" @click="onSubmit">
登录
</a-button>
</a-form-model-item>
</a-form-model>
</div>
<!-- 忘记密码,立即注册 -->
<div class="login-botom">
<span class="password-register" @click="toGetNewPwd">忘记密码?</span>
<span>| </span>
<span class="password-register registeractive" @click="toRegieter"> 立即注册</span>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapState, mapActions } from 'vuex'
import qs from 'qs'
import { messageTips } from '../../components/common/utils'
export default {
data() {
return {
labelCol: { span: 4 },
wrapperCol: { span: 14 },
//这是登录表单的数据绑定对象
form: {
username: '',
password: ''
},
//表单的验证规则
rules: {
// 验证用户名是否合法
username: [
{ required: true, message: '用户名不为空', trigger: 'blur' },
{ min: 3, max: 10, message: '长度在3-10个字符', trigger: 'blur' }
],
// 验证密码是否合法
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 6, max: 15, message: '长度在6-15个字符', trigger: 'blur' }
]
},
// loginInformation: ''
}
},
computed: {
// 将sate,映射为当前组件的计算属性 当时模块化时第一个参数是模块名或路径名
//...mapState('LoginStore')
},
methods: {
// 将mapMutations映射为methods
...mapActions('LoginStore', ['getLoginIn']),
created() { },
//忘记密码
toGetNewPwd() {
this.$router.push('/forgetPwd')
},
//立即注册
toRegieter() {
// console.log(this)
this.$router.push('/register')
},
//点击登录,绑定登录按钮的处理事件
//进行表单的预验证
onSubmit() {
debugger
this.$refs.ruleForm.validate(async valid => {
//如果valid值为false,则不发起网络请求
//valid为true,则发起网络请求
if (!valid) return
//这里开始发请求,去配置axios
// this.getLoginIn(this)
let data1 = qs.stringify(this.form)
const { data: res } = await this.$axios.post('/jiangsu/login', data1)
console.log(res)
if (res.code !== 200) {
// this.loginInformation = res.message
// return this.$message.error('登录失败');
return this.$message.error(res.message);
}
this.$message.success('登录成功');
//1.将登录成功之后的token保存到客户端的seesionStorage中,项目中除了登录之外的其他API
//接口,必须在登录之后才能访问,token只应当在当前网站打开期间有效,所以将token保存在seesionStorage中
window.sessionStorage.setItem("token", res.data.token)
window.sessionStorage.setItem('username', res.data.userName)
window.sessionStorage.setItem('menuInfos', JSON.stringify(res.data))
let hh = JSON.parse(window.sessionStorage.getItem('menuInfos')).menuInfos
//2.通过编程式导航跳转到后台主页,路由地址是 /main
this.$router.push('/main')
})
// this.$router.push('/main')
},
}
}
</script>
<!-- scoped防止组件之间样式冲突 -->
<style lang="scss" scoped>
@import './Login.scss';
</style>
header.vue
<template>
<div id="head">
<div class="head-content" style="width:20%">
<p class="logoTitle">Logo</p>
<span class="staellite">江苏海域海浪精细化数值预报系统</span>
</div>
<div class="head-content">
<ul class="nav">
<!-- <li @click="changeMunu(index)" v-for="(item, index) in routerName" :key="index" -->
<li @click="changeMunu(index)" v-for="(item, index) in this.headerMenu" :key="index"
:class="currentIndex == index ? 'active' : ''">
<router-link :to="item.path">
<!-- 渲染头部导航栏 -->
<span>{{ item.name }}</span>
</router-link>
</li>
</ul>
</div>
<div class="head-content">
<!-- <a-button class="loginOut" type="info" @click="logout">退出</a-button> -->
<div class="getUser">
<span class="iconUser iconfont icon-icon "></span>
<!-- <span class="userNameInformation" style="margin-left: 230px">panxiaolin</span> -->
<!-- <span class="userNameInformation" @click="showUserName" style="margin-left:10px">{{ this.name }}</span> -->
<span class="userNameInformation">{{this.userShow}}</span>
</div>
<div class="loginOut" @click="logout">
<span class="iconfont icon-tuichu userNameInformation"></span>
</div>
</div>
</div>
</template>
<script>
import { routes } from '../../router/index'
// import { dataFormat } from '../../components/common/utils'
// import UserName from './UserName'
export default {
data() {
return {
routerName: routes[4].children,
nowTime: '',
timer: '',
currentIndex: 0,
userShow: '',
menuArray: [],
headerMenu: []
}
},
created() {
// if (!this.currentIndex) {
// this.currentIndex = 0
// }
debugger
this.currentIndex = window.sessionStorage.getItem('saveIndex')
this.userShow = window.sessionStorage.getItem('username')
let menuMap = new Map()
let hh = JSON.parse(window.sessionStorage.getItem('menuInfos')).menuInfos
console.log(hh)
if (hh && hh.length > 0) {
for (let i = 0; i < hh.length; i++) {
menuMap.set(hh[i].menuName, hh[i].menuCode)
}
}
if (menuMap.get('预报产品') !== undefined) {
this.headerMenu.push({
path: '/main/forecastProducts',
// component: Forecastspro,
name: '预报产品'
})
console.log(this.headerMenu)
}
if (menuMap.get('预警产品') !== undefined) {
this.headerMenu.push({
path: '/main/warningProducts',
// component: Warningspro,
name: '预警产品'
})
}
if (menuMap.get('防灾减灾辅助决策') !== undefined) {
this.headerMenu.push({
path: '/main/desicionMakings/typhoneRoute',
// component: DesicionMaks,
name: '防灾减灾辅助决策'
})
}
if (menuMap.get('系统管理') !== undefined) {
this.headerMenu.push({
path: '/main/SystemManangers/usersManage',
// component: SystemManange,
name: '系统管理'
})
}
},
mounted() {
// this.currentTime()
},
beforeDestroy() {
if (this.timer) {
clearInterval(this.timer) // 在Vue实例销毁前,清除我们的定时器
}
},
methods: {
changeMunu(index) {
this.currentIndex = index
window.sessionStorage.setItem('saveIndex', index)
},
logout() {
const _that = this
_that.$confirm({
title: '确定要退出系统吗?',
okText: '确认',
cancelText: '取消',
onOk() {
_that.$axios.post('/jiangsu/logout').then(res => {
const { code } = res.data
if (code === 200) {
// window.sessionStorage.clear()
// _that.$router.push('/login')
window.sessionStorage.removeItem('token')
// window.sessionStorage.removeItem('user')
window.sessionStorage.removeItem('username')
_that.$router.replace('/login')
}
})
},
onCancel() {
console.log('Cancel')
}
})
},
},
computed: {},
// components: {
// UserName
// }
}
</script>
<style lang="scss" scoped>
@import './Header.scss';
</style>
写死的路由规则是在router/index.js里
最后列下在调试过程中所得到的数据过程:
栗子1.
栗子2.
栗子3.