本文档提供了系统所有API接口的总览和统一配置说明。
文件位置: src/api/index.js
- 认证模块 - 用户登录、权限验证
- 部门管理 - 部门增删改查、层级管理
- 角色管理 - 角色权限配置
- 菜单管理 - 菜单配置、动态路由
- 日志管理 - 登录日志、操作日志
- 系统设置 - 系统配置、公告管理
- 主题管理 - 主题配置
// src/api/index.js
import request from '@/utils/request'
// API基础配置
export const API_CONFIG = {
baseURL: process.env.VITE_API_BASE_URL || '/api',
timeout: 10000,
withCredentials: true
}
// 通用请求头
export const COMMON_HEADERS = {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest'
}// 请求拦截器
request.interceptors.request.use(
config => {
// 添加token
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
// 添加时间戳防止缓存
if (config.method === 'get') {
config.params = {
...config.params,
_t: Date.now()
}
}
return config
},
error => {
return Promise.reject(error)
}
)// 响应拦截器
request.interceptors.response.use(
response => {
const { data } = response
// 统一处理业务错误
if (!data.status) {
ElMessage.error(data.msg || '请求失败')
return Promise.reject(new Error(data.msg || '请求失败'))
}
return data
},
error => {
// 统一处理HTTP错误
const { response } = error
if (response) {
switch (response.status) {
case 401:
ElMessage.error('登录已过期,请重新登录')
// 跳转到登录页
router.push('/login')
break
case 403:
ElMessage.error('权限不足')
break
case 404:
ElMessage.error('请求的资源不存在')
break
case 500:
ElMessage.error('服务器内部错误')
break
default:
ElMessage.error('网络请求失败')
}
} else {
ElMessage.error('网络连接失败')
}
return Promise.reject(error)
}
)// GET请求
const getList = (params) => {
return request({
url: '/api/list',
method: 'get',
params
})
}
// POST请求
const createItem = (data) => {
return request({
url: '/api/create',
method: 'post',
data
})
}
// PUT请求
const updateItem = (id, data) => {
return request({
url: `/api/update/${id}`,
method: 'put',
data
})
}
// DELETE请求
const deleteItem = (id) => {
return request({
url: `/api/delete/${id}`,
method: 'delete'
})
}// 成功响应
{
status: true,
msg: '操作成功',
data: {
// 具体数据
},
code: 200
}
// 失败响应
{
status: false,
msg: '错误信息',
data: null,
code: 40001
}
// 分页响应
{
status: true,
data: {
list: [], // 数据列表
total: 100, // 总数量
page: 1, // 当前页
pageSize: 20, // 每页数量
totalPages: 5 // 总页数
}
}200: 请求成功400: 请求参数错误401: 未授权,需要登录403: 权限不足404: 资源不存在500: 服务器内部错误
10001-19999: 用户相关错误20001-29999: 权限相关错误30001-39999: 数据相关错误40001-49999: 业务逻辑错误50001-59999: 系统相关错误
export const ERROR_CODES = {
// 用户相关
USER_NOT_FOUND: 10001,
USER_DISABLED: 10002,
PASSWORD_ERROR: 10003,
// 权限相关
NO_PERMISSION: 20001,
TOKEN_EXPIRED: 20002,
TOKEN_INVALID: 20003,
// 数据相关
DATA_NOT_FOUND: 30001,
DATA_DUPLICATE: 30002,
DATA_INVALID: 30003,
// 业务逻辑
OPERATION_FAILED: 40001,
VALIDATION_FAILED: 40002,
CONSTRAINT_VIOLATION: 40003
}推荐使用以下工具进行API测试:
- Postman: 功能强大的API测试工具
- Insomnia: 轻量级REST客户端
- curl: 命令行工具
- 浏览器开发者工具: 网络面板
// 环境配置
const environments = {
development: {
baseURL: 'http://localhost:3000/api',
timeout: 5000
},
testing: {
baseURL: 'http://test-api.example.com/api',
timeout: 10000
},
production: {
baseURL: 'https://api.example.com/api',
timeout: 15000
}
}// 登录接口测试
describe('Auth API', () => {
test('登录成功', async () => {
const loginData = {
username: 'admin',
password: '123456',
captcha: '1234',
captcha_key: 'test_key'
}
const result = await login(loginData)
expect(result.status).toBe(true)
expect(result.data.token).toBeDefined()
expect(result.data.employeeInfo).toBeDefined()
})
test('登录失败 - 密码错误', async () => {
const loginData = {
username: 'admin',
password: 'wrong_password',
captcha: '1234',
captcha_key: 'test_key'
}
await expect(login(loginData)).rejects.toThrow()
})
})// 请求去重
const pendingRequests = new Map()
const removePendingRequest = (config) => {
const requestKey = `${config.method}:${config.url}`
if (pendingRequests.has(requestKey)) {
const cancelToken = pendingRequests.get(requestKey)
cancelToken.cancel('重复请求')
pendingRequests.delete(requestKey)
}
}
// 缓存策略
const cache = new Map()
const getCachedResponse = (key) => {
const cached = cache.get(key)
if (cached && Date.now() - cached.timestamp < 5 * 60 * 1000) {
return cached.data
}
return null
}// 限制并发请求数量
class RequestQueue {
constructor(maxConcurrent = 6) {
this.maxConcurrent = maxConcurrent
this.running = 0
this.queue = []
}
async add(requestFn) {
return new Promise((resolve, reject) => {
this.queue.push({
requestFn,
resolve,
reject
})
this.process()
})
}
async process() {
if (this.running >= this.maxConcurrent || this.queue.length === 0) {
return
}
this.running++
const { requestFn, resolve, reject } = this.queue.shift()
try {
const result = await requestFn()
resolve(result)
} catch (error) {
reject(error)
} finally {
this.running--
this.process()
}
}
}
const requestQueue = new RequestQueue()// 添加CSRF Token
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content')
if (csrfToken) {
request.defaults.headers.common['X-CSRF-TOKEN'] = csrfToken
}// 输入数据清理
const sanitizeInput = (input) => {
if (typeof input === 'string') {
return input
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''')
}
return input
}// 请求日志过滤敏感信息
const filterSensitiveData = (data) => {
const sensitiveFields = ['password', 'token', 'secret']
const filtered = { ...data }
sensitiveFields.forEach(field => {
if (filtered[field]) {
filtered[field] = '***'
}
})
return filtered
}// 请求性能监控
const performanceMonitor = {
start: (config) => {
config.startTime = Date.now()
},
end: (config, response) => {
const duration = Date.now() - config.startTime
console.log(`API请求耗时: ${config.url} - ${duration}ms`)
// 发送监控数据
if (duration > 3000) {
console.warn(`慢请求警告: ${config.url} - ${duration}ms`)
}
}
}// 错误日志收集
const errorLogger = {
log: (error, context) => {
const errorInfo = {
message: error.message,
stack: error.stack,
url: context.url,
method: context.method,
timestamp: new Date().toISOString(),
userAgent: navigator.userAgent
}
// 发送到日志服务
console.error('API错误:', errorInfo)
}
}最后更新时间:2025-09-19