当前位置: 首页 > article >正文

RuoYi-App根据不同角色权限实现功能按钮显隐

需求

根据角色不同,移动端显示不同功能,效果如下:
在这里插入图片描述

代码实现

该功能和管理后台不太一样;ruoyi自带的管理后台可以控制每个功能按钮,以及不同角色之间的数据权限;但是移动端不需要,只需要控制某个模块的显隐就行,所以只需要修改前端代码进行控制显隐即可;具体逻辑如下:
1、后台将指定角色功能权限保存到数据库
2、app端登录时查询该用户下所对应角色的功能权限,并保存到缓存中
3、跳转到指定路由时,通过自定义功能组件中的权限值和缓存中的数据进行对比,如果存在则显示,不存在则隐藏

上代码

1、查询后台角色权限,并保存到缓存

store/modules 文件夹下新增 permission.js 文件,代码如下

import auth from '@/plugins/auth'
import router, { constantRoutes, dynamicRoutes } from '@/router'
import { getRouters } from '@/api/menu'
import Layout from '@/layout/index'
import ParentView from '@/components/ParentView'
import InnerLink from '@/layout/components/InnerLink'

const permission = {
  state: {
    routes: [],
    addRoutes: [],
    defaultRoutes: [],
    topbarRouters: [],
    sidebarRouters: []
  },
  mutations: {
    SET_ROUTES: (state, routes) => {
      state.addRoutes = routes
      state.routes = constantRoutes.concat(routes)
    },
    SET_DEFAULT_ROUTES: (state, routes) => {
      state.defaultRoutes = constantRoutes.concat(routes)
    },
    SET_TOPBAR_ROUTES: (state, routes) => {
      state.topbarRouters = routes
    },
    SET_SIDEBAR_ROUTERS: (state, routes) => {
      state.sidebarRouters = routes
    },
  },
  actions: {
    // 生成路由
    GenerateRoutes({ commit }) {
      return new Promise(resolve => {
        // 向后端请求路由数据
        getRouters().then(res => {
          const sdata = JSON.parse(JSON.stringify(res.data))
          const rdata = JSON.parse(JSON.stringify(res.data))
          const sidebarRoutes = filterAsyncRouter(sdata)
          const rewriteRoutes = filterAsyncRouter(rdata, false, true)
          const asyncRoutes = filterDynamicRoutes(dynamicRoutes);
          rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true })
          router.addRoutes(asyncRoutes);
          commit('SET_ROUTES', rewriteRoutes)
          commit('SET_SIDEBAR_ROUTERS', constantRoutes.concat(sidebarRoutes))
          commit('SET_DEFAULT_ROUTES', sidebarRoutes)
          commit('SET_TOPBAR_ROUTES', sidebarRoutes)
          resolve(rewriteRoutes)
        })
      })
    }
  }
}

// 遍历后台传来的路由字符串,转换为组件对象
function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) {
  return asyncRouterMap.filter(route => {
    if (type && route.children) {
      route.children = filterChildren(route.children)
    }
    if (route.component) {
      // Layout ParentView 组件特殊处理
      if (route.component === 'Layout') {
        route.component = Layout
      } else if (route.component === 'ParentView') {
        route.component = ParentView
      } else if (route.component === 'InnerLink') {
        route.component = InnerLink
      } else {
        route.component = loadView(route.component)
      }
    }
    if (route.children != null && route.children && route.children.length) {
      route.children = filterAsyncRouter(route.children, route, type)
    } else {
      delete route['children']
      delete route['redirect']
    }
    return true
  })
}

function filterChildren(childrenMap, lastRouter = false) {
  var children = []
  childrenMap.forEach((el, index) => {
    if (el.children && el.children.length) {
      if (el.component === 'ParentView' && !lastRouter) {
        el.children.forEach(c => {
          c.path = el.path + '/' + c.path
          if (c.children && c.children.length) {
            children = children.concat(filterChildren(c.children, c))
            return
          }
          children.push(c)
        })
        return
      }
    }
    if (lastRouter) {
      el.path = lastRouter.path + '/' + el.path
      if (el.children && el.children.length) {
        children = children.concat(filterChildren(el.children, el))
        return
      }
    }
    children = children.concat(el)
  })
  return children
}

// 动态路由遍历,验证是否具备权限
export function filterDynamicRoutes(routes) {
  const res = []
  routes.forEach(route => {
    if (route.permissions) {
      if (auth.hasPermiOr(route.permissions)) {
        res.push(route)
      }
    } else if (route.roles) {
      if (auth.hasRoleOr(route.roles)) {
        res.push(route)
      }
    }
  })
  return res
}

