47 lines
1.5 KiB
TypeScript
47 lines
1.5 KiB
TypeScript
/** 表单校验错误(key 对应 vue-i18n 文案) */
|
||
export class FormValidationError extends Error {
|
||
readonly key: string;
|
||
|
||
constructor(key: string) {
|
||
super(key);
|
||
this.name = 'FormValidationError';
|
||
this.key = key;
|
||
}
|
||
}
|
||
|
||
export function resolveFormError(e: unknown, t: (key: string) => string): string {
|
||
if (e instanceof FormValidationError) return t(e.key);
|
||
if (e instanceof Error && e.message.startsWith('err.')) return t(e.message);
|
||
return t('msg.form_invalid');
|
||
}
|
||
|
||
/** Nest 默认 4xx 响应里 error 常为 "Bad Request" 等泛化文案,真实原因在 message */
|
||
const GENERIC_HTTP_ERRORS = new Set([
|
||
'Bad Request',
|
||
'Unauthorized',
|
||
'Forbidden',
|
||
'Not Found',
|
||
'Conflict',
|
||
'Unprocessable Entity',
|
||
'Internal Server Error',
|
||
]);
|
||
|
||
/** 从 API 错误响应提取可读文案(兼容 GlobalExceptionFilter 与 Nest 默认格式) */
|
||
export function resolveApiError(
|
||
err: unknown,
|
||
t: (key: string) => string,
|
||
fallbackKey = 'msg.save_failed',
|
||
): string {
|
||
const data = (err as { response?: { data?: { error?: string | string[]; message?: string | string[] } } })
|
||
?.response?.data;
|
||
const msgRaw = data?.message;
|
||
const errRaw = data?.error;
|
||
const message = Array.isArray(msgRaw) ? msgRaw.join(';') : msgRaw;
|
||
const error = Array.isArray(errRaw) ? errRaw.join(';') : errRaw;
|
||
if (typeof message === 'string' && message.trim()) {
|
||
if (!error || GENERIC_HTTP_ERRORS.has(error)) return message;
|
||
}
|
||
if (typeof error === 'string' && error.trim() && !GENERIC_HTTP_ERRORS.has(error)) return error;
|
||
return t(fallbackKey);
|
||
}
|