lrf 2 年之前
父节点
当前提交
80482e012b

+ 42 - 0
app/controller/dev/config/.menus.js

@@ -0,0 +1,42 @@
+module.exports = {
+  create: {
+    requestBody: ['name', 'parent_id', 'order_num', 'path', 'component', 'type', 'status', 'icon'],
+  },
+  destroy: {
+    params: ['!id'],
+    service: 'delete',
+  },
+  update: {
+    params: ['!id'],
+    requestBody: ['name', 'parent_id', 'order_num', 'path', 'component', 'type', 'status', 'icon'],
+  },
+  show: {
+    parameters: {
+      params: ['!id'],
+    },
+    service: 'fetch',
+  },
+  index: {
+    parameters: {
+      query: {
+        name: 'name',
+        parent_id: 'parent_id',
+        path: 'path',
+        type: 'type',
+        'meta.createdAt@start': 'meta.createdAt@start',
+        'meta.createdAt@end': 'meta.createdAt@end',
+      },
+      // options: {
+      //   "meta.state": 0 // 默认条件
+      // },
+    },
+    service: 'query',
+    options: {
+      query: ['skip', 'limit'],
+      sort: ['meta.createdAt'],
+      desc: true,
+      count: true,
+    },
+  },
+  getUserMenu: {},
+};

+ 39 - 0
app/controller/dev/config/.role.js

@@ -0,0 +1,39 @@
+module.exports = {
+  create: {
+    requestBody: ['name', 'brief', 'menu', 'code', 'status'],
+  },
+  destroy: {
+    params: ['!id'],
+    service: 'delete',
+  },
+  update: {
+    params: ['!id'],
+    requestBody: ['name', 'brief', 'menu', 'code', 'status'],
+  },
+  show: {
+    parameters: {
+      params: ['!id'],
+    },
+    service: 'fetch',
+  },
+  index: {
+    parameters: {
+      query: {
+        'meta.createdAt@start': 'meta.createdAt@start',
+        'meta.createdAt@end': 'meta.createdAt@end',
+        name: 'name',
+        code: 'code',
+      },
+      // options: {
+      //   "meta.state": 0 // 默认条件
+      // },
+    },
+    service: 'query',
+    options: {
+      query: ['skip', 'limit'],
+      sort: ['meta.createdAt'],
+      desc: true,
+      count: true,
+    },
+  },
+};

+ 13 - 0
app/controller/dev/menus.js

@@ -0,0 +1,13 @@
+'use strict';
+const meta = require('./config/.menus.js');
+const Controller = require('egg').Controller;
+const { CrudController } = require('naf-framework-mongoose-free/lib/controller');
+
+// 菜单
+class MenusController extends Controller {
+  constructor(ctx) {
+    super(ctx);
+    this.service = this.ctx.service.dev.menus;
+  }
+}
+module.exports = CrudController(MenusController, meta);

+ 13 - 0
app/controller/dev/role.js

@@ -0,0 +1,13 @@
+'use strict';
+const meta = require('./config/.role.js');
+const Controller = require('egg').Controller;
+const { CrudController } = require('naf-framework-mongoose-free/lib/controller');
+
+// 角色
+class RoleController extends Controller {
+  constructor(ctx) {
+    super(ctx);
+    this.service = this.ctx.service.dev.role;
+  }
+}
+module.exports = CrudController(RoleController, meta);

+ 26 - 0
app/model/dev/menus.js

@@ -0,0 +1,26 @@
+'use strict';
+const Schema = require('mongoose').Schema;
+const moment = require('moment');
+const metaPlugin = require('naf-framework-mongoose-free/lib/model/meta-plugin');
+const { ObjectId } = require('mongoose').Types;
+// 菜单表
+const menus = {
+  name: { type: String, zh: '菜单名称' },
+  parent_id: { type: String, zh: '父级菜单' },
+  order_num: { type: Number, zh: '显示顺序' },
+  path: { type: String, zh: '路由地址' },
+  component: { type: String, zh: '组件地址' },
+  type: { type: String, zh: '菜单类型' }, // 0:目录,1:菜单,2:子页面.....
+  status: { type: String, zh: '状态', default: '0' }, // 0:使用;1;禁用
+  icon: { type: String, zh: '图标', default: 'icon-shouye' },
+  config: { type: Object }, // 设置,页面的按钮,函数设置
+  remark: { type: String },
+};
+const schema = new Schema(menus, { toJSON: { virtuals: true } });
+schema.index({ id: 1 });
+schema.index({ 'meta.createdAt': 1 });
+schema.plugin(metaPlugin);
+module.exports = app => {
+  const { mongoose } = app;
+  return mongoose.model('Menus', schema, 'menus');
+};

+ 24 - 0
app/model/dev/role.js

