feat: 添加IP白名单/黑名单功能 - 支持单IP、CIDR、IP范围

This commit is contained in:
Your Name
2026-05-07 10:05:03 +08:00
parent 0f9663045c
commit d92cf341b8
5 changed files with 467 additions and 0 deletions
+105
View File
@@ -100,6 +100,7 @@ function loadPage(page) {
case 'files': loadFiles(currentPath); break;
case 'logs': loadLogs(); break;
case 'online': loadOnline(); break;
case 'ip-rules': loadIPRules(); break;
case 'settings': loadConfig(); break;
}
}
@@ -458,3 +459,107 @@ if (token) {
} else {
showLogin();
}
// --- IP规则管理 ---
async function loadIPRules() {
try {
const rules = await api('GET', '/api/ip-rules');
const tbody = document.getElementById('ip-rules-tbody');
if (!rules || !rules.length) {
tbody.innerHTML = '<tr><td colspan="7" style="text-align:center;color:#999;padding:40px">暂无IP规则,所有IP默认允许连接</td></tr>';
return;
}
tbody.innerHTML = rules.map(r => {
const typeLabel = r.type === 'whitelist'
? '<span style="color:#667eea;font-weight:600">白名单</span>'
: '<span style="color:#ff4d4f;font-weight:600">黑名单</span>';
const statusLabel = r.enabled
? '<span class="status-enabled">启用</span>'
: '<span class="status-disabled">禁用</span>';
return `<tr>
<td>${r.id}</td>
<td><code style="background:#f5f5f5;padding:2px 6px;border-radius:3px">${r.ip}</code></td>
<td>${typeLabel}</td>
<td>${r.note || '-'}</td>
<td>${statusLabel}</td>
<td>${formatTime(r.created_at)}</td>
<td class="action-btns">
<button class="btn btn-sm" onclick="editIPRule(${r.id}, '${r.ip}', '${r.type}', '${(r.note||'').replace(/'/g, "\\'")}', ${r.enabled})">编辑</button>
<button class="btn btn-sm" onclick="toggleIPRule(${r.id}, '${r.ip}', '${r.type}', '${(r.note||'').replace(/'/g, "\\'")}', ${r.enabled})">${r.enabled ? '禁用' : '启用'}</button>
<button class="btn btn-sm btn-danger" onclick="deleteIPRule(${r.id})">删除</button>
</td>
</tr>`;
}).join('');
} catch (err) {
showToast(err.message, 'error');
}
}
function showAddIPRule() {
document.getElementById('ip-rule-modal-title').textContent = '添加IP规则';
document.getElementById('ip-rule-edit-id').value = '';
document.getElementById('ip-rule-form').reset();
document.getElementById('ip-rule-enabled').checked = true;
document.getElementById('ip-rule-modal').style.display = 'flex';
}
function editIPRule(id, ip, type, note, enabled) {
document.getElementById('ip-rule-modal-title').textContent = '编辑IP规则';
document.getElementById('ip-rule-edit-id').value = id;
document.getElementById('ip-rule-ip').value = ip;
document.getElementById('ip-rule-type').value = type;
document.getElementById('ip-rule-note').value = note;
document.getElementById('ip-rule-enabled').checked = enabled;
document.getElementById('ip-rule-modal').style.display = 'flex';
}
function closeIPRuleModal() {
document.getElementById('ip-rule-modal').style.display = 'none';
}
document.getElementById('ip-rule-form').addEventListener('submit', async (e) => {
e.preventDefault();
const editId = document.getElementById('ip-rule-edit-id').value;
const data = {
ip: document.getElementById('ip-rule-ip').value,
type: document.getElementById('ip-rule-type').value,
note: document.getElementById('ip-rule-note').value,
enabled: document.getElementById('ip-rule-enabled').checked
};
try {
if (editId) {
await api('PUT', '/api/ip-rules/' + editId, data);
showToast('规则已更新');
} else {
await api('POST', '/api/ip-rules', data);
showToast('规则添加成功');
}
closeIPRuleModal();
loadIPRules();
} catch (err) {
showToast(err.message, 'error');
}
});
async function toggleIPRule(id, ip, type, note, enabled) {
try {
await api('PUT', '/api/ip-rules/' + id, {
ip, type, note, enabled: !enabled
});
showToast(!enabled ? '规则已启用' : '规则已禁用');
loadIPRules();
} catch (err) {
showToast(err.message, 'error');
}
}
async function deleteIPRule(id) {
if (!confirm('确定删除此IP规则吗?')) return;
try {
await api('DELETE', '/api/ip-rules/' + id);
showToast('规则已删除');
loadIPRules();
} catch (err) {
showToast(err.message, 'error');
}
}