301 lines
9.5 KiB
JavaScript
301 lines
9.5 KiB
JavaScript
// DNS查询页面功能实现
|
||
|
||
// 初始化查询页面
|
||
function initQueryPage() {
|
||
console.log('初始化DNS查询页面...');
|
||
setupQueryEventListeners();
|
||
loadQueryHistory();
|
||
}
|
||
|
||
// 执行DNS查询
|
||
async function handleDNSQuery() {
|
||
const domainInput = document.getElementById('dns-query-domain');
|
||
const resultDiv = document.getElementById('query-result');
|
||
|
||
if (!domainInput || !resultDiv) {
|
||
console.error('找不到必要的DOM元素');
|
||
return;
|
||
}
|
||
|
||
const domain = domainInput.value.trim();
|
||
if (!domain) {
|
||
showErrorMessage('请输入域名');
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const response = await fetch(`/api/query?domain=${encodeURIComponent(domain)}`);
|
||
if (!response.ok) {
|
||
throw new Error('查询失败');
|
||
}
|
||
|
||
const result = await response.json();
|
||
displayQueryResult(result, domain);
|
||
saveQueryHistory(domain, result);
|
||
loadQueryHistory();
|
||
} catch (error) {
|
||
console.error('DNS查询出错:', error);
|
||
showErrorMessage('查询失败,请稍后重试');
|
||
}
|
||
}
|
||
|
||
// 显示查询结果
|
||
function displayQueryResult(result, domain) {
|
||
const resultDiv = document.getElementById('query-result');
|
||
if (!resultDiv) return;
|
||
|
||
// 显示结果容器
|
||
resultDiv.classList.remove('hidden');
|
||
|
||
// 解析结果
|
||
const status = result.blocked ? '被屏蔽' : '正常';
|
||
const statusClass = result.blocked ? 'text-danger' : 'text-success';
|
||
const blockType = result.blocked ? result.blockRuleType || '未知' : '正常';
|
||
const blockRule = result.blocked ? result.blockRule || '未知' : '无';
|
||
const blockSource = result.blocked ? result.blocksource || '未知' : '无';
|
||
const timestamp = new Date(result.timestamp).toLocaleString();
|
||
|
||
// 更新结果显示
|
||
document.getElementById('result-domain').textContent = domain;
|
||
document.getElementById('result-status').innerHTML = `<span class="${statusClass}">${status}</span>`;
|
||
document.getElementById('result-type').textContent = blockType;
|
||
|
||
// 检查是否存在屏蔽规则显示元素,如果不存在则创建
|
||
let blockRuleElement = document.getElementById('result-block-rule');
|
||
if (!blockRuleElement) {
|
||
// 创建屏蔽规则显示区域
|
||
const grid = resultDiv.querySelector('.grid');
|
||
if (grid) {
|
||
const newGridItem = document.createElement('div');
|
||
newGridItem.className = 'bg-gray-50 p-4 rounded-lg';
|
||
newGridItem.innerHTML = `
|
||
<h4 class="text-sm font-medium text-gray-500 mb-2">屏蔽规则</h4>
|
||
<p class="text-lg font-semibold" id="result-block-rule">-</p>
|
||
`;
|
||
grid.appendChild(newGridItem);
|
||
blockRuleElement = document.getElementById('result-block-rule');
|
||
}
|
||
}
|
||
|
||
// 更新屏蔽规则显示
|
||
if (blockRuleElement) {
|
||
blockRuleElement.textContent = blockRule;
|
||
}
|
||
|
||
// 检查是否存在屏蔽来源显示元素,如果不存在则创建
|
||
let blockSourceElement = document.getElementById('result-block-source');
|
||
if (!blockSourceElement) {
|
||
// 创建屏蔽来源显示区域
|
||
const grid = resultDiv.querySelector('.grid');
|
||
if (grid) {
|
||
const newGridItem = document.createElement('div');
|
||
newGridItem.className = 'bg-gray-50 p-4 rounded-lg';
|
||
newGridItem.innerHTML = `
|
||
<h4 class="text-sm font-medium text-gray-500 mb-2">屏蔽来源</h4>
|
||
<p class="text-lg font-semibold" id="result-block-source">-</p>
|
||
`;
|
||
grid.appendChild(newGridItem);
|
||
blockSourceElement = document.getElementById('result-block-source');
|
||
}
|
||
}
|
||
|
||
// 更新屏蔽来源显示
|
||
if (blockSourceElement) {
|
||
blockSourceElement.textContent = blockSource;
|
||
}
|
||
|
||
document.getElementById('result-time').textContent = timestamp;
|
||
document.getElementById('result-details').textContent = JSON.stringify(result, null, 2);
|
||
}
|
||
|
||
// 保存查询历史
|
||
function saveQueryHistory(domain, result) {
|
||
// 获取现有历史记录
|
||
let history = JSON.parse(localStorage.getItem('dnsQueryHistory') || '[]');
|
||
|
||
// 创建历史记录项
|
||
const historyItem = {
|
||
domain: domain,
|
||
timestamp: new Date().toISOString(),
|
||
result: {
|
||
blocked: result.blocked,
|
||
blockRuleType: result.blockRuleType,
|
||
blockRule: result.blockRule,
|
||
blocksource: result.blocksource
|
||
}
|
||
};
|
||
|
||
// 添加到历史记录开头
|
||
history.unshift(historyItem);
|
||
|
||
// 限制历史记录数量
|
||
if (history.length > 20) {
|
||
history = history.slice(0, 20);
|
||
}
|
||
|
||
// 保存到本地存储
|
||
localStorage.setItem('dnsQueryHistory', JSON.stringify(history));
|
||
}
|
||
|
||
// 加载查询历史
|
||
function loadQueryHistory() {
|
||
const historyDiv = document.getElementById('query-history');
|
||
if (!historyDiv) return;
|
||
|
||
// 获取历史记录
|
||
const history = JSON.parse(localStorage.getItem('dnsQueryHistory') || '[]');
|
||
|
||
if (history.length === 0) {
|
||
historyDiv.innerHTML = '<div class="text-center text-gray-500 py-4">暂无查询历史</div>';
|
||
return;
|
||
}
|
||
|
||
// 生成历史记录HTML
|
||
const historyHTML = history.map(item => {
|
||
const statusClass = item.result.blocked ? 'text-danger' : 'text-success';
|
||
const statusText = item.result.blocked ? '被屏蔽' : '正常';
|
||
const blockType = item.result.blocked ? item.result.blockRuleType : '正常';
|
||
const blockRule = item.result.blocked ? item.result.blockRule : '无';
|
||
const blockSource = item.result.blocked ? item.result.blocksource : '无';
|
||
const formattedTime = new Date(item.timestamp).toLocaleString();
|
||
|
||
return `
|
||
<div class="flex flex-col md:flex-row justify-between items-start md:items-center p-3 bg-gray-50 rounded-lg hover:bg-gray-100 transition-colors">
|
||
<div class="flex-1">
|
||
<div class="flex items-center space-x-2">
|
||
<span class="font-medium">${item.domain}</span>
|
||
<span class="${statusClass} text-sm">${statusText}</span>
|
||
<span class="text-xs text-gray-500">${blockType}</span>
|
||
</div>
|
||
<div class="text-xs text-gray-500 mt-1">规则: ${blockRule}</div>
|
||
<div class="text-xs text-gray-500 mt-1">来源: ${blockSource}</div>
|
||
<div class="text-xs text-gray-500 mt-1">${formattedTime}</div>
|
||
</div>
|
||
<button class="mt-2 md:mt-0 px-3 py-1 bg-primary text-white text-sm rounded-md hover:bg-primary/90 transition-colors" onclick="requeryFromHistory('${item.domain}')">
|
||
<i class="fa fa-refresh mr-1"></i>重新查询
|
||
</button>
|
||
</div>
|
||
`;
|
||
}).join('');
|
||
|
||
historyDiv.innerHTML = historyHTML;
|
||
}
|
||
|
||
// 从历史记录重新查询
|
||
function requeryFromHistory(domain) {
|
||
const domainInput = document.getElementById('dns-query-domain');
|
||
if (domainInput) {
|
||
domainInput.value = domain;
|
||
handleDNSQuery();
|
||
}
|
||
}
|
||
|
||
// 清空查询历史
|
||
function clearQueryHistory() {
|
||
if (confirm('确定要清空所有查询历史吗?')) {
|
||
localStorage.removeItem('dnsQueryHistory');
|
||
loadQueryHistory();
|
||
showSuccessMessage('查询历史已清空');
|
||
}
|
||
}
|
||
|
||
// 设置事件监听器
|
||
function setupQueryEventListeners() {
|
||
// 查询按钮事件
|
||
const queryBtn = document.getElementById('dns-query-btn');
|
||
if (queryBtn) {
|
||
queryBtn.addEventListener('click', handleDNSQuery);
|
||
}
|
||
|
||
// 输入框回车键事件
|
||
const domainInput = document.getElementById('dns-query-domain');
|
||
if (domainInput) {
|
||
domainInput.addEventListener('keypress', (e) => {
|
||
if (e.key === 'Enter') {
|
||
e.preventDefault();
|
||
handleDNSQuery();
|
||
}
|
||
});
|
||
}
|
||
|
||
// 清空历史按钮事件
|
||
const clearHistoryBtn = document.getElementById('clear-history-btn');
|
||
if (clearHistoryBtn) {
|
||
clearHistoryBtn.addEventListener('click', clearQueryHistory);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
// 显示成功消息
|
||
function showSuccessMessage(message) {
|
||
showNotification(message, 'success');
|
||
}
|
||
|
||
// 显示错误消息
|
||
function showErrorMessage(message) {
|
||
showNotification(message, 'error');
|
||
}
|
||
|
||
// 显示通知
|
||
function showNotification(message, type = 'info') {
|
||
// 移除现有通知
|
||
const existingNotification = document.querySelector('.notification');
|
||
if (existingNotification) {
|
||
existingNotification.remove();
|
||
}
|
||
|
||
// 创建新通知
|
||
const notification = document.createElement('div');
|
||
notification.className = `notification fixed bottom-4 right-4 px-6 py-3 rounded-lg shadow-lg z-50 transform transition-all duration-300 ease-in-out translate-y-0 opacity-0`;
|
||
|
||
// 设置通知样式
|
||
if (type === 'success') {
|
||
notification.classList.add('bg-green-500', 'text-white');
|
||
} else if (type === 'error') {
|
||
notification.classList.add('bg-red-500', 'text-white');
|
||
} else {
|
||
notification.classList.add('bg-blue-500', 'text-white');
|
||
}
|
||
|
||
notification.innerHTML = `
|
||
<div class="flex items-center space-x-2">
|
||
<i class="fa ${type === 'success' ? 'fa-check-circle' : type === 'error' ? 'fa-exclamation-circle' : 'fa-info-circle'}"></i>
|
||
<span>${message}</span>
|
||
</div>
|
||
`;
|
||
|
||
document.body.appendChild(notification);
|
||
|
||
// 显示通知
|
||
setTimeout(() => {
|
||
notification.classList.remove('opacity-0');
|
||
notification.classList.add('opacity-100');
|
||
}, 10);
|
||
|
||
// 3秒后隐藏通知
|
||
setTimeout(() => {
|
||
notification.classList.remove('opacity-100');
|
||
notification.classList.add('opacity-0');
|
||
setTimeout(() => {
|
||
notification.remove();
|
||
}, 300);
|
||
}, 3000);
|
||
}
|
||
|
||
// 页面加载完成后初始化
|
||
if (document.readyState === 'loading') {
|
||
document.addEventListener('DOMContentLoaded', initQueryPage);
|
||
} else {
|
||
initQueryPage();
|
||
}
|
||
|
||
// 当切换到DNS查询页面时重新加载数据
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
// 监听hash变化,当切换到DNS查询页面时重新加载数据
|
||
window.addEventListener('hashchange', () => {
|
||
if (window.location.hash === '#query') {
|
||
initQueryPage();
|
||
}
|
||
});
|
||
}); |