文字游戏
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.
 
 
 
 
 

11 KiB

API 集成完整指南

你好!现在项目已经完全配置好了 axios 和 API 层。以下是完整的说明。

🎯 快速概览

已为你完成的工作

Axios 配置 - 完整的 HTTP 客户端配置 API 服务层 - 登录 API 接口定义 认证 Store - 与后端 API 集成的状态管理 登录页面 - 支持异步 API 调用 环境配置 - 开发和生产环境变量 详细文档 - API 集成指南和后端示例

📁 项目结构

src/
├── api/
│   ├── index.ts           ← axios 实例(请求/响应拦截器)
│   └── auth.ts            ← 登录 API 接口(可扩展)
├── stores/
│   └── auth.ts            ← 认证状态(调用 API)
├── views/
│   └── LoginView.vue      ← 登录页面(异步登录)
└── ...

root/
├── .env.development       ← 开发环境配置
├── .env.production        ← 生产环境配置
├── API_INTEGRATION_GUIDE.md      ← API 集成详细指南
├── BACKEND_API_EXAMPLE.md        ← 后端实现参考
└── ...

🔄 工作流程

1️⃣ 用户登录流程

用户输入用户名和密码
    ↓
点击"登录"按钮
    ↓
LoginView.vue 调用 authStore.login(username, password)
    ↓
authStore 调用 loginApi({ username, password })
    ↓
axios 发送 POST /api/auth/login 请求
    ↓
axios 拦截器处理:
  - 添加 Authorization 头
  - 处理错误响应
    ↓
后端返回 JSON 响应
    ↓
前端解析 response.data(自动由拦截器处理)
    ↓
保存 token 和 user 到 localStorage
    ↓
路由跳转到仪表板

2️⃣ 后续请求流程

任何组件需要调用 API
    ↓
导入 API 函数(如 getUsersApi)
    ↓
await getUsersApi()
    ↓
axios 请求拦截器自动添加 Authorization: Bearer <token>
    ↓
后端验证 token
    ↓
后端返回数据
    ↓
axios 响应拦截器处理(提取 data)
    ↓
组件接收数据

💻 代码实现细节

axios 实例 (src/api/index.ts)

import axios from 'axios'

const instance = axios.create({
  baseURL: import.meta.env.VITE_API_URL || 'http://localhost:3000/api',
  timeout: 10000
})

// 请求拦截器 - 自动添加 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,  // ← 返回 response.data
  (error) => {
    if (error.response?.status === 401) {
      // token 过期,清除并跳转
      localStorage.removeItem('auth_token')
      window.location.href = '/login'
    }
    return Promise.reject(error)
  }
)

export default instance

关键点:

  1. 所有请求自动添加 Authorization: Bearer <token>
  2. 所有响应自动提取 response.data
  3. 401 错误自动清除 token 并跳转

API 接口定义 (src/api/auth.ts)

import http from './index'

export interface LoginRequest {
  username: string
  password: string
}

export interface LoginResponse {
  code: number
  message: string
  data: {
    token: string
    user: User
  }
}

export const loginApi = (credentials: LoginRequest): Promise<LoginResponse> => {
  return http.post('/auth/login', credentials)
}

使用方式:

const response = await loginApi({ username: 'admin', password: '123456' })
// response.code === 200
// response.data.token
// response.data.user

认证 Store (src/stores/auth.ts)

export const useAuthStore = defineStore('auth', () => {
  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)
        return true
      }
    } catch (error) {
      console.error('登录失败:', error)
      return false
    }
  }
  
  return { login, logout, user, token, isAuthenticated }
})

登录页面 (src/views/LoginView.vue)

const handleLogin = async () => {
  loading.value = true
  try {
    // 调用异步登录
    const success = await authStore.login(username.value, password.value)
    if (success) {
      ElMessage.success('登录成功')
      router.push('/admin/dashboard')
    } else {
      ElMessage.error('登录失败')
    }
  } catch (error: any) {
    ElMessage.error(error?.message || '登录出错')
  } finally {
    loading.value = false
  }
}

🛠 后端 API 需要返回什么?

登录接口

端点: POST /api/auth/login

请求:

{
  "username": "admin",
  "password": "123456"
}

响应格式(必须严格按照):

{
  "code": 200,
  "message": "登录成功",
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "user": {
      "id": "1",
      "username": "admin",
      "email": "admin@example.com",
      "role": "admin"
    }
  }
}

关键点:

  • code 必须是 200 表示成功
  • data.token 是 JWT token,后续请求在 Authorization: Bearer <token> 中使用
  • data.user 必须包含至少 id, username, email, role 字段

📝 添加更多 API 接口

例子:用户列表 API

  1. src/api/ 中创建 users.ts
import http from './index'

export interface User {
  id: number
  username: string
  email: string
  role: string
}

export interface UsersResponse {
  code: number
  message: string
  data: {
    items: User[]
    total: number
  }
}

