From 6183aa4da54e21d924bd86d2503d64762991c572 Mon Sep 17 00:00:00 2001 From: LingandRX Date: Sun, 29 Dec 2024 13:59:29 +0800 Subject: [PATCH] =?UTF-8?q?feat(user):=20=E9=87=8D=E6=9E=84=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E6=8E=A7=E5=88=B6=E5=99=A8=EF=BC=8C=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E7=BB=9F=E4=B8=80=E7=9A=84=E5=93=8D=E5=BA=94=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E5=92=8C=E9=94=99=E8=AF=AF=E5=A4=84=E7=90=86=EF=BC=8C=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E7=99=BB=E5=BD=95=E5=92=8C=E5=88=9B=E5=BB=BA=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 8 +++- common/constant/httpStatus.js | 75 +++++++++++++++++++++++++++++++++ common/web/fetchResult.js | 19 +++++++++ config/errorMessages.js | 1 + controllers/userController.js | 78 +++++++++++++++++------------------ routes/index.js | 13 +----- 6 files changed, 141 insertions(+), 53 deletions(-) create mode 100644 common/constant/httpStatus.js create mode 100644 common/web/fetchResult.js diff --git a/app.js b/app.js index f9e8f6b..a015f67 100644 --- a/app.js +++ b/app.js @@ -37,7 +37,13 @@ app.use( }) ) -app.use(cors()) +const corsOptions = { + origin: 'http://localhost:5173', // 指定允许的源 + credentials: true, // 允许发送凭据(如 cookies) + optionsSuccessStatus: 200 // 一些旧的浏览器(IE11, various SmartTVs)需要这个 +}; + +app.use(cors(corsOptions)) async function startServer() { try { diff --git a/common/constant/httpStatus.js b/common/constant/httpStatus.js new file mode 100644 index 0000000..92aeafe --- /dev/null +++ b/common/constant/httpStatus.js @@ -0,0 +1,75 @@ +/** + * HTTP 状态码常量 + */ +export const HTTP_STATUS = { + // 信息响应 (100–199) + CONTINUE: 100, + SWITCHING_PROTOCOLS: 101, + PROCESSING: 102, + + // 成功响应 (200–299) + OK: 200, // 请求成功 + CREATED: 201, // 请求成功并且服务器创建了新的资源 + ACCEPTED: 202, // 已接受 + NON_AUTHORITATIVE_INFORMATION: 203, // 非权威信息 + NO_CONTENT: 204, // 没有内容 + RESET_CONTENT: 205, // 重置内容 + PARTIAL_CONTENT: 206, // 部分内容 + MULTI_STATUS: 207, // 多状态 + ALREADY_REPORTED: 208, // 已报告 + IM_USED: 226, // 我被使用 + + // 重定向消息 (300–399) + MULTIPLE_CHOICES: 300, // 多种选择 + MOVED_PERMANENTLY: 301, // 永久移动 + FOUND: 302, // 查找 + SEE_OTHER: 303, // 查看其他位置 + NOT_MODIFIED: 304, // 未修改 + USE_PROXY: 305, // 使用代理 + TEMPORARY_REDIRECT: 307, // 临时重定向 + PERMANENT_REDIRECT: 308, // 永久重定向 + + // 客户端错误响应 (400–499) + BAD_REQUEST: 400, // 错误请求 + UNAUTHORIZED: 401, // 未授权 + PAYMENT_REQUIRED: 402, // 需要付款 + FORBIDDEN: 403, // 禁止 + NOT_FOUND: 404, // 未找到 + METHOD_NOT_ALLOWED: 405, // 方法禁用 + NOT_ACCEPTABLE: 406, // 请求不接受 + PROXY_AUTHENTICATION_REQUIRED: 407, // 需要代理认证 + REQUEST_TIMEOUT: 408, // 请求超时 + CONFLICT: 409, // 冲突 + GONE: 410, // 已删除 + LENGTH_REQUIRED: 411, // 需要长度 + PRECONDITION_FAILED: 412, // 前提条件失败 + PAYLOAD_TOO_LARGE: 413, // 负载过大 + URI_TOO_LONG: 414, // URI 过长 + UNSUPPORTED_MEDIA_TYPE: 415, // 不支持的媒体类型 + RANGE_NOT_SATISFIABLE: 416, // 请求范围不符合要求 + EXPECTATION_FAILED: 417, // 期望失败 + IM_A_TEAPOT: 418, // 我是一个茶壶 + MISDIRECTED_REQUEST: 421, // 请求错位 + UNPROCESSABLE_ENTITY: 422, // 无法处理的实体 + LOCKED: 423, // 锁定 + FAILED_DEPENDENCY: 424, // 失败依赖 + TOO_EARLY: 425, // 太早 + UPGRADE_REQUIRED: 426, // 升级所需 + PRECONDITION_REQUIRED: 428, // 必须的前提条件 + TOO_MANY_REQUESTS: 429, // 请求过多 + REQUEST_HEADER_FIELDS_TOO_LARGE: 431, // 请求头字段太大 + UNAVAILABLE_FOR_LEGAL_REASONS: 451, // 因法律原因不可用 + + // 服务器错误响应 (500–599) + INTERNAL_SERVER_ERROR: 500, // 内部服务器错误 + NOT_IMPLEMENTED: 501, // 尚未实施 + BAD_GATEWAY: 502, // 错误网关 + SERVICE_UNAVAILABLE: 503, // 服务不可用 + GATEWAY_TIMEOUT: 504, // 网关超时 + HTTP_VERSION_NOT_SUPPORTED: 505, // HTTP 版本不受支持 + VARIANT_ALSO_NEGOTIATES: 506, // 变体也协商 + INSUFFICIENT_STORAGE: 507, // 存储不足 + LOOP_DETECTED: 508, // 检测到循环 + NOT_EXTENDED: 510, // 未扩展 + NETWORK_AUTHENTICATION_REQUIRED: 511 // 需要网络认证 +} diff --git a/common/web/fetchResult.js b/common/web/fetchResult.js new file mode 100644 index 0000000..1745318 --- /dev/null +++ b/common/web/fetchResult.js @@ -0,0 +1,19 @@ +class FetchResult { + constructor(code, msg, data = null) { + if (typeof code !== 'number') { + throw new Error('Code must be a number') + } + if (typeof msg !== 'string') { + throw new Error('Msg must be a string') + } + this.code = code + this.msg = msg + this.data = data !== undefined && data !== null ? data : null + } + + static formatResult(res, code, msg, data = null) { + return res.status(code).json(new FetchResult(code, msg, data)) + } +} + +module.exports = FetchResult diff --git a/config/errorMessages.js b/config/errorMessages.js index 88187c7..379a4a1 100644 --- a/config/errorMessages.js +++ b/config/errorMessages.js @@ -2,6 +2,7 @@ module.exports = { user: { not_found: 'User not found', already_exists: 'User already exists', + account_password_not_match: 'Account and password not match', account_not_match: 'Account not match', password_not_match: 'Password not match', password_incorrect: 'Password incorrect' diff --git a/controllers/userController.js b/controllers/userController.js index 42a2a85..85ced29 100644 --- a/controllers/userController.js +++ b/controllers/userController.js @@ -1,28 +1,34 @@ const { body, validationResult } = require('express-validator') const userService = require('../services/userService') +const FetchResult = require('../common/web/fetchResult') const errorMessages = require('../config/errorMessages') const successMessages = require('../config/successMessages') -exports.getAllUsers = async (req, res) => { +exports.getAllUsers = async (res) => { try { const users = await userService.user_list() - res.json(users) + return FetchResult.formatResult(res, 200, 'success', users) } catch (err) { - res.status(500).json({ error: err.message }) + return FetchResult.formatResult(res, 500, 'Internal server error') } } exports.createUser = [ body('account').isLength({ min: 3 }).withMessage('Account must be at least 3 characters long'), + body('account').isEmpty().withMessage('Account is required'), body('password').isLength({ min: 6 }).withMessage('Password must be at least 6 characters long'), + body('password').isEmpty().withMessage('Password is required'), async (req, res, next) => { const errors = validationResult(req) if (!errors.isEmpty()) { - const formattedErrors = errors.array().map((err) => ({ - field: err.path, // 错误字段名 - message: err.msg // 错误提示消息 - })) - return res.status(400).json({ errors: formattedErrors }) + return FetchResult.formatResult( + res, + 400, + errors + .array() + .map((err) => err.msg) + .join(', ') + ) } next() @@ -31,35 +37,32 @@ exports.createUser = [ try { const user = req.body await userService.create_user(user) - res.status(201).json({ message: successMessages.user.created }) + return FetchResult.formatResult(res, 201, successMessages.user.created) } catch (err) { - if (err.message === errorMessages.user.already_exists) { - return res.status(400).json({ error: err.message }) - } logger('Error creating user: ', err) - return res.status(500).json({ error: 'Internal server error' }) + if (err.message === errorMessages.user.already_exists) { + return FetchResult.formatResult(res, 400, errorMessages.user.already_exists) + } + return FetchResult.formatResult(res, 500, 'Internal server error') } } ] exports.login = [ + body('account').notEmpty().withMessage('Account is required'), + body('password').notEmpty().withMessage('Password is required'), async (req, res, next) => { const errors = validationResult(req) if (!errors.isEmpty()) { - const formattedErrors = errors.array().map((err) => ({ - field: err.path, // 错误字段名 - message: err.msg // 错误提示消息 - })) - return res.status(400).json({ errors: formattedErrors }) - } - - const { account, password } = req.body - - if (!account) { - return res.status(400).json({ error: errorMessages.user.account_not_match }) - } - if (!password) { - return res.status(400).json({ error: errorMessages.user.password_not_match }) + console.log(errors) + return FetchResult.formatResult( + res, + 400, + errors + .array() + .map((err) => err.msg) + .join(', ') + ) } next() @@ -67,21 +70,15 @@ exports.login = [ async (req, res) => { try { const { account, password } = req.body - if (account === 'admin' && password === 'admin') { - req.session.user = { account } - return res.status(200).json({ message: successMessages.user.login }) - } - const user = await userService.login(account, password) + const user = await userService.login(account, password) req.session.user = user - res.status(200).json({ message: successMessages.user.login }) + return FetchResult.formatResult(res, 200, successMessages.user.login) } catch (err) { if (err.message === errorMessages.user.not_found) { - return res.status(404).json({ error: err.message }) + return FetchResult.formatResult(res, 401, errorMessages.user.account_password_not_match) } - console.log(err) - - return res.status(500).json({ error: 'Internal server error' }) + return FetchResult.formatResult(res, 500, 'Internal server error') } } ] @@ -93,11 +90,12 @@ exports.getUserExist = async (req, res) => { const { account } = req.query const exist = await userService.get_user_exist(account) + if (!exist) { - return res.status(404).json({ message: errorMessages.user.not_found }) // 用户未找到,使用 404 错误码 + return FetchResult.formatResult(res, 404, errorMessages.user.not_found) } - return res.status(200).json({ message: successMessages.user.exist }) + return FetchResult.formatResult(res, 200, successMessages.user.exist) } catch (err) { - res.status(500).json({ error: err.message }) + return FetchResult.formatResult(res, 500, 'Internal server error') } } diff --git a/routes/index.js b/routes/index.js index c48ae77..14be9fc 100644 --- a/routes/index.js +++ b/routes/index.js @@ -4,20 +4,9 @@ const userController = require('../controllers/userController') router.get('/', function (req, res, next) { - res.send('respond with a resource') + // res.send('respond with a resource') }) -// router.post('/login', function (req, res, next) { -// const { account, password } = req.body -// console.log(account, password) -// if (account === 'admin' && password === 'admin') { -// req.session.user = { account } -// res.json({ account }) -// } else { -// res.status(401).json({ error: 'Unauthorized' }) -// } -// }) - router.post('/login', userController.login) module.exports = router