diff --git a/config.json b/config.json
index 08f8ad7..a9c3c9c 100644
--- a/config.json
+++ b/config.json
@@ -36,6 +36,11 @@
"name": "My GitHub Rules",
"url": "https://gitea.amazehome.xyz/AMAZEHOME/hosts-and-filters/raw/branch/main/rules/costomize.txt",
"enabled": true
+ },
+ {
+ "name": "China List",
+ "url": "https://gitea.amazehome.xyz/AMAZEHOME/hosts-and-Filters/raw/branch/main/list/china.txt",
+ "enabled": true
}
],
"updateInterval": 3600,
diff --git a/dns-server b/dns-server
deleted file mode 100755
index 27039ec..0000000
Binary files a/dns-server and /dev/null differ
diff --git a/http/server.go b/http/server.go
index 63510e4..ad6fdc0 100644
--- a/http/server.go
+++ b/http/server.go
@@ -731,6 +731,14 @@ func (s *Server) handleShieldBlacklists(w http.ResponseWriter, r *http.Request)
blacklists[targetIndex].LastUpdateTime = time.Now().Format(time.RFC3339)
// 保存更新后的黑名单列表
s.shieldManager.UpdateBlacklist(blacklists)
+ // 更新全局配置中的黑名单
+ s.globalConfig.Shield.Blacklists = blacklists
+ // 保存配置到文件
+ if err := saveConfigToFile(s.globalConfig, "config.json"); err != nil {
+ logger.Error("保存配置文件失败", "error", err)
+ http.Error(w, "保存配置失败", http.StatusInternalServerError)
+ return
+ }
// 重新加载规则以获取最新的远程规则
s.shieldManager.LoadRules()
@@ -753,6 +761,14 @@ func (s *Server) handleShieldBlacklists(w http.ResponseWriter, r *http.Request)
}
s.shieldManager.UpdateBlacklist(newBlacklists)
+ // 更新全局配置中的黑名单
+ s.globalConfig.Shield.Blacklists = newBlacklists
+ // 保存配置到文件
+ if err := saveConfigToFile(s.globalConfig, "config.json"); err != nil {
+ logger.Error("保存配置文件失败", "error", err)
+ http.Error(w, "保存配置失败", http.StatusInternalServerError)
+ return
+ }
json.NewEncoder(w).Encode(map[string]string{"status": "success"})
return
}
@@ -800,6 +816,14 @@ func (s *Server) handleShieldBlacklists(w http.ResponseWriter, r *http.Request)
blacklists = append(blacklists, newEntry)
s.shieldManager.UpdateBlacklist(blacklists)
+ // 更新全局配置中的黑名单
+ s.globalConfig.Shield.Blacklists = blacklists
+ // 保存配置到文件
+ if err := saveConfigToFile(s.globalConfig, "config.json"); err != nil {
+ logger.Error("保存配置文件失败", "error", err)
+ http.Error(w, "保存配置失败", http.StatusInternalServerError)
+ return
+ }
// 重新加载规则以获取新添加的远程规则
s.shieldManager.LoadRules()
@@ -815,6 +839,14 @@ func (s *Server) handleShieldBlacklists(w http.ResponseWriter, r *http.Request)
}
s.shieldManager.UpdateBlacklist(blacklists)
+ // 更新全局配置中的黑名单
+ s.globalConfig.Shield.Blacklists = blacklists
+ // 保存配置到文件
+ if err := saveConfigToFile(s.globalConfig, "config.json"); err != nil {
+ logger.Error("保存配置文件失败", "error", err)
+ http.Error(w, "保存配置失败", http.StatusInternalServerError)
+ return
+ }
// 重新加载所有规则
s.shieldManager.LoadRules()
diff --git a/static/js/shield.js b/static/js/shield.js
index 8f6bd80..7a4a9d1 100644
--- a/static/js/shield.js
+++ b/static/js/shield.js
@@ -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 = '
| 暂无黑名单 |
';
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 = '';
- 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 = '';
+ 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 = '';
+ 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();
}
}