|
@@ -0,0 +1,108 @@
|
|
|
|
|
+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;
|