修复配置更新未写入配置文件的问题

This commit is contained in:
Alex Yang
2025-11-28 01:10:43 +08:00
parent 0e0ac8b016
commit 67c651c804
4 changed files with 163 additions and 31 deletions

View File

@@ -293,6 +293,19 @@ async function loadRemoteBlacklists() {
}
}
// 判断黑名单是否过期超过24小时未更新视为过期
function isBlacklistExpired(lastUpdateTime) {
if (!lastUpdateTime) {
return true; // 从未更新过,视为过期
}
const lastUpdate = new Date(lastUpdateTime);
const now = new Date();
const hoursDiff = (now - lastUpdate) / (1000 * 60 * 60);
return hoursDiff > 24; // 超过24小时视为过期
}
// 更新黑名单表格
function updateBlacklistsTable(blacklists) {
const tbody = document.getElementById('blacklists-table-body');
@@ -300,7 +313,8 @@ function updateBlacklistsTable(blacklists) {
// 清空表格
tbody.innerHTML = '';
if (blacklists.length === 0) {
// 检查黑名单数据是否为空
if (!blacklists || blacklists.length === 0) {
const emptyRow = document.createElement('tr');
emptyRow.innerHTML = '<tr><td colspan="4" class="py-4 text-center text-gray-500">暂无黑名单</td></tr>';
tbody.appendChild(emptyRow);
@@ -316,12 +330,12 @@ function updateBlacklistsTable(blacklists) {
blacklistsToShow.forEach(blacklist => {
const tr = document.createElement('tr');
tr.className = 'border-b border-gray-200';
tr.className = 'border-b border-gray-200 hover:bg-gray-50';
// 名称单元格
const tdName = document.createElement('td');
tdName.className = 'py-3 px-4';
tdName.textContent = blacklist.Name;
tdName.textContent = blacklist.Name || '未命名';
// URL单元格
const tdUrl = document.createElement('td');
@@ -331,29 +345,58 @@ function updateBlacklistsTable(blacklists) {
// 状态单元格
const tdStatus = document.createElement('td');
tdStatus.className = 'py-3 px-4 text-center';
// 判断状态颜色:绿色(正常)、黄色(过期)、灰色(禁用)
let statusColor = 'bg-gray-300'; // 默认禁用
let statusText = '禁用';
if (blacklist.Enabled) {
const expired = isBlacklistExpired(blacklist.lastUpdateTime || blacklist.LastUpdateTime);
if (expired) {
statusColor = 'bg-warning'; // 黄色表示过期
statusText = '过期';
} else {
statusColor = 'bg-success'; // 绿色表示正常
statusText = '正常';
}
}
const statusContainer = document.createElement('div');
statusContainer.className = 'flex items-center justify-center';
const statusDot = document.createElement('span');
statusDot.className = `inline-block w-3 h-3 rounded-full ${blacklist.Enabled ? 'bg-success' : 'bg-gray-300'}`;
tdStatus.appendChild(statusDot);
statusDot.className = `inline-block w-3 h-3 rounded-full ${statusColor}`;
statusDot.title = statusText;
const statusTextSpan = document.createElement('span');
statusTextSpan.className = 'text-sm ml-2';
statusTextSpan.textContent = statusText;
statusContainer.appendChild(statusDot);
statusContainer.appendChild(statusTextSpan);
tdStatus.appendChild(statusContainer);
// 操作单元格
const tdActions = document.createElement('td');
tdActions.className = 'py-3 px-4 text-right space-x-2';
// 新按钮
const updateBtn = document.createElement('button');
updateBtn.className = 'update-blacklist-btn px-3 py-1 bg-primary text-white rounded-md hover:bg-primary/90 transition-colors text-sm';
updateBtn.dataset.url = blacklist.URL;
updateBtn.innerHTML = '<i class="fa fa-refresh"></i>';
updateBtn.addEventListener('click', handleUpdateBlacklist);
// 新按钮
const refreshBtn = document.createElement('button');
refreshBtn.className = 'update-blacklist-btn px-3 py-1 bg-primary text-white rounded-md hover:bg-primary/90 transition-colors text-sm';
refreshBtn.dataset.url = blacklist.URL;
refreshBtn.innerHTML = '<i class="fa fa-refresh"></i>';
refreshBtn.title = '刷新黑名单';
refreshBtn.addEventListener('click', handleUpdateBlacklist);
// 删除按钮
const deleteBtn = document.createElement('button');
deleteBtn.className = 'delete-blacklist-btn px-3 py-1 bg-danger text-white rounded-md hover:bg-danger/90 transition-colors text-sm';
deleteBtn.dataset.url = blacklist.URL;
deleteBtn.innerHTML = '<i class="fa fa-trash"></i>';
deleteBtn.title = '删除黑名单';
deleteBtn.addEventListener('click', handleDeleteBlacklist);
tdActions.appendChild(updateBtn);
tdActions.appendChild(refreshBtn);
tdActions.appendChild(deleteBtn);
tr.appendChild(tdName);
@@ -377,25 +420,35 @@ function updateBlacklistsTable(blacklists) {
// 处理更新单个黑名单
async function handleUpdateBlacklist(e) {
const url = e.target.closest('.update-blacklist-btn').dataset.url;
if (!url) {
showToast('无效的黑名单URL', 'error');
return;
}
showLoading('更新黑名单中...');
try {
const response = await fetch(`/api/shield/blacklists/${encodeURIComponent(url)}/update`, {
method: 'POST'
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
});
if (!response.ok) {
throw new Error('Failed to update blacklist');
const errorData = await response.json().catch(() => ({}));
throw new Error(errorData.error || 'Failed to update blacklist');
}
showSuccessMessage('黑名单更新成功');
// 重新加载黑名单
loadRemoteBlacklists();
// 重新加载统计信息
loadShieldStats();
hideLoading();
showToast('黑名单更新成功');
} catch (error) {
console.error('Error updating blacklist:', error);
showErrorMessage('更新黑名单失败');
console.error('更新黑名单失败:', error);
showToast('更新黑名单失败: ' + error.message, 'error');
} finally {
hideLoading();
}
}
@@ -403,39 +456,71 @@ async function handleUpdateBlacklist(e) {
// 处理删除黑名单
async function handleDeleteBlacklist(e) {
const url = e.target.closest('.delete-blacklist-btn').dataset.url;
if (!url) {
showToast('无效的黑名单URL', 'error');
return;
}
// 确认删除
if (!confirm('确定要删除这个黑名单吗?删除后将无法恢复。')) {
return;
}
showLoading('删除黑名单中...');
try {
const response = await fetch(`/api/shield/blacklists/${encodeURIComponent(url)}`, {
method: 'DELETE'
method: 'DELETE',
headers: {
'Content-Type': 'application/json'
}
});
if (!response.ok) {
throw new Error('Failed to delete blacklist');
const errorData = await response.json().catch(() => ({}));
throw new Error(errorData.error || 'Failed to delete blacklist');
}
showSuccessMessage('黑名单删除成功');
// 重新加载黑名单
loadRemoteBlacklists();
// 重新加载统计信息
loadShieldStats();
hideLoading();
showToast('黑名单删除成功');
} catch (error) {
console.error('Error deleting blacklist:', error);
showErrorMessage('删除黑名单失败');
console.error('删除黑名单失败:', error);
showToast('删除黑名单失败: ' + error.message, 'error');
} finally {
hideLoading();
}
}
// 处理添加黑名单
async function handleAddBlacklist() {
const name = document.getElementById('blacklist-name').value.trim();
const url = document.getElementById('blacklist-url').value.trim();
async function handleAddBlacklist(event) {
// 如果存在event参数则调用preventDefault()防止表单默认提交
if (event && typeof event.preventDefault === 'function') {
event.preventDefault();
}
const nameInput = document.getElementById('blacklist-name');
const urlInput = document.getElementById('blacklist-url');
const name = nameInput ? nameInput.value.trim() : '';
const url = urlInput ? urlInput.value.trim() : '';
// 简单验证
if (!name || !url) {
showErrorMessage('名称和URL不能为空');
return;
}
// 验证URL格式
try {
new URL(url);
} catch (e) {
showErrorMessage('URL格式不正确');
return;
}
showLoading('添加黑名单中...');
try {
const response = await fetch('/api/shield/blacklists', {
@@ -447,13 +532,23 @@ async function handleAddBlacklist() {
});
if (!response.ok) {
throw new Error('Failed to add blacklist');
// 尝试从响应中获取更详细的错误信息
let errorMessage = '添加黑名单失败';
try {
const errorData = await response.json();
if (errorData.error) {
errorMessage = errorData.error;
}
} catch (jsonError) {
// 忽略JSON解析错误
}
throw new Error(errorMessage);
}
showSuccessMessage('黑名单添加成功');
// 清空输入框
document.getElementById('blacklist-name').value = '';
document.getElementById('blacklist-url').value = '';
if (nameInput) nameInput.value = '';
if (urlInput) urlInput.value = '';
// 重新加载黑名单
loadRemoteBlacklists();
// 重新加载统计信息
@@ -461,7 +556,7 @@ async function handleAddBlacklist() {
hideLoading();
} catch (error) {
console.error('Error adding blacklist:', error);
showErrorMessage('添加黑名单失败');
showErrorMessage(error.message || '添加黑名单失败');
hideLoading();
}
}