本文涉及的功能涵盖,登录权限管理,vue指令,模块化。但是登录注册的模块,本章会一概而括,具体功能会根据需求而开发。本文只是提供一种思路,毕竟每个功能都会有参差。
1.主账号新增子账号
创建:第一步我们可能会创建子账号的个人信息等内容,前端会校验格式,并掉接口去查重,手机号,姓名等,如果重复的话会给出提示。
编辑
接下来就是配置子账号的权限了,我们这种是树形结构,用的就是el-tree 的组件
接口返回的树形结构,会携带resourceCode,代表新增时会传给后端,后端同学记录当前勾选的权限是哪些。
接口出参:
编辑
新增权限页面:
编辑
新增保存函数:
kotlin
// 创建子账户
async saveChild() {
let validate = true
try {
validate = await this.$refs['registerForm'].validate()
} catch (err) {
validate = err
}
// el-tree 官方api 获取当前勾选的数据
const temp = this.$refs['tree'].getCheckedNodes(false, true)
// 数据为空 弹窗提示
if (!temp.length) {
this.confirmDialogShow = true
return
}
if (typeof validate === 'boolean') {
this.addLoading = true
//resourceCode 遍历出来组成新数组 并用join方法 转换成字符串
const menuId = temp.map(v => v.resourceCode).join(',')
const param = { ...this.form, newMenuId: menuId, orderAll: 2 }
const { code } = await addChildAccount(param)
if (code === RESPONSE_SUCCESS) {
this.addLoading = false
this.noticeSuccessDialog = true
this.noticeOptions = {
text: this.$t('账户创建成功'),
type: 'success'
}
this.$router.push({ name: 'UserInfo', params: { addNotice: true }})
setTimeout(() => {
this.noticeSuccessDialog = false
}, 5000)
} else {
this.addLoading = false
}
}
}
接口入参:
编辑
新增成功之后,我们需要重新登录,方可使用子账号登录,并获取权限。
登录成功,接口会返回newMenuId字段,里面的每一项代表菜单或者按钮权限
编辑
ini
newMenuId ="Dashboard,findDashboardData,operationPendingOrders,Order,\r\nchatOperationOrder,OrdersList,OrdersUpdate,OrdersCreate,Product,ProductList_ADD,ProductList_EDIT,ProductList_QUERY"
重点就在这块。
2.路由权限
首先在router 文件夹下配置 menu.js文件
javascript
onst menuRoutes = [
{
path: '/dashboard',
name: 'Dashboard',
component: () => import(/* webpackChunkName: "dashboard" */'@/views/dashboard/index'),
meta: { title: '概况', icon: 'overview', chat: true, resourceCode: 'findDashboardData' }
},
{
path: '/order',
name: 'Order',
component: () => import(/* webpackChunkName: "orderList" */'@/views/order/order-list/index'),
meta: { title: '订单1', icon: 'order_icon', chat: true, resourceCode: 'OrdersList' }
},]
登录接口请求成功之后,前端导航栏路由渲染可以根据后端返回的字段进行过滤,当然我们这里是保留导航栏,如果子账号没有权限的话,弹出弹窗提示。
kotlin
this.$store.commit('user/SET_IS_ADMIN', data.useradmin)
const menuList = menuRoutes // 主菜单 //取自 menu.js
const settingList = settingRoutes // 系统设置菜单
this.menuList = { menu: menuList, setting: settingList }
// 递归权限列表
localStorage.setItem('YL_SYSTEM_MENU', JSON.stringify(menuList))
localStorage.setItem('YL_SETTING_MENU', JSON.stringify(settingList))
this.$store.commit('user/SET_SYSTEM_MENU', this.menuList)
在permission.js router.beforeEach 中 接口出参resoureCode包含与前端 resoureCode一致的话,如果当前菜单会有权限,就会next,如果没有就弹出弹窗提示。编辑
示例代码:
scss
if (permissionMenu.length && !permissionMenu.includes(to.meta.resourceCode)) {
// 没有权限的页面 禁止跳转
store.commit('user/permissionDialogShow', true)
if (from.path === '/') {
router.go(-1)
}
NProgress.done()
} else {
next()
}
好,当前的路由权限是这样的,包括在地址栏上输入进入多会被拦截,具体还需要同学根据自身的需求作出相关的改动哈。
3.按钮权限
根据接口字段判断,子账号的菜单,按钮权限存储处理。
kotlin
if (data.useradmin !== 1) {
// 子账户
const menuId = data.newMenuId.split(',')
// 存到vuex中
this.setPermissionMenu(menuId) //采用vuex的配置型api的写法 等同于 this.$store.state.setPermissionMenu
// 跳转权限指定 路由
const router = [...menuList, ...settingList].find(item => menuId.includes(item.meta.resourceCode)).path
this.$router.push({ path: router })
} else {
this.$router.push({ path: '/dashboard' })
}
在store 文件夹中使用模块化引入
编辑
同文件下的state 对象 存储 permissionMenu
css
const state = {
permissionMenu: JSON.parse(localStorage.getItem('permissionMenu')) || []
}
利用vuex的getters 特性进行缓存存储,提高性能优化
ini
const getters = {
permissionMenu: state => state.user.permissionMenu
}
接下来我们去封装用一个vue的指令 全局应用
在directive 文件夹下 新建一个modules
directive ----> modules ---> permission.js(此文件命名会影响,指令的命名哦)
编辑
permission.js
javascript
import store from '../../store'
export default {
inserted: function(el, binding) { //el:元素 binding:元素绑定的属性相关数据
const userPermissions = store.state.user.permissionMenu // 用户的权限列表
// 获取指令的参数,即所需的权限
const requiredPermission = binding.value //对应的就是resouceCode
// 如果用户的权限列表中不包含所需的权限
if (userPermissions.length && !userPermissions.includes(requiredPermission)) {
// 隐藏按钮
el.style.display = 'none'
// el.parentNode?.removeChild(el); // 移除元素
}
}
}
同级module 文件夹中 index.js
javascript
import Vue from 'vue'
const files = require.context(
// 指定的目录
'./modules',
// 不查找子目录
false,
// js 文件
/.+.js$/)
// 按模块引入
// files.keys(): 打印出来为['./focus.js','/loadmore.js']
files.keys().forEach(fileName => {
const directiveConfig = files(fileName) // 获取指令函数
const directiveName = fileName // 获取指令名
.replace(/^.//, '') // 去除开头的'./'
.replace(/.\w+$/, '') // 去除文件扩展名
Vue.directive(directiveName, directiveConfig.default || directiveConfig) //vue 全局注册指令
})
main.js 就可直接导入模块化指令
编辑
我们在其他的文件中
ini
<el-button v-permission="'OrdersUpdate'" /> //OrdersUpdate 对应resouceCode
其他的按钮 也是同样配置的哦。
封装v-permission的指令,其实同理跟v-if很像哦,但是会使用之中比较优雅的写法。
本篇会提供一种思路和逻辑哦,但是具体的代码实现肯定还是根据当前的项目整体结构做出相应的改变哦。
祝大家国庆节快乐哦。天天无bug哦