fix team pro tag

This commit is contained in:
2025-04-23 20:04:37 +08:00
parent bee8369a6b
commit ed01b88e04
5 changed files with 404 additions and 119 deletions

View File

@@ -8,43 +8,132 @@ export interface ApiResponse<T = unknown> {
message?: string;
}
// Common function for authenticated API requests to LIMQ
/**
* 通用的LIMQ API请求函数包含重试机制和错误处理
*/
export async function limqRequest<T = unknown>(
endpoint: string,
method: 'GET' | 'POST' | 'PUT' | 'DELETE' = 'GET',
data?: Record<string, unknown>
data?: Record<string, unknown>,
options?: {
retryCount?: number;
retryDelay?: number;
timeout?: number;
}
): Promise<ApiResponse<T>> {
// Get current session
const { data: { session } } = await supabase.auth.getSession();
// 默认配置
const retryCount = options?.retryCount ?? 2; // 默认重试2次
const retryDelay = options?.retryDelay ?? 1000; // 默认延迟1秒
const timeout = options?.timeout ?? 10000; // 默认超时10秒
if (!session) {
throw new Error('No active session. User must be authenticated.');
let lastError: Error | null = null;
let currentRetry = 0;
// 创建延迟函数
const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
// 重试循环
while (currentRetry <= retryCount) {
try {
console.log(`[API] ${method} ${endpoint} 尝试 ${currentRetry + 1}/${retryCount + 1}`);
// 获取会话
const { data: { session } } = await supabase.auth.getSession();
// 检查会话是否存在
if (!session) {
console.error(`[API] 未找到活跃会话,用户需要登录`);
if (currentRetry < retryCount) {
currentRetry++;
console.log(`[API] 等待 ${retryDelay}ms 后重试获取会话...`);
await delay(retryDelay);
continue;
}
return {
success: false,
error: '需要登录才能访问API'
};
}
// 获取API基础URL
const baseUrl = process.env.NEXT_PUBLIC_LIMQ_API;
if (!baseUrl) {
throw new Error('API URL未配置');
}
const url = `${baseUrl}${endpoint.startsWith('/') ? endpoint : '/' + endpoint}`;
console.log(`[API] 请求URL: ${url}`);
// 构建请求选项
const fetchOptions: RequestInit = {
method,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${session.access_token}`
},
mode: 'cors'
};
if (data && (method === 'POST' || method === 'PUT')) {
fetchOptions.body = JSON.stringify(data);
console.log(`[API] 请求数据:`, data);
}
// 添加超时控制
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
fetchOptions.signal = controller.signal;
// 发送请求
const response = await fetch(url, fetchOptions);
clearTimeout(timeoutId); // 清除超时控制
// 处理响应
if (!response.ok) {
const errorData = await response.json().catch(() => null);
console.error(`[API] 请求失败: ${response.status} ${response.statusText}`, errorData);
// 对于认证错误,尝试重试
if ((response.status === 401 || response.status === 403) && currentRetry < retryCount) {
currentRetry++;
console.log(`[API] 认证错误,等待 ${retryDelay}ms 后重试...`);
await delay(retryDelay);
continue;
}
throw new Error(errorData?.error || `请求失败: ${response.status}`);
}
// 成功响应
const responseData = await response.json();
console.log(`[API] ${method} ${endpoint} 成功`);
return responseData;
} catch (error) {
lastError = error instanceof Error ? error : new Error(String(error));
console.error(`[API] 请求出错:`, lastError);
// 对于超时和网络错误,尝试重试
if (currentRetry < retryCount &&
(error instanceof DOMException && error.name === 'AbortError' ||
error instanceof TypeError && error.message.includes('network'))) {
currentRetry++;
console.log(`[API] 网络错误,等待 ${retryDelay}ms 后重试...`);
await delay(retryDelay);
continue;
}
// 已达到最大重试次数或不是网络错误
break;
}
}
const baseUrl = process.env.NEXT_PUBLIC_LIMQ_API;
const url = `${baseUrl}${endpoint.startsWith('/') ? endpoint : '/' + endpoint}`;
const options: RequestInit = {
method,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${session.access_token}`
},
mode: 'cors'
// 所有重试均失败
console.error(`[API] ${method} ${endpoint} 失败,已重试 ${currentRetry}`);
return {
success: false,
error: lastError?.message || '请求失败,请稍后重试'
};
if (data && (method === 'POST' || method === 'PUT')) {
options.body = JSON.stringify(data);
}
const response = await fetch(url, options);
if (!response.ok) {
const errorData = await response.json().catch(() => null);
throw new Error(
errorData?.error || `Request failed with status ${response.status}`
);
}
return response.json();
}