# 前端 API 规范 ## 概述 前端 API 层封装所有 HTTP 请求,与后端接口一一对应。API 文件位于 `ui/src/api/` 目录,按模块分组,使用封装后的 `VAxios` 发送请求。 :::tip 设计原则 - 每个后端模块对应一个 API 文件 - 函数命名统一使用 `名词 + 动词` 格式(与后端保持一致) - 请求路径使用相对路径(`/position/page`),不含 `/api/v1` 前缀(由 Axios baseURL 统一拼接) - 统一通过 `http.request()` 发送请求 ::: ## 目录结构 ``` ui/src/api/ ├── common/ # 公共 API(上传、字典按编码查询、城市、模板下载) │ ├── index.ts │ ├── menu.ts │ ├── user.ts │ └── city.ts ├── system/ # 系统模块 │ ├── user.ts │ ├── role.ts │ ├── menu.ts │ ├── dept.ts │ ├── position.ts │ ├── level.ts │ ├── dictionary.ts │ ├── loginLog.ts │ ├── operLog.ts │ └── tenant.ts ├── data/ # 数据模块 │ ├── param.ts │ ├── config.ts │ ├── dictionary.ts │ ├── notice.ts │ └── city.ts ├── content/ # 内容模块 │ ├── article.ts │ ├── category.ts │ └── link.ts ├── monitor/ # 监控模块 │ └── job.ts ├── file/ # 文件模块 │ └── fileTemplate.ts ├── tool/ # 工具模块 │ ├── generator.ts │ └── example.ts ├── setting/ # 设置模块 │ ├── profile.ts │ └── web.ts ├── region/ # 区域模块 │ └── region.ts └── dashboard/ # 仪表盘 ├── console.ts └── message.ts ``` ## 函数命名规范 | 操作 | 命名格式 | 示例 | HTTP 方法 | |------|---------|------|----------| | 分页查询 | `getXxxList` 或 `getXxxPage` | `getPositionList` | GET | | 全量列表 | `getXxxAllList` | `getPositionAllList` | GET | | 详情查询 | `getXxxDetail` | `getPositionDetail` | GET | | 添加 | `xxxAdd` | `positionAdd` | POST | | 编辑 | `xxxUpdate` | `positionUpdate` | PUT | | 删除 | `xxxDelete` | `positionDelete` | DELETE | | 批量删除 | `xxxBatchDelete` | `positionBatchDelete` | DELETE | | 导入 | `xxxImport` | `levelImport` | POST | | 导出 | `xxxExport` | `levelExport` | GET | :::warning 命名风格 实际代码中采用 `positionAdd` 而非 `addPosition`(名词在前、动词在后),与后端 Python 函数命名风格一致。 ::: ## API 文件标准模板 以岗位管理(`api/system/position.ts`)为标准: ```typescript import { http } from '@/utils/http/axios'; /** * @description: 岗位列表(分页) */ export function getPositionList(params?) { return http.request({ url: '/position/page', method: 'GET', params, }); } /** * 获取全部岗位列表(不分页) * @param params 参数 * @returns 返回结果 */ export function getPositionAllList(params?) { return http.request({ url: '/position/list', method: 'GET', params, }); } /** * @description: 根据ID获取详情 */ export function getPositionDetail(positionId) { return http.request({ url: '/position/detail/' + positionId, method: 'get', }); } /** * @description: 添加岗位 */ export function positionAdd(data: any) { return http.request({ url: '/position/add', method: 'POST', data, }); } /** * @description: 更新岗位 */ export function positionUpdate(data: any) { return http.request({ url: '/position/update', method: 'PUT', data, }); } /** * @description: 删除岗位 */ export function positionDelete(positionId) { return http.request({ url: '/position/delete/' + positionId, method: 'DELETE', }); } /** * @description: 批量删除岗位 */ export function positionBatchDelete(data: any) { return http.request({ url: '/position/batchDelete', method: 'DELETE', data, }); } ``` ## 完整示例:用户模块 ```typescript // api/system/user.ts import { http } from '@/utils/http/axios'; export interface BasicResponseModel { code: number; msg: string; data: T; } export interface BasicPageParams { pageNo: number; pageSize: number; total: number; } /** @description: 获取用户列表 */ export function getUserList(params) { return http.request({ url: '/user/page', method: 'get', params }); } /** @description: 根据ID获取详情 */ export function getUserDetail(userId) { return http.request({ url: '/user/detail/' + userId, method: 'get' }); } /** @description: 添加用户 */ export function userAdd(data: any) { return http.request({ url: '/user/add', method: 'POST', data }); } /** @description: 更新用户 */ export function userUpdate(data: any) { return http.request({ url: '/user/update', method: 'PUT', data }); } /** @description: 删除用户 */ export function userDelete(userId) { return http.request({ url: '/user/delete/' + userId, method: 'DELETE' }); } /** @description: 批量删除用户 */ export function userBatchDelete(data: any) { return http.request({ url: '/user/batchDelete', method: 'DELETE', data }); } /** @description: 重置密码 */ export function resetPwd(data: any) { return http.request({ url: '/user/resetPwd', method: 'PUT', data }); } /** @description: 导出用户 */ export function userExport(params) { return http.request({ url: '/user/export', method: 'GET' }); } ``` ## 请求路径规则 URL 使用相对路径,不含 `/api/v1` 前缀(由 Axios 实例的 `baseURL` 统一拼接): | 后端路由 | 前端 URL | 说明 | |----------|----------|------| | `GET /api/v1/position/page` | `/position/page` | baseURL 已含 `/api/v1` | | `GET /api/v1/position/detail/{id}` | `/position/detail/` + id | 路径参数拼接 | | `POST /api/v1/position/add` | `/position/add` | - | | `PUT /api/v1/position/update` | `/position/update` | - | | `DELETE /api/v1/position/delete/{id}` | `/position/delete/` + id | - | | `DELETE /api/v1/position/batchDelete` | `/position/batchDelete` | body 传 ID 数组 | ## params 与 data 区别 | 参数 | 适用方法 | 说明 | |------|----------|------| | `params` | GET | query 参数,拼接到 URL 后面 | | `data` | POST / PUT / DELETE | body 参数,放在请求体中 | ```typescript // GET 请求:params 拼到 URL http.request({ url: '/position/page', method: 'GET', params: { pageNo: 1, pageSize: 10 } }); // 实际请求: /api/v1/position/page?pageNo=1&pageSize=10 // POST 请求:data 放 body http.request({ url: '/position/add', method: 'POST', data: { name: '测试', status: 1 } }); // 实际请求: /api/v1/position/add body: {"name":"测试","status":1} ``` ## 公共 API 公共 API 位于 `api/common/index.ts`,包含跨模块复用的接口: ```typescript import { http } from '@/utils/http/axios'; /** 本地文件上传 */ export function upload(data) { return http.request({ url: '/upload/uploadFile', method: 'post', data }); } /** 根据字典编码查询字典项 */ export function getDictItemByCode(code) { return http.request({ url: '/dict/item/getDictItemList/' + code, method: 'GET' }); } /** 下载模板 */ export function getTemplateByCode(code: any) { return http.request({ url: '/file/template/getTemplateByCode/' + code, method: 'GET' }); } ``` ## 响应格式 后端统一返回 `{code, data, msg, ok}` 格式: ```json { "code": 0, "data": { "records": [...], "total": 100 }, "msg": "操作成功", "ok": true } ``` 前端 Axios 拦截器自动处理: - `ok: true` → 返回 `res.data` - `ok: false` → 弹出 `res.msg` 错误提示 - `code: 401` → token 失效,跳转登录页 页面中无需手动判断,直接使用返回值: ```typescript const loadDataTable = async (res: any) => { const result = await getPositionList({ ...formParams, ...res }); return result; // BasicTable 自动处理分页数据 }; ``` ## 总结 前端 API 规范:每个后端模块对应一个 API 文件,函数命名使用 `名词+动词` 格式(`positionAdd` / `positionDelete`)。URL 使用相对路径(不含 `/api/v1` 前缀),GET 用 `params`,POST/PUT/DELETE 用 `data`。统一通过 `http.request()` 发送请求,响应拦截器自动处理错误。