Files
gamer/server/utils/helpers.js
T
lizhilunandClaude Opus 4.6 d551841035 refactor: 系统优化 - 错误处理、输入验证、无限滚动
主要改进:
- 新增配置管理 (server/config.js)
- 新增日志工具 (server/utils/logger.js)
- 添加全局错误处理中间件,统一错误响应格式
- 添加输入验证和 AppError 错误类
- 重构 db.js 迁移逻辑,代码更清晰
- 前端列表改为无限滚动加载,每页 20 条
- 封装 AppState 状态管理模块

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 10:39:58 +08:00

99 lines
2.4 KiB
JavaScript

/**
* 应用错误类
*/
class AppError extends Error {
constructor(message, status = 400) {
super(message);
this.status = status;
this.expose = true; // 允许向客户端暴露错误信息
}
}
/**
* 日期范围辅助函数
*/
function getMonthRange(qYear, qMonth) {
const now = new Date();
const y = Number(qYear) || now.getFullYear();
const m = Number(qMonth) || (now.getMonth() + 1);
const startDate = `${y}-${String(m).padStart(2, '0')}-01`;
const nm = m + 1 > 12 ? 1 : m + 1;
const ny = m + 1 > 12 ? y + 1 : y;
const endDate = `${ny}-${String(nm).padStart(2, '0')}-01`;
return { startDate, endDate };
}
/**
* CSV行解析(处理引号内的逗号)
*/
function parseCSVLine(line) {
const result = [];
let current = '';
let inQuotes = false;
for (let i = 0; i < line.length; i++) {
const ch = line[i];
if (inQuotes) {
if (ch === '"' && line[i + 1] === '"') { current += '"'; i++; }
else if (ch === '"') { inQuotes = false; }
else { current += ch; }
} else {
if (ch === '"') { inQuotes = true; }
else if (ch === ',') { result.push(current); current = ''; }
else { current += ch; }
}
}
result.push(current);
return result;
}
/**
* 输入验证函数
*/
function validateRequired(obj, fields) {
const missing = fields.filter(f => obj[f] === undefined || obj[f] === null || obj[f] === '');
if (missing.length > 0) {
throw new AppError(`缺少必填字段: ${missing.join(', ')}`, 400);
}
}
function validateNumber(value, field, min, max) {
const num = Number(value);
if (isNaN(num)) {
throw new AppError(`${field} 必须是数字`, 400);
}
if (min !== undefined && num < min) {
throw new AppError(`${field} 不能小于 ${min}`, 400);
}
if (max !== undefined && num > max) {
throw new AppError(`${field} 不能大于 ${max}`, 400);
}
return num;
}
function validateString(value, field, maxLength) {
if (typeof value !== 'string') {
throw new AppError(`${field} 必须是字符串`, 400);
}
if (maxLength && value.length > maxLength) {
throw new AppError(`${field} 长度不能超过 ${maxLength}`, 400);
}
return value.trim();
}
function validateInList(value, field, list) {
if (!list.includes(value)) {
throw new AppError(`${field} 值无效`, 400);
}
return value;
}
module.exports = {
AppError,
getMonthRange,
parseCSVLine,
validateRequired,
validateNumber,
validateString,
validateInList
};