前端权限流程(基于rbac实现思想)

1. 权限控制

1.1. 实现思想

基于rbac权限控制思想实现,给用户分配角色,给角色分配权限

给用户分配角色业务

注意:上方图片是个示例图,代表给用户分配职位(角色),页面中使用了Element-plus的el-         checkbox组件和el-checkbox-group组件

静态结构(不完整)

          <el-form-item label="用户姓名"><el-input v-model="userParams.username" :disabled="true"></el-input></el-form-item><el-form-item label="职位列表"><el-checkbox>全选</el-checkbox><!-- 显示职位的的复选框 --><el-checkbox-group><el-checkboxv-for="(role, index) in 10":key="index":label="index">{{ index }}</el-checkbox></el-checkbox-group></el-form-item>

获取&&存储数据

首先先获取全部的职位(角色)的数据与当前用户已有的职位(角色)的数据,分别进行保存

//收集顶部复选框全选数据
let checkAll = ref<boolean>(false)
//控制顶部全选复选框不确定的样式
let isIndeterminate = ref<boolean>(true)
//存储全部职位的数据
let allRole = ref<AllRole>([])
//当前用户已有的职位
let userRole = ref<AllRole>([])
//分配角色按钮的回调
const setRole = async (row: User) => {//存储已有的用户信息Object.assign(userParams, row)//获取全部的职位的数据与当前用户已有的职位的数据let result: AllRoleResponseData = await reqAllRole(userParams.id as number)if (result.code == 200) {//存储全部的职位allRole.value = result.data.allRolesList//存储当前用户已有的职位userRole.value = result.data.assignRoles//抽屉显示出来drawer1.value = true}
}

展示数据

<!-- 抽屉结构:用户某一个已有的账号进行职位分配 --><el-drawer v-model="drawer1"><template #header><h4>分配角色(职位)</h4></template><template #default><el-form><el-form-item label="用户姓名"><el-input v-model="userParams.username" :disabled="true"></el-input></el-form-item><el-form-item label="职位列表"><el-checkbox@change="handleCheckAllChange"v-model="checkAll":indeterminate="isIndeterminate">全选</el-checkbox><!-- 显示职位的的复选框 --><el-checkbox-groupv-model="userRole"@change="handleCheckedCitiesChange"><el-checkboxv-for="(role, index) in allRole":key="index":label="role">{{ role.roleName }}</el-checkbox></el-checkbox-group></el-form-item></el-form></template></el-drawer>

详细解释

全选部分:

@change:全选框点击时的回调

v-model:绑定的数据,根据这个值决定是否全选(是一个布尔值)

:indeterminate:不确定状态,既没有全选也没有全不选

 


复选框部分:

v-for="(role, index) in allRole":遍历allRole。

:label="role":收集的数据(勾上的数据)

v-model="userRole":绑定收集的数据,也就是收集的数据存储到userRole中。

@change:勾选变化时的回调(点击每个复选框都会执行的回调)

 


全选框勾选的回调:

实现原理:函数会将勾选与否注入到val中,如果是,就将全部数据(allRole)赋值给选中的数据(userRole),选中的数据通过v-model实现页面的同步变化

该函数会接收到一个布尔值,如果为真代表全选按钮被勾选,在回调中需要将全部角色(职位)数据赋值给在el-checkbox-group使用v-model绑定的变量中(该变量表示被选中的数据)

//顶部的全部复选框的change事件
const handleCheckAllChange = (val: boolean) => {//val:true(全选)|false(没有全选)userRole.value = val ? allRole.value : []//不确定的样式(确定样式)isIndeterminate.value = false
}

复选框

每勾选一个复选框就会执行该函数,并收集勾选的数据到数组中传递进该函数

在函数内部判断数组的长度是否等于全部角色数据,如果等于需要将上方的权限按钮勾上,因为已经使用v-model绑定了,所以直接给checkAll.value赋一个布尔值即可