// 获取用户列表
export const getUsersApi = (
  page: number = 1,
  limit: number = 10
): Promise<UsersResponse> => {
  return http.get('/users', {
    params: { page, limit }
  })
}

// 创建用户
export const createUserApi = (data: User): Promise<any> => {
  return http.post('/users', data)
}

// 更新用户
export const updateUserApi = (id: number, data: Partial<User>): Promise<any> => {
  return http.put(`/users/${id}`, data)
}

// 删除用户
export const deleteUserApi = (id: number): Promise<any> => {
  return http.delete(`/users/${id}`)
}
  1. 在组件中使用:
import { getUsersApi } from '@/api/users'

const users = ref([])
const loading = ref(false)

const fetchUsers = async () => {
  loading.value = true
  try {
    const response = await getUsersApi(1, 10)
    if (response.code === 200) {
      users.value = response.data.items
    }
  } catch (error) {
    ElMessage.error('获取用户列表失败')
  } finally {
    loading.value = false
  }
}

onMounted(() => {
  fetchUsers()
})

🌐 环境配置

开发环境 (.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
console.log(baseURL) // 自动根据环境选择

// 或直接在 axios 配置中
baseURL: import.meta.env.VITE_API_URL || 'http://localhost:3000/api'

🧪 测试步骤

1. 启动后端服务

# Node.js Express 示例
node server.js

# 或 Python Flask 示例
python app.py

# 或你自己的后端服务

2. 验证后端在运行

访问 http://localhost:3000/api/auth/login (应该看到 404 或错误,说明服务在运行)

3. 使用 cURL 测试登录

curl -X POST http://localhost:3000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"123456"}'

应该返回:

{
  "code": 200,
  "message": "登录成功",
  "data": {
    "token": "...",
    "user": {...}
  }
}

4. 启动前端

npm run dev

5. 在前端登录

  • 访问 http://localhost:5173
  • 输入用户名和密码
  • 点击登录
  • 如果成功,应该跳转到仪表板

6. 检查浏览器开发者工具

  • Network 标签: 查看请求和响应
  • Application 标签: 查看 localStorage 中的 auth_token
  • Console 标签: 查看是否有错误

🔒 安全建议

  1. 始终使用 HTTPS (生产环境)
  2. 密码必须加密存储 (使用 bcrypt 等)
  3. 使用 JWT 令牌 而不是 session
  4. 设置合理的 token 过期时间 (如 7 天)
  5. 实现 token 刷新机制 (可选但推荐)
  6. 验证 CORS 配置 只允许特定域名
  7. 记录所有登录尝试 用于审计
  8. 使用速率限制 防止暴力破解

常见问题

Q: 如何在其他组件中获取当前用户?

import { useAuthStore } from '@/stores/auth'

const authStore = useAuthStore()
console.log(authStore.user) // 当前用户
console.log(authStore.token) // 当前 token

Q: 如何处理 token 刷新?

参考 src/api/auth.ts 中已定义的 refreshTokenApi 函数,在响应拦截器中实现 token 刷新逻辑。

Q: 如何在请求中添加其他头信息?

// 在 src/api/index.ts 中修改请求拦截器
instance.interceptors.request.use((config) => {
  const token = localStorage.getItem('auth_token')
  if (token) {
    config.headers.Authorization = `Bearer ${token}`
  }
  // 添加其他头
  config.headers['X-Custom-Header'] = 'value'
  return config
})

Q: 如何处理超时错误?

const login = async () => {
  try {
    await authStore.login(username, password)
  } catch (error: any) {
    if (error.code === 'ECONNABORTED') {
      ElMessage.error('请求超时,请检查网络')
    } else {
      ElMessage.error(error.message)
    }
  }
}

Q: 前后端如何联调?

  1. 后端启动在 http://localhost:3000
  2. 前端启动在 http://localhost:5173
  3. 确保 .env.developmentVITE_API_URL=http://localhost:3000/api
  4. 后端需要配置 CORS 允许 http://localhost:5173 访问

Q: CORS 错误怎么解决?

后端需要配置 CORS:

Express 示例:

const cors = require('cors')
app.use(cors({
  origin: 'http://localhost:5173',
  credentials: true
}))

Flask 示例:

from flask_cors import CORS
CORS(app, resources={r"/api/*": {"origins": "http://localhost:5173"}})

📚 相关文档

🎉 总结

你现在有:

完整的 axios 配置(请求/响应拦截器) API 服务层架构 登录示例(已与后端集成) 完整的类型定义 (TypeScript) 环境变量配置 详细的文档和后端示例

下一步:

  1. 启动你的后端服务,确保监听 3000 端口
  2. 实现后端的 /api/auth/login 接口,返回上述格式的 JSON
  3. 运行 npm run dev 启动前端
  4. 测试登录功能

有任何问题,请参考文档或查看相关代码注释!🚀