Files
TurboHR/backend/src/middleware/errorHandler.ts
T
freedakgmail 2968484d2d 优化: 大文件拆分+代码分割+按需加载+console清理+any类型替换
- Money.tsx (2260行→54行): 拆分为 money/ 子目录4个组件, React.lazy二级分割
- AIAssistant.tsx (2038行→63行): 拆分为 ai-assistant/ 子目录6个组件, React.lazy二级分割
- xlsx改为动态导入, OvertimeTab从345KB降至12.7KB
- api-services.ts: 请求参数 any→Record<string,unknown>
- 移除前端3处console.log残留
- 后端console替换为pino logger
- 前后端未使用import/变量清理
- Zod schema验证: termination/platform/special-status/work-process
- 新增 leave.routes.ts, acceptance-test.routes.ts
- UI组件: PageGuide, QueryError, Stepper
2026-08-04 07:53:37 +08:00

65 lines
1.9 KiB
TypeScript

import { Request, Response, NextFunction } from 'express'
import { ZodError } from 'zod'
import { PrismaClientKnownRequestError } from '@prisma/client/runtime/library'
import { AppError } from '../lib/AppError'
import logger from '../lib/logger'
export function errorHandler(err: unknown, _req: Request, res: Response, _next: NextFunction) {
if (err instanceof AppError) {
return res.status(err.statusCode).json({
success: false,
error: { code: err.code, message: err.message },
})
}
if (err instanceof ZodError) {
return res.status(422).json({
success: false,
error: {
code: 'VALIDATION_ERROR',
message: '输入校验失败',
details: err.errors.map((e) => ({ path: e.path.join('.'), message: e.message })),
},
})
}
if (err instanceof PrismaClientKnownRequestError) {
if (err.code === 'P2002') {
return res.status(400).json({
success: false,
error: { code: 'DUPLICATE', message: '数据已存在,请勿重复操作' },
})
}
if (err.code === 'P2025') {
return res.status(404).json({
success: false,
error: { code: 'NOT_FOUND', message: '记录不存在' },
})
}
}
if (typeof err === 'object' && err !== null && 'code' in err && 'message' in err) {
const e = err as { code: string; message: string }
const statusMap: Record<string, number> = {
NOT_FOUND: 404,
CONFLICT: 409,
VALIDATION_ERROR: 422,
PLAN_LIMIT: 403,
AUTH_FAILED: 401,
TOKEN_INVALID: 401,
ACCOUNT_DISABLED: 403,
DUPLICATE: 400,
}
return res.status(statusMap[e.code] || 400).json({
success: false,
error: { code: e.code, message: e.message },
})
}
logger.error({ err }, 'Unhandled error')
return res.status(500).json({
success: false,
error: { code: 'INTERNAL_ERROR', message: '服务器内部错误' },
})
}