const Router = require('@koa/router'); const router = new Router({ prefix: '/api/user' }); const util = require('../utils/util'); const userService = require('../service/user.service'); const projectService = require('../service/projects.service'); const projectUserService = require('../service/project.user.service'); const pageRoleService = require('../service/pagesRole.service'); const pageService = require('../service/pages.service'); const menuService = require('../service/menu.service'); const publishService = require('../service/publish.service'); const roleService = require('../service/roles.service'); const imgcloudService = require('../service/imgcloud.service'); const md5 = require('md5.js'); const nodemailer = require('nodemailer'); const config = require('../config'); const request = require('../utils/request'); const { Keyv } = require('keyv'); const keyv = new Keyv(); /** * 用户登录 */ router.post('/login', async (ctx) => { const { userName, userPwd, openId } = ctx.request.body; if (!userName || !userPwd) { util.fail(ctx, '用户名或密码不能为空'); return; } const pwd = new md5().update(userPwd).digest('hex'); const res = await userService.findUser(userName, pwd, openId || userName); if (!res) { util.fail(ctx, '用户名或密码错误'); return; } if (!res.openId && openId) { const cacheUser = await keyv.get(openId); if (cacheUser) { await userService.bindOpenId({ ...cacheUser, id: res.id }); } } console.log("user res信息") console.log(res) const token = util.createToken({ userName, userId: res.id, nickName: res.nickName }); userService.updateUserInfo(res.id); util.success(ctx, { userId: res.id, userName, token, }); console.log("新的token:"+token) }); /** * 微信授权登录 */ router.post('/wechat', async (ctx) => { const { code } = ctx.request.body; if (!code) { util.fail(ctx, 'code不能为空'); return; } const response = await request.get( `https://api.weixin.qq.com/sns/oauth2/access_token?appid=${config.WECHAT_APP_ID}&secret=${config.WECHAT_APP_SECRET}&code=${code}&grant_type=authorization_code`, {}, ); const { access_token, openid, unionid, errcode } = JSON.parse(response.data); if (errcode) { util.success(ctx, ''); return; } const wxUser = await userService.findUser(openid, openid, openid); if (wxUser) { userService.updateUserInfo(wxUser.id); const token = util.createToken({ userName: wxUser.userName, userId: wxUser.id, nickName: wxUser.nickName }); util.success(ctx, { userId: wxUser.id, userName: wxUser.userName, token, }); return; } const res1 = await request.get(`https://api.weixin.qq.com/sns/userinfo?access_token=${access_token}&openid=${openid}`); const { nickname, headimgurl } = JSON.parse(res1.data); await keyv.set( openid, { openid, unionid, nickname, headimgurl, }, 3 * 60 * 1000, ); util.success(ctx, { openId: openid, }); }); /** * 获取用户信息 */ router.get('/info', async (ctx) => { const { userId } = util.decodeToken(ctx); const res = await userService.profile(userId); util.success(ctx, res); }); /** * 获取个人信息 */ router.get('/profile', async (ctx) => { const { userId } = util.decodeToken(ctx); const res = await userService.profile(userId); util.success(ctx, res); }); /** * 用户搜索 */ router.post('/search', async (ctx) => { const { keyword } = ctx.request.body; if (!keyword) { util.fail(ctx, '关键字不能为空'); return; } const res = await userService.search(keyword); if (!res) { util.fail(ctx, '当前用户名不存在'); return; } util.success(ctx, res); }); /** * 用户信息更新 */ router.post('/update/profile', async (ctx) => { const { nickName, avatar } = ctx.request.body; if (!nickName && !avatar) { util.fail(ctx, '参数异常,请重新提交'); return; } const { userId } = util.decodeToken(ctx); await userService.updateUserInfo(userId, nickName, avatar); util.success(ctx, '更新成功'); }); /** * 用户注册 - 发送验证码 */ router.post('/sendEmail', async (ctx) => { try { const { email } = ctx.request.body; if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) { util.fail(ctx, '邮箱不能为空或格式错误'); return; } const val = await keyv.get(email); if (val) { util.fail(ctx, '验证码已发送,请查收'); return; } let transporter = nodemailer.createTransport({ host: config.EMAIL_HOST, port: config.EMAIL_PORT, auth: { user: config.EMAIL_USER, // 你的Gmail地址 pass: config.EMAIL_PASSWORD, // 你的Gmail密码或应用专用密码 }, }); const random = Math.random().toString().slice(2, 7).replace(/^(0)+/, '1'); let mailOptions = { from: `"Marsview" <${config.EMAIL_USER}>`, // 发送者地址 to: email, // 接收者列表 subject: 'Marsview账号注册', // 主题行 text: '验证码发送', // 纯文字正文 html: `当前验证码为:${random},3分钟内有效。

感谢您体验 Marsview 搭建平台,线上平台不保证数据的稳定性,建议有条件用户,切换到 Marsview 私有化部署服务,您在使用过程中遇到任何问题均联系我。

邮 箱:marsview@163.com
微 信:17611021717`, // HTML正文 }; await transporter.sendMail(mailOptions); await keyv.set(email, random, 3 * 60 * 1000); util.success(ctx, '发送成功'); } catch (error) { util.fail(ctx, error.message); } }); /** * 用户注册 */ router.post('/regist', async (ctx) => { const { userName, code, userPwd } = ctx.request.body; if (!userName || !userPwd) { util.fail(ctx, '用户名或密码不能为空'); return; } if (!code) { util.fail(ctx, '邮箱验证码不能为空'); return; } const val = await keyv.get(userName); if (!val) { util.fail(ctx, '验证码已过期'); return; } if (val != code) { util.fail(ctx, '验证码错误'); return; } const user = await userService.search(userName); if (user) { util.fail(ctx, '当前用户已存在'); return; } const nickName = userName.split('@')[0]; const pwd = new md5().update(userPwd).digest('hex'); const res = await userService.create(nickName, userName, pwd); if (res.affectedRows == 1) { // 生成用户token const token = util.createToken({ userName, userId: res.insertId }); util.success(ctx, { userId: res.id, userName, token, }); } else { util.fail(ctx, '注册失败,请重试'); } }); /** * 忘记密码 - 生成链接 */ router.post('/password/forget', async (ctx) => { const { userEmail } = ctx.request.body; if (!userEmail) { util.fail(ctx, '邮箱不能为空'); return; } const user = await userService.search(userEmail); if (!user) { util.fail(ctx, '当前用户不存在'); return; } // 生成验证码,保存在redis中,用来验证链接有效期 const random = Math.random().toString().slice(2, 7); await keyv.set(userEmail, random, 5 * 60 * 1000); // 生成加密后token const token = util.createToken({ userEmail }); // 发送邮件 let transporter = nodemailer.createTransport({ host: config.EMAIL_HOST, port: config.EMAIL_PORT, auth: { user: config.EMAIL_USER, // 你的Gmail地址 pass: config.EMAIL_PASSWORD, // 你的Gmail密码或应用专用密码 }, }); let mailOptions = { from: `"Marsview" <${config.EMAIL_USER}>`, // 发送者地址 to: userEmail, // 接收者列表 subject: 'Marsview密码找回', // 主题行 text: '验证码发送', // 纯文字正文 html: `Hello,${userEmail}!
我们收到了你重置密码的申请,请点击下方按链接行重置,重置密码
链接 3分钟内有效,请尽快操作,如不是你发起的请求,请忽略。`, // HTML正文 }; await transporter.sendMail(mailOptions); util.success(ctx, '发送成功'); }); /** * 忘记密码 - 获取账号 */ router.post('/password/getUserByToken', async (ctx) => { const { resetToken } = ctx.request.query; const { userEmail } = util.decodeResetToken(resetToken); const val = await keyv.get(userEmail); if (!val) { util.fail(ctx, '链接已失效,请重新操作'); return; } util.success(ctx, userEmail); }); /** * 忘记密码 - 重置密码 */ router.post('/password/reset', async (ctx) => { const { resetToken, userPwd } = ctx.request.body; if (!resetToken) { util.fail(ctx, '重置Token不能为空'); return; } if (!userPwd) { util.fail(ctx, '重置密码不能为空'); return; } const { userEmail } = util.decodeResetToken(resetToken); if (!userEmail) { util.fail(ctx, 'Token 识别错误,请重新操作'); return; } const val = await keyv.get(userEmail); if (!val) { util.fail(ctx, '链接已失效,请重新操作'); return; } const pwd = new md5().update(userPwd).digest('hex'); await userService.resetPwd(userEmail, pwd); await keyv.delete(userEmail); util.success(ctx, '更新成功'); }); /** * 密码修改 */ router.post('/password/update', async (ctx) => { const { oldPwd, userPwd, confirmPwd } = ctx.request.body; if (!oldPwd || !userPwd || !confirmPwd) { util.fail(ctx, '密码不能为空'); return; } if (userPwd !== confirmPwd) { util.fail(ctx, '两次密码不一致'); return; } const { userName } = util.decodeToken(ctx); try { const res = await userService.verifyOldPwd(userName, oldPwd); if (res) { const pwd = new md5().update(userPwd).digest('hex'); await userService.resetPwd(userName, pwd); util.success(ctx, '密码更改成功'); } else { util.fail(ctx, '原密码输入错误'); } } catch (error) { util.fail(ctx, error.message); } }); /** * 用户注销 */ router.post('/logout', async (ctx) => { const { userId, userName } = util.decodeToken(ctx); if (userId == 50) { util.fail(ctx, '管理员账号不支持注销'); return; } // 删除用户所有项目 await projectService.deleteAllProject(userId, userName); // 删除用户所有关联 await projectUserService.deleteAllProjectUser(userId); // 删除用户所有页面角色 await pageRoleService.deleteAllPageRole(userId); // 删除用户所有页面 await pageService.deleteAllPage(userId, userName); // 删除用户所有菜单 await menuService.deleteAllMenu(userId); // 删除用户所有发布 await publishService.deleteAllPublish(userId); // 删除用户所有角色 await roleService.deleteAllRole(userId); // 删除用户 await userService.deleteUser(userId, userName); // 删除用户图片 await imgcloudService.deleteAllImg(userId); util.success(ctx, '注销成功'); }); /** * 查询子用户列表 */ router.get('/subUser/list', async (ctx) => { const { userId } = util.decodeToken(ctx); const { pageNum, pageSize, keyword } = ctx.request.query; const { total } = await userService.getSubUsersCount(userId, keyword); if (total == 0) { return util.success(ctx, { list: [], total: 0, pageSize: +pageSize || 12, pageNum: +pageNum || 1, }); } const list = await userService.getSubUsersList(userId, pageNum || 1, pageSize || 12, keyword); util.success(ctx, { list, total, pageSize: +pageSize, pageNum: +pageNum, }); }); // 创建子用户 router.post('/subUser/create', async (ctx) => { const { userName, userPwd } = ctx.request.body; if (!userName || !userPwd) { util.fail(ctx, '用户名或密码不能为空'); return; } const { userId } = util.decodeToken(ctx); const user = await userService.search(userName); if (user) { util.fail(ctx, '当前用户已存在'); return; } const nickName = userName.split('@')[0]; const pwd = new md5().update(userPwd).digest('hex'); const res = await userService.create(nickName, userName, pwd, userId); if (res.affectedRows == 1) { util.success(ctx, '注册成功'); } else { util.fail(ctx, '注册失败,请重试'); } }); // 删除子用户 router.post('/subUser/delete', async (ctx) => { const { id } = ctx.request.body; if (!id) { util.fail(ctx, '用户ID不能为空'); return; } const { userId } = util.decodeToken(ctx); const res = await userService.deleteSubUser(id, userId); if (res.affectedRows == 1) { util.success(ctx, '删除成功'); } else { util.fail(ctx, '删除失败,请重试'); } }); //addbywanghao sso 20250512 router.post('/ssoLogin', async (ctx) => { const { userIdno } = ctx.request.body; if (!userIdno ) { util.fail(ctx, 'userIdno不能为空'); return; } const res = await userService.findUserSso(userIdno); if (!res) { util.fail(ctx, 'userIdno 不存在,暂无权限'); return; } console.log("user res信息") console.log(res) const token = util.createToken({ userName: res.userName, userId: res.id, nickName: res.nickName }); userService.updateUserInfo(res.id); util.success(ctx, { userId: res.id, userName: res.userName, token, }); console.log("sso新的token:"+token) }); module.exports = router;