feat(system): 添加API密钥管理功能

- 新增API密钥创建表单界面
- 实现API密钥名称输入验证
- 添加表单提交和取消功能
- 集成密钥管理弹窗组件
- 支持密钥信息的双向数据绑定
- 添加表单校验规则和错误提示
- 实现密钥创建成功后的消息通知
- 提供密钥管理模块的基础架构支持
This commit is contained in:
2025-11-26 18:32:44 +08:00
commit 562b020e57
1153 changed files with 224736 additions and 0 deletions

View File

@@ -0,0 +1,352 @@
/**
* 增强的 API 请求工具
*/
import axios, { AxiosRequestConfig, AxiosError } from 'axios';
import { apiPerformanceMonitor } from './performance';
import { memoryCache } from './cache-manager';
import { getToken } from './token-util';
import { API_BASE_URL, TOKEN_HEADER_NAME } from '@/config/setting';
// 请求配置接口
interface EnhancedRequestConfig extends AxiosRequestConfig {
// 缓存配置
cache?: {
enabled: boolean;
expiry?: number;
key?: string;
tags?: string[];
};
// 重试配置
retry?: {
times: number;
delay: number;
condition?: (error: AxiosError) => boolean;
};
// 性能监控
performance?: boolean;
// 请求去重
dedupe?: boolean;
// 超时重试
timeoutRetry?: boolean;
}
// 请求队列管理
class RequestQueue {
private pendingRequests = new Map<string, Promise<any>>();
// 生成请求键
private generateKey(config: AxiosRequestConfig): string {
const { method, url, params, data } = config;
return `${method}_${url}_${JSON.stringify(params)}_${JSON.stringify(data)}`;
}
// 添加请求到队列
add<T>(config: AxiosRequestConfig, executor: () => Promise<T>): Promise<T> {
const key = this.generateKey(config);
if (this.pendingRequests.has(key)) {
return this.pendingRequests.get(key);
}
const promise = executor().finally(() => {
this.pendingRequests.delete(key);
});
this.pendingRequests.set(key, promise);
return promise;
}
// 清除队列
clear(): void {
this.pendingRequests.clear();
}
}
// 重试机制
class RetryManager {
static async retry<T>(
fn: () => Promise<T>,
config: { times: number; delay: number; condition?: (error: any) => boolean }
): Promise<T> {
let lastError: any;
for (let i = 0; i <= config.times; i++) {
try {
return await fn();
} catch (error) {
lastError = error;
// 检查是否应该重试
if (i < config.times && (!config.condition || config.condition(error as AxiosError))) {
await this.delay(config.delay * Math.pow(2, i)); // 指数退避
console.warn(`请求重试 ${i + 1}/${config.times}:`, error);
} else {
break;
}
}
}
throw lastError;
}
private static delay(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
// 增强的请求类
export class EnhancedRequest {
private instance = axios.create({
baseURL: API_BASE_URL,
timeout: 30000
});
private requestQueue = new RequestQueue();
constructor() {
this.setupInterceptors();
}
private setupInterceptors() {
// 请求拦截器
this.instance.interceptors.request.use(
(config) => {
// 添加认证头
const token = getToken();
if (token && config.headers) {
config.headers[TOKEN_HEADER_NAME] = token;
}
// 添加请求时间戳
(config as any).startTime = Date.now();
return config;
},
(error) => {
return Promise.reject(error);
}
);
// 响应拦截器
this.instance.interceptors.response.use(
(response) => {
// 记录性能数据
const config = response.config as any;
if (config.startTime) {
const duration = Date.now() - config.startTime;
apiPerformanceMonitor.recordApiCall(config.url, duration);
}
return response;
},
(error) => {
// 记录错误的性能数据
const config = error.config as any;
if (config && config.startTime) {
const duration = Date.now() - config.startTime;
apiPerformanceMonitor.recordApiCall(config.url, duration);
}
return Promise.reject(error);
}
);
}
// 通用请求方法
async request<T = any>(config: EnhancedRequestConfig): Promise<T> {
const {
cache,
retry,
performance = true,
dedupe = true,
timeoutRetry = true,
...axiosConfig
} = config;
// 生成缓存键
const cacheKey = cache?.key || this.generateCacheKey(axiosConfig);
// 尝试从缓存获取
if (cache?.enabled) {
const cachedData = memoryCache.get<T>(cacheKey);
if (cachedData !== null) {
return cachedData;
}
}
// 请求执行器
const executor = async (): Promise<T> => {
const response = await this.instance.request<T>(axiosConfig);
// 缓存响应数据
if (cache?.enabled && response.data) {
memoryCache.set(
cacheKey,
response.data,
cache.expiry,
cache.tags
);
}
return response.data;
};
// 请求去重
if (dedupe) {
return this.requestQueue.add(axiosConfig, async () => {
// 重试机制
if (retry) {
return RetryManager.retry(executor, {
...retry,
condition: retry.condition || this.shouldRetry
});
}
return executor();
});
}
// 重试机制
if (retry) {
return RetryManager.retry(executor, {
...retry,
condition: retry.condition || this.shouldRetry
});
}
return executor();
}
// GET 请求
get<T = any>(url: string, config?: EnhancedRequestConfig): Promise<T> {
return this.request<T>({
...config,
method: 'GET',
url
});
}
// POST 请求
post<T = any>(url: string, data?: any, config?: EnhancedRequestConfig): Promise<T> {
return this.request<T>({
...config,
method: 'POST',
url,
data
});
}
// PUT 请求
put<T = any>(url: string, data?: any, config?: EnhancedRequestConfig): Promise<T> {
return this.request<T>({
...config,
method: 'PUT',
url,
data
});
}
// DELETE 请求
delete<T = any>(url: string, config?: EnhancedRequestConfig): Promise<T> {
return this.request<T>({
...config,
method: 'DELETE',
url
});
}
// 批量请求
async batch<T = any>(requests: EnhancedRequestConfig[]): Promise<T[]> {
const promises = requests.map(config => this.request<T>(config));
return Promise.all(promises);
}
// 并发控制请求
async concurrent<T = any>(
requests: EnhancedRequestConfig[],
limit: number = 5
): Promise<T[]> {
const results: T[] = [];
for (let i = 0; i < requests.length; i += limit) {
const batch = requests.slice(i, i + limit);
const batchResults = await this.batch<T>(batch);
results.push(...batchResults);
}
return results;
}
// 生成缓存键
private generateCacheKey(config: AxiosRequestConfig): string {
const { method, url, params, data } = config;
return `api_${method}_${url}_${JSON.stringify(params)}_${JSON.stringify(data)}`;
}
// 判断是否应该重试
private shouldRetry(error: AxiosError): boolean {
// 网络错误或超时错误重试
if (!error.response) {
return true;
}
// 5xx 服务器错误重试
const status = error.response.status;
return status >= 500 && status < 600;
}
// 清除缓存
clearCache(tags?: string[]): void {
if (tags) {
memoryCache.clearByTags(tags);
} else {
memoryCache.clear();
}
}
// 取消所有请求
cancelAll(): void {
this.requestQueue.clear();
}
}
// 全局实例
export const enhancedRequest = new EnhancedRequest();
// 便捷方法
export const { get, post, put, delete: del, batch, concurrent } = enhancedRequest;
// 带缓存的 GET 请求
export function cachedGet<T = any>(
url: string,
config?: Omit<EnhancedRequestConfig, 'cache'> & {
expiry?: number;
tags?: string[];
}
): Promise<T> {
const { expiry = 5 * 60 * 1000, tags, ...restConfig } = config || {};
return enhancedRequest.get<T>(url, {
...restConfig,
cache: {
enabled: true,
expiry,
tags
}
});
}
// 带重试的请求
export function retryRequest<T = any>(
config: EnhancedRequestConfig,
retryTimes: number = 3,
retryDelay: number = 1000
): Promise<T> {
return enhancedRequest.request<T>({
...config,
retry: {
times: retryTimes,
delay: retryDelay
}
});
}