一、后端对接部分
通过前端固定文件中记录的菜单树形结构进行显示或者隐藏侧边栏菜单控制角色菜单权限
由于本框架有不同的模块,因此无法统一用最简单的文件传输形式传给后端存储,所以由以下方式多选出来的结果集传给后端保存,前端通过后端保存的结果集判断是否包含此权限
上述结构最终会形成如下数组结构,分为不同模块,每个模块都有自己的回显多选菜单,数据权限的选中结果和菜单选中结果
[
{
"label": "系统模块",
"value": "baseHome",
"selectedKeys": [],
"checkedKeys": [
"baseHome_index"
],
"requestChecked": [
"/数据1",
"/数据2"
],
"requestList": [
{
"labelName": "工作台",
"keyName": "baseHome_index",
"requestList": [
{
"label": "数据1",
"value": "/数据1"
},
{
"label": "数据2",
"value": "/数据2"
}
]
}
]
},
{
"label": "安防模块",
"value": "security",
"selectedKeys": [],
"checkedKeys": [
"security_comprehensive",
"security_personList",
"security_carList"
],
"requestChecked": [
"/mange",
"/req",
"/mange",
"/req",
"/mange",
"/req",
"/mange",
"/req"
],
"requestList": [
{
"labelName": "人员信息列表",
"keyName": "security_personList",
"requestList": [
{
"label": "借口1",
"value": "/mange"
},
{
"label": "借口2",
"value": "/req"
}
]
},
{
"labelName": "人员信息列表",
"keyName": "security_personList",
"requestList": [
{
"label": "借口1",
"value": "/mange"
},
{
"label": "借口2",
"value": "/req"
}
]
},
{
"labelName": "车辆信息列表",
"keyName": "security_carList",
"requestList": [
{
"label": "借口1",
"value": "/mange"
},
{
"label": "借口2",
"value": "/req"
}
]
},
{
"labelName": "车辆信息列表",
"keyName": "security_carList",
"requestList": [
{
"label": "借口1",
"value": "/mange"
},
{
"label": "借口2",
"value": "/req"
}
]
}
]
},
{
"label": "安全教育",
"value": "education",
"selectedKeys": [],
"checkedKeys": [
"education_index"
],
"requestChecked": [
"/安全教育数据1"
],
"requestList": [
{
"labelName": "安全教育工作台",
"keyName": "education_index",
"requestList": [
{
"label": "安全教育数据1",
"value": "/安全教育数据1"
}
]
}
]
}
]
前端发送该格式的json字符串给后端,后端需要保存字符串格式方便编辑回显,同时需要把里面的checkedKeys组合成一个新的数组,requestChecked组合成一个新的数组,在前台登录之后获取该用户的权限只需要这两个数组结果,前端通过比对是否包含这个数组中的值控制权限显示,例如
authRouter: ["baseHome_securityDevice", "baseHome_index", "baseHome_personList", "baseHome_roleList", "baseHome_logList", "baseHome_moduleList"],
authPath: ["/","/req","/req/add","/req/getList"],
每个不同的模块对应后端不同的包,由模块控制管理
模块以及模块对应的路由都在前端文件写死,只控制他的状态,通过checked控制此模块是否开启,如果后端没有部署该模块的接口包,则永远为关闭状态,只有开启的模块才可以进行上述角色中对该模块进行菜单管理
{ label: "系统模块", value: "baseHome", description: "这是系统模块", checked: true, children: 路由文件 },
{ label: "安防模块", value: "security", description: "这是安防模块", checked: true, children: 路由文件 },
{ label: "安全教育", value: "education", description: "这是安全教育", checked: true, children:路由文件 },
二、前端代码处理
前端权限通过比对后端存的值来切割现在展示的侧边栏
//通过请求路由菜单接口获取权限路由,把不存在的路由置灰
const routerStore = useRouterStore()
this.siderRouter.forEach((item, index) => {
item.disabled = true;
if (item.hasOwnProperty("children") && item.children.length != 0) {
item.children.forEach((itemChild, indexChild) => {
if (routerStore.authRouter.indexOf(itemChild.key) != -1) {
itemChild.disabled = false;
item.disabled = false;
} else {
itemChild.disabled = true;
}
// 管理员的判断不置灰权限
if(useStore().userInfo.userId == '-1'){
itemChild.disabled = false;
item.disabled = false;
}
});
} else {
if (routerStore.authRouter.indexOf(item.key) != -1) {
item.disabled = false;
} else {
item.disabled = true;
}
}
// 管理员的判断不置灰权限
if(useStore().userInfo.userId == '-1'){
item.disabled = false;
}
});
本地文件通过更改disable标出哪些是没有权限的节点不删减源文件,在父框架中调用时先赋值再判断如果disable为true则切割不展示
//处理切割菜单
this.sideRouter.forEach((item, index) => {
if (item.hasOwnProperty("children") && item.children.length != 0) {
item.children.forEach((itemChild, indexChild) => {
if (itemChild.disabled) {
item.children.splice(itemChild);
}
});
} else if (item.disabled) {
this.sideRouter.splice(item);
}
});
前端pinia
路由权限文件解读
label | 中文名 |
key | 对应router的name,antd侧边栏默认自动读取这个key用于点击跳转 |
disabled | 权限中是否启用这个菜单,在处理方法中判断true的切割掉,最后把剩下的赋值给最外层的侧边栏,源文件部分不做切割只用disable做标识 |
parentPathName | 父节点的router的name |
childrenPathName | 重要:侧边栏只分一级和二级,剩余的属于这个模块的路由如果不在这里归纳进数组,在头部模块栏切换时出现刷新或者后退前进操作将无法知道每个当前的路由的父级模块是谁侧边栏哪一个该选中,因此每个最低一级的侧边栏需要把他所属的页面router的name值放进这个数组,在父级路由守卫有重要作用,此做法避免了为了寻找某个路由的模块遍历所有的路由文件影响性能 |
moudel | 这个侧边栏属于哪个模块,用于路由守卫方便判断不用遍历路由表提升性能 |
requestList | 该层级包含哪些数据接口,和上面childrenPathName一样最底层一级需要把这个模块所有的接口全部写上,在权限判断是否能调用接口的axios全局拦截器里面有重要作用 |
children | 如果有下一级则在children中展示,默认侧边栏只做两级,因为路由守卫和头部侧边公共组件还有axios全局拦截器有多次遍历操作,层级过高的树形结构影响性能 |
siderRouter: [
{
label: "工作台",
key: "energy_index",
icon: h(HomeOutlined),
disabled: false,
onlyAdmin: "0",
parentPathName: "",
number: 1,
childrenPathName: [],
moudel: "energy",
requestList: [{ label: "能耗数据1", value: "/能耗数据1" }],
},
{
label: "智能照明管理",
key: "energy_lighting",
icon: h(SoundOutlined),
disabled: false,
onlyAdmin: "0",
parentPathName: "",
number: 1,
requestList: [],
childrenPathName: [],
moudel: "energy",
children: [
{
label: "运行参数设置",
key: "energy_parameter",
disabled: false,
onlyAdmin: "0",
parentPathName: "energy_lighting",
childrenPathName: [],
moudel: "energy",
requestList: [
{ label: "能耗数据2", value: "/能耗数据2" },
{ label: "能耗数据3", value: "/能耗数据3" },
],
number: 1,
},
{
label: "告警管理",
key: "energy_alarmList",
disabled: false,
onlyAdmin: "0",
parentPathName: "energy_lighting",
childrenPathName: [],
moudel: "energy",
requestList: [
{ label: "能耗数据2", value: "/能耗数据2" },
{ label: "能耗数据3", value: "/能耗数据3" },
],
number: 1,
},
{
label: "电能耗TOP10",
key: "energy_consumptionList",
disabled: false,
onlyAdmin: "0",
parentPathName: "energy_lighting",
childrenPathName: [],
moudel: "energy",
requestList: [
{ label: "能耗数据2", value: "/能耗数据2" },
{ label: "能耗数据3", value: "/能耗数据3" },
],
number: 1,
},
{
label: "数据监测",
key: "energy_monitoringList",
disabled: false,
onlyAdmin: "0",
parentPathName: "energy_lighting",
childrenPathName: [],
moudel: "energy",
requestList: [
{ label: "能耗数据2", value: "/能耗数据2" },
{ label: "能耗数据3", value: "/能耗数据3" },
],
number: 1,
},
{
label: "计算关系管理",
key: "energy_RelationshipList",
disabled: false,
onlyAdmin: "0",
parentPathName: "energy_lighting",
childrenPathName: [],
moudel: "energy",
requestList: [
{ label: "能耗数据2", value: "/能耗数据2" },
{ label: "能耗数据3", value: "/能耗数据3" },
],
number: 1,
},
{
label: "智能控制",
key: "energy_controlList",
disabled: false,
onlyAdmin: "0",
parentPathName: "energy_lighting",
childrenPathName: [],
moudel: "energy",
requestList: [
{ label: "能耗数据2", value: "/能耗数据2" },
{ label: "能耗数据3", value: "/能耗数据3" },
],
number: 1,
},
],
},
],
三、重构权限部分
总平台上传上面的文件,由列表管理部分可以对其进行删减增加,手动控制
租户平台通过租户号获取开通的模块拿到所有权限路由,再由管理员分配菜单和接口权限