//顶部全部的复选框的change事件
const handleCheckedCitiesChange = (value: string[]) => {//顶部复选框的勾选数据//代表:勾选上的项目个数与全部的职位个数相等,顶部的复选框勾选上checkAll.value = value.length === allRole.value.length//不确定的样式isIndeterminate.value = value.length !== allRole.value.length
}

当点击确定按钮的回调

需要收集两个参数:第一个:当前用户的id标识,第二个:从收集好的userRole中使用map过滤出选中的角色的id标识(数组)

然后发起分配用户角色的请求,请求成功,重新获取更新完毕用户的信息。

//确定按钮的回调(分配职位)
const confirmClick = async () => {//收集参数let data: SetRoleData = {userId: userParams.id as number,roleIdList: userRole.value.map((item) => {return item.id as number}),}//分配用户的职位let result: any = await reqSetUserRole(data)if (result.code == 200) {//提示信息ElMessage({ type: 'success', message: '分配职务成功' })//关闭抽屉drawer1.value = false//获取更新完毕用户的信息,更新完毕留在当前页getHasUser(pageNo.value)}
}

 看到这里,相信你一定有收获!!!

给角色分配权限业务

静态结构

当点击上图中的分配权限按钮时,会弹出一个抽屉组件(el-drawer),利用树组件展示所有权限数据,并可以看到点击的角色已有的权限数据(勾选的)

注意:上方图片是个示例图,代表给角色分配权限,页面中使用了Element-plus的el-table和el-drawer,el-tree组件。

注意:因为这是在vue3和typescript项目中,所以进行了类型限制。

type这里MenuData与MenuList互相调用,适合这种树状的数据结构(type还可以定义多个复杂类型)

//菜单与按钮数据的ts类型
export interface MenuData {id: numbercreateTime: stringupdateTime: stringpid: numbername: stringcode: stringtoCode: stringtype: numberstatus: nulllevel: numberchildren?: MenuListselect: boolean
}
export type MenuList = MenuData[]

分配权限按钮

获取&&存储数据

根据角色id发送请求获取全部角色权限数据(包含该角色已有的职位)

//准备一个数组:数组用于存储勾选的节点的ID(四级的)
let selectArr = ref<number[]>([])
//已有的职位的数据
const setPermisstion = async (row: RoleData) => {//抽屉显示出来drawer.value = true//收集当前要分类权限的职位的数据Object.assign(RoleParams, row)//根据职位获取权限的数据let result: MenuResponseData = await reqAllMenuList(RoleParams.id as number)if (result.code == 200) {menuArr.value = result.data//下面这行代码下面会具体讲解,可以先往下看selectArr.value = filterSelectArr(menuArr.value, [])}
}

 使用树组件展示全部权限数据(树组件详细使用说明)

我们重点关注el-tree组件,先介绍一些常用属性和方法

const defaultProps = {//子树为节点对象的childrenchildren: 'children',//节点标签为节点对象的name属性label: 'name',
}

常用属性: 

1. data:展示的数据(数据源)

2. show-checkbox:节点是否可被选择(点击可以选中)

3. node-key:每个树节点用来作为唯一标识的属性,整棵树应该是唯一的(如果树中包含children子数据,该属性不能省略)

4. default-expand-all:默认展开所有节点

5. default-checked-keys:默认勾选的节点的 key 的数组(是一个数组,数组中存放的就是上面node-key存放的唯一标识)

6. default-expanded-keys:默认展开的节点的 key 的数组(是一个数组,数组中存放的就是上面node-key存放的唯一标识)

7. current-node-key:当前选中的节点(可以是number或string类型)

8. props:接收一个对象,对象中可以包含以下两个属性(还可以包含其他属性,这里只列举了以下两个)

label:指定节点标签为节点对象的某个属性值(就是代表了要在页面中展示的节点名称) ,children:指定子树为节点对象的某个属性值(就是代表去哪个字段下读取数据当作子节点的数据)(注意:label和children这两个属性名是不变的,属性值需要根据项目需要进行修改)


常用方法:

