后台管理端调整
This commit is contained in:
@@ -0,0 +1,498 @@
|
||||
import { ApiResponse } from '@/types';
|
||||
|
||||
// API配置
|
||||
interface ApiConfig {
|
||||
baseUrl: string;
|
||||
timeout: number;
|
||||
retries: number;
|
||||
}
|
||||
|
||||
// Twilio配置
|
||||
interface TwilioConfig {
|
||||
accountSid: string;
|
||||
authToken: string;
|
||||
phoneNumber: string;
|
||||
}
|
||||
|
||||
// Stripe配置
|
||||
interface StripeConfig {
|
||||
publishableKey: string;
|
||||
secretKey: string;
|
||||
}
|
||||
|
||||
// OpenAI配置
|
||||
interface OpenAIConfig {
|
||||
apiKey: string;
|
||||
model: string;
|
||||
}
|
||||
|
||||
class ApiManager {
|
||||
private config: ApiConfig;
|
||||
private twilioConfig?: TwilioConfig;
|
||||
private stripeConfig?: StripeConfig;
|
||||
private openaiConfig?: OpenAIConfig;
|
||||
|
||||
constructor(config: ApiConfig) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
// 配置第三方服务
|
||||
configureTwilio(config: TwilioConfig) {
|
||||
this.twilioConfig = config;
|
||||
}
|
||||
|
||||
configureStripe(config: StripeConfig) {
|
||||
this.stripeConfig = config;
|
||||
}
|
||||
|
||||
configureOpenAI(config: OpenAIConfig) {
|
||||
this.openaiConfig = config;
|
||||
}
|
||||
|
||||
// 通用HTTP请求方法
|
||||
private async request<T>(
|
||||
endpoint: string,
|
||||
options: RequestInit = {}
|
||||
): Promise<ApiResponse<T>> {
|
||||
const url = `${this.config.baseUrl}${endpoint}`;
|
||||
|
||||
const defaultHeaders = {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
...options,
|
||||
headers: {
|
||||
...defaultHeaders,
|
||||
...options.headers,
|
||||
},
|
||||
signal: AbortSignal.timeout(this.config.timeout),
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
return {
|
||||
success: false,
|
||||
error: data.message || `HTTP ${response.status}: ${response.statusText}`,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('API请求失败:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : '网络请求失败',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// GET请求
|
||||
async get<T>(endpoint: string, params?: Record<string, any>): Promise<ApiResponse<T>> {
|
||||
const url = new URL(`${this.config.baseUrl}${endpoint}`);
|
||||
if (params) {
|
||||
Object.entries(params).forEach(([key, value]) => {
|
||||
if (value !== undefined && value !== null) {
|
||||
url.searchParams.append(key, String(value));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return this.request<T>(url.pathname + url.search);
|
||||
}
|
||||
|
||||
// POST请求
|
||||
async post<T>(endpoint: string, data?: any): Promise<ApiResponse<T>> {
|
||||
return this.request<T>(endpoint, {
|
||||
method: 'POST',
|
||||
body: data ? JSON.stringify(data) : undefined,
|
||||
});
|
||||
}
|
||||
|
||||
// PUT请求
|
||||
async put<T>(endpoint: string, data?: any): Promise<ApiResponse<T>> {
|
||||
return this.request<T>(endpoint, {
|
||||
method: 'PUT',
|
||||
body: data ? JSON.stringify(data) : undefined,
|
||||
});
|
||||
}
|
||||
|
||||
// DELETE请求
|
||||
async delete<T>(endpoint: string): Promise<ApiResponse<T>> {
|
||||
return this.request<T>(endpoint, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
// Twilio相关API
|
||||
async initiateCall(callData: {
|
||||
from: string;
|
||||
to: string;
|
||||
sourceLanguage: string;
|
||||
targetLanguage: string;
|
||||
type: 'ai' | 'human' | 'video' | 'sign';
|
||||
}): Promise<ApiResponse<{ callSid: string; status: string }>> {
|
||||
if (!this.twilioConfig) {
|
||||
return {
|
||||
success: false,
|
||||
error: 'Twilio配置未初始化',
|
||||
};
|
||||
}
|
||||
|
||||
// 模拟Twilio API调用
|
||||
console.log('发起Twilio通话:', callData);
|
||||
|
||||
// 模拟API响应
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
callSid: `CA${Date.now().toString()}`,
|
||||
status: 'initiated',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async endCall(callSid: string): Promise<ApiResponse<{ status: string }>> {
|
||||
if (!this.twilioConfig) {
|
||||
return {
|
||||
success: false,
|
||||
error: 'Twilio配置未初始化',
|
||||
};
|
||||
}
|
||||
|
||||
console.log('结束Twilio通话:', callSid);
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
status: 'completed',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async getCallStatus(callSid: string): Promise<ApiResponse<{
|
||||
status: string;
|
||||
duration: number;
|
||||
startTime: string;
|
||||
endTime?: string;
|
||||
}>> {
|
||||
if (!this.twilioConfig) {
|
||||
return {
|
||||
success: false,
|
||||
error: 'Twilio配置未初始化',
|
||||
};
|
||||
}
|
||||
|
||||
console.log('查询通话状态:', callSid);
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 300));
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
status: 'completed',
|
||||
duration: 900,
|
||||
startTime: '2024-01-15T10:30:00Z',
|
||||
endTime: '2024-01-15T10:45:00Z',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Stripe相关API
|
||||
async createPaymentIntent(paymentData: {
|
||||
amount: number;
|
||||
currency: string;
|
||||
customerId?: string;
|
||||
description?: string;
|
||||
}): Promise<ApiResponse<{ clientSecret: string; paymentIntentId: string }>> {
|
||||
if (!this.stripeConfig) {
|
||||
return {
|
||||
success: false,
|
||||
error: 'Stripe配置未初始化',
|
||||
};
|
||||
}
|
||||
|
||||
console.log('创建Stripe支付意向:', paymentData);
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 800));
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
clientSecret: `pi_${Date.now()}_secret_${Math.random().toString(36).substr(2, 9)}`,
|
||||
paymentIntentId: `pi_${Date.now()}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async confirmPayment(paymentIntentId: string): Promise<ApiResponse<{
|
||||
status: string;
|
||||
amount: number;
|
||||
currency: string;
|
||||
}>> {
|
||||
if (!this.stripeConfig) {
|
||||
return {
|
||||
success: false,
|
||||
error: 'Stripe配置未初始化',
|
||||
};
|
||||
}
|
||||
|
||||
console.log('确认Stripe支付:', paymentIntentId);
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 1200));
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
status: 'succeeded',
|
||||
amount: 2500,
|
||||
currency: 'cny',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async refundPayment(paymentIntentId: string, amount?: number): Promise<ApiResponse<{
|
||||
refundId: string;
|
||||
status: string;
|
||||
amount: number;
|
||||
}>> {
|
||||
if (!this.stripeConfig) {
|
||||
return {
|
||||
success: false,
|
||||
error: 'Stripe配置未初始化',
|
||||
};
|
||||
}
|
||||
|
||||
console.log('Stripe退款:', { paymentIntentId, amount });
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
refundId: `re_${Date.now()}`,
|
||||
status: 'succeeded',
|
||||
amount: amount || 2500,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// OpenAI相关API
|
||||
async translateText(textData: {
|
||||
text: string;
|
||||
sourceLanguage: string;
|
||||
targetLanguage: string;
|
||||
context?: string;
|
||||
}): Promise<ApiResponse<{ translatedText: string; confidence: number }>> {
|
||||
if (!this.openaiConfig) {
|
||||
return {
|
||||
success: false,
|
||||
error: 'OpenAI配置未初始化',
|
||||
};
|
||||
}
|
||||
|
||||
console.log('OpenAI文本翻译:', textData);
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 1500));
|
||||
|
||||
// 模拟翻译结果
|
||||
const translations: Record<string, string> = {
|
||||
'zh-CN_en-US': 'Hello, this is a translated text.',
|
||||
'en-US_zh-CN': '您好,这是翻译后的文本。',
|
||||
'zh-CN_ja-JP': 'こんにちは、これは翻訳されたテキストです。',
|
||||
};
|
||||
|
||||
const key = `${textData.sourceLanguage}_${textData.targetLanguage}`;
|
||||
const translatedText = translations[key] || 'Translation completed.';
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
translatedText,
|
||||
confidence: 0.95,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async transcribeAudio(audioData: {
|
||||
audioUrl: string;
|
||||
language: string;
|
||||
}): Promise<ApiResponse<{ transcription: string; confidence: number }>> {
|
||||
if (!this.openaiConfig) {
|
||||
return {
|
||||
success: false,
|
||||
error: 'OpenAI配置未初始化',
|
||||
};
|
||||
}
|
||||
|
||||
console.log('OpenAI音频转录:', audioData);
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
transcription: '这是转录的音频内容,包含了用户的语音信息。',
|
||||
confidence: 0.92,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async translateDocument(documentData: {
|
||||
fileUrl: string;
|
||||
fileName: string;
|
||||
sourceLanguage: string;
|
||||
targetLanguage: string;
|
||||
quality: 'draft' | 'professional' | 'certified';
|
||||
}): Promise<ApiResponse<{ taskId: string; estimatedTime: number }>> {
|
||||
if (!this.openaiConfig) {
|
||||
return {
|
||||
success: false,
|
||||
error: 'OpenAI配置未初始化',
|
||||
};
|
||||
}
|
||||
|
||||
console.log('OpenAI文档翻译:', documentData);
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
taskId: `task_${Date.now()}`,
|
||||
estimatedTime: 1800, // 30分钟
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async getTranslationProgress(taskId: string): Promise<ApiResponse<{
|
||||
status: 'pending' | 'processing' | 'completed' | 'failed';
|
||||
progress: number;
|
||||
translatedFileUrl?: string;
|
||||
}>> {
|
||||
if (!this.openaiConfig) {
|
||||
return {
|
||||
success: false,
|
||||
error: 'OpenAI配置未初始化',
|
||||
};
|
||||
}
|
||||
|
||||
console.log('查询翻译进度:', taskId);
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
|
||||
// 模拟进度查询
|
||||
const progress = Math.floor(Math.random() * 100);
|
||||
const status = progress >= 100 ? 'completed' : 'processing';
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
status,
|
||||
progress,
|
||||
translatedFileUrl: status === 'completed' ? `/downloads/translated_${taskId}.pdf` : undefined,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// 文件上传
|
||||
async uploadFile(file: File, type: 'document' | 'audio' | 'video'): Promise<ApiResponse<{
|
||||
fileUrl: string;
|
||||
fileName: string;
|
||||
fileSize: number;
|
||||
uploadId: string;
|
||||
}>> {
|
||||
console.log('上传文件:', { name: file.name, size: file.size, type });
|
||||
|
||||
// 模拟文件上传
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
fileUrl: `/uploads/${type}/${Date.now()}_${file.name}`,
|
||||
fileName: file.name,
|
||||
fileSize: file.size,
|
||||
uploadId: `upload_${Date.now()}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// 重试机制
|
||||
async retryRequest<T>(
|
||||
requestFn: () => Promise<ApiResponse<T>>,
|
||||
maxRetries: number = this.config.retries
|
||||
): Promise<ApiResponse<T>> {
|
||||
let lastError: string = '';
|
||||
|
||||
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
||||
try {
|
||||
const result = await requestFn();
|
||||
if (result.success) {
|
||||
return result;
|
||||
}
|
||||
lastError = result.error || '未知错误';
|
||||
} catch (error) {
|
||||
lastError = error instanceof Error ? error.message : '请求失败';
|
||||
}
|
||||
|
||||
if (attempt < maxRetries) {
|
||||
// 指数退避策略
|
||||
const delay = Math.pow(2, attempt - 1) * 1000;
|
||||
await new Promise(resolve => setTimeout(resolve, delay));
|
||||
console.log(`重试请求 (${attempt}/${maxRetries})...`);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: false,
|
||||
error: `请求失败,已重试${maxRetries}次: ${lastError}`,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 创建API实例
|
||||
const apiConfig: ApiConfig = {
|
||||
baseUrl: process.env.REACT_APP_API_URL || 'http://localhost:3001/api',
|
||||
timeout: 30000,
|
||||
retries: 3,
|
||||
};
|
||||
|
||||
export const api = new ApiManager(apiConfig);
|
||||
|
||||
// 初始化第三方服务配置
|
||||
if (process.env.REACT_APP_TWILIO_ACCOUNT_SID) {
|
||||
api.configureTwilio({
|
||||
accountSid: process.env.REACT_APP_TWILIO_ACCOUNT_SID,
|
||||
authToken: process.env.REACT_APP_TWILIO_AUTH_TOKEN || '',
|
||||
phoneNumber: process.env.REACT_APP_TWILIO_PHONE_NUMBER || '',
|
||||
});
|
||||
}
|
||||
|
||||
if (process.env.REACT_APP_STRIPE_PUBLISHABLE_KEY) {
|
||||
api.configureStripe({
|
||||
publishableKey: process.env.REACT_APP_STRIPE_PUBLISHABLE_KEY,
|
||||
secretKey: process.env.REACT_APP_STRIPE_SECRET_KEY || '',
|
||||
});
|
||||
}
|
||||
|
||||
if (process.env.REACT_APP_OPENAI_API_KEY) {
|
||||
api.configureOpenAI({
|
||||
apiKey: process.env.REACT_APP_OPENAI_API_KEY,
|
||||
model: process.env.REACT_APP_OPENAI_MODEL || 'gpt-3.5-turbo',
|
||||
});
|
||||
}
|
||||
|
||||
// 导出类型和实例
|
||||
export type { ApiConfig, TwilioConfig, StripeConfig, OpenAIConfig };
|
||||
export { ApiManager };
|
||||
Reference in New Issue
Block a user