import dayjs from 'dayjs'; import { isEnv } from '../config/config.default.js'; import { Log, User } from '../model/index.js'; import { getTokenFu } from '../middleware/jwt.js'; import { passWordJia, passWordJie } from '../util/pass.js'; import resSend from '../util/resSend.js'; import { generateCaptcha, ipLocResFu } from '../util/index.js'; // 登录模块 需要做定时器处理,防止短时间多次发送 let loginFlag: any = {}; export const clearLoginCode = () => { loginFlag = {}; }; const loginTimeFu = (key: string) => { if (loginFlag[key].loginFlagTime === 0) loginFlag[key].loginFlagTime = Date.now(); const nowTime = Date.now(); if (nowTime - loginFlag[key].loginFlagTime <= 60000) loginFlag[key].loginFlagNum++; }; const user = { getCode: async (req: any, res: any) => { req.apiDescription = '用户模块-获取验证码'; const clientIp = ipLocResFu(req); const captcha = generateCaptcha(); // 将验证码文本存入session(小写以便不区分大小写校验) const captchaTxt = captcha.text.toLowerCase(); if (loginFlag[clientIp]) loginFlag[clientIp].loginFlagCode = captchaTxt; else loginFlag[clientIp] = { loginFlagCode: captchaTxt }; // console.log('生成的验证码(开发调试用):', captchaTxt); // 调试时可查看 // 设置响应头,告诉浏览器这是SVG图片 res.type('svg'); res.send(captcha.data); }, login: async (req: any, res: any) => { req.apiDescription = '用户模块-用户登录'; const clientIp = ipLocResFu(req); if (!loginFlag[clientIp]) { loginFlag[clientIp] = { loginFlagNum: 0, loginFlagTime: 0, loginFlagRef: null, loginFlagCode: '', }; } if (loginFlag[clientIp].loginFlagNum >= 5) { if (loginFlag[clientIp].loginFlagRef) clearTimeout(loginFlag[clientIp].loginFlagRef); loginFlag[clientIp].loginFlagRef = setTimeout(() => { loginFlag[clientIp].loginFlagNum = 0; loginFlag[clientIp].loginFlagTime = 0; loginFlag[clientIp].loginFlagRef = null; }, 60 * 1 * 1000); return resSend(res, 500, '请稍后重试'); } else { const codeTxt = req.body.code.toLowerCase(); if (loginFlag[clientIp].loginFlagCode === codeTxt || (isEnv && codeTxt === '1111')) { const dbUser = await User.findOne({ userName: req.body.userName, }).select('+passWord'); if (dbUser && dbUser._id) { const pass1 = passWordJie(dbUser.passWord); const pass2 = passWordJie(req.body.passWord); if (pass1 === pass2) { loginFlag[clientIp].loginFlagCode = ''; loginFlag[clientIp].loginFlagNum = 0; loginFlag[clientIp].loginFlagTime = 0; delete loginFlag[clientIp]; const dbUserJson: any = dbUser.toObject(); delete dbUserJson.passWord; // 获取token const token = await getTokenFu(dbUserJson); // 登录模块记录日志,由于没有token,需要特殊处理 req.userName = dbUserJson.userName; return resSend(res, 0, '登录成功', { user: dbUserJson, token }); } else { loginTimeFu(clientIp); return resSend(res, 400, '密码错误'); } } else { loginTimeFu(clientIp); return resSend(res, 400, '用户名错误'); } } else { loginTimeFu(clientIp); return resSend(res, 400, '验证码错误'); } } }, loginText: async (req: any, res: any) => { req.apiDescription = '用户模块-用户登录调试'; const dbUser = await User.findOne({ userName: req.body.userName, }); if (dbUser && dbUser._id) { const dbUserJson: any = dbUser.toJSON(); // 获取token const token = await getTokenFu(dbUserJson); return resSend(res, 0, '获取token成功', { token }); } else { return resSend(res, 400, '用户名错误'); } }, addOrEdit: async (req: any, res: any) => { // console.log('xxxxxqqqxxx', JSON.stringify(req.body)); // 拿到参数模型 if (req.body._id) { // 编辑用户 // 检查用户是否存在 const existingUser: any = await User.findById(req.body._id); if (!existingUser) return resSend(res, 404, '用户不存在'); // 更新字段 // 过滤一些字段 const filetStr = ['userName', 'passWord']; Object.keys(req.body).forEach((key) => { if (key !== '_id' && req.body[key] !== undefined) { if (!filetStr.includes(key)) { existingUser[key] = req.body[key]; } } }); existingUser.updateTime = dayjs().format('YYYY-MM-DD HH:mm:ss'); const updatedUser = await existingUser.save(); const userObj = updatedUser.toObject(); delete userObj.passWord; req.apiDescription = `用户模块-编辑用户-${userObj.userName}`; return resSend(res, 0, '编辑用户成功', userObj); } else { const infoModel = new User({ ...req.body, passWord: passWordJia('Aa147852') }); // 新增用户 // 判断用户名是否已经存在 const dbUser = await User.findOne({ userName: req.body.userName }); if (dbUser && dbUser._id) { return resSend(res, 400, '用户名已存在'); } else { infoModel.createTime = dayjs().format('YYYY-MM-DD HH:mm:ss'); infoModel.updateTime = dayjs().format('YYYY-MM-DD HH:mm:ss'); // 保存数据到数据库 const dbBack = await infoModel.save(); // 将文档转换为普通对象并删除密码字段 const userObj = dbBack.toObject(); req.apiDescription = `用户模块-新增用户-${userObj.userName}`; delete userObj.passWord; return resSend(res, 0, '新增用户成功', userObj); } } }, list: async (req: any, res: any) => { req.apiDescription = '用户模块-获取用户列表'; // 拿到参数模型 // const userModel = new User(req.body); const { pageNum = 1, pageSize = 10, searchKey = '' } = req.body; // 构建查询条件 const query: any = {}; if (searchKey) { // 使用正则表达式实现模糊查询,'i'表示不区分大小写 query.userName = { $regex: searchKey, $options: 'i' }; } // 计算跳过的文档数量 const skip = (pageNum - 1) * pageSize; // 并行执行:获取总条数和查询当前页数据 const [total, data] = await Promise.all([ // 获取满足条件的总记录数 User.countDocuments(query), // 查询当前页数据 User.find(query).skip(skip).limit(parseInt(pageSize)).sort({ createdAt: -1 }), // 按创建时间倒序 ]); // 计算总页数 const totalPages = Math.ceil(total / pageSize); return resSend(res, 0, '获取用户列表成功', { list: data, pageNum: parseInt(pageNum), pageSize: parseInt(pageSize), total, totalPages, }); }, log: async (req: any, res: any) => { req.apiDescription = '用户模块-获取操作日志'; // 拿到参数模型 // const userModel = new User(req.body); const { pageNum = 1, pageSize = 10, searchKey = '', startTime = '', endTime = '' } = req.body; // 构建查询条件 const query: any = {}; // 1. 处理模糊搜索条件 if (searchKey) { query.userName = { $regex: searchKey, $options: 'i' }; // 'i'表示不区分大小写 } // 2. 处理时间范围条件 if (startTime && endTime) { query.createTime = { $gte: startTime, $lte: endTime, }; } // 计算跳过的文档数量 const skip = (pageNum - 1) * pageSize; // 并行执行:获取总条数和查询当前页数据 const [total, data] = await Promise.all([ // 获取满足条件的总记录数 Log.countDocuments(query), // 查询当前页数据,按时间倒序排列 Log.find(query).sort({ createTime: -1 }).skip(skip).limit(parseInt(pageSize)), ]); // 计算总页数 const totalPages = Math.ceil(total / pageSize); return resSend(res, 0, '获取日志列表成功', { list: data, pageNum: parseInt(pageNum), pageSize: parseInt(pageSize), total, totalPages, }); }, resetPassWord: async (req: any, res: any) => { const _id = req.params._id; if (_id) { const resPassWord = passWordJia('Aa147852'); const filter = { _id }; const update = { $set: { passWord: resPassWord, updateTime: dayjs().format('YYYY-MM-DD HH:mm:ss'), }, }; const result = await User.findOneAndUpdate(filter, update); if (result) { req.apiDescription = `用户模块-重置密码-${result.userName}`; return resSend(res, 0, '重置密码成功'); } else return resSend(res, 404, '未找到对应用户或密码未变更'); } else return resSend(res, 400, '用户_id不能为空'); }, editPassWord: async (req: any, res: any) => { req.apiDescription = `用户模块-修改自己的密码`; const dbUser = await User.findOne({ userName: req.user.userName, }).select('+passWord'); const { oldPassword, newPassword } = req.body; const oldPassRes = passWordJie(oldPassword); const pass1 = passWordJie(dbUser!.passWord); if (oldPassRes === pass1) { const filter = { userName: req.user.userName }; const update = { $set: { passWord: newPassword, updateTime: dayjs().format('YYYY-MM-DD HH:mm:ss'), }, }; const result = await User.updateOne(filter, update); if (result.modifiedCount === 1) return resSend(res, 0, '修改密码成功'); else return resSend(res, 404, '未找到对应用户或密码未变更'); } else return resSend(res, 400, '旧密码错误'); }, del: async (req: any, res: any) => { const { _id } = req.params; // 从URL参数中获取用户ID // 1. 根据ID查找用户 const user = await User.findById(_id); if (!user) return resSend(res, 404, '用户不存在'); if (user.isAdmin === 1) return resSend(res, 500, '管理员无法删除'); const deletedUser: any = await User.findByIdAndDelete(_id); req.apiDescription = `用户模块-删除用户-${deletedUser.userName}`; return resSend(res, 0, '删除用户成功'); }, setAuthority: async (req: any, res: any) => { const { _id, authorityIds } = req.body; if (!_id) return resSend(res, 400, '_id不能为空'); let authorityIdsRes: any[] = authorityIds || []; authorityIdsRes = authorityIdsRes.map((v) => Number(v)); if (!authorityIdsRes.length) return resSend(res, 400, '权限数组不能为空'); const updatedUser = await User.findByIdAndUpdate( _id, // 用户ID { authorityIds: authorityIdsRes, updateTime: dayjs().format('YYYY-MM-DD HH:mm:ss'), }, // 要更新的字段 { new: true, // 返回更新后的文档 runValidators: true, // 确保更新操作也运行Schema级别的验证 } ); if (!updatedUser) return resSend(res, 404, '未找到该用户'); req.apiDescription = `用户模块-修改用户页面权限-${updatedUser.userName}`; return resSend(res, 0, '用户权限更新成功'); }, getInfo: async (req: any, res: any) => { const { _id } = req.params; if (!_id) return resSend(res, 400, '_id不能为空'); // 根据ID查询用户信息 const user = await User.findById(_id); if (!user) { return resSend(res, 404, '未找到该用户'); } req.apiDescription = `用户模块-获取用户详情-${user.userName}`; return resSend(res, 0, '获取用户详情成功', user); }, }; export default user;