/** * 通用网络/接口错误分类器 * * 适用场景: * - uniapp 各端统一错误分类(diy.js / 商品 / 订单 / 自定义页面等) * - 任意传入 {statusCode, errMsg, message} 形式错误对象的位置 * * 设计要点: * 1) 与 Vue / $lang 解耦:不调用任何 i18n 函数,只返回分类结果 + 原始错误字段 * 调用方拿到 type 后,自行决定使用 $lang('http.timeout') / $lang('http.serverError') * 或其它命名空间的文案,完全保持各模块原有的 key 命名习惯 * 2) 通用网络/接口错误统一映射到 common.http.* 命名空间: * - http.networkError: 通用网络异常(兜底) * - http.timeout: 请求超时 * - http.serverError: 服务器错误(5xx) * - http.notFound: 接口不存在(404) * - http.auth: 无访问权限(401/403) * - http.unknown: 其他非 2xx * 3) 兼容多种错误对象形态: * - uniapp request: { statusCode, errMsg, data } * - axios: { response: { status }, message } * - fetch / 原生: { message, name } * * @param {Object|string} err 错误对象或后端业务消息字符串 * @returns {{ type: string, statusCode?: number, errMsg?: string, raw?: any }} * - type 取值: * 'business' - 后端返回的业务消息字符串(已透传到 raw) * 'empty' - 错误对象为空 * 'notFound' - HTTP 404 * 'server' - HTTP 5xx * 'auth' - HTTP 401 / 403 * 'request' - 其它非 2xx 状态码 * 'timeout' - errMsg 含 timeout * 'network' - errMsg 含 connect / network / fail * 'unknown' - 无法分类 * - statusCode: 若有则原样返回 * - errMsg: 归一后的原始消息 * - raw: 原始输入,方便调用方进一步处理 */ export function classifyHttpError(err) { // 1) 无错误对象 if (!err) { return { type: 'empty', raw: err }; } // 2) 后端直接返回的业务消息(字符串) if (typeof err === 'string') { return { type: 'business', raw: err }; } // 3) 字段归一(兼容 uni / axios / 原生 Error) const statusCode = err.statusCode ?? err.response?.status ?? err.status; const errMsg = err.errMsg || err.message || ''; if (statusCode) { if (statusCode === 404) return { type: 'notFound', statusCode, errMsg, raw: err }; if (statusCode >= 500) return { type: 'server', statusCode, errMsg, raw: err }; if (statusCode === 401 || statusCode === 403) return { type: 'auth', statusCode, errMsg, raw: err }; return { type: 'request', statusCode, errMsg, raw: err }; } if (/timeout/i.test(errMsg)) { return { type: 'timeout', errMsg, raw: err }; } if (/(connect|network|fail)/i.test(errMsg)) { return { type: 'network', errMsg, raw: err }; } return { type: 'unknown', errMsg, raw: err }; } /** * 根据 classifyHttpError 的结果,映射到 common.http.* 命名空间的 i18n key * * 通用网络/接口错误统一走 http.*,调用方通过 $lang(key) 解析文案。 * 原 diy.errTimeout 这类 key 已合并到 http.*,保持项目国际化更专业。 * * @param {string} type classifyHttpError 返回的 type * @returns {string|null} 对应的 http.* key;type='business' 时返回 null(透传 raw) */ export function httpErrorKey(type) { switch (type) { case 'empty': return 'http.networkError'; case 'business': return null; // 透传,不用 key case 'notFound': return 'http.notFound'; case 'server': return 'http.serverError'; case 'auth': return 'http.auth'; case 'request': return 'http.unknown'; case 'timeout': return 'http.timeout'; case 'network': return 'http.networkError'; case 'unknown': default: return 'http.networkError'; } } export default { classifyHttpError, httpErrorKey, };