update
This commit is contained in:
@@ -0,0 +1,374 @@
|
||||
// 域名信息管理模块
|
||||
// 用于管理远程域名信息列表的加载、更新和显示
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// 域名信息列表缓存
|
||||
let domainInfoCache = null;
|
||||
let cacheTimestamp = 0;
|
||||
const CACHE_DURATION = 5 * 60 * 1000; // 5 分钟缓存
|
||||
|
||||
/**
|
||||
* 加载域名信息列表
|
||||
*/
|
||||
function loadDomainInfoLists() {
|
||||
const tbody = document.getElementById('domain-info-lists-table-body');
|
||||
if (!tbody) {
|
||||
console.warn('未找到域名信息列表表格元素');
|
||||
return;
|
||||
}
|
||||
|
||||
showLoading(tbody);
|
||||
|
||||
// 检查缓存
|
||||
if (domainInfoCache && (Date.now() - cacheTimestamp) < CACHE_DURATION) {
|
||||
console.log('使用缓存的域名信息列表');
|
||||
renderDomainInfoLists(domainInfoCache);
|
||||
return;
|
||||
}
|
||||
|
||||
apiRequest('/api/domain-info')
|
||||
.then(data => {
|
||||
domainInfoCache = data;
|
||||
cacheTimestamp = Date.now();
|
||||
renderDomainInfoLists(data);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('获取域名信息列表失败:', error);
|
||||
showError(tbody, '获取域名信息列表失败');
|
||||
window.showNotification('获取域名信息列表失败', 'error');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染域名信息列表
|
||||
*/
|
||||
function renderDomainInfoLists(data) {
|
||||
const tbody = document.getElementById('domain-info-lists-table-body');
|
||||
if (!tbody) return;
|
||||
|
||||
tbody.innerHTML = '';
|
||||
|
||||
if (!data || !data.lists || data.lists.length === 0) {
|
||||
const emptyRow = document.createElement('tr');
|
||||
emptyRow.innerHTML = '<td colspan="6" class="py-4 text-center text-gray-500">暂无域名信息列表</td>';
|
||||
tbody.appendChild(emptyRow);
|
||||
return;
|
||||
}
|
||||
|
||||
const fragment = document.createDocumentFragment();
|
||||
|
||||
data.lists.forEach((list, index) => {
|
||||
const tr = document.createElement('tr');
|
||||
tr.className = 'border-b border-gray-200 hover:bg-gray-50';
|
||||
|
||||
const typeLabel = getTypeLabel(list.type);
|
||||
const statusClass = list.enabled ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-800';
|
||||
const statusText = list.enabled ? '启用' : '禁用';
|
||||
|
||||
tr.innerHTML = `
|
||||
<td class="py-3 px-4 font-medium">${escapeHtml(list.name)}</td>
|
||||
<td class="py-3 px-4">
|
||||
<span class="px-2 py-1 rounded-full text-xs font-medium ${statusClass}">${statusText}</span>
|
||||
</td>
|
||||
<td class="py-3 px-4">
|
||||
<span class="px-2 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800">${typeLabel}</span>
|
||||
</td>
|
||||
<td class="py-3 px-4 text-center">${list.ruleCount || 0}</td>
|
||||
<td class="py-3 px-4 text-sm text-gray-600">${formatLastUpdateTime(list.lastUpdateTime)}</td>
|
||||
<td class="py-3 px-4 text-center">
|
||||
<div class="flex space-x-2 justify-center">
|
||||
<button onclick="window.domainInfo.updateDomainInfo('${list.type}')"
|
||||
class="px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600 text-sm"
|
||||
title="更新此列表">
|
||||
更新
|
||||
</button>
|
||||
<button onclick="window.domainInfo.removeDomainInfo('${list.type}')"
|
||||
class="px-3 py-1 bg-red-500 text-white rounded hover:bg-red-600 text-sm"
|
||||
title="删除此列表">
|
||||
删除
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
`;
|
||||
|
||||
fragment.appendChild(tr);
|
||||
});
|
||||
|
||||
tbody.appendChild(fragment);
|
||||
|
||||
// 更新统计信息
|
||||
updateDomainInfoStats(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新域名信息统计
|
||||
*/
|
||||
function updateDomainInfoStats(data) {
|
||||
if (document.getElementById('domain-info-count')) {
|
||||
document.getElementById('domain-info-count').textContent = data.domainInfoCount || 0;
|
||||
}
|
||||
if (document.getElementById('threat-count')) {
|
||||
document.getElementById('threat-count').textContent = data.threatCount || 0;
|
||||
}
|
||||
if (document.getElementById('tracker-count')) {
|
||||
document.getElementById('tracker-count').textContent = data.trackerCount || 0;
|
||||
}
|
||||
if (document.getElementById('last-update-time')) {
|
||||
document.getElementById('last-update-time').textContent = formatLastUpdateTime(data.lastUpdateTime);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新域名信息
|
||||
*/
|
||||
function updateDomainInfo(type) {
|
||||
const url = `/api/domain-info/update/${encodeURIComponent(type)}`;
|
||||
|
||||
apiRequest(url, 'POST')
|
||||
.then(data => {
|
||||
if (data.status === 'success') {
|
||||
window.showNotification(`域名信息更新任务已启动:${getTypeLabel(type)}`, 'success');
|
||||
// 延迟刷新列表
|
||||
setTimeout(() => {
|
||||
loadDomainInfoLists();
|
||||
}, 2000);
|
||||
} else {
|
||||
window.showNotification(`更新失败:${data.message || '未知错误'}`, 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('更新域名信息失败:', error);
|
||||
window.showNotification('更新域名信息失败', 'error');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新所有域名信息
|
||||
*/
|
||||
function updateAllDomainInfo() {
|
||||
if (!confirm('确定要更新所有域名信息吗?这可能需要一些时间。')) {
|
||||
return;
|
||||
}
|
||||
|
||||
apiRequest('/api/domain-info/update', 'POST')
|
||||
.then(data => {
|
||||
if (data.status === 'success') {
|
||||
window.showNotification('所有域名信息更新任务已启动', 'success');
|
||||
setTimeout(() => {
|
||||
loadDomainInfoLists();
|
||||
}, 2000);
|
||||
} else {
|
||||
window.showNotification(`更新失败:${data.message || '未知错误'}`, 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('更新所有域名信息失败:', error);
|
||||
window.showNotification('更新所有域名信息失败', 'error');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取类型标签
|
||||
*/
|
||||
function getTypeLabel(type) {
|
||||
const labels = {
|
||||
'domain-info': '域名信息',
|
||||
'threat-database': '威胁数据库',
|
||||
'tracker': '跟踪器'
|
||||
};
|
||||
return labels[type] || type;
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化最后更新时间
|
||||
*/
|
||||
function formatLastUpdateTime(timeStr) {
|
||||
if (!timeStr) return '从未更新';
|
||||
const date = new Date(timeStr);
|
||||
const now = new Date();
|
||||
const diff = now - date;
|
||||
|
||||
const minutes = Math.floor(diff / 60000);
|
||||
const hours = Math.floor(diff / 3600000);
|
||||
const days = Math.floor(diff / 86400000);
|
||||
|
||||
if (minutes < 1) return '刚刚';
|
||||
if (minutes < 60) return `${minutes}分钟前`;
|
||||
if (hours < 24) return `${hours}小时前`;
|
||||
if (days < 30) return `${days}天前`;
|
||||
|
||||
return date.toLocaleDateString('zh-CN');
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示加载状态
|
||||
*/
|
||||
function showLoading(container) {
|
||||
container.innerHTML = `
|
||||
<tr>
|
||||
<td colspan="6" class="py-8 text-center">
|
||||
<div class="flex items-center justify-center">
|
||||
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500"></div>
|
||||
<span class="ml-3 text-gray-600">加载中...</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示错误状态
|
||||
*/
|
||||
function showError(container, message) {
|
||||
container.innerHTML = `
|
||||
<tr>
|
||||
<td colspan="6" class="py-8 text-center text-red-500">
|
||||
<svg class="w-12 h-12 mx-auto mb-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||
</svg>
|
||||
${escapeHtml(message)}
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* HTML 转义
|
||||
*/
|
||||
function escapeHtml(text) {
|
||||
const div = document.createElement('div');
|
||||
div.textContent = text;
|
||||
return div.innerHTML;
|
||||
}
|
||||
|
||||
/**
|
||||
* API 请求封装
|
||||
*/
|
||||
function apiRequest(url, method = 'GET', data = null) {
|
||||
const options = {
|
||||
method: method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
credentials: 'same-origin' // 添加认证信息
|
||||
};
|
||||
|
||||
if (data && method !== 'GET') {
|
||||
options.body = JSON.stringify(data);
|
||||
}
|
||||
|
||||
return fetch(url, options)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||
}
|
||||
return response.json();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示添加列表模态框
|
||||
*/
|
||||
function showAddListModal() {
|
||||
const modal = document.getElementById('add-domain-info-modal');
|
||||
if (modal) {
|
||||
modal.classList.remove('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏添加列表模态框
|
||||
*/
|
||||
function hideAddListModal() {
|
||||
const modal = document.getElementById('add-domain-info-modal');
|
||||
if (modal) {
|
||||
modal.classList.add('hidden');
|
||||
// 重置表单
|
||||
document.getElementById('add-domain-info-form').reset();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加域名信息列表
|
||||
*/
|
||||
function addDomainInfo(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const name = document.getElementById('list-name').value.trim();
|
||||
const url = document.getElementById('list-url').value.trim();
|
||||
const type = document.getElementById('list-type').value;
|
||||
const enabled = document.getElementById('list-enabled').checked;
|
||||
|
||||
if (!name || !url) {
|
||||
window.showNotification('请填写名称和URL', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
const data = {
|
||||
name: name,
|
||||
url: url,
|
||||
type: type,
|
||||
enabled: enabled
|
||||
};
|
||||
|
||||
apiRequest('/api/domain-info/add', 'POST', data)
|
||||
.then(response => {
|
||||
if (response.status === 'success') {
|
||||
window.showNotification('域名信息列表添加成功', 'success');
|
||||
hideAddListModal();
|
||||
loadDomainInfoLists();
|
||||
} else {
|
||||
window.showNotification(`添加失败:${response.message || '未知错误'}`, 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('添加域名信息列表失败:', error);
|
||||
window.showNotification('添加域名信息列表失败', 'error');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除域名信息列表
|
||||
*/
|
||||
function removeDomainInfo(type) {
|
||||
if (!confirm('确定要删除此域名信息列表吗?此操作不可恢复。')) {
|
||||
return;
|
||||
}
|
||||
|
||||
apiRequest(`/api/domain-info/remove/${encodeURIComponent(type)}`, 'POST')
|
||||
.then(response => {
|
||||
if (response.status === 'success') {
|
||||
window.showNotification('域名信息列表删除成功', 'success');
|
||||
loadDomainInfoLists();
|
||||
} else {
|
||||
window.showNotification(`删除失败:${response.message || '未知错误'}`, 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('删除域名信息列表失败:', error);
|
||||
window.showNotification('删除域名信息列表失败', 'error');
|
||||
});
|
||||
}
|
||||
|
||||
// 绑定添加列表表单提交事件
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const form = document.getElementById('add-domain-info-form');
|
||||
if (form) {
|
||||
form.addEventListener('submit', addDomainInfo);
|
||||
}
|
||||
});
|
||||
|
||||
// 暴露到全局命名空间
|
||||
window.domainInfo = {
|
||||
loadDomainInfoLists,
|
||||
updateDomainInfo,
|
||||
updateAllDomainInfo,
|
||||
renderDomainInfoLists,
|
||||
showAddListModal,
|
||||
hideAddListModal,
|
||||
removeDomainInfo
|
||||
};
|
||||
|
||||
})();
|
||||
Reference in New Issue
Block a user