我最近在做后台管理系统时碰到了很突然的bug,有必要记录一下这些内容。
Bug: 由于不同的用户使用后台管理系统的内容不一样,当用户登录系统后,系统应该显示相应的菜单项。用户拥有某个二级菜单项的访问权限,但系统不显示某个二级菜单项,或者说系统直接把包含这个二级菜单项的一级菜单隐藏了,默认该用户没有访问该菜单项的权限。
解决方案:在“生成菜单项功能”所在的jsx
文件内,找到生成菜单列表的函数(getMenuNodes()
)以及判断当前登录用户对某个菜单项是否有访问权限的函数(hasAuth()
),在hasAuth()
内加一个判断:如果当前用户有此一级菜单项的某个子菜单项的访问权限,则生成这个子菜单项。
部分关键代码如下:
hasAuth = (item) => {
const { key, isPublic } = item;
const menus = memoryUtils.user.role.menus;
const username = memoryUtils.user.username;
//1. 如果当前用户是admin
//3. 如果当前item是公开的
//2. 当前用户有此item的权限:key有没有在menus中
if (username === "admin" || isPublic || menus.indexOf(key) !== -1) {
return true;
} else if (item.children) {
//如果当前用户有此item的某个子item的权限
return !!item.children.find(child => menus.indexOf(child.key) !== -1);
}
return false;
};
/* 根据menu的数据数组生成对应的标签数组 */
getMenuNodes = (menuList) => {
//得到当前请求的路径
const path = this.props.location.pathname;
return menuList.reduce((pre, item) => {
//如果当前用户有item对应的权限,才需要显示对应的菜单项
if (this.hasAuth(item)) {
if (!item.children) {
pre.push(
<Menu.Item key={item.key}>
<Link to={item.key}>
<Icon type={item.icon} />
<span>{item.title}</span>
</Link>
</Menu.Item>
);
} else {
//查找一个与当前请求路径相匹配的子item
const cItem = item.children.find(
cItem => path.indexOf(cItem.key) === 0
);
if (cItem) {
//如果存在,说明当前item的子列表需要打开
this.openKey = item.key;
}
pre.push((
<SubMenu
key={item.key}
title={
<span>
<Icon type={item.icon} />
<span>{item.title}</span>
</span>
}
>
{this.getMenuNodes(item.children)}
</SubMenu>
))
}
}
return pre
}, [])
};