
本文介绍如何基于系统模块定义和用户实际权限,生成一个带布尔标记(1/0)的权限映射对象,实现模块动作级的细粒度权限比对与结构化输出。
本文介绍如何基于系统模块定义和用户实际权限,生成一个带布尔标记(1/0)的权限映射对象,实现模块动作级的细粒度权限比对与结构化输出。
在权限管理系统中,常需将完整的系统功能模块(modules)与当前用户实际拥有的操作权限(user_modules)进行逐动作比对,并以结构化方式标注每个动作是否被授权(1 表示允许,0 表示禁止)。注意:user_modules 通常只包含用户有权限的子集,且可能缺失某些模块或动作,因此比对逻辑必须具备健壮的空值处理能力。
以下是一个简洁、可复用的解决方案,使用原生 JavaScript 实现:
const modules = {
"member": {
"actions": ["create", "edit"]
},
"subscription": {
"actions": ["create", "edit", "move_out", "renew", "void"]
}
};
const user_modules = {
"subscription": {
"actions": ["create", "edit"]
}
};
const result = Object.fromEntries(
Object.entries(modules).map(([moduleName, moduleDef]) => [
moduleName,
{
...moduleDef,
actions: Object.fromEntries(
moduleDef.actions.map(action => [
action,
(user_modules[moduleName]?.actions?.includes(action) ?? false) ? 1 : 0
])
)
}
])
);
console.log(result);
// 输出:
// {
// "member": {
// "actions": { "create": 0, "edit": 0 }
// },
// "subscription": {
// "actions": { "create": 1, "edit": 1, "move_out": 0, "renew": 0, "void": 0 }
// }
// }
✅ 关键设计说明:
- 使用
Object.entries()+Object.fromEntries()实现模块级遍历与重建; - 对每个模块的动作数组,通过
map()转换为[action, flag]键值对数组,再转为对象——确保actions字段由数组变为键值映射对象(如"create": 1),符合目标输出格式; - 利用可选链
?.和空值合并??安全访问user_modules[moduleName]?.actions,避免因模块缺失导致运行时错误; - 无需预先初始化所有模块的权限,天然兼容
user_modules中未声明的模块(全部标记为0)。
⚠️ 注意事项:
- 原始数据中
actions是字符串数组,输出中应为对象(非数组),因此不能直接复用原数组结构;若后端要求保持数组形式(如[{"create": 1}, {"edit": 0}]),需另行调整序列化逻辑; - 若需支持嵌套权限(如带参数的 action)、动态角色继承或多层级权限校验,建议封装为通用
diffPermissions(modules, userModules)工具函数,并增加类型校验(如 TypeScript 接口); - 在大型应用中,该逻辑宜置于服务端或权限中间件中执行,避免前端暴露完整模块结构。
此方案兼顾可读性、健壮性与扩展性,适用于 RBAC 权限模型下的前端权限渲染或 API 响应组装场景。