使用el-tree树组件提供的方法时,需要先在el-tree组件标签上利用ref打上标识(<el-tree ref="xxx"> </el-tree>),然后通过ref得到el-tree组件实例才能调用对应方法!

1. getCheckedKeys:如果在el-tree标签上设置了show-checkbox属性且被选中,通过树组件实例.getCheckedKeys进行调用,它将返回当前选中节点key的数组(该数组由所有被选中的节点的id属性组成【为什么是id属性呢?        因为:在el-tree标签上设置了node-key="id"属性。所以该方法会收集所有选中的节点对象的id属性】)


 2. getHalfCheckedKeys:如果在el-tree标签上设置了show-checkbox属性且被选中,通过树组件实例.getHalfCheckedKeys进行调用,它将返回当前半选中的节点的id属性组成的数组
如遇这种情况该方法一般会和上面的getCheckedKeys配合使用


在树组件中展示已分配的权限

为什么要使用递归函数?
因为不能直接根据1级,2级,3级的select属性进行判断,要判断最内层的职位对象的select属性是真是假,因为层级较深要判断最内层的职位对象的select属性,所以使用了递归函数

具体实现思路:
    目的:要先对返回的全部权限数据进行过滤,找到最内层的职位对象,根据其select属性判断!
    封装一个递归函数,接收两个参数,一个全部权限数据,一个空数组(用于存放满足level为4级职位对象中的select属性为真的职位的id),在递归函数    中使用for Each遍历全部权限数据,判断item.select && item.level === 4如果满足说明到最内层了,将当前这个对象的id属性(item.id)push到空数组中,否则代表没有到最内层,继续判断item.children && item.children.length > 0 满足该条件递归调用    filterSelectArr(item.children,initArr),最后返回这个过滤好的数组,交给el-tree组件的default-checked-keys属性,那么就可以找出该角色已有的权限就可以在树组件选中了

