update
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
[dns]
|
||||
port = 53
|
||||
upstreamDNS = 10.35.10.200
|
||||
dnssecUpstreamDNS = 208.67.220.220, 208.67.222.222
|
||||
saveInterval = 10
|
||||
cacheTTL = 10
|
||||
enableDNSSEC = false
|
||||
queryMode = parallel
|
||||
queryTimeout = 5000
|
||||
enableFastReturn = true
|
||||
noDNSSECDomains = amazehome.cn, addr.arpa, amazehome.xyz, .cn
|
||||
enableIPv6 = false
|
||||
cacheMode = file
|
||||
cacheSize = 100
|
||||
maxCacheTTL = 30
|
||||
minCacheTTL = 5
|
||||
domain_akamai = 10.35.10.200:53
|
||||
domain_amazehome.cn = 10.35.10.200:53
|
||||
domain_amazehome.xyz = 10.35.10.200:53
|
||||
domain_microsoft.com = 10.35.10.200:53
|
||||
domain_addr.arpa = 10.35.10.200:53
|
||||
domain_akadns = 10.35.10.200:53
|
||||
|
||||
[http]
|
||||
port = 8081
|
||||
host = 0.0.0.0
|
||||
enableAPI = true
|
||||
username = admin
|
||||
password = admin
|
||||
|
||||
[shield]
|
||||
updateInterval = 3600
|
||||
blockMethod = NXDOMAIN
|
||||
customBlockIP = 0.0.0.2
|
||||
statsSaveInterval = 60
|
||||
blacklist_AdGuard_DNS_filter = https://gitea.amazehome.xyz/AMAZEHOME/hosts-and-filters/raw/branch/main/filter.txt,true
|
||||
blacklist_Adaway_Default_Blocklist = https://gitea.amazehome.xyz/AMAZEHOME/hosts-and-Filters/raw/branch/main/hosts/adaway.txt,true
|
||||
blacklist_CHN_anti_AD = https://gitea.amazehome.xyz/AMAZEHOME/hosts-and-Filters/raw/branch/main/list/easylist.txt,true
|
||||
blacklist_My_GitHub_Rules = https://gitea.amazehome.xyz/AMAZEHOME/hosts-and-filters/raw/branch/main/rules/costomize.txt,true
|
||||
blacklist_CNList = https://gitea.amazehome.xyz/AMAZEHOME/hosts-and-filters/raw/branch/main/list/china.list,false
|
||||
blacklist_大圣净化 = http://gitea.amazehome.xyz/AMAZEHOME/hosts-and-Filters/raw/branch/main/hosts/dsjh.txt,true
|
||||
blacklist_Hate_and_Junk = http://gitea.amazehome.xyz/AMAZEHOME/hosts-and-filters/raw/branch/main/hate-and-junk-extended.txt,true
|
||||
blacklist_My_Gitlab_Hosts = http://gitea.amazehome.xyz/AMAZEHOME/hosts-and-filters/raw/branch/main/hosts/costomize.txt,true
|
||||
blacklist_Anti_Remote_Requests = http://gitea.amazehome.xyz/AMAZEHOME/hosts-and-filters/raw/branch/main/hosts/anti-remoterequests.txt,true
|
||||
blacklist_URL_Based = http://gitea.amazehome.xyz/AMAZEHOME/hosts-and-filters/raw/branch/main/rules/url-based-adguard.txt,true
|
||||
blacklist_My_Gitlab_A_T_Rules = http://gitea.amazehome.xyz/AMAZEHOME/hosts-and-filters/raw/branch/main/rules/ads-and-trackers.txt,true
|
||||
blacklist_My_Gitlab_Malware_List = http://gitea.amazehome.xyz/AMAZEHOME/hosts-and-filters/raw/branch/main/rules/malware.txt,true
|
||||
blacklist_hosts = http://gitea.amazehome.xyz/AMAZEHOME/hosts-and-Filters/raw/branch/main/hosts/costomize.txt,true
|
||||
blacklist_AWAvenue_Ads_Rule = http://gitea.amazehome.xyz/AMAZEHOME/hosts-and-Filters/raw/branch/main/rules/AWAvenue-Ads-Rule.txt,true
|
||||
blacklist_诈骗域名 = https://gitea.amazehome.xyz/AMAZEHOME/hosts-and-filters/raw/branch/main/rules/cheat.txt,true
|
||||
|
||||
[domainInfo]
|
||||
updateInterval = 3600
|
||||
enableAutoUpdate = true
|
||||
domainInfo_域名信息列表 = https://gitea.amazehome.xyz/AMAZEHOME/domain-info/raw/branch/main/domains/domain-info.json,domain-info,true
|
||||
domainInfo_威胁数据库 = https://gitea.amazehome.xyz/AMAZEHOME/domain-info/src/branch/main/threats/threats-database.csv,threat-database,true
|
||||
domainInfo_跟踪器列表 = https://gitea.amazehome.xyz/AMAZEHOME/domain-info/raw/branch/main/tracker/trackers.json,tracker,true
|
||||
|
||||
[gfwList]
|
||||
ip = 127.0.0.1
|
||||
content =
|
||||
enabled = false
|
||||
|
||||
[log]
|
||||
level = debug
|
||||
maxSize = 100
|
||||
maxBackups = 10
|
||||
maxAge = 30
|
||||
|
||||
[queryLog]
|
||||
# 基本配置
|
||||
enabled = true
|
||||
ringBufferSize = 10000
|
||||
|
||||
# SQLite 主库配置
|
||||
databasePath = data/query_logs.db
|
||||
maxDatabaseSizeMB = 1024
|
||||
enableWAL = true
|
||||
|
||||
# 归档配置
|
||||
archiveEnabled = true
|
||||
archiveDir = data/archive
|
||||
archivePrefix = querylog
|
||||
compressionLevel = 6
|
||||
|
||||
# 清理配置
|
||||
retentionDays = 0
|
||||
retentionMonths = 0
|
||||
|
||||
# 查询配置
|
||||
queryTimeout = 5
|
||||
enableCache = true
|
||||
cacheTTL = 300
|
||||
|
||||
[threat]
|
||||
enabled = true
|
||||
queryRateThreshold = 0
|
||||
nxDomainThreshold = 0
|
||||
maxDomainLength = 0
|
||||
suspiciousPatterns = malware,phishing,trojan,virus,ransomware
|
||||
unusualQueryTypes = TXT,SRV,MX
|
||||
alertRetentionDays = 0
|
||||
threatDatabasePath = ./static/domain-info/threats/threats-database.csv
|
||||
Executable
BIN
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+175
-6
@@ -47,11 +47,18 @@
|
||||
<span>屏蔽管理</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#domain-info"
|
||||
class="flex items-center px-4 py-3 text-gray-700 hover:bg-gray-100 rounded-md transition-all">
|
||||
<i class="fa fa-database mr-3 text-lg"></i>
|
||||
<span>域名信息管理</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#hosts"
|
||||
class="flex items-center px-4 py-3 text-gray-700 hover:bg-gray-100 rounded-md transition-all">
|
||||
<i class="fa fa-file-text mr-3 text-lg"></i>
|
||||
<span>Hosts管理</span>
|
||||
<span>Hosts 管理</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
@@ -146,11 +153,18 @@
|
||||
<span>屏蔽管理</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#domain-info"
|
||||
class="flex items-center px-4 py-3 text-gray-700 hover:bg-gray-100 rounded-md transition-all">
|
||||
<i class="fa fa-database mr-3 text-lg"></i>
|
||||
<span>域名信息管理</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#hosts"
|
||||
class="flex items-center px-4 py-3 text-gray-700 hover:bg-gray-100 rounded-md transition-all">
|
||||
<i class="fa fa-file-text mr-3 text-lg"></i>
|
||||
<span>Hosts管理</span>
|
||||
<span>Hosts 管理</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
@@ -730,6 +744,164 @@
|
||||
|
||||
|
||||
|
||||
<!-- 添加域名信息列表模态框 -->
|
||||
<div id="add-domain-info-modal" class="fixed inset-0 bg-black/50 flex items-center justify-center z-50 hidden">
|
||||
<div class="bg-white rounded-lg w-full max-w-md p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h3 class="text-lg font-semibold">添加域名信息列表</h3>
|
||||
<button onclick="window.domainInfo.hideAddListModal()"
|
||||
class="p-2 rounded-full hover:bg-gray-100 transition-colors">
|
||||
<i class="fa fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
<form id="add-domain-info-form">
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">名称</label>
|
||||
<input type="text" id="list-name" required
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">URL</label>
|
||||
<input type="url" id="list-url" required
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">类型</label>
|
||||
<select id="list-type" required
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent">
|
||||
<option value="domain-info">域名信息</option>
|
||||
<option value="threat-database">威胁数据库</option>
|
||||
<option value="tracker">跟踪器</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="flex items-center space-x-2">
|
||||
<input type="checkbox" id="list-enabled" checked
|
||||
class="rounded border-gray-300 text-primary focus:ring-primary">
|
||||
<span class="text-sm text-gray-700">启用</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-6 flex space-x-3">
|
||||
<button type="button" onclick="window.domainInfo.hideAddListModal()"
|
||||
class="px-4 py-2 border border-gray-300 rounded-md hover:bg-gray-50 transition-colors text-sm flex-1">
|
||||
取消
|
||||
</button>
|
||||
<button type="submit"
|
||||
class="px-4 py-2 bg-primary text-white rounded-md hover:bg-primary/90 transition-colors text-sm flex-1">
|
||||
添加
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 域名信息管理页面内容(初始隐藏) -->
|
||||
<div id="domain-info-content" class="hidden space-y-6">
|
||||
<!-- 域名信息统计卡片 -->
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4 sm:gap-6">
|
||||
<!-- 域名信息数量卡片 -->
|
||||
<div class="bg-blue-50 rounded-lg p-3 sm:p-4 card-shadow relative overflow-hidden transition-all hover:shadow-md">
|
||||
<div class="absolute -bottom-6 -right-6 w-20 h-20 sm:w-24 sm:h-24 rounded-full bg-primary opacity-10"></div>
|
||||
<div class="relative z-10">
|
||||
<div class="flex items-center justify-between mb-3 sm:mb-4">
|
||||
<h3 class="text-xs sm:text-sm text-gray-500 font-medium">域名信息数量</h3>
|
||||
<div class="p-1.5 sm:p-2 rounded-full bg-primary/10 text-primary">
|
||||
<i class="fa fa-database text-xs sm:text-sm"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<div class="flex items-end justify-between">
|
||||
<p class="text-2xl sm:text-3xl font-bold" id="domain-info-count">0</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 威胁域名数量卡片 -->
|
||||
<div class="bg-red-50 rounded-lg p-3 sm:p-4 card-shadow relative overflow-hidden transition-all hover:shadow-md">
|
||||
<div class="absolute -bottom-6 -right-6 w-20 h-20 sm:w-24 sm:h-24 rounded-full bg-danger opacity-10"></div>
|
||||
<div class="relative z-10">
|
||||
<div class="flex items-center justify-between mb-3 sm:mb-4">
|
||||
<h3 class="text-xs sm:text-sm text-gray-500 font-medium">威胁域名数量</h3>
|
||||
<div class="p-1.5 sm:p-2 rounded-full bg-danger/10 text-danger">
|
||||
<i class="fa fa-exclamation-triangle text-xs sm:text-sm"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<div class="flex items-end justify-between">
|
||||
<p class="text-2xl sm:text-3xl font-bold" id="threat-count">0</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 跟踪器数量卡片 -->
|
||||
<div class="bg-purple-50 rounded-lg p-3 sm:p-4 card-shadow relative overflow-hidden transition-all hover:shadow-md">
|
||||
<div class="absolute -bottom-6 -right-6 w-20 h-20 sm:w-24 sm:h-24 rounded-full bg-purple-500 opacity-10"></div>
|
||||
<div class="relative z-10">
|
||||
<div class="flex items-center justify-between mb-3 sm:mb-4">
|
||||
<h3 class="text-xs sm:text-sm text-gray-500 font-medium">跟踪器数量</h3>
|
||||
<div class="p-1.5 sm:p-2 rounded-full bg-purple-500/10 text-purple-500">
|
||||
<i class="fa fa-bullseye text-xs sm:text-sm"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<div class="flex items-end justify-between">
|
||||
<p class="text-2xl sm:text-3xl font-bold" id="tracker-count">0</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 域名信息列表管理 -->
|
||||
<div class="bg-white rounded-lg p-4 sm:p-6 card-shadow">
|
||||
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between mb-4 sm:mb-6">
|
||||
<h3 class="text-base sm:text-lg font-semibold mb-3 sm:mb-0">远程域名信息列表</h3>
|
||||
<div class="flex space-x-2 sm:space-x-3">
|
||||
<button onclick="window.domainInfo.updateAllDomainInfo()"
|
||||
class="px-3 sm:px-4 py-2 bg-primary text-white rounded-md hover:bg-primary/90 transition-colors text-sm flex items-center">
|
||||
<i class="fa fa-refresh mr-2"></i>
|
||||
更新所有列表
|
||||
</button>
|
||||
<button onclick="window.domainInfo.showAddListModal()"
|
||||
class="px-3 sm:px-4 py-2 bg-green-500 text-white rounded-md hover:bg-green-600 transition-colors text-sm flex items-center">
|
||||
<i class="fa fa-plus mr-2"></i>
|
||||
添加列表
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 最后更新时间 -->
|
||||
<div class="mb-4 text-sm text-gray-500">
|
||||
<i class="fa fa-clock-o mr-2"></i>
|
||||
最后更新时间:<span id="last-update-time">从未更新</span>
|
||||
</div>
|
||||
|
||||
<!-- 域名信息列表表格 -->
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-gray-200">
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th class="px-3 sm:px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">名称</th>
|
||||
<th class="px-3 sm:px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">状态</th>
|
||||
<th class="px-3 sm:px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">类型</th>
|
||||
<th class="px-3 sm:px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">规则数量</th>
|
||||
<th class="px-3 sm:px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">最后更新</th>
|
||||
<th class="px-3 sm:px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="domain-info-lists-table-body" class="bg-white divide-y divide-gray-200">
|
||||
<!-- 动态生成 -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 威胁告警页面内容(初始隐藏) -->
|
||||
<div id="threats-content" class="hidden space-y-6">
|
||||
<!-- 威胁统计卡片 -->
|
||||
@@ -2219,16 +2391,13 @@
|
||||
<script src="js/api.js"></script>
|
||||
<script src="js/dashboard.js"></script>
|
||||
<script src="js/shield.js"></script>
|
||||
<script src="js/modules/domain-info.js"></script>
|
||||
<script src="js/hosts.js"></script>
|
||||
<script src="js/query.js"></script>
|
||||
<script src="js/logs.js"></script>
|
||||
<script src="js/config.js"></script>
|
||||
<script src="js/about.js"></script>
|
||||
|
||||
<!-- 直接渲染滚动列表的静态HTML内容 -->
|
||||
|
||||
<script src="js/whois.js"></script>
|
||||
<!-- 威胁告警页面脚本 -->
|
||||
<script src="js/threats.js"></script>
|
||||
</body>
|
||||
|
||||
|
||||
@@ -0,0 +1,374 @@
|
||||
// 域名信息管理模块
|
||||
// 用于管理远程域名信息列表的加载、更新和显示
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// 域名信息列表缓存
|
||||
let domainInfoCache = null;
|
||||
let cacheTimestamp = 0;
|
||||
const CACHE_DURATION = 5 * 60 * 1000; // 5 分钟缓存
|
||||
|
||||
/**
|
||||
* 加载域名信息列表
|
||||
*/
|
||||
function loadDomainInfoLists() {
|
||||
const tbody = document.getElementById('domain-info-lists-table-body');
|
||||
if (!tbody) {
|
||||
console.warn('未找到域名信息列表表格元素');
|
||||
return;
|
||||
}
|
||||
|
||||
showLoading(tbody);
|
||||
|
||||
// 检查缓存
|
||||
if (domainInfoCache && (Date.now() - cacheTimestamp) < CACHE_DURATION) {
|
||||
console.log('使用缓存的域名信息列表');
|
||||
renderDomainInfoLists(domainInfoCache);
|
||||
return;
|
||||
}
|
||||
|
||||
apiRequest('/api/domain-info')
|
||||
.then(data => {
|
||||
domainInfoCache = data;
|
||||
cacheTimestamp = Date.now();
|
||||
renderDomainInfoLists(data);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('获取域名信息列表失败:', error);
|
||||
showError(tbody, '获取域名信息列表失败');
|
||||
window.showNotification('获取域名信息列表失败', 'error');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染域名信息列表
|
||||
*/
|
||||
function renderDomainInfoLists(data) {
|
||||
const tbody = document.getElementById('domain-info-lists-table-body');
|
||||
if (!tbody) return;
|
||||
|
||||
tbody.innerHTML = '';
|
||||
|
||||
if (!data || !data.lists || data.lists.length === 0) {
|
||||
const emptyRow = document.createElement('tr');
|
||||
emptyRow.innerHTML = '<td colspan="6" class="py-4 text-center text-gray-500">暂无域名信息列表</td>';
|
||||
tbody.appendChild(emptyRow);
|
||||
return;
|
||||
}
|
||||
|
||||
const fragment = document.createDocumentFragment();
|
||||
|
||||
data.lists.forEach((list, index) => {
|
||||
const tr = document.createElement('tr');
|
||||
tr.className = 'border-b border-gray-200 hover:bg-gray-50';
|
||||
|
||||
const typeLabel = getTypeLabel(list.type);
|
||||
const statusClass = list.enabled ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-800';
|
||||
const statusText = list.enabled ? '启用' : '禁用';
|
||||
|
||||
tr.innerHTML = `
|
||||
<td class="py-3 px-4 font-medium">${escapeHtml(list.name)}</td>
|
||||
<td class="py-3 px-4">
|
||||
<span class="px-2 py-1 rounded-full text-xs font-medium ${statusClass}">${statusText}</span>
|
||||
</td>
|
||||
<td class="py-3 px-4">
|
||||
<span class="px-2 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800">${typeLabel}</span>
|
||||
</td>
|
||||
<td class="py-3 px-4 text-center">${list.ruleCount || 0}</td>
|
||||
<td class="py-3 px-4 text-sm text-gray-600">${formatLastUpdateTime(list.lastUpdateTime)}</td>
|
||||
<td class="py-3 px-4 text-center">
|
||||
<div class="flex space-x-2 justify-center">
|
||||
<button onclick="window.domainInfo.updateDomainInfo('${list.type}')"
|
||||
class="px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600 text-sm"
|
||||
title="更新此列表">
|
||||
更新
|
||||
</button>
|
||||
<button onclick="window.domainInfo.removeDomainInfo('${list.type}')"
|
||||
class="px-3 py-1 bg-red-500 text-white rounded hover:bg-red-600 text-sm"
|
||||
title="删除此列表">
|
||||
删除
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
`;
|
||||
|
||||
fragment.appendChild(tr);
|
||||
});
|
||||
|
||||
tbody.appendChild(fragment);
|
||||
|
||||
// 更新统计信息
|
||||
updateDomainInfoStats(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新域名信息统计
|
||||
*/
|
||||
function updateDomainInfoStats(data) {
|
||||
if (document.getElementById('domain-info-count')) {
|
||||
document.getElementById('domain-info-count').textContent = data.domainInfoCount || 0;
|
||||
}
|
||||
if (document.getElementById('threat-count')) {
|
||||
document.getElementById('threat-count').textContent = data.threatCount || 0;
|
||||
}
|
||||
if (document.getElementById('tracker-count')) {
|
||||
document.getElementById('tracker-count').textContent = data.trackerCount || 0;
|
||||
}
|
||||
if (document.getElementById('last-update-time')) {
|
||||
document.getElementById('last-update-time').textContent = formatLastUpdateTime(data.lastUpdateTime);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新域名信息
|
||||
*/
|
||||
function updateDomainInfo(type) {
|
||||
const url = `/api/domain-info/update/${encodeURIComponent(type)}`;
|
||||
|
||||
apiRequest(url, 'POST')
|
||||
.then(data => {
|
||||
if (data.status === 'success') {
|
||||
window.showNotification(`域名信息更新任务已启动:${getTypeLabel(type)}`, 'success');
|
||||
// 延迟刷新列表
|
||||
setTimeout(() => {
|
||||
loadDomainInfoLists();
|
||||
}, 2000);
|
||||
} else {
|
||||
window.showNotification(`更新失败:${data.message || '未知错误'}`, 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('更新域名信息失败:', error);
|
||||
window.showNotification('更新域名信息失败', 'error');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新所有域名信息
|
||||
*/
|
||||
function updateAllDomainInfo() {
|
||||
if (!confirm('确定要更新所有域名信息吗?这可能需要一些时间。')) {
|
||||
return;
|
||||
}
|
||||
|
||||
apiRequest('/api/domain-info/update', 'POST')
|
||||
.then(data => {
|
||||
if (data.status === 'success') {
|
||||
window.showNotification('所有域名信息更新任务已启动', 'success');
|
||||
setTimeout(() => {
|
||||
loadDomainInfoLists();
|
||||
}, 2000);
|
||||
} else {
|
||||
window.showNotification(`更新失败:${data.message || '未知错误'}`, 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('更新所有域名信息失败:', error);
|
||||
window.showNotification('更新所有域名信息失败', 'error');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取类型标签
|
||||
*/
|
||||
function getTypeLabel(type) {
|
||||
const labels = {
|
||||
'domain-info': '域名信息',
|
||||
'threat-database': '威胁数据库',
|
||||
'tracker': '跟踪器'
|
||||
};
|
||||
return labels[type] || type;
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化最后更新时间
|
||||
*/
|
||||
function formatLastUpdateTime(timeStr) {
|
||||
if (!timeStr) return '从未更新';
|
||||
const date = new Date(timeStr);
|
||||
const now = new Date();
|
||||
const diff = now - date;
|
||||
|
||||
const minutes = Math.floor(diff / 60000);
|
||||
const hours = Math.floor(diff / 3600000);
|
||||
const days = Math.floor(diff / 86400000);
|
||||
|
||||
if (minutes < 1) return '刚刚';
|
||||
if (minutes < 60) return `${minutes}分钟前`;
|
||||
if (hours < 24) return `${hours}小时前`;
|
||||
if (days < 30) return `${days}天前`;
|
||||
|
||||
return date.toLocaleDateString('zh-CN');
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示加载状态
|
||||
*/
|
||||
function showLoading(container) {
|
||||
container.innerHTML = `
|
||||
<tr>
|
||||
<td colspan="6" class="py-8 text-center">
|
||||
<div class="flex items-center justify-center">
|
||||
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500"></div>
|
||||
<span class="ml-3 text-gray-600">加载中...</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示错误状态
|
||||
*/
|
||||
function showError(container, message) {
|
||||
container.innerHTML = `
|
||||
<tr>
|
||||
<td colspan="6" class="py-8 text-center text-red-500">
|
||||
<svg class="w-12 h-12 mx-auto mb-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||
</svg>
|
||||
${escapeHtml(message)}
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* HTML 转义
|
||||
*/
|
||||
function escapeHtml(text) {
|
||||
const div = document.createElement('div');
|
||||
div.textContent = text;
|
||||
return div.innerHTML;
|
||||
}
|
||||
|
||||
/**
|
||||
* API 请求封装
|
||||
*/
|
||||
function apiRequest(url, method = 'GET', data = null) {
|
||||
const options = {
|
||||
method: method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
credentials: 'same-origin' // 添加认证信息
|
||||
};
|
||||
|
||||
if (data && method !== 'GET') {
|
||||
options.body = JSON.stringify(data);
|
||||
}
|
||||
|
||||
return fetch(url, options)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||
}
|
||||
return response.json();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示添加列表模态框
|
||||
*/
|
||||
function showAddListModal() {
|
||||
const modal = document.getElementById('add-domain-info-modal');
|
||||
if (modal) {
|
||||
modal.classList.remove('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏添加列表模态框
|
||||
*/
|
||||
function hideAddListModal() {
|
||||
const modal = document.getElementById('add-domain-info-modal');
|
||||
if (modal) {
|
||||
modal.classList.add('hidden');
|
||||
// 重置表单
|
||||
document.getElementById('add-domain-info-form').reset();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加域名信息列表
|
||||
*/
|
||||
function addDomainInfo(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const name = document.getElementById('list-name').value.trim();
|
||||
const url = document.getElementById('list-url').value.trim();
|
||||
const type = document.getElementById('list-type').value;
|
||||
const enabled = document.getElementById('list-enabled').checked;
|
||||
|
||||
if (!name || !url) {
|
||||
window.showNotification('请填写名称和URL', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
const data = {
|
||||
name: name,
|
||||
url: url,
|
||||
type: type,
|
||||
enabled: enabled
|
||||
};
|
||||
|
||||
apiRequest('/api/domain-info/add', 'POST', data)
|
||||
.then(response => {
|
||||
if (response.status === 'success') {
|
||||
window.showNotification('域名信息列表添加成功', 'success');
|
||||
hideAddListModal();
|
||||
loadDomainInfoLists();
|
||||
} else {
|
||||
window.showNotification(`添加失败:${response.message || '未知错误'}`, 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('添加域名信息列表失败:', error);
|
||||
window.showNotification('添加域名信息列表失败', 'error');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除域名信息列表
|
||||
*/
|
||||
function removeDomainInfo(type) {
|
||||
if (!confirm('确定要删除此域名信息列表吗?此操作不可恢复。')) {
|
||||
return;
|
||||
}
|
||||
|
||||
apiRequest(`/api/domain-info/remove/${encodeURIComponent(type)}`, 'POST')
|
||||
.then(response => {
|
||||
if (response.status === 'success') {
|
||||
window.showNotification('域名信息列表删除成功', 'success');
|
||||
loadDomainInfoLists();
|
||||
} else {
|
||||
window.showNotification(`删除失败:${response.message || '未知错误'}`, 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('删除域名信息列表失败:', error);
|
||||
window.showNotification('删除域名信息列表失败', 'error');
|
||||
});
|
||||
}
|
||||
|
||||
// 绑定添加列表表单提交事件
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const form = document.getElementById('add-domain-info-form');
|
||||
if (form) {
|
||||
form.addEventListener('submit', addDomainInfo);
|
||||
}
|
||||
});
|
||||
|
||||
// 暴露到全局命名空间
|
||||
window.domainInfo = {
|
||||
loadDomainInfoLists,
|
||||
updateDomainInfo,
|
||||
updateAllDomainInfo,
|
||||
renderDomainInfoLists,
|
||||
showAddListModal,
|
||||
hideAddListModal,
|
||||
removeDomainInfo
|
||||
};
|
||||
|
||||
})();
|
||||
+150
-1
@@ -1480,4 +1480,153 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
initShieldPage();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
// ========== 域名信息管理相关功能 ==========
|
||||
|
||||
// 加载远程域名信息列表
|
||||
async function loadRemoteDomainInfoLists() {
|
||||
// 检查是否有有效的缓存数据
|
||||
const cachedDomainInfo = window.pageDataCache && window.pageDataCache.getCache('domain_info_lists');
|
||||
if (cachedDomainInfo) {
|
||||
console.log('使用缓存的域名信息列表');
|
||||
updateDomainInfoListsTable(cachedDomainInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/domain-info');
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`加载失败:${response.status}`);
|
||||
}
|
||||
|
||||
const domainInfo = await response.json();
|
||||
|
||||
// 更新域名信息列表 UI
|
||||
updateDomainInfoListsTable(domainInfo);
|
||||
|
||||
// 存储数据到缓存
|
||||
if (window.pageDataCache) {
|
||||
window.pageDataCache.setCache('domain_info_lists', domainInfo);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载域名信息列表失败:', error);
|
||||
showNotification('加载域名信息列表失败', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// 更新域名信息列表表格
|
||||
function updateDomainInfoListsTable(data) {
|
||||
if (!data) return;
|
||||
|
||||
// 更新统计信息
|
||||
if (document.getElementById('domain-info-count')) {
|
||||
document.getElementById('domain-info-count').textContent = data.domainInfoCount || 0;
|
||||
}
|
||||
if (document.getElementById('threat-count')) {
|
||||
document.getElementById('threat-count').textContent = data.threatCount || 0;
|
||||
}
|
||||
if (document.getElementById('tracker-count')) {
|
||||
document.getElementById('tracker-count').textContent = data.trackerCount || 0;
|
||||
}
|
||||
|
||||
// 渲染列表(如果页面有表格元素)
|
||||
if (window.domainInfo && typeof window.domainInfo.renderDomainInfoLists === 'function') {
|
||||
window.domainInfo.renderDomainInfoLists(data);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新所有域名信息
|
||||
async function updateAllDomainInfo() {
|
||||
if (!confirm('确定要更新所有域名信息吗?这可能需要一些时间。')) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/domain-info/update', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`更新失败:${response.status}`);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.status === 'success') {
|
||||
showNotification('所有域名信息更新任务已启动', 'success');
|
||||
// 清除缓存
|
||||
if (window.pageDataCache) {
|
||||
window.pageDataCache.clearCache('domain_info_lists');
|
||||
}
|
||||
// 延迟刷新
|
||||
setTimeout(() => {
|
||||
loadRemoteDomainInfoLists();
|
||||
}, 2000);
|
||||
} else {
|
||||
showNotification(`更新失败:${result.message || '未知错误'}`, 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('更新所有域名信息失败:', error);
|
||||
showNotification('更新所有域名信息失败', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// 更新指定类型的域名信息
|
||||
async function updateDomainInfoByType(type) {
|
||||
const typeLabels = {
|
||||
'domain-info': '域名信息',
|
||||
'threat-database': '威胁数据库',
|
||||
'tracker': '跟踪器'
|
||||
};
|
||||
|
||||
const typeName = typeLabels[type] || type;
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/domain-info/update/${encodeURIComponent(type)}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`更新失败:${response.status}`);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.status === 'success') {
|
||||
showNotification(`${typeName}更新任务已启动`, 'success');
|
||||
// 清除缓存
|
||||
if (window.pageDataCache) {
|
||||
window.pageDataCache.clearCache('domain_info_lists');
|
||||
}
|
||||
// 延迟刷新
|
||||
setTimeout(() => {
|
||||
loadRemoteDomainInfoLists();
|
||||
}, 2000);
|
||||
} else {
|
||||
showNotification(`更新失败:${result.message || '未知错误'}`, 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`更新${typeName}失败:`, error);
|
||||
showNotification(`更新${typeName}失败`, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// 在 initShieldPage 中添加域名信息列表加载(如果页面存在相关元素)
|
||||
const originalInitShieldPage = window.initShieldPage;
|
||||
window.initShieldPage = async function() {
|
||||
if (originalInitShieldPage) {
|
||||
await originalInitShieldPage();
|
||||
}
|
||||
|
||||
// 如果页面有域名信息管理相关元素,则加载
|
||||
if (document.getElementById('domain-info-lists-table-body')) {
|
||||
await loadRemoteDomainInfoLists();
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user