签入版本

This commit is contained in:
2026-10-08 17:50:29 +08:00
parent 809750b47e
commit e213a9b31d
444 changed files with 39366 additions and 37533 deletions
@@ -1,19 +1,20 @@
# 8.2 错误码对照表
:::tip 概述
所有接口返回统一的 JSON 结构,通过 `code` 字段区分业务状态。前端应根据 `code` 做差异化处理。
所有接口返回统一的 JSON 结构,通过 `code` 字段区分业务状态。前端应根据 `code` 做差异化处理。本表汇总系统全部错误码与常见错误消息(消息均来自源码中的真实文案)。
:::
## 业务错误码
| code | ok | 含义 | 使用场景 | 前端处理 |
|------|-----|------|----------|----------|
| `0` | true | 成功 | 所有成功操作 | 正常处理 data |
| `1` | false | 一般失败 | 业务逻辑失败 | 显示 msg 提示 |
| `401` | false | 未授权 | Token 缺失/无效/过期 | 跳转登录页 |
| `403` | false | 禁止访问 | 权限不足/租户异常/演示环境 | 显示无权限提示 |
| `404` | false | 数据不存在 | 查询单条记录为空 | 显示数据不存在 |
| `422` | false | 参数验证失败 | 表单验证不通过 | 显示具体字段错误 |
| code | ok | HTTP | 含义 | 使用场景 | 前端处理 |
|------|-----|------|------|----------|----------|
| `0` | true | 200 | 成功 | 所有成功操作 | 正常处理 data |
| `1` | false | 200 | 一般失败 | 业务逻辑失败、FormRequest 格式错误 | 显示 msg 提示 |
| `401` | false | 200 | 未授权 | Token 缺失/无效/过期 | 跳转登录页 |
| `403` | false | **403** | 禁止访问 | 权限不足/租户异常/演示环境 | 显示无权限提示 |
| `404` | false | 200 | 数据不存在 | 查询单条记录为空 / 路由不存在 | 显示数据不存在 |
| `422` | false | 200 | 参数验证失败 | 代码内手动 `Validator::validate()` 不通过 | 显示具体字段错误 |
| `500` | false | 200 | 服务器异常 | 未捕获异常 | 显示通用错误 + 记录日志 |
## 响应示例
@@ -21,33 +22,66 @@
## 常见错误消息
### 认证相关
### 认证相关(Authenticate 中间件 / AuthController)
| 消息 | code/HTTP | 原因 | 解决方案 |
|------|------|------|----------|
| `未提供认证令牌` | 401/200 | 请求头缺少 Authorization | 携带 token(Bearer 前缀可选) |
| `Expired token` | 401/200 | Token 超过有效期 | 调用 `/api/refresh` 刷新或重新登录 |
| `Signature verification failed` | 401/200 | 密钥不匹配或令牌被篡改 | 检查 `JWT_SECRET` 是否一致 |
| `无效的access_token` | 401/200 | 拿 refresh_token 访问业务接口 | 使用 access_token |
| `用户名或密码错误` | 1/200 | 账号或密码不正确(统一提示) | 检查输入 |
| `账号已被禁用` | 1/200 | 用户 status != 1 | 联系管理员 |
| `验证码错误` / `请输入验证码` | 1/200 | 验证码过期/不匹配/缺失 | 重新获取验证码 |
| `缺少refresh_token` | 1/200 | 刷新未传参 | 检查请求体 |
| `refresh_token已失效` | 1/200 | 旧令牌已用过(一次性)或被吊销 | 用最新的 refresh_token |
| `用户不存在或已被禁用` | 1/200 | 刷新时用户状态异常 | 重新登录 |
| `旧密码错误` | 1/200 | 修改密码时旧密码不匹配 | 核对旧密码 |
### 权限与租户相关(Authenticate / ResolveTenant / DemoMiddleware)
| 消息 | code/HTTP | 原因 | 解决方案 |
|------|------|------|----------|
| `无访问权限:{权限码}` | 403/403 | 用户无该接口权限 | 联系管理员分配权限节点 |
| `用户不存在,请重新登录` | 401/200 | token 有效但用户被删除 | 重新登录 |
| `租户不存在` | 403/403 | 租户数据被删除 | 检查租户数据 |
| `租户已被禁用` | 403/403 | 租户 status != 1 | 联系平台管理员启用 |
| `租户已过期` | 403/403 | 租户 expire_time 已过 | 续费或联系平台 |
| `演示模式下禁止操作` | 403/403 | 演示模式下写操作被拦截 | 非演示环境操作 / `#[DemoAllow]` 放行 |
### 业务相关(Service 层 BizException)
| 消息 | 原因 | 解决方案 |
|------|------|----------|
| `未提供认证令牌` | 请求头缺少 Authorization | 携带 Token |
| `无效的认证令牌` | Token 类型不是 access | 使用 access_token |
| `token已过期` | Token 超过有效期 | 调用刷新接口或重新登录 |
| `用户名或密码错误` | 账号或密码不正确 | 检查输入 |
| `账号已被禁用` | 用户 status != 1 | 联系管理员 |
### 权限相关
| 消息 | 原因 | 解决方案 |
|------|------|----------|
| `无访问权限:xxx` | 用户无该接口权限 | 联系管理员分配权限 |
| `租户已被禁用` | 租户 status != 1 | 联系平台管理员 |
| `租户已过期` | 租户 expire_time 已过 | 续费或联系平台 |
| `演示环境,禁止操作` | 演示模式下写操作被拦截 | 非演示环境操作 |
### 业务相关
| 消息 | 原因 | 解决方案 |
|------|------|----------|
| `xxx已存在` | 唯一性校验失败 | 修改重复字段值 |
| `数据不存在` | 记录已被删除或不存在 | 刷新列表 |
| `{字段中文名}已存在` | 唯一性校验失败(uniqueFields) | 修改重复字段值 |
| `数据不存在` | 记录已被删除或不存在(_detail 404) | 刷新列表 |
| `缺少id参数` | update/delete 未传 id | 检查请求参数 |
| `请选择要删除的数据` | 批量删除时 ids 为空 | 先选择数据 |
| `该部门下存在子部门,不可删除` | 删除前钩子校验 | 先删除子部门 |
| `存在子部门,不可删除` | beforeDelete 钩子校验(DeptService) | 先删除子部门 |
| `存在子菜单,不可删除` | 菜单删除保护(MenuService) | 先删除子菜单 |
| `存在子分类,不可删除` | 分类删除保护(CategoryService,仅校验子级) | 先删除子分类 |
| `该租户下存在用户,不可删除` | 租户删除保护 | 先迁移或删除租户用户 |
| `已达到最大用户数限制` | 租户用户数达到 `max_user_num` | 调大租户用户上限或清理用户 |
| `旧密码错误` | 个人中心改密 | 核对旧密码 |
### 参数与上传相关(FormRequest / UploadController / CaptchaService)
| 消息 | code | 原因 | 解决方案 |
|------|------|------|----------|
| `参数验证失败` | 1 | FormRequest rules 不通过(data 为字段明细) | 按 data 修正入参 |
| `请选择文件` | 1 | 上传未带 file | 检查表单文件字段 |
| `不支持的文件格式,允许:...` | 1 | 扩展名不在白名单 | 转换格式或调整 `FILE_EXT` |
| `文件大小不能超过 NMB` | 1 | 超过 `FILE_MAX_SIZE` | 压缩文件或调大限制 |
| `不支持的上传类型,允许:image,file` | 1 | type 参数非法 | 传 `image` 或 `file` |
| `请求过于频繁,请 N 秒后重试` | 1 | 验证码获取触发 IP 限流 | 等待窗口期 |
| `模板不存在` | 1 | 按编码查文件模板为空 | 检查 code |
### 服务器相关
| 消息 | code | 原因 | 解决方案 |
|------|------|------|----------|
| `操作失败`(生产) | 500 | 未知异常(详情在服务端日志) | 查 `storage/logs/` 日志定位 |
| 异常原文(仅 `APP_DEBUG=true`) | 500 | 调试模式返回真实异常 | **生产必须关闭 APP_DEBUG** |
## 前端错误处理
@@ -60,13 +94,13 @@ axios.interceptors.response.use(response => {
return data; // 成功
}
if (code === 401) {
if (code === 401 || response.status === 401) {
// Token 过期,跳转登录
router.push('/login');
return;
}
if (code === 403) {
if (code === 403 || response.status === 403) {
ElMessage.error(msg || '无权限');
return;
}
@@ -75,4 +109,8 @@ axios.interceptors.response.use(response => {
ElMessage.error(msg || '操作失败');
return Promise.reject(new Error(msg));
});
```
```
:::tip 排查顺序
接口异常时按序确认:`HTTP 状态`(403 直接处理)→ `code`(401 跳转登录,其余按分支)→ `msg`(展示给用户)→ `data`(验证错误明细 / 服务端日志)。
:::