feat: 支持用户级别IP黑白名单 - 可为单个用户设置独立的IP访问规则
This commit is contained in:
+17
-7
@@ -463,13 +463,20 @@ if (token) {
|
||||
// --- IP规则管理 ---
|
||||
async function loadIPRules() {
|
||||
try {
|
||||
const rules = await api('GET', '/api/ip-rules');
|
||||
const filter = document.getElementById('ip-rule-filter').value;
|
||||
let url = '/api/ip-rules';
|
||||
if (filter === 'global') url += '?username=__empty__';
|
||||
else if (filter === 'user') url += '?username=__has__';
|
||||
const rules = await api('GET', url);
|
||||
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>';
|
||||
tbody.innerHTML = '<tr><td colspan="8" style="text-align:center;color:#999;padding:40px">暂无IP规则,所有IP默认允许连接</td></tr>';
|
||||
return;
|
||||
}
|
||||
tbody.innerHTML = rules.map(r => {
|
||||
const scopeLabel = r.username
|
||||
? `<span style="color:#e67e22;font-weight:600">用户: ${r.username}</span>`
|
||||
: '<span style="color:#667eea;font-weight:600">全局</span>';
|
||||
const typeLabel = r.type === 'whitelist'
|
||||
? '<span style="color:#667eea;font-weight:600">白名单</span>'
|
||||
: '<span style="color:#ff4d4f;font-weight:600">黑名单</span>';
|
||||
@@ -478,14 +485,15 @@ async function loadIPRules() {
|
||||
: '<span class="status-disabled">禁用</span>';
|
||||
return `<tr>
|
||||
<td>${r.id}</td>
|
||||
<td>${scopeLabel}</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" onclick="editIPRule(${r.id}, '${r.username||''}', '${r.ip}', '${r.type}', '${(r.note||'').replace(/'/g, "\\'")}', ${r.enabled})">编辑</button>
|
||||
<button class="btn btn-sm" onclick="toggleIPRule(${r.id}, '${r.username||''}', '${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>`;
|
||||
@@ -503,9 +511,10 @@ function showAddIPRule() {
|
||||
document.getElementById('ip-rule-modal').style.display = 'flex';
|
||||
}
|
||||
|
||||
function editIPRule(id, ip, type, note, enabled) {
|
||||
function editIPRule(id, username, ip, type, note, enabled) {
|
||||
document.getElementById('ip-rule-modal-title').textContent = '编辑IP规则';
|
||||
document.getElementById('ip-rule-edit-id').value = id;
|
||||
document.getElementById('ip-rule-username').value = username;
|
||||
document.getElementById('ip-rule-ip').value = ip;
|
||||
document.getElementById('ip-rule-type').value = type;
|
||||
document.getElementById('ip-rule-note').value = note;
|
||||
@@ -521,6 +530,7 @@ document.getElementById('ip-rule-form').addEventListener('submit', async (e) =>
|
||||
e.preventDefault();
|
||||
const editId = document.getElementById('ip-rule-edit-id').value;
|
||||
const data = {
|
||||
username: document.getElementById('ip-rule-username').value,
|
||||
ip: document.getElementById('ip-rule-ip').value,
|
||||
type: document.getElementById('ip-rule-type').value,
|
||||
note: document.getElementById('ip-rule-note').value,
|
||||
@@ -541,10 +551,10 @@ document.getElementById('ip-rule-form').addEventListener('submit', async (e) =>
|
||||
}
|
||||
});
|
||||
|
||||
async function toggleIPRule(id, ip, type, note, enabled) {
|
||||
async function toggleIPRule(id, username, ip, type, note, enabled) {
|
||||
try {
|
||||
await api('PUT', '/api/ip-rules/' + id, {
|
||||
ip, type, note, enabled: !enabled
|
||||
username, ip, type, note, enabled: !enabled
|
||||
});
|
||||
showToast(!enabled ? '规则已启用' : '规则已禁用');
|
||||
loadIPRules();
|
||||
|
||||
Reference in New Issue
Block a user