记录下使用Nodejs开发服务端
开头
这篇文章完善了一下关于用户表的增删改查
思路
首先是给用户表相关接口加上/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 中一些常用的操作符:
- Op.eq: 等于 (=)
- Op.ne: 不等于 (!=)
- Op.lt: 小于 (<)
- Op.lte: 小于等于 (<=)
- Op.gt: 大于 (>)
- Op.gte: 大于等于 (>=)
- Op.between: 在某个范围内 (BETWEEN … AND …)
- Op.like: 类似于 (LIKE)
- Op.in: 在数组中 (IN)
- Op.notIn: 不在数组中 (NOT IN)
- Op.and: 并且 (AND)
- 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;