@@ -0,0 +1,24 @@
+'use strict';
+const Schema = require('mongoose').Schema;
+const metaPlugin = require('naf-framework-mongoose-free/lib/model/meta-plugin');
+
+// 角色表
+const role = {
+  name: { type: String, required: false, zh: '名称' }, //
+  brief: { type: String, required: false, zh: '简介' }, //
+  menu: { type: Object, required: false, zh: '菜单权限' }, // mode: all:超级管理员,所有权限/select:选择的权限
+  code: { type: String, zh: '编码' },
+  status: { type: String, required: false, zh: '状态', default: '0' }, // 0:正常;1停用
+};
+const schema = new Schema(role, { toJSON: { getters: true, virtuals: true } });
+schema.index({ id: 1 });
+schema.index({ 'meta.createdAt': 1 });
+schema.index({ name: 1 });
+schema.index({ code: 1 });
+
+schema.plugin(metaPlugin);
+
+module.exports = app => {
+  const { mongoose } = app;
+  return mongoose.model('Role', schema, 'role');
+};

+ 94 - 0
app/service/dev/menus.js

@@ -0,0 +1,94 @@
+'use strict';
+const { CrudService } = require('naf-framework-mongoose-free/lib/service');
+const { BusinessError, ErrorCode } = require('naf-core').Error;
+const _ = require('lodash');
+const assert = require('assert');
+const { ObjectId } = require('mongoose').Types;
+
+//
+class MenusService extends CrudService {
+  constructor(ctx) {
+    super(ctx, 'menus');
+    this.model = this.ctx.model.Dev.Menus;
+  }
+  async query(query = {}) {
+    let list = await this.model.find(query).sort({ order_num: 1 });
+    if (list.length > 0) list = JSON.parse(JSON.stringify(list));
+    let treeMenu = list.filter(f => !f.parent_id);
+    treeMenu = this.treeMenu(list, treeMenu);
+    return treeMenu;
+  }
+
+  treeMenu(allMenus, nowMenu) {
+    for (const nm of nowMenu) {
+      const { _id, parent_id } = nm;
+      // 查下下级其是否有目录
+      let children = allMenus.filter(f => ObjectId(f.parent_id).equals(_id));
+      children = this.treeMenu(allMenus, children);
+      if (children.length > 0) nm.children = children;
+      // 换父级组件的名称
+      if (parent_id) {
+        const r = allMenus.find(f => ObjectId(f._id).equals(parent_id));
+        if (r) nm.parent_name = r.name;
+      }
+    }
+    nowMenu = _.orderBy(nowMenu, [ 'order_num', [ 'asc' ]]);
+    return nowMenu;
+  }
+
+  async getUserMenu() {
+    const userInfo = await this.ctx.service.system.user.getUserInfo();
+    const userInfoMenu = _.get(userInfo, 'role.menu');
+    const userInfoMenuMode = _.get(userInfo, 'role.menu.mode');
+    // 全部权限,直接返回
+    if (userInfoMenuMode === 'all') return await this.query();
+    const userInfoMenuIds = Object.keys(userInfoMenu).filter(f => f !== 'mode');
+    let menus = await this.model.find();
+    menus = JSON.parse(JSON.stringify(menus));
+    const res = this.getParent(menus, userInfoMenuIds);
+    return res;
+  }
+  /**
+   * 查找选中的菜单
+   * @param {Array} allMenu 树形菜单
+   * @param {Array} nowMenu 选中的菜单id
+   */
+  getParent(allMenu, nowMenu) {
+    let arr = [];
+    // 递归查找上级
+    const checkParent = (menus, tid) => {
+      const cparr = [];
+      const parent = menus.find(f => ObjectId(f._id).equals(tid));
+      if (!parent) return;
+      const { parent_id } = parent;
+      cparr.push(parent);
+      if (!parent_id) return cparr;
+      const pp = checkParent(menus, parent_id);
+      cparr.push(...pp);
+      return cparr;
+    };
+    nowMenu = allMenu.filter(f => nowMenu.find(nf => f.path === nf));
+    for (const nm of nowMenu) {
+      arr.push(nm);
+      const { parent_id } = nm;
+      if (!parent_id) continue;
+      const parent = checkParent(allMenu, parent_id);
+      arr.push(...parent);
+    }
+    arr = _.uniqBy(arr, '_id');
+    const headLevel = arr.filter(f => !f.parent_id);
+    // 变成树形结构
+    const toTree = (allMenu, menus) => {
+      for (const m of menus) {
+        const children = allMenu.filter(f => ObjectId(f.parent_id).equals(m._id));
+        toTree(allMenu, children);
+        m.children = children;
+      }
+      return menus;
+    };
+    arr = toTree(arr, headLevel);
+    return arr;
+  }
+}
+
+module.exports = MenusService;

