180 lines
5.4 KiB
JavaScript
180 lines
5.4 KiB
JavaScript
/**
|
|
* API客户端 - 处理所有AJAX请求
|
|
*/
|
|
class APIClient {
|
|
constructor(baseURL = '/api') {
|
|
this.baseURL = baseURL;
|
|
this.defaultHeaders = {
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json'
|
|
};
|
|
this.cache = new Map();
|
|
this.cacheTimeout = 5 * 60 * 1000; // 5分钟缓存
|
|
}
|
|
|
|
/**
|
|
* 获取所有数据表列表
|
|
*/
|
|
async getTables() {
|
|
const cacheKey = 'tables';
|
|
|
|
// 检查缓存
|
|
if (this.cache.has(cacheKey)) {
|
|
const cached = this.cache.get(cacheKey);
|
|
if (Date.now() - cached.timestamp < this.cacheTimeout) {
|
|
return cached.data;
|
|
}
|
|
}
|
|
|
|
const response = await fetch(`${this.baseURL}/tables`);
|
|
if (!response.ok) throw new Error('Failed to fetch tables');
|
|
|
|
const data = await response.json();
|
|
this.cache.set(cacheKey, { data, timestamp: Date.now() });
|
|
return data;
|
|
}
|
|
|
|
/**
|
|
* 获取数据表数据
|
|
* @param {string} tableAlias - 表别名
|
|
* @param {Object} params - 查询参数
|
|
*/
|
|
async getTableData(tableAlias, params = {}) {
|
|
const url = new URL(`${this.baseURL}/data/${tableAlias}`, window.location.origin);
|
|
|
|
// 添加查询参数
|
|
Object.keys(params).forEach(key => {
|
|
if (params[key] !== undefined && params[key] !== '') {
|
|
url.searchParams.append(key, params[key]);
|
|
}
|
|
});
|
|
|
|
const cacheKey = url.toString();
|
|
|
|
// 检查缓存(搜索参数相关的缓存)
|
|
if (this.cache.has(cacheKey) && !params.search) {
|
|
const cached = this.cache.get(cacheKey);
|
|
if (Date.now() - cached.timestamp < this.cacheTimeout) {
|
|
return cached.data;
|
|
}
|
|
}
|
|
|
|
// 使用 AbortController 支持请求取消
|
|
const controller = new AbortController();
|
|
const timeoutId = setTimeout(() => controller.abort(), 10000); // 10秒超时
|
|
|
|
try {
|
|
const response = await fetch(url, {
|
|
signal: controller.signal,
|
|
headers: this.defaultHeaders
|
|
});
|
|
|
|
clearTimeout(timeoutId);
|
|
|
|
if (!response.ok) throw new Error('Failed to fetch table data');
|
|
|
|
const data = await response.json();
|
|
|
|
// 缓存非搜索请求的结果
|
|
if (!params.search) {
|
|
this.cache.set(cacheKey, { data, timestamp: Date.now() });
|
|
}
|
|
|
|
return data;
|
|
} catch (error) {
|
|
clearTimeout(timeoutId);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取数据详情
|
|
* @param {string} tableAlias - 表别名
|
|
* @param {string|number} id - 记录ID
|
|
*/
|
|
async getRecordDetail(tableAlias, id) {
|
|
const cacheKey = `detail:${tableAlias}:${id}`;
|
|
|
|
// 检查缓存
|
|
if (this.cache.has(cacheKey)) {
|
|
const cached = this.cache.get(cacheKey);
|
|
if (Date.now() - cached.timestamp < this.cacheTimeout) {
|
|
return cached.data;
|
|
}
|
|
}
|
|
|
|
const controller = new AbortController();
|
|
const timeoutId = setTimeout(() => controller.abort(), 5000);
|
|
|
|
try {
|
|
const response = await fetch(`${this.baseURL}/data/${tableAlias}/detail/${id}`, {
|
|
signal: controller.signal
|
|
});
|
|
|
|
clearTimeout(timeoutId);
|
|
|
|
if (!response.ok) throw new Error('Failed to fetch record detail');
|
|
|
|
const data = await response.json();
|
|
this.cache.set(cacheKey, { data, timestamp: Date.now() });
|
|
return data;
|
|
} catch (error) {
|
|
clearTimeout(timeoutId);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取可用模板列表
|
|
* @param {string} tableName - 表名
|
|
*/
|
|
async getAvailableTemplates(tableName) {
|
|
const cacheKey = `templates:${tableName}`;
|
|
|
|
// 检查缓存
|
|
if (this.cache.has(cacheKey)) {
|
|
const cached = this.cache.get(cacheKey);
|
|
if (Date.now() - cached.timestamp < this.cacheTimeout) {
|
|
return cached.data;
|
|
}
|
|
}
|
|
|
|
const response = await fetch(`/api/templates/${tableName}/available`);
|
|
if (!response.ok) throw new Error('Failed to fetch templates');
|
|
|
|
const data = await response.json();
|
|
this.cache.set(cacheKey, { data, timestamp: Date.now() });
|
|
return data;
|
|
}
|
|
|
|
/**
|
|
* 验证模板
|
|
* @param {string} tableName - 表名
|
|
* @param {string} templateType - 模板类型
|
|
*/
|
|
async validateTemplate(tableName, templateType) {
|
|
const response = await fetch(`/api/templates/${tableName}/validate?type=${templateType}`);
|
|
return response.json();
|
|
}
|
|
|
|
/**
|
|
* 获取模板预览
|
|
* @param {string} tableName - 表名
|
|
* @param {string} templateType - 模板类型
|
|
*/
|
|
async getTemplatePreview(tableName, templateType) {
|
|
const response = await fetch(`/api/templates/${tableName}/preview?type=${templateType}`);
|
|
if (!response.ok) throw new Error('Failed to fetch template preview');
|
|
return response.text();
|
|
}
|
|
|
|
/**
|
|
* 清空缓存
|
|
*/
|
|
clearCache() {
|
|
this.cache.clear();
|
|
}
|
|
}
|
|
|
|
// 全局API客户端实例
|
|
window.apiClient = new APIClient(); |