记录下使用Nodejs开发服务端(5)

开头

这篇文章完善了一下关于用户表的增删改查

思路

首先是给用户表相关接口加上/user的前缀,再设计一下接口。这里将创建和修改接口并为一个,如果传入了id就用作修改数据,如果没有传入id就当作是新增。删除接口考虑了批量和单个删除的情况,查询这里做了一个分页查询,将分页独立到工具里方便以后重复使用。

代码展示

controllers/userController.js

const userService = require("../services/userService");
const { successResponse, errorResponse } = require("../utils/response");

// 新增或修改用户
exports.upsertUser = async (ctx) => {
  try {
    const userData = ctx.request.body;

    // 调用服务层的 upsertUser 方法
    await userService.upsertUser(userData);

    // 根据是否有id判断是新增还是修改
    const message = userData.id ? "用户更新成功" : "用户创建成功";

    // 返回成功消息
    successResponse(ctx, null, message);
  } catch (error) {
    errorResponse(ctx, error.message);
  }
};

// 删除或批量删除用户
exports.deleteUsers = async (ctx) => {
  try {
    const ids = ctx.request.body.ids;

    if (!ids) {
      errorResponse(ctx, "需要传入用户id", 400);
      return;
    }

    // 调用服务层的 deleteUsers 方法
    const result = await userService.deleteUsers(ids);

    // 根据返回的结果判断是单个删除还是批量删除
    let message;
    if (Array.isArray(ids)) {
      message = `成功删除 ${result} 个用户`;
    } else {
      message = "用户删除成功";
    }

    successResponse(ctx, null, message);
  } catch (error) {
    errorResponse(ctx, error.message);
  }
};
//查询用户(分页)
exports.getPaginatedUsers = async (ctx) => {
  try {
    const {
      page,
      pageSize,
      username,
      email,
      department_id,
      role_id,
      startDate,
      endDate,
    } = ctx.request.body;

    const result = await userService.getPaginatedUsers({
      page,
      pageSize,
      username,
      email,
      department_id,
      role_id,
      startDate,
      endDate,
    });
    successResponse(ctx, result, "用户已成功获取");
  } catch (error) {
    errorResponse(ctx, error.message);
  }
};

services/userService.js

这里从 Sequelize 库中导入 Op 对象,它包含了各种操作符,用于构建复杂的查询条件。例如使用 Op 来表示等于、不等于、大于、小于、在某个范围内等条件。以下是 Op 中一些常用的操作符:

  1. Op.eq: 等于 (=)
  2. Op.ne: 不等于 (!=)
  3. Op.lt: 小于 (<)
  4. Op.lte: 小于等于 (<=)
  5. Op.gt: 大于 (>)
  6. Op.gte: 大于等于 (>=)
  7. Op.between: 在某个范围内 (BETWEEN … AND …)
  8. Op.like: 类似于 (LIKE)
  9. Op.in: 在数组中 (IN)
  10. Op.notIn: 不在数组中 (NOT IN)
  11. Op.and: 并且 (AND)
  12. Op.or: 或者 (OR)
const User = require("../models/user");
const bcrypt = require("bcryptjs");
const paginate = require("../utils/pagination");
const { Op } = require("sequelize");

// 新增或修改用户
exports.upsertUser = async (userData) => {
  if (userData.id) {
    // 修改用户
    const user = await User.findByPk(userData.id);

    if (!user) {
      throw new Error("User not found");
    }

    // 如果传入了密码,则需要重新加密
    if (userData.password) {
      userData.password = await bcrypt.hash(userData.password, 8);
    }

    return await user.update(userData);
  } else {
    // 新增用户
    const hashedPassword = await bcrypt.hash(userData.password, 8);
    const newUser = {
      username: userData.username,
      password: hashedPassword,
      email: userData.email,
      department_id: userData.department_id,
      role_id: userData.role_id,
    };

    return await User.create(newUser);
  }
};

// 删除或批量删除用户
exports.deleteUsers = async (ids) => {
  if (!Array.isArray(ids)) {
    // 单个删除
    const id = ids;
    const user = await User.findByPk(id);

    if (!user) {
      throw new Error("没有找到该用户");
    }

    return await user.destroy();
  } else {
    // 批量删除
    return await User.destroy({
      where: {
        id: ids,
      },
    });
  }
};

// 查询用户(分页)
exports.getPaginatedUsers = async (query) => {
  const {
    page,
    pageSize,
    username,
    email,
    department_id,
    role_id,
    startDate,
    endDate,
  } = query;

  // 构建查询条件
  const whereClause = {};
  if (username) {
    whereClause.username = { [Op.like]: `%${username}%` };
  }
  if (email) {
    whereClause.email = { [Op.like]: `%${email}%` };
  }
  if (department_id) {
    whereClause.department_id = { [Op.like]: `%${department_id}%` };
  }
  if (role_id) {
    whereClause.role_id = { [Op.like]: `%${role_id}%` };
  }
  if (startDate && endDate) {
    whereClause.created_at = {
      [Op.between]: [new Date(startDate), new Date(endDate)],
    };
  } else if (startDate) {
    whereClause.created_at = {
      [Op.gte]: new Date(startDate),
    };
  } else if (endDate) {
    whereClause.created_at = {
      [Op.lte]: new Date(endDate),
    };
  }
  const options = {
    where: whereClause,
    order: [["created_at", "DESC"]], // 按创建时间降序排列
  };

  return await paginate(User, options, page, pageSize);
};

routes/userRoutes.js

const Router = require("koa-router");
const router = new Router({ prefix: "/user" }); // 设置前缀为 /user
const {
  upsertUser,
  deleteUsers,
  getPaginatedUsers,
} = require("../controllers/userController");

// 创建或修改用户
router.post("/upsert", upsertUser);
// 删除或批量删除用户
router.delete("/delete", deleteUsers);
// 查询用户(分页)
router.post("/list", getPaginatedUsers);

module.exports = router;

utils/pagination.js 分页

/**
 * 分页工具函数
 * @param {Object} Model - Sequelize 模型实例
 * @param {Object} options - 查询选项
 * @param {number} page - 当前页码
 * @param {number} pageSize - 每页显示条数
 * @returns {Promise<Object>} 返回包含分页数据和分页信息的对象
 */
async function paginate(Model, options, page, pageSize) {
  const offset = (page - 1) * pageSize;
  const limit = pageSize;

  // 执行分页查询
  const { count, rows } = await Model.findAndCountAll({
    ...options,
    limit: limit,
    offset: offset,
  });

  return {
    total: count, // 总记录数
    totalPages: Math.ceil(count / pageSize), // 总页数
    currentPage: page, // 当前页码
    pageSize: pageSize, // 每页显示条数
    data: rows, // 当前页的数据
  };
}

module.exports = paginate;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值