Files
dns-server/static/js/modules/rules.js
Alex Yang 85320611cb web重做
2025-11-24 01:53:26 +08:00

270 lines
7.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 屏蔽规则管理模块
// 全局变量
let rules = [];
let currentPage = 1;
let itemsPerPage = 50; // 默认每页显示50条规则
let filteredRules = [];
// 初始化屏蔽规则面板
function initRulesPanel() {
// 加载规则列表
loadRules();
// 绑定添加规则按钮事件
document.getElementById('add-rule-btn').addEventListener('click', addNewRule);
// 绑定刷新规则按钮事件
document.getElementById('reload-rules-btn').addEventListener('click', reloadRules);
// 绑定搜索框事件
document.getElementById('rule-search').addEventListener('input', filterRules);
// 绑定每页显示数量变更事件
document.getElementById('items-per-page').addEventListener('change', () => {
itemsPerPage = parseInt(document.getElementById('items-per-page').value);
currentPage = 1; // 重置为第一页
renderRulesList();
});
// 绑定分页按钮事件
document.getElementById('prev-page-btn').addEventListener('click', goToPreviousPage);
document.getElementById('next-page-btn').addEventListener('click', goToNextPage);
document.getElementById('first-page-btn').addEventListener('click', goToFirstPage);
document.getElementById('last-page-btn').addEventListener('click', goToLastPage);
}
// 加载规则列表
async function loadRules() {
try {
const rulesPanel = document.getElementById('rules-panel');
showLoading(rulesPanel);
const data = await apiRequest('/shield', 'GET');
rules = data.rules || [];
filteredRules = [...rules];
currentPage = 1; // 重置为第一页
renderRulesList();
} catch (error) {
showError('加载规则失败:' + error.message);
} finally {
const rulesPanel = document.getElementById('rules-panel');
hideLoading(rulesPanel);
}
}
// 渲染规则列表
function renderRulesList() {
const rulesList = document.getElementById('rules-list');
const paginationInfo = document.getElementById('pagination-info');
// 清空列表
rulesList.innerHTML = '';
if (filteredRules.length === 0) {
rulesList.innerHTML = '<tr><td colspan="4" class="text-center">暂无规则</td></tr>';
paginationInfo.textContent = '共0条规则';
updatePaginationButtons();
return;
}
// 计算分页数据
const totalPages = Math.ceil(filteredRules.length / itemsPerPage);
const startIndex = (currentPage - 1) * itemsPerPage;
const endIndex = Math.min(startIndex + itemsPerPage, filteredRules.length);
const currentRules = filteredRules.slice(startIndex, endIndex);
// 渲染当前页的规则
currentRules.forEach((rule, index) => {
const row = document.createElement('tr');
const globalIndex = startIndex + index;
row.innerHTML = `
<td class="rule-id">${globalIndex + 1}</td>
<td class="rule-content"><pre>${escapeHtml(rule)}</pre></td>
<td class="rule-actions">
<button class="btn btn-danger btn-sm delete-rule" data-index="${globalIndex}">
<i class="fas fa-trash"></i> 删除
</button>
</td>
`;
rulesList.appendChild(row);
});
// 绑定删除按钮事件
document.querySelectorAll('.delete-rule').forEach(button => {
button.addEventListener('click', (e) => {
const index = parseInt(e.currentTarget.dataset.index);
deleteRule(index);
});
});
// 更新分页信息
paginationInfo.textContent = `显示 ${startIndex + 1}-${endIndex} 条,共 ${filteredRules.length} 条规则,第 ${currentPage}/${totalPages}`;
// 更新分页按钮状态
updatePaginationButtons();
}
// 更新分页按钮状态
function updatePaginationButtons() {
const totalPages = Math.ceil(filteredRules.length / itemsPerPage);
const prevBtn = document.getElementById('prev-page-btn');
const nextBtn = document.getElementById('next-page-btn');
const firstBtn = document.getElementById('first-page-btn');
const lastBtn = document.getElementById('last-page-btn');
prevBtn.disabled = currentPage === 1;
nextBtn.disabled = currentPage === totalPages || totalPages === 0;
firstBtn.disabled = currentPage === 1;
lastBtn.disabled = currentPage === totalPages || totalPages === 0;
}
// 上一页
function goToPreviousPage() {
if (currentPage > 1) {
currentPage--;
renderRulesList();
}
}
// 下一页
function goToNextPage() {
const totalPages = Math.ceil(filteredRules.length / itemsPerPage);
if (currentPage < totalPages) {
currentPage++;
renderRulesList();
}
}
// 第一页
function goToFirstPage() {
currentPage = 1;
renderRulesList();
}
// 最后一页
function goToLastPage() {
currentPage = Math.ceil(filteredRules.length / itemsPerPage);
renderRulesList();
}
// 添加新规则
async function addNewRule() {
const ruleInput = document.getElementById('rule-input');
const rule = ruleInput.value.trim();
if (!rule) {
showNotification('请输入规则内容', 'warning');
return;
}
try {
const response = await apiRequest('/shield/rule', 'POST', { rule });
if (response.success) {
rules.push(rule);
filteredRules = [...rules];
ruleInput.value = '';
// 添加后跳转到最后一页,显示新添加的规则
currentPage = Math.ceil(filteredRules.length / itemsPerPage);
renderRulesList();
showNotification('规则添加成功', 'success');
} else {
showNotification('规则添加失败:' + (response.message || '未知错误'), 'error');
}
} catch (error) {
showError('添加规则失败:' + error.message);
}
}
// 删除规则
async function deleteRule(index) {
if (!confirm('确定要删除这条规则吗?')) {
return;
}
try {
const rule = filteredRules[index];
const response = await apiRequest('/shield/rule', 'DELETE', { rule });
if (response.success) {
// 在原规则列表中找到并删除
const originalIndex = rules.indexOf(rule);
if (originalIndex !== -1) {
rules.splice(originalIndex, 1);
}
// 在过滤后的列表中删除
filteredRules.splice(index, 1);
// 如果当前页没有数据了,回到上一页
const totalPages = Math.ceil(filteredRules.length / itemsPerPage);
if (currentPage > totalPages && totalPages > 0) {
currentPage = totalPages;
}
renderRulesList();
showNotification('规则删除成功', 'success');
} else {
showNotification('规则删除失败:' + (response.message || '未知错误'), 'error');
}
} catch (error) {
showError('删除规则失败:' + error.message);
}
}
// 重新加载规则
async function reloadRules() {
if (!confirm('确定要重新加载所有规则吗?这将覆盖当前内存中的规则。')) {
return;
}
try {
const rulesPanel = document.getElementById('rules-panel');
showLoading(rulesPanel);
await apiRequest('/shield/reload', 'POST');
// 重新加载规则列表
await loadRules();
showNotification('规则重新加载成功', 'success');
} catch (error) {
showError('重新加载规则失败:' + error.message);
} finally {
const rulesPanel = document.getElementById('rules-panel');
hideLoading(rulesPanel);
}
}
// 过滤规则
function filterRules() {
const searchTerm = document.getElementById('rule-search').value.toLowerCase();
if (searchTerm) {
filteredRules = rules.filter(rule => rule.toLowerCase().includes(searchTerm));
} else {
filteredRules = [...rules];
}
currentPage = 1; // 重置为第一页
renderRulesList();
}
// HTML转义防止XSS攻击
function escapeHtml(text) {
const map = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#039;'
};
return text.replace(/[&<>"']/g, m => map[m]);
}
// 导出初始化函数
window.initRulesPanel = initRulesPanel;