Files
vf_react/src/devtools/apiDebugger.js
2025-11-10 20:05:53 +08:00

254 lines
7.6 KiB
JavaScript

// src/debug/apiDebugger.js
/**
* API 调试工具
* 生产环境临时调试使用,后期可整体删除 src/debug/ 目录
*/
import axios from 'axios';
import { getApiBase } from '@utils/apiConfig';
class ApiDebugger {
constructor() {
this.requestLog = [];
this.maxLogSize = 100;
this.isLogging = true;
}
/**
* 初始化 Axios 拦截器
*/
init() {
// 请求拦截器
axios.interceptors.request.use(
(config) => {
if (this.isLogging) {
const logEntry = {
type: 'request',
timestamp: new Date().toISOString(),
method: config.method.toUpperCase(),
url: config.url,
baseURL: config.baseURL,
fullURL: this._getFullURL(config),
headers: config.headers,
data: config.data,
params: config.params,
};
this._addLog(logEntry);
console.log(
`%c[API Request] ${logEntry.method} ${logEntry.fullURL}`,
'color: #2196F3; font-weight: bold;',
{
headers: config.headers,
data: config.data,
params: config.params,
}
);
}
return config;
},
(error) => {
console.error('[API Request Error]', error);
return Promise.reject(error);
}
);
// 响应拦截器
axios.interceptors.response.use(
(response) => {
if (this.isLogging) {
const logEntry = {
type: 'response',
timestamp: new Date().toISOString(),
method: response.config.method.toUpperCase(),
url: response.config.url,
fullURL: this._getFullURL(response.config),
status: response.status,
statusText: response.statusText,
headers: response.headers,
data: response.data,
};
this._addLog(logEntry);
console.log(
`%c[API Response] ${logEntry.method} ${logEntry.fullURL} - ${logEntry.status}`,
'color: #4CAF50; font-weight: bold;',
{
status: response.status,
data: response.data,
headers: response.headers,
}
);
}
return response;
},
(error) => {
if (this.isLogging) {
const logEntry = {
type: 'error',
timestamp: new Date().toISOString(),
method: error.config?.method?.toUpperCase() || 'UNKNOWN',
url: error.config?.url || 'UNKNOWN',
fullURL: error.config ? this._getFullURL(error.config) : 'UNKNOWN',
status: error.response?.status,
statusText: error.response?.statusText,
message: error.message,
data: error.response?.data,
};
this._addLog(logEntry);
console.error(
`%c[API Error] ${logEntry.method} ${logEntry.fullURL}`,
'color: #F44336; font-weight: bold;',
{
status: error.response?.status,
message: error.message,
data: error.response?.data,
}
);
}
return Promise.reject(error);
}
);
console.log('%c[API Debugger] Initialized', 'color: #FF9800; font-weight: bold;');
}
/**
* 获取完整 URL
*/
_getFullURL(config) {
const baseURL = config.baseURL || '';
const url = config.url || '';
const fullURL = baseURL + url;
// 添加查询参数
if (config.params) {
const params = new URLSearchParams(config.params).toString();
return params ? `${fullURL}?${params}` : fullURL;
}
return fullURL;
}
/**
* 添加日志
*/
_addLog(entry) {
this.requestLog.unshift(entry);
if (this.requestLog.length > this.maxLogSize) {
this.requestLog = this.requestLog.slice(0, this.maxLogSize);
}
}
/**
* 获取所有日志
*/
getLogs(type = 'all') {
if (type === 'all') {
return this.requestLog;
}
return this.requestLog.filter((log) => log.type === type);
}
/**
* 清空日志
*/
clearLogs() {
this.requestLog = [];
console.log('[API Debugger] Logs cleared');
}
/**
* 导出日志为 JSON
*/
exportLogs() {
const blob = new Blob([JSON.stringify(this.requestLog, null, 2)], {
type: 'application/json',
});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `api-logs-${Date.now()}.json`;
a.click();
URL.revokeObjectURL(url);
console.log('[API Debugger] Logs exported');
}
/**
* 打印日志统计
*/
printStats() {
const stats = {
total: this.requestLog.length,
requests: this.requestLog.filter((log) => log.type === 'request').length,
responses: this.requestLog.filter((log) => log.type === 'response').length,
errors: this.requestLog.filter((log) => log.type === 'error').length,
};
console.table(stats);
return stats;
}
/**
* 手动发送 API 请求(测试用)
*/
async testRequest(method, endpoint, data = null, config = {}) {
const apiBase = getApiBase();
const url = `${apiBase}${endpoint}`;
console.log(`[API Debugger] Testing ${method.toUpperCase()} ${url}`);
try {
const response = await axios({
method,
url,
data,
...config,
});
console.log('[API Debugger] Test succeeded:', response.data);
return response.data;
} catch (error) {
console.error('[API Debugger] Test failed:', error);
throw error;
}
}
/**
* 开启/关闭日志记录
*/
toggleLogging(enabled) {
this.isLogging = enabled;
console.log(`[API Debugger] Logging ${enabled ? 'enabled' : 'disabled'}`);
}
/**
* 获取最近的错误
*/
getRecentErrors(count = 10) {
return this.requestLog.filter((log) => log.type === 'error').slice(0, count);
}
/**
* 按 URL 过滤日志
*/
getLogsByURL(urlPattern) {
return this.requestLog.filter((log) => log.url && log.url.includes(urlPattern));
}
/**
* 按状态码过滤日志
*/
getLogsByStatus(status) {
return this.requestLog.filter((log) => log.status === status);
}
}
// 导出单例
export const apiDebugger = new ApiDebugger();
export default apiDebugger;