You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
7.6 KiB
7.6 KiB
API 集成指南
概述
项目已完整配置 axios,包括请求拦截器、响应拦截器和 API 服务层。
文件结构
src/api/
├── index.ts # axios 实例配置(请求/响应拦截器)
└── auth.ts # 登录相关 API 接口定义
核心概念
1. axios 实例配置 (src/api/index.ts)
// 创建 axios 实例
const instance = axios.create({
baseURL: 'http://localhost:3000/api', // 从环境变量读取
timeout: 10000
})
请求拦截器:自动在请求头添加 Authorization token
instance.interceptors.request.use((config) => {
const token = localStorage.getItem('auth_token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
})
响应拦截器:统一处理错误和 token 过期
instance.interceptors.response.use(
(response) => response.data, // 成功时返回 data
(error) => {
if (error.response?.status === 401) {
// Token 过期,清除登录状态并跳转到登录页
}
}
)
2. API 服务层 (src/api/auth.ts)
定义所有 API 接口和类型:
// 定义请求/响应类型
export interface LoginRequest {
username: string
password: string
}
export interface LoginResponse {
code: number
message: string
data: {
token: string
user: User
}
}
// 定义 API 接口
export const loginApi = (credentials: LoginRequest): Promise<LoginResponse> => {
return http.post('/auth/login', credentials)
}
3. 状态管理 (src/stores/auth.ts)
在 Pinia store 中调用 API:
const login = async (username: string, password: string): Promise<boolean> => {
try {
const response = await loginApi({ username, password })
if (response.code === 200 && response.data) {
token.value = response.data.token
user.value = response.data.user
// 保存到本地存储
localStorage.setItem('auth_token', token.value)
localStorage.setItem('user', JSON.stringify(user.value))
return true
}
} catch (error) {
console.error('登录失败:', error)
return false
}
}
登录流程详解
前端请求流程
1. 用户在登录页输入用户名和密码
↓
2. 点击"登录"按钮调用 handleLogin()
↓
3. authStore.login(username, password) 被调用
↓
4. loginApi({ username, password }) 发送 HTTP 请求
↓
5. axios 拦截器处理(添加 headers 等)
↓
6. 发送 POST /auth/login 请求到后端
后端需要返回的数据格式
{
"code": 200,
"message": "登录成功",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": "1",
"username": "admin",
"email": "admin@example.com",
"role": "admin"
}
}
}
字段说明:
code: HTTP 状态码(200 表示成功)message: 返回消息data.token: JWT token,用于后续请求认证data.user: 用户信息对象id: 用户 IDusername: 用户名email: 邮箱role: 用户角色(admin 或 user)
环境配置
.env.development (开发环境)
VITE_API_URL=http://localhost:3000/api
.env.production (生产环境)
VITE_API_URL=https://api.example.com/api
在代码中获取环境变量
const baseURL = import.meta.env.VITE_API_URL || 'http://localhost:3000/api'
使用示例
1. 调用登录 API
import { loginApi } from '@/api/auth'
const response = await loginApi({
username: 'admin',
password: '123456'
})
if (response.code === 200) {
console.log('登录成功,用户信息:', response.data.user)
console.log('Token:', response.data.token)
}
2. 在组件中使用 store
<script setup lang="ts">
import { useAuthStore } from '@/stores/auth'
const authStore = useAuthStore()
const login = async () => {
const success = await authStore.login('admin', '123456')
if (success) {
// 登录成功,跳转
router.push('/admin/dashboard')
}
}
</script>
3. 创建新的 API 接口
在 src/api/ 中创建新文件,如 users.ts:
import http from './index'
export interface User {
id: number
username: string
email: string
role: string
}
// 获取用户列表
export const getUsersApi = (page: number, limit: number) => {
return http.get('/users', {
params: { page, limit }
})
}
// 创建用户
export const createUserApi = (data: User) => {
return http.post('/users', data)
}
// 更新用户
export const updateUserApi = (id: number, data: Partial<User>) => {
return http.put(`/users/${id}`, data)
}
// 删除用户
export const deleteUserApi = (id: number) => {
return http.delete(`/users/${id}`)
}
错误处理
全局错误处理
axios 响应拦截器已处理以下情况:
| 状态码 | 处理方式 |
|---|---|
| 401 | Token 过期,清除登录状态,跳转到登录页 |
| 其他 4xx/5xx | 返回错误信息 |
| 网络错误 | 返回"网络错误"提示 |
在组件中处理错误
try {
const response = await loginApi({ username, password })
// 处理成功
} catch (error: any) {
ElMessage.error(error?.message || '登录失败')
}
请求示例
POST 请求 (登录)
// 请求
POST /api/auth/login
Content-Type: application/json
Authorization: Bearer <token>
{
"username": "admin",
"password": "123456"
}
// 响应
{
"code": 200,
"message": "登录成功",
"data": {
"token": "...",
"user": { ... }
}
}
GET 请求 (获取列表)
// 请求
GET /api/users?page=1&limit=10
Authorization: Bearer <token>
// 响应
{
"code": 200,
"message": "成功",
"data": {
"items": [...],
"total": 100
}
}
PUT 请求 (更新)
// 请求
PUT /api/users/1
Content-Type: application/json
Authorization: Bearer <token>
{
"username": "new_name",
"email": "new@email.com"
}
// 响应
{
"code": 200,
"message": "更新成功",
"data": { ... }
}
常见问题
Q: Token 过期怎么处理?
A: 后端返回 401 时,拦截器会自动清除 token 并跳转到登录页。
Q: 如何添加其他请求头?
A: 修改 src/api/index.ts 中的拦截器:
instance.interceptors.request.use((config) => {
config.headers['Custom-Header'] = 'value'
return config
})
Q: 如何处理超时?
A: 已在 axios 配置中设置 timeout: 10000(10秒)。修改 src/api/index.ts 中的 timeout 值。
Q: 如何调用 API 时显示加载状态?
A: 在组件中使用 loading ref:
const loading = ref(false)
loading.value = true
try {
const response = await loginApi(...)
} finally {
loading.value = false
}
集成后端步骤
-
启动后端服务
# 后端服务应该运行在 http://localhost:3000 -
更新 API 地址 (如果不同)
修改 .env.development 中的 VITE_API_URL -
确保后端返回正确格式
{ "code": 200, "message": "...", "data": { ... } } -
测试登录流程
- 访问 http://localhost:5173
- 输入用户名和密码
- 查看浏览器控制台的网络请求
-
检查 Token 存储
- 打开浏览器开发者工具 → Application → LocalStorage
- 应该看到
auth_token和user字段
下一步
- 集成后端登录接口
- 添加用户列表 API (
src/api/users.ts) - 添加产品 API (
src/api/products.ts) - 添加订单 API (
src/api/orders.ts) - 实现 token 刷新机制
- 添加错误日志上报