更新完善页面
This commit is contained in:
@@ -0,0 +1,217 @@
|
||||
/**
|
||||
* v2 API 统一错误码系统
|
||||
*
|
||||
* 设计原则:
|
||||
* - code: 0 表示成功(与 HTTP 状态码解耦)
|
||||
* - 非零 code 表示失败,按模块分段
|
||||
* - 兼容 v1(code: 200 = 成功),通过 v2 响应头区分版本
|
||||
*
|
||||
* 错误码分段:
|
||||
* 0 — 成功
|
||||
* 1xxx — 通用错误(参数/鉴权/权限/限流)
|
||||
* 2xxx — 用户模块
|
||||
* 3xxx — 商品模块
|
||||
* 4xxx — 订单模块
|
||||
* 5xxx — 购物车模块
|
||||
* 6xxx — 库存模块
|
||||
* 7xxx — 退款模块
|
||||
* 8xxx — 积分模块
|
||||
* 9xxx — 其他模块
|
||||
*/
|
||||
|
||||
// ============ 通用错误码 1xxx ============
|
||||
const SUCCESS = 0
|
||||
|
||||
const ERR_BAD_REQUEST = 1000 // 请求参数错误
|
||||
const ERR_UNAUTHORIZED = 1001 // 未登录/Token 无效
|
||||
const ERR_FORBIDDEN = 1002 // 无权限
|
||||
const ERR_NOT_FOUND = 1003 // 资源不存在
|
||||
const ERR_CONFLICT = 1004 // 资源冲突
|
||||
const ERR_RATE_LIMIT = 1005 // 请求过于频繁
|
||||
const ERR_INTERNAL = 1006 // 服务器内部错误
|
||||
const ERR_VALIDATION = 1007 // 数据校验失败
|
||||
const ERR_DEPRECATED = 1008 // 接口已废弃
|
||||
|
||||
// ============ 用户模块 2xxx ============
|
||||
const ERR_USER_NOT_FOUND = 2001
|
||||
const ERR_USER_PASSWORD = 2002 // 密码错误
|
||||
const ERR_USER_DISABLED = 2003 // 账号已禁用
|
||||
const ERR_USER_EXISTS = 2004 // 用户已存在
|
||||
const ERR_USER_PHONE_INVALID = 2005
|
||||
|
||||
// ============ 商品模块 3xxx ============
|
||||
const ERR_GOODS_NOT_FOUND = 3001
|
||||
const ERR_GOODS_OFF_SHELF = 3002 // 商品已下架
|
||||
const ERR_GOODS_STOCK_LOW = 3003 // 库存不足
|
||||
const ERR_GOODS_NAME_DUPLICATE = 3004
|
||||
|
||||
// ============ 订单模块 4xxx ============
|
||||
const ERR_ORDER_NOT_FOUND = 4001
|
||||
const ERR_ORDER_STATUS = 4002 // 订单状态不允许此操作
|
||||
const ERR_ORDER_EMPTY = 4003 // 订单为空
|
||||
const ERR_ORDER_CANNOT_CANCEL = 4004
|
||||
|
||||
// ============ 购物车模块 5xxx ============
|
||||
const ERR_CART_ITEM_NOT_FOUND = 5001
|
||||
const ERR_CART_QUANTITY_INVALID = 5002
|
||||
const ERR_CART_GOODS_OFF_SHELF = 5003
|
||||
|
||||
// ============ 库存模块 6xxx ============
|
||||
const ERR_STOCK_NEGATIVE = 6001 // 库存不能为负
|
||||
const ERR_STOCK_LOG_NOT_FOUND = 6002
|
||||
|
||||
// ============ 退款模块 7xxx ============
|
||||
const ERR_REFUND_NOT_FOUND = 7001
|
||||
const ERR_REFUND_AMOUNT_INVALID = 7002
|
||||
const ERR_REFUND_DUPLICATE = 7003 // 已有待处理退款
|
||||
const ERR_REFUND_STATUS = 7004 // 退款状态不允许此操作
|
||||
|
||||
// ============ 积分模块 8xxx ============
|
||||
const ERR_POINTS_INSUFFICIENT = 8001
|
||||
const ERR_POINTS_GOODS_NOT_FOUND = 8002
|
||||
const ERR_POINTS_GOODS_OFF_SHELF = 8003
|
||||
const ERR_POINTS_GOODS_NO_STOCK = 8004
|
||||
const ERR_POINTS_DELTA_EXCEED = 8005 // 积分变动超限
|
||||
|
||||
// ============ 错误码映射表 ============
|
||||
const ERROR_MESSAGES = {
|
||||
[SUCCESS]: 'success',
|
||||
[ERR_BAD_REQUEST]: '请求参数错误',
|
||||
[ERR_UNAUTHORIZED]: '未登录或登录已过期',
|
||||
[ERR_FORBIDDEN]: '无权限访问',
|
||||
[ERR_NOT_FOUND]: '资源不存在',
|
||||
[ERR_CONFLICT]: '资源冲突',
|
||||
[ERR_RATE_LIMIT]: '请求过于频繁,请稍后再试',
|
||||
[ERR_INTERNAL]: '服务器内部错误',
|
||||
[ERR_VALIDATION]: '数据校验失败',
|
||||
[ERR_DEPRECATED]: '接口已废弃',
|
||||
[ERR_USER_NOT_FOUND]: '用户不存在',
|
||||
[ERR_USER_PASSWORD]: '密码错误',
|
||||
[ERR_USER_DISABLED]: '账号已禁用',
|
||||
[ERR_USER_EXISTS]: '用户已存在',
|
||||
[ERR_USER_PHONE_INVALID]: '手机号格式错误',
|
||||
[ERR_GOODS_NOT_FOUND]: '商品不存在',
|
||||
[ERR_GOODS_OFF_SHELF]: '商品已下架',
|
||||
[ERR_GOODS_STOCK_LOW]: '库存不足',
|
||||
[ERR_GOODS_NAME_DUPLICATE]: '商品名称已存在',
|
||||
[ERR_ORDER_NOT_FOUND]: '订单不存在',
|
||||
[ERR_ORDER_STATUS]: '订单状态不允许此操作',
|
||||
[ERR_ORDER_EMPTY]: '订单为空',
|
||||
[ERR_ORDER_CANNOT_CANCEL]: '订单无法取消',
|
||||
[ERR_CART_ITEM_NOT_FOUND]: '购物车商品不存在',
|
||||
[ERR_CART_QUANTITY_INVALID]: '数量无效',
|
||||
[ERR_CART_GOODS_OFF_SHELF]: '商品已下架',
|
||||
[ERR_STOCK_NEGATIVE]: '库存不能为负数',
|
||||
[ERR_STOCK_LOG_NOT_FOUND]: '库存记录不存在',
|
||||
[ERR_REFUND_NOT_FOUND]: '退款申请不存在',
|
||||
[ERR_REFUND_AMOUNT_INVALID]: '退款金额无效',
|
||||
[ERR_REFUND_DUPLICATE]: '已有待处理的退款申请',
|
||||
[ERR_REFUND_STATUS]: '退款状态不允许此操作',
|
||||
[ERR_POINTS_INSUFFICIENT]: '积分不足',
|
||||
[ERR_POINTS_GOODS_NOT_FOUND]: '积分商品不存在',
|
||||
[ERR_POINTS_GOODS_OFF_SHELF]: '积分商品已下架',
|
||||
[ERR_POINTS_GOODS_NO_STOCK]: '积分商品库存不足',
|
||||
[ERR_POINTS_DELTA_EXCEED]: '积分变动超出允许范围',
|
||||
}
|
||||
|
||||
// ============ v1 错误码 → v2 映射 ============
|
||||
const V1_TO_V2_MAP = {
|
||||
200: SUCCESS,
|
||||
400: ERR_BAD_REQUEST,
|
||||
401: ERR_UNAUTHORIZED,
|
||||
403: ERR_FORBIDDEN,
|
||||
404: ERR_NOT_FOUND,
|
||||
500: ERR_INTERNAL,
|
||||
}
|
||||
|
||||
// ============ v2 错误码 → HTTP 状态码映射 ============
|
||||
const CODE_TO_HTTP_STATUS = {
|
||||
[SUCCESS]: 200,
|
||||
[ERR_BAD_REQUEST]: 400,
|
||||
[ERR_UNAUTHORIZED]: 401,
|
||||
[ERR_FORBIDDEN]: 403,
|
||||
[ERR_NOT_FOUND]: 404,
|
||||
[ERR_CONFLICT]: 409,
|
||||
[ERR_RATE_LIMIT]: 429,
|
||||
[ERR_INTERNAL]: 500,
|
||||
[ERR_VALIDATION]: 422,
|
||||
[ERR_DEPRECATED]: 410,
|
||||
}
|
||||
|
||||
// ============ 工具函数 ============
|
||||
|
||||
/**
|
||||
* 生成 v2 标准响应
|
||||
* @param {number} code - 错误码(0 = 成功)
|
||||
* @param {*} data - 响应数据
|
||||
* @param {string} [message] - 自定义消息(默认从映射表取)
|
||||
* @returns {{ code: number, data: *, message: string }}
|
||||
*/
|
||||
function respond(code, data, message) {
|
||||
return {
|
||||
code,
|
||||
data: code === SUCCESS ? data : null,
|
||||
message: message || ERROR_MESSAGES[code] || '未知错误',
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功响应快捷方法
|
||||
*/
|
||||
function success(data, message) {
|
||||
return respond(SUCCESS, data, message)
|
||||
}
|
||||
|
||||
/**
|
||||
* 错误响应快捷方法
|
||||
*/
|
||||
function error(code, message) {
|
||||
return respond(code, null, message)
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 v1 风格响应转换为 v2 风格
|
||||
* v1: { code: 200, data, message }
|
||||
* v2: { code: 0, data, message }
|
||||
*/
|
||||
function fromV1(v1Body) {
|
||||
if (!v1Body || typeof v1Body.code !== 'number') return v1Body
|
||||
const v2Code = V1_TO_V2_MAP[v1Body.code] ?? v1Body.code
|
||||
return {
|
||||
code: v2Code,
|
||||
data: v2Code === SUCCESS ? v1Body.data : null,
|
||||
message: v1Body.message || ERROR_MESSAGES[v2Code] || '',
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 v2 错误码对应的 HTTP 状态码
|
||||
*/
|
||||
function toHttpStatus(code) {
|
||||
return CODE_TO_HTTP_STATUS[code] || 400
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
// 错误码常量
|
||||
SUCCESS,
|
||||
ERR_BAD_REQUEST, ERR_UNAUTHORIZED, ERR_FORBIDDEN, ERR_NOT_FOUND,
|
||||
ERR_CONFLICT, ERR_RATE_LIMIT, ERR_INTERNAL, ERR_VALIDATION, ERR_DEPRECATED,
|
||||
ERR_USER_NOT_FOUND, ERR_USER_PASSWORD, ERR_USER_DISABLED, ERR_USER_EXISTS, ERR_USER_PHONE_INVALID,
|
||||
ERR_GOODS_NOT_FOUND, ERR_GOODS_OFF_SHELF, ERR_GOODS_STOCK_LOW, ERR_GOODS_NAME_DUPLICATE,
|
||||
ERR_ORDER_NOT_FOUND, ERR_ORDER_STATUS, ERR_ORDER_EMPTY, ERR_ORDER_CANNOT_CANCEL,
|
||||
ERR_CART_ITEM_NOT_FOUND, ERR_CART_QUANTITY_INVALID, ERR_CART_GOODS_OFF_SHELF,
|
||||
ERR_STOCK_NEGATIVE, ERR_STOCK_LOG_NOT_FOUND,
|
||||
ERR_REFUND_NOT_FOUND, ERR_REFUND_AMOUNT_INVALID, ERR_REFUND_DUPLICATE, ERR_REFUND_STATUS,
|
||||
ERR_POINTS_INSUFFICIENT, ERR_POINTS_GOODS_NOT_FOUND, ERR_POINTS_GOODS_OFF_SHELF,
|
||||
ERR_POINTS_GOODS_NO_STOCK, ERR_POINTS_DELTA_EXCEED,
|
||||
// 映射表
|
||||
ERROR_MESSAGES,
|
||||
V1_TO_V2_MAP,
|
||||
CODE_TO_HTTP_STATUS,
|
||||
// 工具函数
|
||||
respond,
|
||||
success,
|
||||
error,
|
||||
fromV1,
|
||||
toHttpStatus,
|
||||
}
|
||||
Reference in New Issue
Block a user