手把手教你实现一个vue3+ts+nodeJS后台管理系统(十二)

385 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第12天,点击查看活动详情

前言

前面我们已经能够得到权限的树状结构,接下来我们就能够实现权限模块的接口。我们同样来实现一下获取菜单列表和添加菜单接口。主要分以下步骤:

1.校验入参

2.获取/增加数据

3.返回信息

校验信息

菜单的入参信息校验存在相对地址的校验,需要利用正则表达式来实现。同时对于component即路由文件地址字段,它还存在Layout和路由路径两种情况需要考虑到,用allow('Layout')即可包含到(因所有子路由的父路由例如系统管理都是不存在页面信息的,这时需要将它的路由文件地址设为Layout)。其它规则的编写与之前的模块类似。

let joi = require('joi');
// 允许未设置规则的未知键
joi = joi.defaults((schema) =>
  schema.options({
    allowUnknown: true
  })
);
/**
 * string() 值必须是字符串
 * alphanum() 值只能是包含 a-zA-Z0-9 的字符串
 * min(length) 最小长度
 * max(length) 最大长度
 * required() 值是必填项,不能为 undefined
 * pattern(正则表达式) 值必须符合正则表达式的规则
 */
// 菜单的校验规则
const title = joi.string().required();
const name = joi.string().alphanum().required();
// 正则匹配相对路径,在顶级菜单的时候允许为字符串Layout
const component = joi
  .string()
  .pattern(/^/[^\s]*$/)
  .required()
  .allow('Layout');
const path = joi
  .string()
  .pattern(/^/[^\s]*$/)
  .required();
const sort = joi.number().min(0).required();
const redirect = joi.string().pattern(/^/[^\s]*$/);
const permission = joi.string().alphanum();
const menu_id = joi.number().integer().min(0).required();
const parent_id = joi.number().integer().min(0).required();
const hidden = joi.number().valid(0, 1);
const type = joi.string().valid('M', 'B', 'C');
​
// 菜单的验证规则对象
exports.add_menu_schema = joi.object().keys({
  parent_id,
  title,
  sort,
  type,
  name,
  component,
  path,
  redirect,
  permission,
  hidden
});
exports.edit_menu_schema = joi.object().keys({
  parent_id,
  title,
  sort,
  type,
  name,
  component,
  path,
  redirect,
  permission,
  hidden
});
exports.delete_menu_schema = joi.object().keys({
  menu_id
});
exports.get_menu_schema = joi.object().keys({
  menu_id
});

添加菜单

首先添加路由

router/menu.js

const express = require('express');
// 创建路由对象
const router = express.Router();
const handler = require('../router_handler/menu');
​
// 获取菜单列表
router.get('/listMenu', handler.getMenuList);
// 添加菜单
router.post('/addMenu', handler.addMenu);

校验入参完成将校验后的信息添加进数据库,之后返回成功与失败的信息

router_handler/menu.js

const MenusModel = require('../model/menus');
const Sequelize = require('sequelize');
const Op = Sequelize.Op;
// 导入需要的验证规则对象
const { add_menu_schema, edit_menu_schema, delete_menu_schema, get_menu_schema } = require('../schema/menu');
​
exports.addMenu = (req, res) => {
  // 校验入参
  const { value, error } = add_menu_schema.validate(req.body);
  if (error) throw error;
  // 创建数据库条目
  MenusModel.create(value).then(function (menu) {
  // 返回信息
    if (!menu) {
      return res.send({
        code: 1,
        message: '创建失败',
        data: null
      });
    }
    return res.send({
      code: 0,
      message: '创建成功',
      data: menu.menu_id
    });
  });
};

测试

image.png

获取菜单列表

上文手把手教你实现一个vue3+ts+nodeJS后台管理系统(十一)我们实现了获取树状结构数据的列表的方法,本文我们直接使用获取返回即可。

...
exports.getMenuList = (req, res) => {
  MenusModel.getListTree(req.query).then(function (menuTree) {
    return res.send({
      code: 0,
      message: '获取成功',
      data: menuTree || []
    });
  });
};

测试

可以看到得到了父子菜单嵌套的树状结构

image.png