项目中要实现一个给不同角色赋予菜单权限的效果,项目用的react版本16.8.6,antd版本较老,用的3.26.7,树状菜单展示赋权用的antd TreeSelect,要实现的效果如下图所示
开发过程中碰到问题如下:
<TreeSelect
style={{ width: '100%' }}
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
treeData={roleTreeList}
treeCheckable="true"
showCheckedStrategy={SHOW_ALL}
placeholder="请设置菜单权限"
onChange={onTreeChange} />
假设某个1级菜单目录-系统管理下,有3个子菜单,用户管理、角色管理、菜单管理,用treeselect赋权时,我只选了用户管理和角色管理2个子菜单,实际上的treeselect values中应该要包含父级菜单系统管理的id的,但是因为系统管理下的3个子菜单没有全部选中,即使 showCheckedStrategy={SHOW_ALL},在获取treeselect value时是拿不到系统管理的key值的。
我通过后台来解决的,我的解决方式如下:
1.前台没找到好的办法,通过组件来拿到系统管理及其父节点(有可能存在多级的情况)的key值,前台传值不变。(找到一个帖子,好像可以在前台获取到系统管理及其父节点的key)参考https://www.cnblogs.com/makalochen/p/14103050.html
2.后台拿到前台传过来的所有key值,递归查找所有父节点后,跟前台传值做并集后做唯一值筛选。这样保证可以拿到所有前台漏掉的父节点值。入库时的数据不会有问题
3.这样会导致一个新问题出现,就是由于系统管理父节点的值入库了,在treeselect上明明应该是只显示系统管理和用户管理、角色管理两个子菜单的,但是如果从库里面拿数据的话,系统管理的key默认也是选中的,会变成了系统管理下的3个子菜单都是选中的状态
4. 第3步中的问题我是这么处理的,数据库中存入了系统管理的节点id,但是在treeselect绑定values值时,过滤掉这些父节点的key值,具体sql类似如下,我这里是角色赋权,在角色创建时指定角色有权限操作的菜单树。角色表上加一个字段menuCheckStrictly,默认为true。然后入库时父节点key值即使入库,再取数据库值绑定到treeselect时,由于角色menuCheckStrictly为true,会过滤掉这些父节点key值。
select m.menu_id from sys_menu m left join sys_role_menu rm on m.menu_id = rm.menu_id where rm.role_id = #{roleId}
<if test="menuCheckStrictly"> and m.menu_id not in (select m.parent_id from sys_menu m inner join sys_role_menu rm on m.menu_id = rm.menu_id and rm.role_id = #{roleId}) </if>
order by m.parent_id, m.order_num
整个操作,已经测试成功,基本达到我的要求。