## Context `AllExceptionsFilter` 目前把 `HttpException` 统一映射为 `code = HTTP 状态 ×100`;业务 throw 都是 `BadRequestException/ConflictException/NotFoundException('字符串')`,无 code。前端 `ApiError(code, message)` 已读 code,但无稳定业务码可分支。动机见 proposal.md - Why。 ## Goals / Non-Goals **Goals:** - 建立单一错误码注册表与 `BusinessException`,迁移关键业务错误。 **Non-Goals:** - 不一次性迁移全部 throw(逐步);不引入错误码国际化/多语言。 ## Decisions ### D1 — code 方案:`[域码 2 位][序 3 位]` 5 位数字。域码固定:00 通用、10 认证、11 用户、12 角色、13 资源、14 组织、15 租户、16 字典、17 配置、18 审计、19 登录、20 会话、21 通知。HTTP 状态由 `BusinessException` 单独携带,`code` 与 HTTP 解耦。 ### D2 — `BusinessException` + 过滤器识别 `src/common/business-exception.ts`:`class BusinessException extends HttpException { constructor(code, message, status = 400) }`。`AllExceptionsFilter`:若为 `BusinessException` 用其 `code`,否则回退 `status×100`。 ### D3 — 注册表为单一事实源 `src/common/error-codes.ts` 集中登记:通用码 + 各域码,注释标明 HTTP 状态。新增业务错误先在注册表加码,再 `throw new BusinessException(ErrorCodes.XXX, '...')`。 ### D4 — 迁移关键错误(示例集) 迁移:登录(账号或密码错误/锁定/停用)、待改密门禁、用户名冲突、原密码错误、用户/租户/资源不存在、越权等高频错误;其余保留字符串(可后续迁移)。 ## Risks / Trade-offs - **[code 与 HTTP 解耦后前端需注意]** → 前端 `ApiError.code` 现为业务码;HTTP 状态仍用于 401 自动刷新(http.ts 按 status 判断,不受影响)。 - **[迁移不完整]** → 未迁移的仍回退 `status×100`,与注册码并存,逐步收敛。 ## Migration Plan 无数据迁移;纯后端代码 + 文档。回滚即撤销。 ## Open Questions 无。