# RuoYi-Vue 前后端交互规范 > 文档版本:v1.0 | 生成日期:2026-06-28 | 适用范围:RuoYi-Vue 全项目 --- ## 1. API 接口清单 ### 1.1 接口总览 项目共包含 **35 个前端 API 模块文件**,**19 个后端 Controller**,梳理出 **约 180+ 个 API 端点**。 ### 1.2 按模块分类 #### 1.2.1 系统管理模块(system) | 序号 | 模块 | 前端 API 文件 | 后端 Controller | 接口数 | 基础路径 | |------|------|--------------|-----------------|--------|----------| | 1 | 用户管理 | `system/user.js` | `SysUserController` | 13 | `/system/user` | | 2 | 角色管理 | `system/role.js` | `SysRoleController` | 11 | `/system/role` | | 3 | 菜单管理 | `system/menu.js` | `SysMenuController` | 7 | `/system/menu` | | 4 | 部门管理 | `system/dept.js` | `SysDeptController` | 8 | `/system/dept` | | 5 | 岗位管理 | `system/post.js` | `SysPostController` | 5 | `/system/post` | | 6 | 字典类型 | `system/dict/type.js` | `SysDictTypeController` | 7 | `/system/dict/type` | | 7 | 字典数据 | `system/dict/data.js` | `SysDictDataController` | 6 | `/system/dict/data` | | 8 | 参数配置 | `system/config.js` | `SysConfigController` | 7 | `/system/config` | | 9 | 公告管理 | `system/notice.js` | `SysNoticeController` | 5 | `/system/notice` | **系统管理模块小计:69 个接口** #### 1.2.2 监控模块(monitor) | 序号 | 模块 | 前端 API 文件 | 后端 Controller | 接口数 | 基础路径 | |------|------|--------------|-----------------|--------|----------| | 1 | 在线用户 | `monitor/online.js` | `SysUserOnlineController` | 2 | `/monitor/online` | | 2 | 登录日志 | `monitor/logininfor.js` | `SysLogininforController` | 3 | `/monitor/logininfor` | | 3 | 操作日志 | `monitor/operlog.js` | `SysOperlogController` | 3 | `/monitor/operlog` | | 4 | 服务监控 | `monitor/server.js` | `ServerController` | 1 | `/monitor/server` | | 5 | 缓存监控 | `monitor/cache.js` | `CacheController` | 1 | `/monitor/cache` | | 6 | 定时任务 | `monitor/job.js` | `SysJobController` | 7 | `/monitor/job` | | 7 | 任务日志 | `monitor/jobLog.js` | `SysJobLogController` | 3 | `/monitor/jobLog` | **监控模块小计:20 个接口** #### 1.2.3 业务模块 — 记账系统(booksystem) | 序号 | 模块 | 前端 API 文件 | 后端 Controller | 接口数 | 基础路径 | |------|------|--------------|-----------------|--------|----------| | 1 | 交易账户 | `booksystem/account.js` | `AccountController` | 5 | `/booksystem/account` | | 2 | 交易记账 | `booksystem/book.js` | `AccountBookController` | 5 | `/booksystem/book` | | 3 | 当日操作 | `booksystem/operations.js` | `OperationsController` | 5 | `/booksystem/operations` | | 4 | 单笔统计 | `booksystem/statistics.js` | `StatisticsController` | 5 | `/booksystem/statistics` | | 5 | 持仓统计 | `booksystem/statistictotal.js` | `StatisticsTotalController` | 5 | `/booksystem/statistictotal` | | 6 | 当日持仓 | `booksystem/statisticremain.js` | `StatisticsRemainController` | 5 | `/booksystem/statisticremain` | **记账系统模块小计:30 个接口** #### 1.2.4 业务模块 — 股票系统(stocksystem) | 序号 | 模块 | 前端 API 文件 | 后端 Controller | 接口数 | 基础路径 | |------|------|--------------|-----------------|--------|----------| | 1 | 行情数据 | `stocksystem/stocks.js` | `StocksController` | 6 (+16 扩展) | `/stocksystem/stocks` | | 2 | 基础数据 | `stocksystem/stockbasic.js` | `StockBasicController` | 5 | `/stocksystem/stockbasic` | | 3 | 财务数据 | `stocksystem/financial.js` | `StockFinancialController` | 5 | `/stocksystem/financial` | | 4 | 指数行情 | `stocksystem/stockindex.js` | `StockIndexController` | 5 | `/stocksystem/stockindex` | | 5 | 涨跌停板 | `stocksystem/stockslimit.js` | `StocksLimitController` | 5 | `/stocksystem/stockslimit` | | 6 | 动量结果 | `stocksystem/trends.js` | `TrendsController` | 5 (+9 扩展) | `/stocksystem/trends` | | 7 | 动量个股 | `stocksystem/trendStocks.js` | `StocksInTrendController` | 5 | `/stocksystem/trendStocks` | | 8 | 创新高低 | `stocksystem/newrecord.js` | `StocksNewRecordController` | 5 (+2 扩展) | `/stocksystem/newrecord` | | 9 | 股票记账 | `stocksystem/book.js` | `StocksBookController` | 5 | `/stocksystem/book` | **股票系统模块小计:约 63 个接口** #### 1.2.5 工具与通用模块 | 序号 | 模块 | 前端 API 文件 | 后端 Controller | 接口数 | 基础路径 | |------|------|--------------|-----------------|--------|----------| | 1 | 代码生成 | `tool/gen.js` | `GenController` | 9 | `/tool/gen` | | 2 | 登录认证 | `login.js` | `SysLoginController` / `CaptchaController` | 6 | `/login`, `/register` 等 | | 3 | 路由信息 | `menu.js` | `SysLoginController` | 1 | `/getRouters` | | 4 | 首页聚合 | `index.js` | 多 Controller 组合 | 16 | 分散 | | 5 | 通用上传 | - | `CommonController` | 2 | `/common/upload`, `/common/download` | **工具与通用模块小计:约 34 个接口** ### 1.3 分类统计 | 模块大类 | 接口数量 | 占比 | |----------|----------|------| | 系统管理 | ~69 | 38% | | 监控管理 | ~20 | 11% | | 记账系统 | ~30 | 17% | | 股票系统 | ~63 | 35% | | 工具与通用 | ~34 | - | | **合计** | **~182** | **100%** | --- ## 2. 请求/响应格式 ### 2.1 统一响应格式 所有 API 接口统一使用 `AjaxResult` 作为响应载体,其本质是 `HashMap`。 #### 2.1.1 成功响应(无数据) ```json { "code": 200, "msg": "操作成功" } ``` #### 2.1.2 成功响应(带数据) ```json { "code": 200, "msg": "操作成功", "data": { "userId": 1, "userName": "admin" } } ``` #### 2.1.3 成功响应(多字段 — AjaxResult.put 扩展) ```json { "code": 200, "msg": "操作成功", "data": { /* 用户详情 */ }, "roles": [ /* 角色列表 */ ], "posts": [ /* 岗位列表 */ ], "postIds": [1, 2], "roleIds": [1] } ``` > **注意**:后端使用 `ajax.put(key, value)` 动态追加字段,前端通过 `response.roles` 等方式访问。 #### 2.1.4 分页响应(TableDataInfo) ```json { "total": 100, "rows": [ { "userId": 1, "userName": "admin" }, { "userId": 2, "userName": "test" } ], "code": 200, "msg": "查询成功" } ``` | 字段 | 类型 | 说明 | |------|------|------| | `total` | `long` | 总记录数 | | `rows` | `List` | 当前页数据列表 | | `code` | `int` | 状态码(固定 200) | | `msg` | `String` | 消息文本 | #### 2.1.5 失败响应 ```json { "code": 500, "msg": "新增用户'admin'失败,登录账号已存在" } ``` ### 2.2 请求格式规范 #### 2.2.1 查询列表(GET) ```javascript // 前端 export function listUser(query) { return request({ url: '/system/user/list', method: 'get', params: query }) } // 请求参数通过 URL Query 传递 GET /system/user/list?pageNum=1&pageSize=10&userName=admin&status=0 ``` #### 2.2.2 查询详情(GET + PathVariable) ```javascript export function getUser(userId) { return request({ url: '/system/user/' + userId, method: 'get' }) } // 请求 GET /system/user/1 ``` #### 2.2.3 新增(POST + JSON Body) ```javascript export function addUser(data) { return request({ url: '/system/user', method: 'post', data: data }) } // 请求头: Content-Type: application/json;charset=utf-8 POST /system/user Body: { "userName": "test", "phonenumber": "13800138000" } ``` #### 2.2.4 修改(PUT + JSON Body) ```javascript export function updateUser(data) { return request({ url: '/system/user', method: 'put', data: data }) } PUT /system/user Body: { "userId": 1, "userName": "admin" } ``` #### 2.2.5 删除(DELETE + PathVariable) ```javascript export function delUser(userId) { return request({ url: '/system/user/' + userId, method: 'delete' }) } DELETE /system/user/1 ``` > 后端实际接收 `Long[]` 数组,支持批量删除:`DELETE /system/user/1,2,3` #### 2.2.6 文件下载(POST + Blob) ```javascript export function download(url, params, filename) { return service.post(url, params, { transformRequest: [(params) => { return tansParams(params) }], headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, responseType: 'blob' }) } ``` #### 2.2.7 登录请求(跳过 Token) ```javascript export function login(username, password, code, uuid) { return request({ url: '/login', headers: { isToken: false }, // 不携带 Token method: 'post', data: { username, password, code, uuid } }) } ``` ### 2.3 登录认证机制 | 环节 | 说明 | |------|------| | Token 载体 | JWT Token | | Token 传递 | `Authorization: Bearer {token}` | | 请求头配置 | `axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'` | | Token 跳过 | `headers: { isToken: false }` | | 超时时间 | 60 秒(验证码接口 20 秒) | --- ## 3. 错误处理机制 ### 3.1 前端响应拦截器 位置:`ruoyi-ui/src/utils/request.js` ```javascript service.interceptors.response.use(res => { const code = res.data.code || 200; // 默认成功 const msg = errorCode[code] || res.data.msg || errorCode['default'] // 二进制数据直接返回 if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') { return res.data } if (code === 401) { // 弹出确认框 → 重新登录 MessageBox.confirm('登录状态已过期...', '系统提示', {...}) return Promise.reject('无效的会话...') } else if (code === 500) { // 全局 Message.error 提示 Message({ message: msg, type: 'error' }) return Promise.reject(new Error(msg)) } else if (code !== 200) { // 其他错误码 → Notification.error Notification.error({ title: msg }) return Promise.reject('error') } else { return res.data // 正常返回 } }, error => { // HTTP 层错误处理 let { message } = error; if (message == "Network Error") { message = "后端接口连接异常"; } else if (message.includes("timeout")) { message = "系统接口请求超时"; } else if (message.includes("Request failed with status code")) { message = "系统接口" + message.substr(message.length - 3) + "异常"; } Message({ message, type: 'error', duration: 5000 }) return Promise.reject(error) }) ``` ### 3.2 后端全局异常处理 位置:`ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java` | 异常类型 | 处理方式 | 返回状态码 | |----------|----------|------------| | `AccessDeniedException` | 权限校验失败 | `403` — "没有权限,请联系管理员授权" | | `HttpRequestMethodNotSupportedException` | 不支持的请求方法 | `500` — 异常消息 | | `ServiceException` | 业务异常(带自定义 code) | code 或 `500` | | `BindException` | 参数校验失败 | `500` — 校验错误消息 | | `MethodArgumentNotValidException` | @Valid 校验失败 | `500` — 字段错误消息 | | `DemoModeException` | 演示模式限制 | `500` — "演示模式,不允许操作" | | `RuntimeException` | 未知运行时异常 | `500` — 异常消息 | | `Exception` | 兜底系统异常 | `500` — 异常消息 | ### 3.3 错误码体系 位置:`ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java` | 状态码 | 常量名 | 含义 | |--------|--------|------| | 200 | `SUCCESS` | 操作成功 | | 201 | `CREATED` | 对象创建成功 | | 202 | `ACCEPTED` | 请求已被接受 | | 204 | `NO_CONTENT` | 操作成功但无返回数据 | | 301 | `MOVED_PERM` | 资源已永久移除 | | 303 | `SEE_OTHER` | 重定向 | | 304 | `NOT_MODIFIED` | 资源未修改 | | 400 | `BAD_REQUEST` | 参数错误 | | 401 | `UNAUTHORIZED` | 未授权 / Token 过期 | | 403 | `FORBIDDEN` | 访问受限 / 权限不足 | | 404 | `NOT_FOUND` | 资源/服务未找到 | | 405 | `BAD_METHOD` | 不支持的 HTTP 方法 | | 409 | `CONFLICT` | 资源冲突/被锁 | | 415 | `UNSUPPORTED_TYPE` | 不支持的媒体类型 | | 500 | `ERROR` | 系统内部错误 | | 501 | `NOT_IMPLEMENTED` | 接口未实现 | #### 前端错误码映射 位置:`ruoyi-ui/src/utils/errorCode.js` ```javascript export default { '401': '认证失败,无法访问系统资源', '403': '当前操作没有权限', '404': '访问资源不存在', 'default': '系统未知错误,请反馈给管理员' } ``` > **注意**:前端仅映射了 3 个业务错误码,其余错误码(400、409、415 等)直接 fallback 到后端返回的 `msg` 或 `default`。 ### 3.4 错误处理流程图 ``` HTTP 层错误 业务层错误 │ │ ▼ ▼ Network Error / Timeout res.data.code │ │ ▼ ▼ Message.error code === 401 → MessageBox.confirm → 跳转登录 code === 500 → Message.error code !== 200 → Notification.error code === 200 → 正常返回 res.data ``` --- ## 4. 分页 / 排序 / 过滤 ### 4.1 分页实现 基于 **PageHelper** 实现,采用 ThreadLocal 模式。 #### 4.1.1 后端处理流程 ``` 前端请求 后端处理 │ │ │ GET /system/user/list │ │ ?pageNum=1&pageSize=10 │ ▼ ▼ TableSupport.buildPageRequest() │ ▼ PageUtils.startPage() │ ▼ PageHelper.startPage(pageNum, pageSize, orderBy) │ ▼ 执行 MyBatis 查询(自动添加 LIMIT) │ ▼ BaseController.getDataTable(list) │ ▼ new PageInfo(list).getTotal() → total return TableDataInfo { total, rows, code, msg } ``` #### 4.1.2 分页参数 | 参数名 | 类型 | 必填 | 默认值 | 说明 | |--------|------|------|--------|------| | `pageNum` | `Integer` | 否 | - | 当前页码(从 1 开始) | | `pageSize` | `Integer` | 否 | - | 每页记录数 | | `orderByColumn` | `String` | 否 | - | 排序字段名 | | `isAsc` | `String` | 否 | - | 排序方向:`asc` 或 `desc`,多字段用逗号分隔 | | `reasonable` | `Boolean` | 否 | - | 分页合理化(pageNum<=0 查第一页,pageNum>总页数查最后一页) | #### 4.1.3 后端代码示例 ```java @GetMapping("/list") public TableDataInfo list(SysUser user) { startPage(); // 从请求参数读取分页信息 List list = userService.selectUserList(user); return getDataTable(list); // 封装为 TableDataInfo } ``` ### 4.2 排序规范 #### 4.2.1 排序参数传递 ```javascript // 前端通过分页组件传递 { pageNum: 1, pageSize: 10, orderByColumn: 'createTime', isAsc: 'desc' } ``` #### 4.2.2 多字段排序 ``` isAsc: createTime desc,updateTime desc ``` #### 4.2.3 SQL 注入防护 ```java // SqlUtil.escapeOrderBySql() 方法对排序字段进行转义 // 只允许字母、数字、下划线、点号、逗号、空格、ASC、DESC String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy()); PageHelper.orderBy(orderBy); ``` ### 4.3 过滤规范 #### 4.3.1 列表查询过滤 采用 **对象参数绑定** 方式: ```java // 后端 @GetMapping("/list") public TableDataInfo list(SysUser user) { startPage(); // user 对象自动绑定 query 参数中的字段 List list = userService.selectUserList(user); return getDataTable(list); } // 前端 GET /system/user/list?userName=admin&phonenumber=138&status=0 ``` #### 4.3.2 权限过滤 ```java // 每个接口通过 @PreAuthorize 进行权限校验 @PreAuthorize("@ss.hasPermi('system:user:list')") @GetMapping("/list") public TableDataInfo list(SysUser user) { ... } ``` #### 4.3.3 数据权限过滤 ```java // 在 Service 层通过 AOP 实现数据权限(部门数据范围) // 支持:全部数据、本部门数据、本部门及以下、仅本人数据、自定义数据范围 ``` ### 4.4 导出/导入规范 | 操作 | HTTP 方法 | 路径模式 | 说明 | |------|-----------|----------|------| | 导出 Excel | `POST` | `/{module}/export` | 直接写入 HttpServletResponse | | 导入 Excel | `POST` | `/{module}/importData` | MultipartFile + updateSupport 参数 | | 下载模板 | `POST` | `/{module}/importTemplate` | 返回空模板文件 | --- ## 5. 存在的问题 ### 5.1 问题清单 | # | 问题类型 | 严重程度 | 问题描述 | 涉及范围 | 优化建议 | |---|----------|----------|----------|----------|----------| | 1 | **响应格式不统一** | 高 | `AjaxResult`(普通 CRUD)与 `TableDataInfo`(分页列表)返回结构完全不同:前者用 `data` 字段,后者用 `rows` + `total` 字段。前端需要分别处理两种响应结构,增加认知负担。 | 全部列表接口 vs 详情/操作接口 | 统一使用单一响应结构,如 `{ code, msg, data: { list, total } }`,或在 TableDataInfo 中也使用 `data` 字段包裹 | | 2 | **错误码体系不完整** | 中 | 前端 `errorCode.js` 仅映射了 401/403/404 三个错误码,400/409/415 等 HTTP 标准错误码未做前端映射,全部 fallback 到 `default` 或后端 `msg`。后端虽定义了 16 个状态码,但实际使用集中在 200 和 500。 | 全局错误处理 | 完善前端错误码映射表;后端减少 500 的滥用,对参数错误返回 400,对业务冲突返回 409 | | 3 | **排序字段 SQL 注入风险** | 高 | 虽然使用了 `SqlUtil.escapeOrderBySql()` 进行过滤,但正则表达式级别的过滤存在被绕过的可能。排序参数直接从请求参数读取并拼接到 SQL ORDER BY 子句中。 | `TableSupport` + `SqlUtil` | 使用白名单机制,仅允许传入已知的字段名;或使用 MyBatis 动态 SQL 的 `` 标签做安全排序 | | 4 | **前后端 API 路径不一致** | 中 | 前端 `index.js` 调用 `/stocksystem/stocks/groupLimitlist`,而后端 `StocksController` 中该方法被注释了权限控制(`@PreAuthorize` 被注释)。另外部分接口前端使用 `/querylist`,后端映射为 `/list`,存在冗余接口。 | 股票系统模块 | 清理未使用的接口;补全权限控制;统一前后端路径命名规范 | | 5 | **分页参数隐式依赖** | 中 | 分页参数通过 `ServletUtils.getParameter()` 从 HttpServletRequest 中隐式读取,而非通过 `@RequestParam` 显式声明。这使得 API 文档(如 Swagger)无法自动生成分页参数说明,API 可读性差。 | `TableSupport.getPageDomain()` | 使用 `@RequestParam(defaultValue = "1") Integer pageNum` 显式声明分页参数,或使用 `PageRequest` 对象作为 Controller 方法参数 | | 6 | **HTTP 状态码与业务状态码混用** | 中 | 后端 HTTP Response 的 Status Code 始终为 200,真正的业务状态码在响应体 `code` 字段中。这导致前端无法利用 HTTP 状态码进行路由/拦截逻辑,也与 RESTful 最佳实践不符。 | 全局 | 保持当前模式(业界常见做法)但需在文档中明确说明;或改为 HTTP Status Code 与业务 code 一致 | | 7 | **GET 请求参数转换方式不标准** | 低 | 前端 GET 请求的 `params` 被手动拼接为 URL 字符串(`tansParams` 函数),而不是使用 axios 原生的 `paramsSerializer`。这可能导致特殊字符编码问题。 | `request.js` 请求拦截器 | 使用 axios 的 `paramsSerializer` 配置,或 `URLSearchParams` 进行参数序列化 | | 8 | **批量删除路径参数格式不一致** | 低 | 部分 Controller 使用 `@DeleteMapping("/{ids}")` 接收 `Long[]`,但 URL 中数组的传递格式(逗号分隔 vs 多次参数)缺乏统一规范,前端需要手动拼接字符串。 | 所有支持批量删除的接口 | 统一使用 `@DeleteMapping` + `@RequestParam List ids` 或 `@RequestBody` 传递数组 | | 9 | **大量调试代码未清理** | 低 | `StocksController` 中存在大量 `System.out.println()` 调试输出(超过 50 处),以及大段被注释的代码(1000+ 行)。这些代码在生产环境中会污染日志,且增加维护成本。 | `stock-system` 模块 | 统一替换为 `logger.info/debug`;清理历史注释代码 | | 10 | **接口文档缺失** | 中 | 项目虽引入了 Swagger 依赖(`TestController` 中有示例),但所有业务 Controller 均未添加 Swagger 注解(`@Api`、`@ApiOperation`、`@ApiParam` 等),导致无法自动生成 API 文档。 | 全部 Controller | 补充 Swagger/OpenAPI 注解;或接入 SpringDoc / Knife4j | ### 5.2 综合优化建议 #### 短期优化(1-2 周) 1. **补充前端错误码映射**:在 `errorCode.js` 中补充 400/409/415 等常见错误码的中文提示 2. **清理调试代码**:将 `StocksController` 中的 `System.out.println` 替换为 `logger` 3. **补全权限注解**:取消 `StocksController` 中被注释的 `@PreAuthorize` #### 中期优化(1-2 月) 4. **接入 API 文档**:为所有 Controller 补充 Swagger 注解,启用 Knife4j 文档页面 5. **规范分页参数**:考虑使用 `@Validated` 显式声明分页参数 6. **统一响应格式**:评估是否需要统一 `AjaxResult` 和 `TableDataInfo` 的字段结构 #### 长期优化(持续) 7. **排序安全加固**:实施白名单机制替代正则过滤 8. **RESTful 对齐**:评估是否将业务状态码与 HTTP 状态码对齐 9. **API 版本管理**:当接口变更时引入 `/api/v1/` 等版本前缀 --- ## 附录 ### A. 关键技术栈 | 层级 | 技术 | 版本 | |------|------|------| | 前端框架 | Vue 2 + Element UI | 2.x | | HTTP 客户端 | Axios | - | | 后端框架 | Spring Boot | 2.x | | Web 框架 | Spring MVC | - | | 权限框架 | Spring Security | - | | 分页组件 | PageHelper | - | | ORM | MyBatis | - | ### B. 核心文件路径 | 文件 | 路径 | |------|------| | 前端请求封装 | `ruoyi-ui/src/utils/request.js` | | 前端错误码映射 | `ruoyi-ui/src/utils/errorCode.js` | | 前端 API 目录 | `ruoyi-ui/src/api/` | | 后端统一响应 | `ruoyi-common/.../AjaxResult.java` | | 后端分页响应 | `ruoyi-common/.../TableDataInfo.java` | | 后端分页工具 | `ruoyi-common/.../PageUtils.java` | | 后端排序支持 | `ruoyi-common/.../TableSupport.java` | | 后端全局异常 | `ruoyi-framework/.../GlobalExceptionHandler.java` | | 后端状态码常量 | `ruoyi-common/.../HttpStatus.java` | | 后端 BaseController | `ruoyi-common/.../BaseController.java` | ### C. HTTP 方法使用统计 | 方法 | 用途 | 使用频率 | |------|------|----------| | `GET` | 查询列表、查询详情、查询树结构、下载 | ~45% | | `POST` | 新增、登录、注册、导出、导入、分析 | ~30% | | `PUT` | 修改、状态变更、授权、重置密码 | ~20% | | `DELETE` | 删除、清空日志、刷新缓存 | ~5% |