268 lines
6.3 KiB
JavaScript
268 lines
6.3 KiB
JavaScript
// 统一响应处理模块
|
||
const { DATA_VERSION } = require('../user_init_data');
|
||
|
||
/**
|
||
* 成功响应
|
||
* @param {any} data 返回数据
|
||
* @param {string} message 成功消息
|
||
* @param {Object} extra 额外信息
|
||
* @returns {Object} 响应对象
|
||
*/
|
||
function success(data = null, message = "Success", extra = {}) {
|
||
return {
|
||
code: 200,
|
||
data: data,
|
||
msg: message,
|
||
timestamp: Date.now(),
|
||
version: DATA_VERSION,
|
||
...extra
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 错误响应
|
||
* @param {number} code 错误码
|
||
* @param {string} message 错误消息
|
||
* @param {any} data 错误相关数据
|
||
* @returns {Object} 响应对象
|
||
*/
|
||
function error(code, message, data = null) {
|
||
return {
|
||
code: code,
|
||
msg: message,
|
||
data: data,
|
||
timestamp: Date.now(),
|
||
version: DATA_VERSION
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 参数错误响应
|
||
* @param {string} message 错误消息
|
||
* @param {any} data 错误相关数据
|
||
* @returns {Object} 响应对象
|
||
*/
|
||
function badRequest(message = "Bad request", data = null) {
|
||
return error(-3, message, data);
|
||
}
|
||
|
||
/**
|
||
* 用户未找到响应
|
||
* @param {string} message 错误消息
|
||
* @returns {Object} 响应对象
|
||
*/
|
||
function userNotFound(message = "User not found") {
|
||
return error(-4, message);
|
||
}
|
||
|
||
/**
|
||
* 系统错误响应
|
||
* @param {string} message 错误消息
|
||
* @param {Error} err 错误对象
|
||
* @returns {Object} 响应对象
|
||
*/
|
||
function systemError(message = "System error", err = null) {
|
||
const errorData = err ? {
|
||
error_message: err.message,
|
||
error_stack: process.env.NODE_ENV === 'development' ? err.stack : undefined
|
||
} : null;
|
||
|
||
return error(-5, message, errorData);
|
||
}
|
||
|
||
/**
|
||
* 资源不足响应
|
||
* @param {string} resource 资源名称
|
||
* @param {number} current 当前数量
|
||
* @param {number} required 需要数量
|
||
* @returns {Object} 响应对象
|
||
*/
|
||
function insufficientResource(resource, current = 0, required = 0) {
|
||
return error(-6, `Insufficient ${resource}`, {
|
||
resource: resource,
|
||
current: current,
|
||
required: required,
|
||
shortage: required - current
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 资源已存在响应
|
||
* @param {string} resource 资源名称
|
||
* @param {any} identifier 资源标识
|
||
* @returns {Object} 响应对象
|
||
*/
|
||
function resourceExists(resource, identifier = null) {
|
||
return error(-7, `${resource} already exists`, {
|
||
resource: resource,
|
||
identifier: identifier
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 操作被拒绝响应
|
||
* @param {string} reason 拒绝原因
|
||
* @param {any} data 相关数据
|
||
* @returns {Object} 响应对象
|
||
*/
|
||
function operationDenied(reason, data = null) {
|
||
return error(-8, `Operation denied: ${reason}`, data);
|
||
}
|
||
|
||
/**
|
||
* 未知命令响应
|
||
* @param {string} command 命令名
|
||
* @param {Array} availableCommands 可用命令列表
|
||
* @returns {Object} 响应对象
|
||
*/
|
||
function unknownCommand(command, availableCommands = []) {
|
||
return error(-2, `Unknown command: ${command}`, {
|
||
command: command,
|
||
available_commands: availableCommands
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 包装异步操作,统一错误处理
|
||
* @param {Function} operation 异步操作函数
|
||
* @param {string} operationName 操作名称
|
||
* @returns {Function} 包装后的函数
|
||
*/
|
||
function wrapAsync(operation, operationName = "Operation") {
|
||
return async (...args) => {
|
||
try {
|
||
const result = await operation(...args);
|
||
|
||
// 如果操作返回的是错误格式,直接返回
|
||
if (result && typeof result === 'object' && result.code !== undefined) {
|
||
return result;
|
||
}
|
||
|
||
// 如果是成功结果,包装为成功响应
|
||
return success(result, `${operationName} completed successfully`);
|
||
} catch (error) {
|
||
console.error(`${operationName} error:`, error);
|
||
return systemError(`${operationName} failed`, error);
|
||
}
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 验证必需参数
|
||
* @param {Object} params 参数对象
|
||
* @param {Array} requiredFields 必需字段列表
|
||
* @returns {Object|null} 如果验证失败返回错误响应,否则返回null
|
||
*/
|
||
function validateRequiredParams(params, requiredFields) {
|
||
if (!params || typeof params !== 'object') {
|
||
return badRequest("Invalid parameters");
|
||
}
|
||
|
||
const missingFields = [];
|
||
for (const field of requiredFields) {
|
||
if (params[field] === undefined || params[field] === null) {
|
||
missingFields.push(field);
|
||
}
|
||
}
|
||
|
||
if (missingFields.length > 0) {
|
||
return badRequest(`Missing required parameters: ${missingFields.join(', ')}`, {
|
||
missing_fields: missingFields,
|
||
required_fields: requiredFields
|
||
});
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* 验证数值参数
|
||
* @param {any} value 要验证的值
|
||
* @param {string} fieldName 字段名
|
||
* @param {Object} options 验证选项
|
||
* @returns {Object|null} 如果验证失败返回错误响应,否则返回null
|
||
*/
|
||
function validateNumber(value, fieldName, options = {}) {
|
||
const {
|
||
min = Number.NEGATIVE_INFINITY,
|
||
max = Number.POSITIVE_INFINITY,
|
||
integer = false
|
||
} = options;
|
||
|
||
if (typeof value !== 'number' || isNaN(value)) {
|
||
return badRequest(`${fieldName} must be a number`);
|
||
}
|
||
|
||
if (integer && !Number.isInteger(value)) {
|
||
return badRequest(`${fieldName} must be an integer`);
|
||
}
|
||
|
||
if (value < min) {
|
||
return badRequest(`${fieldName} must be at least ${min}`);
|
||
}
|
||
|
||
if (value > max) {
|
||
return badRequest(`${fieldName} must be at most ${max}`);
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* 创建分页响应
|
||
* @param {Array} items 数据项
|
||
* @param {number} total 总数
|
||
* @param {number} page 当前页
|
||
* @param {number} pageSize 页大小
|
||
* @param {string} message 成功消息
|
||
* @returns {Object} 响应对象
|
||
*/
|
||
function paginated(items, total, page, pageSize, message = "Data retrieved successfully") {
|
||
const totalPages = Math.ceil(total / pageSize);
|
||
|
||
return success({
|
||
items: items,
|
||
pagination: {
|
||
current_page: page,
|
||
page_size: pageSize,
|
||
total_items: total,
|
||
total_pages: totalPages,
|
||
has_next: page < totalPages,
|
||
has_prev: page > 1
|
||
}
|
||
}, message);
|
||
}
|
||
|
||
/**
|
||
* 错误码常量
|
||
*/
|
||
const ERROR_CODES = {
|
||
SUCCESS: 200,
|
||
OPERATION_FAILED: -1,
|
||
UNKNOWN_COMMAND: -2,
|
||
BAD_REQUEST: -3,
|
||
USER_NOT_FOUND: -4,
|
||
SYSTEM_ERROR: -5,
|
||
INSUFFICIENT_RESOURCE: -6,
|
||
RESOURCE_EXISTS: -7,
|
||
OPERATION_DENIED: -8
|
||
};
|
||
|
||
module.exports = {
|
||
success,
|
||
error,
|
||
badRequest,
|
||
userNotFound,
|
||
systemError,
|
||
insufficientResource,
|
||
resourceExists,
|
||
operationDenied,
|
||
unknownCommand,
|
||
wrapAsync,
|
||
validateRequiredParams,
|
||
validateNumber,
|
||
paginated,
|
||
ERROR_CODES
|
||
};
|
||
|