const { AccessControl } = require('accesscontrol'); const { buildAc } = require('./can'); class Menu { ac; menuList; /** * * @param {AccessControl} ac * @param {*} menuList */ constructor(menuList, ac) { this.ac = ac; this.menu = { name: 'ROOT', children: menuList, } } /* * 深度优先 */ travelDFS(menu, callback, depth) { depth = depth || 0; if (menu.children) { menu.children.forEach(c => this.travelDFS(c, callback, depth + 1)) } callback(menu, depth); } /* * 广度优先 */ travelBFS(menu, callback, depth) { depth = depth || 0; callback(menu, depth); if (menu.children) { menu.children.forEach(c => this.travelBFS(c, callback, depth + 1)) } } checkPermission(role, permission) { permission.role = role; return this.ac.permission(permission).granted; } /* * 根据角色获取菜单 */ getByRole(role) { let menu = this.dcopy(this.menu); this.travelDFS(menu, (item) => { let keep = item.permission ? this.checkPermission(role, item.permission) : true; item.keep = item.children ? item.children.some(c => c.keep) : keep; }); this.travelBFS(menu, (item) => { if (item.children) item.children = item.children.filter(c => c.keep); }); //移除无用信息 this.travelBFS(menu, (item) => { delete item.permission; delete item.keep; }); //this.print(menu); //console.log(JSON.stringify(menu, null, 2)); return menu.children; } print(menu) { menu = menu || this.menu; this.travelBFS(menu, (item, depth) => { console.log( '\t\t\t\t\t\t\t\t\t'.substr(0, depth), depth, item.name, item.url); }) } dcopy(obj) { return JSON.parse(JSON.stringify(obj)); } } if (require.main === module) { (async () => { let username = 'chengen.test'; let user = await require('../../models').User.findOne({ username }); if (!user) throw new Error(`user ${username}`); let ac = await buildAc(user._id); const menu = new Menu(require('./menu-config'), ac); menu.print(); let roleMenu = menu.getByRole('user'); //let roleMenu = menu.getByRole('调解员'); console.log(JSON.stringify(roleMenu, null, 2)); })().catch(console.error) } module.exports = Menu;