ForcePilot/web/src/apis/base.js

154 lines
4.3 KiB
JavaScript
Raw Normal View History

2025-05-02 23:56:59 +08:00
import { useUserStore } from '@/stores/user'
import { message } from 'ant-design-vue'
/**
* 基础API请求封装
* 提供统一的请求方法自动处理认证头和错误
*/
/**
* 发送API请求的基础函数
* @param {string} url - API端点
* @param {Object} options - 请求选项
* @param {boolean} requiresAuth - 是否需要认证头
* @returns {Promise} - 请求结果
*/
export async function apiRequest(url, options = {}, requiresAuth = false) {
try {
// 默认请求配置
const requestOptions = {
...options,
headers: {
'Content-Type': 'application/json',
...options.headers,
},
}
// 如果需要认证,添加认证头
if (requiresAuth) {
const userStore = useUserStore()
if (!userStore.isLoggedIn) {
throw new Error('用户未登录')
}
2025-05-04 21:04:01 +08:00
2025-05-02 23:56:59 +08:00
Object.assign(requestOptions.headers, userStore.getAuthHeaders())
}
// 发送请求
const response = await fetch(url, requestOptions)
2025-05-04 21:04:01 +08:00
2025-05-02 23:56:59 +08:00
// 处理API返回的错误
if (!response.ok) {
// 尝试解析错误信息
let errorMessage = `请求失败: ${response.status}`
2025-05-04 21:04:01 +08:00
let errorData = null
2025-05-02 23:56:59 +08:00
try {
2025-05-04 21:04:01 +08:00
errorData = await response.json()
2025-05-02 23:56:59 +08:00
errorMessage = errorData.detail || errorData.message || errorMessage
} catch (e) {
// 如果无法解析JSON使用默认错误信息
}
// 特殊处理401和403错误
if (response.status === 401) {
// 如果是认证失败,可能需要重新登录
const userStore = useUserStore()
if (userStore.isLoggedIn) {
// 如果用户认为自己已登录但收到401则可能是令牌过期
const isTokenExpired = errorData &&
(errorData.detail?.includes('令牌已过期') ||
2025-05-04 21:04:01 +08:00
errorData.detail?.includes('token expired') ||
errorMessage?.includes('令牌已过期') ||
errorMessage?.includes('token expired'))
2025-05-04 21:04:01 +08:00
message.error(isTokenExpired ? '登录已过期,请重新登录' : '认证失败,请重新登录')
2025-05-02 23:56:59 +08:00
userStore.logout()
2025-05-04 21:04:01 +08:00
// 使用setTimeout确保消息显示后再跳转
setTimeout(() => {
window.location.href = '/login'
}, 1500)
2025-05-02 23:56:59 +08:00
}
throw new Error('未授权,请先登录')
} else if (response.status === 403) {
throw new Error('没有权限执行此操作')
}
throw new Error(errorMessage)
}
// 检查Content-Type以确定如何处理响应
const contentType = response.headers.get('Content-Type')
if (contentType && contentType.includes('application/json')) {
return await response.json()
}
return await response.text()
} catch (error) {
console.error('API请求错误:', error)
throw error
}
}
/**
* 发送GET请求
2025-05-04 21:04:01 +08:00
* @param {string} url - API端点
2025-05-02 23:56:59 +08:00
* @param {Object} options - 请求选项
* @param {boolean} requiresAuth - 是否需要认证
* @returns {Promise} - 请求结果
*/
export function apiGet(url, options = {}, requiresAuth = false) {
return apiRequest(url, { method: 'GET', ...options }, requiresAuth)
}
/**
* 发送POST请求
* @param {string} url - API端点
* @param {Object} data - 请求体数据
* @param {Object} options - 其他请求选项
* @param {boolean} requiresAuth - 是否需要认证
* @returns {Promise} - 请求结果
*/
export function apiPost(url, data = {}, options = {}, requiresAuth = false) {
return apiRequest(
2025-05-04 21:04:01 +08:00
url,
{
method: 'POST',
2025-05-02 23:56:59 +08:00
body: JSON.stringify(data),
2025-05-04 21:04:01 +08:00
...options
},
2025-05-02 23:56:59 +08:00
requiresAuth
)
}
/**
* 发送PUT请求
* @param {string} url - API端点
* @param {Object} data - 请求体数据
* @param {Object} options - 其他请求选项
* @param {boolean} requiresAuth - 是否需要认证
* @returns {Promise} - 请求结果
*/
export function apiPut(url, data = {}, options = {}, requiresAuth = false) {
return apiRequest(
2025-05-04 21:04:01 +08:00
url,
{
method: 'PUT',
2025-05-02 23:56:59 +08:00
body: JSON.stringify(data),
2025-05-04 21:04:01 +08:00
...options
},
2025-05-02 23:56:59 +08:00
requiresAuth
)
}
/**
* 发送DELETE请求
* @param {string} url - API端点
* @param {Object} options - 请求选项
* @param {boolean} requiresAuth - 是否需要认证
* @returns {Promise} - 请求结果
*/
export function apiDelete(url, options = {}, requiresAuth = false) {
return apiRequest(url, { method: 'DELETE', ...options }, requiresAuth)
2025-05-04 21:04:01 +08:00
}