From fb66a9efe760c01df9101e8b51aa1b31527e74fc Mon Sep 17 00:00:00 2001 From: ozh Date: Tue, 15 Sep 2026 11:06:26 +0800 Subject: [PATCH] =?UTF-8?q?feat(http):=20=E9=94=99=E8=AF=AF=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E6=94=AF=E6=8C=81=E5=AD=97=E7=AC=A6=E4=B8=B2=E4=B8=9A?= =?UTF-8?q?=E5=8A=A1=E7=A0=81=E5=B9=B6=E6=96=B0=E5=A2=9E=20AuthExpiredErro?= =?UTF-8?q?r?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/http/errors.ts | 12 ++++++++++-- src/http/index.ts | 2 +- tests/unit/http/errors.spec.ts | 25 +++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 tests/unit/http/errors.spec.ts diff --git a/src/http/errors.ts b/src/http/errors.ts index 85c33f8..89d04ea 100644 --- a/src/http/errors.ts +++ b/src/http/errors.ts @@ -6,10 +6,18 @@ export class ApiError extends Error { } } -// 业务错误(code !== 0) +// 业务错误(后端 Code 为字符串,如 '200'/'500'/'401') export class BusinessError extends Error { - constructor(message: string, public readonly code: number) { + constructor(message: string, public readonly code: string) { super(message) this.name = 'BusinessError' } } + +// 登录态失效(HTTP 401 或业务码 401),触发踢回登录页 +export class AuthExpiredError extends Error { + constructor(message: string) { + super(message) + this.name = 'AuthExpiredError' + } +} diff --git a/src/http/index.ts b/src/http/index.ts index 1929be5..b1581e1 100644 --- a/src/http/index.ts +++ b/src/http/index.ts @@ -1,2 +1,2 @@ export { request } from './client' -export { ApiError, BusinessError } from './errors' +export { ApiError, BusinessError, AuthExpiredError } from './errors' diff --git a/tests/unit/http/errors.spec.ts b/tests/unit/http/errors.spec.ts new file mode 100644 index 0000000..2e552e8 --- /dev/null +++ b/tests/unit/http/errors.spec.ts @@ -0,0 +1,25 @@ +import { describe, it, expect } from 'vitest' +import { ApiError, BusinessError, AuthExpiredError } from '@/http/errors' + +describe('HTTP 错误类型', () => { + it('BusinessError.code 接受字符串业务码(后端 Code 为字符串)', () => { + const err = new BusinessError('用户未登录', '401') + expect(err).toBeInstanceOf(BusinessError) + expect(err.code).toBe('401') + expect(err.message).toBe('用户未登录') + expect(err.name).toBe('BusinessError') + }) + + it('AuthExpiredError 是独立错误类型,可被 catch 分流', () => { + const err = new AuthExpiredError('登录已过期') + expect(err).toBeInstanceOf(AuthExpiredError) + expect(err).toBeInstanceOf(Error) + expect(err.name).toBe('AuthExpiredError') + expect(err.message).toBe('登录已过期') + }) + + it('ApiError 保留 statusCode', () => { + const err = new ApiError('HTTP 404', 404) + expect(err.statusCode).toBe(404) + }) +})