echoes/frontend/services/apiService.ts

118 lines
3.5 KiB
TypeScript
Raw Normal View History

// File path: /d:/data/echoes/frontend/services/apiService.ts
/**
* ApiConfig接口用于配置API服务的基本信息
*/
interface ApiConfig {
baseURL: string; // API的基础URL
timeout?: number; // 请求超时时间(可选)
}
export class ApiService {
private static instance: ApiService; // ApiService的单例实例
private baseURL: string; // API的基础URL
private timeout: number; // 请求超时时间
/**
* ApiService实例
* @param config ApiConfig配置对象
*/
private constructor(config: ApiConfig) {
this.baseURL = config.baseURL;
this.timeout = config.timeout || 10000; // 默认超时时间为10000毫秒
}
/**
* ApiService的单例实例
* @param config ApiConfig配置对象
* @returns ApiService实例
*/
public static getInstance(config?: ApiConfig): ApiService {
if (!this.instance && config) {
this.instance = new ApiService(config);
}
return this.instance;
}
/**
*
* @returns Promise<string>
* @throws Error
*/
private async getSystemToken(): Promise<string> {
const credentials = localStorage.getItem('system_credentials');
if (!credentials) {
throw new Error('System credentials not found');
}
try {
const response = await fetch(`${this.baseURL}/auth/system`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(JSON.parse(credentials)),
});
if (!response.ok) {
throw new Error('Failed to get system token');
}
const { token } = await response.json();
return token;
} catch (error) {
console.error('Error getting system token:', error);
throw error;
}
}
/**
* API请求
* @param endpoint API端点
* @param options
* @param requiresAuth true
* @returns Promise<T> API响应数据
* @throws Error
*/
public async request<T>(
endpoint: string,
options: RequestInit = {},
requiresAuth = true
): Promise<T> {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
try {
const headers = new Headers(options.headers);
if (requiresAuth) {
const token = await this.getSystemToken();
headers.set('Authorization', `Bearer ${token}`);
}
const response = await fetch(`${this.baseURL}${endpoint}`, {
...options,
headers,
signal: controller.signal,
});
if (!response.ok) {
throw new Error(`API Error: ${response.statusText}`);
}
const data = await response.json();
return data as T;
} catch (error: any) {
if (error.name === 'AbortError') {
throw new Error('Request timeout');
}
throw error;
} finally {
clearTimeout(timeoutId);
}
}
}
export default ApiService.getInstance({
baseURL: import.meta.env.VITE_API_BASE_URL,
});