//分配权限按钮的回调
//已有的职位的数据
const setPermisstion = async (row: RoleData) => {//抽屉显示出来drawer.value = true//收集当前要分类权限的职位的数据Object.assign(RoleParams, row)//根据职位获取权限的数据let result: MenuResponseData = await reqAllMenuList(RoleParams.id as number)if (result.code == 200) {menuArr.value = result.data/*最后返回这个过滤好的数组,交给el-tree组件的default-checked-keys属性,那么就可以找出该角色已有的权限就可以在树组件选中了*/selectArr.value = filterSelectArr(menuArr.value, [])}
}
// 递归函数
const filterSelectArr = (allData: any, initArr: any) => {allData.forEach((item: any) => {if (item.select && item.level == 4) {initArr.push(item.id)}if (item.children && item.children.length > 0) {//层层递进,直到最内层的职位对象的level属性===4filterSelectArr(item.children, initArr)}})//返回这个过滤好的数组return initArr
} 

收集用户分配的权限

我们这里收集主要用到了2个方法:getCheckedKeys、getHalfCheckedKeys。它们会返回已选择以及半选择用户的id数组(这两个方法上方都有详细解释)

//抽屉确定按钮的回调
const handler = async () => {//职位(角色)的IDconst roleId = RoleParams.id as number//选中节点的ID		getCheckedKeys方法会得到show-checkbox为true选中的全部节点对象的id组成的数组//为什么是能收集到id 		因为el-tree配置了node-key="id"属性let arr = tree.value.getCheckedKeys()//半选的IDlet arr1 = tree.value.getHalfCheckedKeys()let permissionId = arr.concat(arr1)//下发权限let result: any = await reqSetPermisstion(roleId, permissionId)if (result.code == 200) {//抽屉关闭drawer.value = false//提示信息ElMessage({ type: 'success', message: '分配权限成功' })//页面刷新window.location.reload()}
}

继续加油!


1.2. 实现深度

3级权限:模块权限、页面权限、按钮权限

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/72570.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

软件高级架构师 - 软件工程

补充中 测试 测试类型 静态测试 动态测试 测试阶段 单元测试中&#xff0c;包含性能测试&#xff0c;如下&#xff1a; 集成测试中&#xff0c;包含以下&#xff1a; 维护 遗留系统处置 高水平低价值&#xff1a;采取集成 对于这类系统&#xff0c;采取 集成 的方式&…

python3.13安装教程【2025】python3.13超详细图文教程(包含安装包)

文章目录 前言一、python3.13安装包下载二、Python 3.13安装步骤三、Python3.13验证 前言 本教程将为你详细介绍 Python 3.13 python3.13安装教程&#xff0c;帮助你顺利搭建起 Python 3.13 开发环境&#xff0c;快速投身于 Python 编程的精彩实践中。 一、python3.13安装包下…

【极客时间】浏览器工作原理与实践-2 宏观视角下的浏览器 (6讲) - 2.5 渲染流程(上):HTML、CSS和JavaScript,是如何变成页面的?

https://time.geekbang.org/column/article/118205 2.5 渲染流程&#xff08;上&#xff09;&#xff1a;HTML、CSS和JavaScript&#xff0c;是如何变成页面的&#xff1f; 2.4讲了导航相关的流程&#xff0c;那导航被提交后又会怎么样呢&#xff1f; 就进入了渲染阶段。 这…

小模型和小数据可以实现AGI吗

小模型和小数据很难实现真正的 通用人工智能&#xff08;AGI, Artificial General Intelligence&#xff09;&#xff0c;但在特定任务或受限环境下&#xff0c;可以通过高效的算法和优化方法实现“近似 AGI” 的能力。 1. 为什么小模型小数据难以实现 AGI&#xff1f; AGI 需…

Android14 OTA差分包升级报kPayloadTimestampError (51)

由于VF 架构&#xff0c; 所以镜像的打包时间可能存在偏差&#xff0c; 如 boot.img 和 客制化的一些镜像打包 可能会在 vendor 侧进行打包。 而 与system 侧进行merge 时&#xff0c;时间戳比较乱&#xff0c;为了解决这个问题&#xff0c;让时间戳进行统一。 使用adb方式验证…

CMake学习笔记(一):工程的新建和如何将源文件生成二进制文件

cmake是我们在工作过程中比较常见的一个工具&#xff0c;该系列文章是自己用来学习的笔记。目前只是记录下自己学习cmake的过程中的一些重要的知识点&#xff0c;其是以项目需求为导向并非完整的cmake的学习路线和系统&#xff0c;同样也并非适合所有的人。 1.生成一个可执行文…

重定位(1)

一、重定位 1、对于有强大ROM的板子&#xff0c;他们会将上电后的程序放到指定RAM内存 2、无强大片内ROM的板子&#xff0c;自己编程序让他知道RAM内存指定位置 指定位置&#xff1a;就是链接地址&#xff0c;指定哪里&#xff0c;哪里就被编译好一块内存用来存放上电的程序 …

自由学习记录(41)

代理服务器的核心功能是在客户端&#xff08;用户设备&#xff09;和目标服务器&#xff08;网站/资源服务器&#xff09;之间充当“中介”&#xff0c;具体过程如下&#xff1a; 代理服务器的工作流程 当客户端希望访问某个网站&#xff08;比如 example.com&#xff09;时&…

Jadx Gui 的详细介绍、安装指南、使用方法及配置说明

Jadx Gui&#xff1a;安卓应用逆向分析神器 一、Jadx Gui 简介 Jadx 是一款开源的 Android 反编译工具&#xff0c;支持将 .apk、.aab、.dex 等文件反编译为可读的 Java/Kotlin 源代码和资源文件&#xff08;如 XML、PNG&#xff09;。其特点包括&#xff1a; 图形化界面&am…

Linux+apache之 浏览器访问云服务器磁盘的图片,通过tomcat

https://javab.blog.csdn.net/article/details/80580520 安装tomcact 修改添加 <Context docBase"/home/wyp/images" path"/img" debug"0" reloadable"true" />修改完成后保存重启tomcat服务。 测试访问方式&#xff1a;http…

软件工程与实践(第4版 新形态) 练习与实践1

软件工程与实践&#xff08;第4版 新形态&#xff09; 练习与实践1 1.填空题 (1)程序&#xff0c;文档 (2)系统软件&#xff0c;支撑软件&#xff0c;应用软件 (3)系统方法 (4)软件开发和维护 (5)工程的概念、原理、技术和方法 (6)实现软件的优质高产 (7)软件开发技术和…

基于遗传算法的无人机三维路径规划仿真步骤详解

基于遗传算法的无人机三维路径规划仿真步骤详解 一、问题定义 目标:在三维空间内,寻找从起点到终点的最优路径,需满足: 避障:避开所有障碍物。路径最短:总飞行距离尽可能短。平滑性:转折角度不宜过大,降低机动能耗。输入: 三维地图(含障碍物,如立方体、圆柱体)。起…

LIUNX学习-线程

线程概念 一个进程需要访的大部分资源&#xff0c;诸如自身的代码、数据、new\malloc的空间数据、命令行参数和环境变量、动态库、甚至是系统调用访问内核代码…都是通过虚拟地址空间来访问的。换而言之&#xff0c;进程地址空间是进程的资源窗口&#xff01;&#xff01;   …

1.Big-endian/ little endian大端对齐、小端对齐

一、大端模式、小端模式的介绍 Little endian&#xff1a;是低位字节排放在内存的低地址端、高位字节排放在内存的高地址端。 Big-endian&#xff1a;是高位字节排放在内存的低地址端、低位字节排放在内存的高地址端。 西门子是大端模式&#xff0c;因为比如 MW100 MB100(高位…

[mybatis]resultMap详解

resultMap Mybatis中提供了resultMap功能&#xff0c;可以将数据库查询结果映射到Java对象&#xff0c;用于解决 字段名与属性名不一致 或 复杂关系&#xff08;如一对多&#xff09;的映射问题。 比如一个User类&#xff0c;在它的属性里还有另一个子对象&#xff08;或者多…

SpringBoot Actuator

SpringBoot Actuator 一、简介二、入门1、依赖2、默认监控指标3、查询监控指标4、全量监控指标 三、Spring Boot Admin1、主要功能2、Admin3、Client4、应用墙5、其他 四、定制化1、定制Health端点2、定制Info端点3、定制Metrics端点4、定制Endpoint端点 一、简介 SpringBoot自…

python标识符

在 Python 中&#xff0c;标识符&#xff08;Identifier&#xff09;是指用来标识变量、函数、类、模块等的名称。标识符的命名规则如下&#xff1a; 1. 标识符的命名规则 字母、数字和下划线&#xff1a;标识符可以由字母&#xff08;a-z, A-Z&#xff09;、数字&#xff08;…

06 HarmonyOS Next性能优化之LazyForEach 列表渲染基础与实现详解 (一)

温馨提示&#xff1a;本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦&#xff01; 目录 一、代码结构概览二、详细代码解析1. 数据源管理实现2. 数据结构定义3. 优化的列表项组件4. 主列表组件实现 一、代码结构概览 本文将详细解…

vscode 查看3d

目录 1. vscode-3d-preview obj查看ok 2. vscode-obj-viewer 没找到这个插件&#xff1a; 3. 3D Viewer for Vscode 查看obj失败 1. vscode-3d-preview obj查看ok 可以查看obj 显示过程&#xff1a;开始是绿屏&#xff0c;过了1到2秒&#xff0c;后来就正常看了。 2. vsc…

excel 斜向拆分单元格

右键-合并单元格 右键-设置单元格格式-边框 在设置好分割线后&#xff0c;你可以开始输入文字。 需要注意的是&#xff0c;文字并不会自动分成上下两行。 为了达到你期望的效果&#xff0c;你可以通过 同过左对齐、上对齐 空格键或使用【AltEnter】组合键来调整单元格中内容的…