+ 40 - 0
app/service/dev/role.js

@@ -0,0 +1,40 @@
+'use strict';
+const { CrudService } = require('naf-framework-mongoose-free/lib/service');
+const { BusinessError, ErrorCode } = require('naf-core').Error;
+const _ = require('lodash');
+const assert = require('assert');
+const { ObjectId } = require('mongoose').Types;
+//
+class RoleService extends CrudService {
+  constructor(ctx) {
+    super(ctx, 'role');
+    this.model = this.ctx.model.Dev.Role;
+  }
+
+  // async afterUpdate(filter, body, data) {
+  //   try {
+  //     const { _id } = data;
+  //     // 更新redis的角色信息
+  //     const keys = await this.app.redis.keys('user:*');
+  //     for (const key of keys) {
+  //       let ui = await this.app.redis.get(key);
+  //       if (!ui) continue;
+  //       ui = JSON.parse(ui);
+  //       if (!ObjectId(ui.role._id).equals(_id)) continue;
+  //       const arr = key.split(':');
+  //       const user_id = _.last(arr);
+  //       const { populate } = this.ctx.service.system.user.getRefMods();
+  //       const user = await this.ctx.model.System.User.findById(user_id).populate(populate);
+  //       if (!user) continue;
+  //       await this.ctx.service.system.user.setUserInRedis(user);
+  //     }
+  //   } catch (error) {
+  //     console.log('更新redis角色信息失败');
+  //     console.log(error);
+  //   }
+
+  //   return data;
+  // }
+}
+
+module.exports = RoleService;

+ 2 - 0
app/z_router/dev/index.js

@@ -4,4 +4,6 @@
 module.exports = app => {
   require('./dictIndex')(app); // 字典目录
   require('./dictData')(app); // 字典内容
+  require('./menus')(app); // 菜单
+  require('./role')(app); // 字典
 };

+ 20 - 0
app/z_router/dev/menus.js

@@ -0,0 +1,20 @@
+'use strict';
+// 路由配置
+const path = require('path');
+const regPath = path.resolve('app', 'public', 'routerRegister');
+const routerRegister = require(regPath);
+const rkey = 'menus';
+const ckey = 'dev.menus';
+const keyZh = '菜单';
+const routes = [
+  { method: 'post', path: `${rkey}/getUserMenu`, controller: `${ckey}.getUserMenu`, name: `${ckey}GetUserMenu`, zh: `获取用户菜单${keyZh}` },
+  { method: 'get', path: `${rkey}`, controller: `${ckey}.index`, name: `${ckey}Query`, zh: `${keyZh}列表查询` },
+  { method: 'get', path: `${rkey}/:id`, controller: `${ckey}.show`, name: `${ckey}Show`, zh: `${keyZh}查询` },
+  { method: 'post', path: `${rkey}`, controller: `${ckey}.create`, middleware: [ 'password' ], name: `${ckey}Create`, zh: `创建${keyZh}` },
+  { method: 'post', path: `${rkey}/:id`, controller: `${ckey}.update`, name: `${ckey}Update`, zh: `修改${keyZh}` },
+  { method: 'delete', path: `${rkey}/:id`, controller: `${ckey}.destroy`, name: `${ckey}Delete`, zh: `删除${keyZh}` },
+];
+
+module.exports = app => {
+  routerRegister(app, routes, keyZh, rkey, ckey);
+};

+ 19 - 0
app/z_router/dev/role.js

@@ -0,0 +1,19 @@
+'use strict';
+// 路由配置
+const path = require('path');
+const regPath = path.resolve('app', 'public', 'routerRegister');
+const routerRegister = require(regPath);
+const rkey = 'role';
+const ckey = 'dev.role';
+const keyZh = '角色';
+const routes = [
+  { method: 'get', path: `${rkey}`, controller: `${ckey}.index`, name: `${ckey}Query`, zh: `${keyZh}列表查询` },
+  { method: 'get', path: `${rkey}/:id`, controller: `${ckey}.show`, name: `${ckey}Show`, zh: `${keyZh}查询` },
+  { method: 'post', path: `${rkey}`, controller: `${ckey}.create`, middleware: [ 'password' ], name: `${ckey}Create`, zh: `创建${keyZh}` },
+  { method: 'post', path: `${rkey}/:id`, controller: `${ckey}.update`, name: `${ckey}Update`, zh: `修改${keyZh}` },
+  { method: 'delete', path: `${rkey}/:id`, controller: `${ckey}.destroy`, name: `${ckey}Delete`, zh: `删除${keyZh}` },
+];
+
+module.exports = app => {
+  routerRegister(app, routes, keyZh, rkey, ckey);
+};