308 lines
10 KiB
JavaScript
308 lines
10 KiB
JavaScript
// 初始化Hosts面板
|
||
function initHostsPanel() {
|
||
// 加载Hosts列表
|
||
loadHosts();
|
||
|
||
// 初始化事件监听器
|
||
initHostsEventListeners();
|
||
}
|
||
|
||
// 初始化事件监听器
|
||
function initHostsEventListeners() {
|
||
// 添加Hosts按钮
|
||
document.getElementById('add-hosts').addEventListener('click', addHostsEntry);
|
||
|
||
// Hosts过滤
|
||
document.getElementById('hosts-filter').addEventListener('input', filterHosts);
|
||
|
||
// 按Enter键添加Hosts
|
||
document.getElementById('hosts-domain').addEventListener('keypress', function(e) {
|
||
if (e.key === 'Enter') {
|
||
addHostsEntry();
|
||
}
|
||
});
|
||
}
|
||
|
||
// 加载Hosts列表
|
||
function loadHosts() {
|
||
const tbody = document.getElementById('hosts-table').querySelector('tbody');
|
||
showLoading(tbody);
|
||
|
||
// 更新API路径,使用完整路径
|
||
apiRequest('/shield/hosts', 'GET')
|
||
.then(data => {
|
||
// 处理不同格式的响应数据
|
||
let hostsData;
|
||
if (Array.isArray(data)) {
|
||
hostsData = data;
|
||
} else if (data && data.hosts) {
|
||
hostsData = data.hosts;
|
||
} else {
|
||
hostsData = [];
|
||
}
|
||
|
||
renderHosts(hostsData);
|
||
|
||
// 更新Hosts数量统计
|
||
if (window.updateHostsCount && typeof window.updateHostsCount === 'function') {
|
||
window.updateHostsCount(hostsData.length);
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('获取Hosts列表失败:', error);
|
||
|
||
if (tbody) {
|
||
tbody.innerHTML = '<tr><td colspan="3" class="text-center py-4">' +
|
||
'<div class="empty-state">' +
|
||
'<div class="empty-icon"><i class="fas fa-server text-muted"></i></div>' +
|
||
'<div class="empty-title text-muted">加载失败</div>' +
|
||
'<div class="empty-description text-muted">无法获取Hosts列表,请稍后重试</div>' +
|
||
'</div>' +
|
||
'</td></tr>';
|
||
}
|
||
|
||
if (typeof window.showNotification === 'function') {
|
||
window.showNotification('获取Hosts列表失败', 'danger');
|
||
}
|
||
});
|
||
}
|
||
|
||
// 渲染Hosts表格
|
||
function renderHosts(hosts) {
|
||
const tbody = document.getElementById('hosts-table').querySelector('tbody');
|
||
if (!tbody) return;
|
||
|
||
if (!hosts || hosts.length === 0) {
|
||
// 使用更友好的空状态显示
|
||
tbody.innerHTML = '<tr><td colspan="3" class="text-center py-4">' +
|
||
'<div class="empty-state">' +
|
||
'<div class="empty-icon"><i class="fas fa-file-alt text-muted"></i></div>' +
|
||
'<div class="empty-title text-muted">暂无Hosts条目</div>' +
|
||
'<div class="empty-description text-muted">添加自定义Hosts条目以控制DNS解析</div>' +
|
||
'</div>' +
|
||
'</td></tr>';
|
||
return;
|
||
}
|
||
|
||
tbody.innerHTML = '';
|
||
|
||
hosts.forEach(entry => {
|
||
addHostsToTable(entry.ip, entry.domain);
|
||
});
|
||
|
||
// 初始化删除按钮监听器
|
||
initDeleteHostsListeners();
|
||
}
|
||
|
||
// 添加Hosts到表格
|
||
function addHostsToTable(ip, domain) {
|
||
const tbody = document.getElementById('hosts-table').querySelector('tbody');
|
||
const row = document.createElement('tr');
|
||
|
||
row.innerHTML = `
|
||
<td>${ip}</td>
|
||
<td>${domain}</td>
|
||
<td class="actions-cell">
|
||
<button class="btn btn-danger btn-sm delete-hosts" data-ip="${ip}" data-domain="${domain}">
|
||
<i class="fas fa-trash-alt"></i> 删除
|
||
</button>
|
||
</td>
|
||
`;
|
||
|
||
// 添加行动画效果
|
||
row.style.opacity = '0';
|
||
row.style.transform = 'translateY(10px)';
|
||
tbody.appendChild(row);
|
||
|
||
// 使用requestAnimationFrame确保动画平滑
|
||
requestAnimationFrame(() => {
|
||
row.style.transition = 'opacity 0.3s ease, transform 0.3s ease';
|
||
row.style.opacity = '1';
|
||
row.style.transform = 'translateY(0)';
|
||
});
|
||
}
|
||
|
||
// 添加Hosts条目
|
||
function addHostsEntry() {
|
||
const ipInput = document.getElementById('hosts-ip');
|
||
const domainInput = document.getElementById('hosts-domain');
|
||
|
||
const ip = ipInput.value.trim();
|
||
const domain = domainInput.value.trim();
|
||
|
||
if (!ip) {
|
||
if (typeof window.showNotification === 'function') {
|
||
window.showNotification('请输入IP地址', 'warning');
|
||
}
|
||
ipInput.focus();
|
||
return;
|
||
}
|
||
|
||
if (!domain) {
|
||
if (typeof window.showNotification === 'function') {
|
||
window.showNotification('请输入域名', 'warning');
|
||
}
|
||
domainInput.focus();
|
||
return;
|
||
}
|
||
|
||
// 简单的IP地址格式验证
|
||
if (!isValidIp(ip)) {
|
||
if (typeof window.showNotification === 'function') {
|
||
window.showNotification('请输入有效的IP地址', 'warning');
|
||
}
|
||
ipInput.focus();
|
||
return;
|
||
}
|
||
|
||
// 修复重复API调用问题,只调用一次
|
||
apiRequest('/shield/hosts', 'POST', { ip: ip, domain: domain })
|
||
.then(data => {
|
||
// 处理不同的响应格式
|
||
if (data.success || data.status === 'success') {
|
||
if (typeof window.showNotification === 'function') {
|
||
window.showNotification('Hosts条目添加成功', 'success');
|
||
}
|
||
|
||
// 清空输入框并聚焦到域名输入
|
||
ipInput.value = '';
|
||
domainInput.value = '';
|
||
domainInput.focus();
|
||
|
||
// 重新加载Hosts列表
|
||
loadHosts();
|
||
|
||
// 触发数据刷新事件
|
||
if (typeof window.triggerDataRefresh === 'function') {
|
||
window.triggerDataRefresh('hosts');
|
||
}
|
||
} else {
|
||
if (typeof window.showNotification === 'function') {
|
||
window.showNotification(`添加失败: ${data.message || '未知错误'}`, 'danger');
|
||
}
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('添加Hosts条目失败:', error);
|
||
if (typeof window.showNotification === 'function') {
|
||
window.showNotification('添加Hosts条目失败', 'danger');
|
||
}
|
||
});
|
||
}
|
||
|
||
// 删除Hosts条目
|
||
function deleteHostsEntry(ip, domain) {
|
||
// 找到要删除的行并添加删除动画
|
||
const rows = document.querySelectorAll('#hosts-table tbody tr');
|
||
let targetRow = null;
|
||
|
||
rows.forEach(row => {
|
||
if (row.cells[0].textContent === ip && row.cells[1].textContent === domain) {
|
||
targetRow = row;
|
||
}
|
||
});
|
||
|
||
if (targetRow) {
|
||
targetRow.style.transition = 'opacity 0.3s ease, transform 0.3s ease';
|
||
targetRow.style.opacity = '0';
|
||
targetRow.style.transform = 'translateX(-20px)';
|
||
}
|
||
|
||
// 更新API路径
|
||
apiRequest('/shield/hosts', 'DELETE', { ip: ip, domain: domain })
|
||
.then(data => {
|
||
// 处理不同的响应格式
|
||
if (data.success || data.status === 'success') {
|
||
// 等待动画完成后重新加载列表
|
||
setTimeout(() => {
|
||
if (typeof window.showNotification === 'function') {
|
||
window.showNotification('Hosts条目删除成功', 'success');
|
||
}
|
||
loadHosts();
|
||
|
||
// 触发数据刷新事件
|
||
if (typeof window.triggerDataRefresh === 'function') {
|
||
window.triggerDataRefresh('hosts');
|
||
}
|
||
}, 300);
|
||
} else {
|
||
// 恢复行样式
|
||
if (targetRow) {
|
||
targetRow.style.opacity = '1';
|
||
targetRow.style.transform = 'translateX(0)';
|
||
}
|
||
|
||
if (typeof window.showNotification === 'function') {
|
||
window.showNotification(`删除失败: ${data.message || '未知错误'}`, 'danger');
|
||
}
|
||
}
|
||
})
|
||
.catch(error => {
|
||
// 恢复行样式
|
||
if (targetRow) {
|
||
targetRow.style.opacity = '1';
|
||
targetRow.style.transform = 'translateX(0)';
|
||
}
|
||
|
||
console.error('删除Hosts条目失败:', error);
|
||
if (typeof window.showNotification === 'function') {
|
||
window.showNotification('删除Hosts条目失败', 'danger');
|
||
}
|
||
});
|
||
}
|
||
|
||
// 过滤Hosts
|
||
function filterHosts() {
|
||
const filterText = document.getElementById('hosts-filter').value.toLowerCase();
|
||
const rows = document.querySelectorAll('#hosts-table tbody tr');
|
||
|
||
rows.forEach(row => {
|
||
const ip = row.cells[0].textContent.toLowerCase();
|
||
const domain = row.cells[1].textContent.toLowerCase();
|
||
|
||
row.style.display = (ip.includes(filterText) || domain.includes(filterText)) ? '' : 'none';
|
||
});
|
||
}
|
||
|
||
// 为删除按钮添加事件监听器
|
||
function initDeleteHostsListeners() {
|
||
document.querySelectorAll('.delete-hosts').forEach(button => {
|
||
button.addEventListener('click', function() {
|
||
const ip = this.getAttribute('data-ip');
|
||
const domain = this.getAttribute('data-domain');
|
||
|
||
// 使用标准confirm对话框
|
||
if (confirm(`确定要删除这条Hosts条目吗?\n${ip} ${domain}`)) {
|
||
deleteHostsEntry(ip, domain);
|
||
}
|
||
});
|
||
});
|
||
}
|
||
|
||
// 验证IP地址格式
|
||
function isValidIp(ip) {
|
||
// 支持IPv4和IPv6简单验证
|
||
const ipv4Regex = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$/;
|
||
const ipv6Regex = /^([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}$/;
|
||
|
||
return ipv4Regex.test(ip) || ipv6Regex.test(ip);
|
||
}
|
||
|
||
// 导出函数,供其他模块调用
|
||
window.updateHostsCount = function(count) {
|
||
const hostsCountElement = document.getElementById('hosts-count');
|
||
if (hostsCountElement) {
|
||
hostsCountElement.textContent = count;
|
||
}
|
||
}
|
||
|
||
// 导出初始化函数
|
||
window.initHostsPanel = initHostsPanel;
|
||
|
||
// 注册到面板导航系统
|
||
if (window.registerPanelModule) {
|
||
window.registerPanelModule('hosts-panel', {
|
||
init: initHostsPanel,
|
||
refresh: loadHosts
|
||
});
|
||
} |