export const loadView = (view) => {
  if (process.env.NODE_ENV === 'development') {
    return (resolve) => require([`@/views/${view}`], resolve)
  } else {
    // 使用 import 实现生产环境的路由懒加载
    return () => import(`@/views/${view}`)
  }
}

export default permission

2、获取缓存数据,用于权限比对

修改 store/getters.js文件,代码如下:

const getters = {
	token: state => state.user.token,
	avatar: state => state.user.avatar,
	name: state => state.user.name,
	userId: state => state.user.userId,
	nickName: state => state.user.nickName,
	roles: state => state.user.roles,
	permissions: state => state.user.permissions,

	intoArray: state => state.intoStore.intoArray,
	detailArray: state => state.intoStore.detailArray,

	permission_routes: state => state.permission.routes,
	topbarRouters: state => state.permission.topbarRouters,
	defaultRoutes: state => state.permission.defaultRoutes,
	sidebarRouters: state => state.permission.sidebarRouters,
}
export default getters

3、自定义权限组件

在store文件夹下新增 directive/index.js、directive/permission/hasPermi.js、directive/permission/hasRole.js三个js文件,代码依次如下:

index.js
import hasRole from './permission/hasRole'
import hasPermi from './permission/hasPermi'

const install = function (Vue) {
  Vue.directive('hasRole', hasRole)
  Vue.directive('hasPermi', hasPermi)
}

if (window.Vue) {
  window['hasRole'] = hasRole
  window['hasPermi'] = hasPermi
  Vue.use(install); // eslint-disable-line
}

export default install
hasPermi.js
 /**
 * v-hasPermi 操作权限处理
 * Copyright (c) 2019 hgkc
 */

import store from '@/store'

export default {
  inserted(el, binding, vnode) {
    const { value } = binding
    const all_permission = "*:*:*";
    const permissions = store.getters && store.getters.permissions

    if (value && value instanceof Array && value.length > 0) {
      const permissionFlag = value

      const hasPermissions = permissions.some(permission => {
        return all_permission === permission || permissionFlag.includes(permission)
      })

      if (!hasPermissions) {
        el.parentNode && el.parentNode.removeChild(el)
      }
    } else {
      throw new Error(`请设置操作权限标签值`)
    }
  }
}

hasRole.js
 /**
 * v-hasRole 角色权限处理
 * Copyright (c) 2019 hgkc
 */

import store from '@/store'

export default {
  inserted(el, binding, vnode) {
    const { value } = binding
    const super_admin = "admin";
    const roles = store.getters && store.getters.roles

    if (value && value instanceof Array && value.length > 0) {
      const roleFlag = value

      const hasRole = roles.some(role => {
        return super_admin === role || roleFlag.includes(role)
      })

      if (!hasRole) {
        el.parentNode && el.parentNode.removeChild(el)
      }
    } else {
      throw new Error(`请设置角色权限标签值"`)
    }
  }
}

4、引入自定义功能组件

修改main.js文件,代码如下

import Vue from 'vue'
import App from './App'
import store from './store' // store
import plugins from './plugins' // plugins
import './permission' // permission
import directive from './store/directive'
Vue.use(plugins)
import uView from "uview-ui";
Vue.use(uView);
Vue.use(directive);

Vue.config.productionTip = false
Vue.prototype.$store = store

App.mpType = 'app'

const app = new Vue({
  ...App
})


app.$mount()

验证是否可用

在需要根据权限显隐的功能按钮上使用 v-hasPermi ;如下图:
在这里插入图片描述
截图中的权限标识在后台管理系统中进行维护:
在这里插入图片描述


http://www.kler.cn/a/320562.html

相关文章:

  • OpenHarmony(鸿蒙南向)——平台驱动指南【I2C】
  • 简易STL实现 | 红黑树的实现
  • SpringCloud-07 GateWay01 网关技术
  • 使用Okhttp-服务器不支持缓存的解决办法
  • C++之Person类
  • JavaScript中的无穷大
  • 华为静态路由(route-static)
  • 【Unity navigation面板】
  • 在 deepin 上除了 Steam,还能怎么玩游戏?
  • Python中性能优化与高级应用
  • Java律师法律咨询小程序
  • 卷轴模式商城APP开发搭建全流程解析
  • Pandas和Seaborn可视化详解
  • Spring Boot 学习之路 -- Service 层
  • elastic search 向量检索的过程包括数据写入与查询
  • 网络安全入门教程(非常详细)从零基础入门到精通,看完这一篇你就是网络安全高手了。
  • C++密码安全检测
  • 我与Linux的爱恋:进程创建|终止
  • 昇腾Ascend C算子性能优化
  • yolo自动化项目实例解析(六)自建UI(主窗口、预览窗口)