## 重写DNS日志详情弹窗方案

### 1. 问题分析
当前弹窗代码存在以下问题：
- 代码结构复杂，大量嵌套条件和重复逻辑
- 样式不够现代，布局不够灵活
- 响应式设计不足，在大屏幕上显示效果不佳
- 代码冗余，重复的记录解析逻辑
- 可维护性差，HTML结构直接写在JavaScript字符串中

### 2. 设计思路
- **组件化设计**：将弹窗拆分为更小的可复用组件
- **简化逻辑**：重构DNS解析记录处理逻辑，减少重复代码
- **现代样式**：使用更现代的CSS布局和样式
- **响应式设计**：优化在不同屏幕尺寸下的显示效果
- **更好的用户体验**：添加动画效果、改进交互体验
- **更清晰的代码结构**：提高可维护性

### 3. 实现方案

#### 3.1 重构`showLogDetailModal`函数
- 简化函数结构，分离关注点
- 将DNS解析记录处理逻辑提取为独立函数
- 使用更现代的DOM API创建元素

#### 3.2 优化DNS解析记录处理
- 创建独立的`formatDNSRecords`函数
- 统一处理各种格式的DNS记录
- 减少重复代码，提高可维护性

#### 3.3 现代CSS样式
- 使用更现代的CSS类名和布局
- 优化响应式设计，支持不同屏幕尺寸
- 添加动画效果，提升用户体验

#### 3.4 改进HTML结构
- 使用更清晰的语义化HTML
- 优化布局结构，提高可读性
- 支持更好的响应式设计

### 4. 代码实现
```javascript
// 独立的DNS记录格式化函数
function formatDNSRecords(log, result) {
    if (result === 'blocked') return '无';
    
    let records = '';
    const sources = [
        log.answers,
        log.answer,
        log.Records,
        log.records,
        log.response
    ];
    
    for (const source of sources) {
        if (records) break;
        if (!source || source === '无') continue;
        
        // 处理数组类型
        if (Array.isArray(source)) {
            records = source.map(answer => {
                const type = answer.type || answer.Type || '未知';
                let value = answer.value || answer.Value || answer.data || answer.Data || '未知';
                const ttl = answer.TTL || answer.ttl || answer.expires || '未知';
                
                // 增强的记录值提取逻辑
                if (typeof value === 'string') {
                    value = value.trim();
                    // 处理制表符分隔的格式
                    if (value.includes('\t') || value.includes('\\t')) {
                        const parts = value.replace(/\\t/g, '\t').split('\t');
                        if (parts.length >= 4) {
                            value = parts[parts.length - 1].trim();
                        }
                    }
                    // 处理JSON格式
                    else if (value.startsWith('{') && value.endsWith('}')) {
                        try {
                            const parsed = JSON.parse(value);
                            value = parsed.data || parsed.value || value;
                        } catch (e) {}
                    }
                }
                
                return `${type}: ${value} (ttl=${ttl})`;
            }).join('\n').trim();
        }
        // 处理字符串类型
        else if (typeof source === 'string') {
            // 尝试解析为JSON数组
            if (source.startsWith('[') && source.endsWith(']')) {
                try {
                    const parsed = JSON.parse(source);
                    if (Array.isArray(parsed)) {
                        records = parsed.map(answer => {
                            const type = answer.type || answer.Type || '未知';
                            let value = answer.value || answer.Value || answer.data || answer.Data || '未知';
                            const ttl = answer.TTL || answer.ttl || answer.expires || '未知';
                            
                            if (typeof value === 'string') {
                                value = value.trim();
                            }
                            
                            return `${type}: ${value} (ttl=${ttl})`;
                        }).join('\n').trim();
                    }
                } catch (e) {
                    // 解析失败，尝试直接格式化
                    records = formatDNSString(source);
                }
            } else {
                // 直接格式化字符串
                records = formatDNSString(source);
            }
        }
    }
    
    return records || '无解析记录';
}

// 格式化DNS字符串记录
function formatDNSString(str) {
    const recordLines = str.split('\n').map(line => line.trim()).filter(line => line !== '');
    
    return recordLines.map(line => {
        // 检查是否已经是标准格式
        if (line.includes(':') && line.includes('(')) {
            return line;
        }
        // 尝试解析为标准DNS格式
        const parts = line.split(/\s+/);
        if (parts.length >= 5) {
            const type = parts[3];
            const value = parts.slice(4).join(' ');
            const ttl = parts[1];
            return `${type}: ${value} (ttl=${ttl})`;
        }
        // 无法解析，返回原始行
        return line;
    }).join('\n');
}

// 重写后的showLogDetailModal函数
async function showLogDetailModal(log) {
    if (!log) {
        console.error('No log data provided!');
        return;
    }
    
    try {
        // 安全获取log属性，提供默认值
        const timestamp = log.timestamp ? new Date(log.timestamp) : null;
        const dateStr = timestamp ? timestamp.toLocaleDateString() : '未知';
        const timeStr = timestamp ? timestamp.toLocaleTimeString() : '未知';
        const domain = log.domain || '未知';
        const queryType = log.queryType || '未知';
        const result = log.result || '未知';
        const responseTime = log.responseTime || '未知';
        const clientIP = log.clientIP || '未知';
        const location = log.location || '未知';
        const fromCache = log.fromCache || false;
        const dnssec = log.dnssec || false;
        const edns = log.edns || false;
        const dnsServer = log.dnsServer || '无';
        const dnssecServer = log.dnssecServer || '无';
        const blockRule = log.blockRule || '无';
        
        // 检查域名是否在跟踪器数据库中
        const trackerInfo = await isDomainInTrackerDatabase(log.domain);
        const isTracker = trackerInfo !== null;
        
        // 格式化DNS解析记录
        const dnsRecords = formatDNSRecords(log, result);
        
        // 创建模态框容器
        const modalContainer = document.createElement('div');
        modalContainer.className = 'fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center p-4 animate-fade-in';
        modalContainer.style.zIndex = '9999';
        
        // 创建模态框内容
        const modalContent = document.createElement('div');
        modalContent.className = 'bg-white rounded-xl shadow-2xl w-full max-w-2xl max-h-[90vh] overflow-y-auto animate-slide-in';
        
        // 创建标题栏
        const header = document.createElement('div');
        header.className = 'sticky top-0 bg-white border-b border-gray-200 px-6 py-4 flex justify-between items-center';
        
        const title = document.createElement('h3');
        title.className = 'text-xl font-semibold text-gray-900';
        title.textContent = '日志详情';
        
        const closeButton = document.createElement('button');
        closeButton.innerHTML = '<i class="fa fa-times text-xl"></i>';
        closeButton.className = 'text-gray-500 hover:text-gray-700 focus:outline-none transition-colors';
        closeButton.onclick = () => closeModal();
        
        header.appendChild(title);
        header.appendChild(closeButton);
        
        // 创建内容区域
        const content = document.createElement('div');
        content.className = 'p-6 space-y-6';
        
        // 基本信息部分
        const basicInfo = document.createElement('div');
        basicInfo.className = 'space-y-4';
        
        const basicInfoTitle = document.createElement('h4');
        basicInfoTitle.className = 'text-sm font-medium text-gray-700 uppercase tracking-wider';
        basicInfoTitle.textContent = '基本信息';
        
        const basicInfoGrid = document.createElement('div');
        basicInfoGrid.className = 'grid grid-cols-1 md:grid-cols-2 gap-4';
        
        // 添加基本信息项
        basicInfoGrid.innerHTML = `
            <div class="space-y-1">
                <div class="text-xs text-gray-500">日期</div>
                <div class="text-sm font-medium text-gray-900">${dateStr}</div>
            </div>
            <div class="space-y-1">
                <div class="text-xs text-gray-500">时间</div>
                <div class="text-sm font-medium text-gray-900">${timeStr}</div>
            </div>
            <div class="space-y-1">
                <div class="text-xs text-gray-500">状态</div>
                <div class="text-sm font-medium ${result === 'blocked' ? 'text-red-600' : result === 'allowed' ? 'text-green-600' : 'text-gray-500'}">
                    ${result === 'blocked' ? '已拦截' : result === 'allowed' ? '允许' : result}
                </div>
            </div>
            <div class="space-y-1">
                <div class="text-xs text-gray-500">域名</div>
                <div class="text-sm font-medium text-gray-900 break-all">${domain}</div>
            </div>
            <div class="space-y-1">
                <div class="text-xs text-gray-500">类型</div>
                <div class="text-sm font-medium text-gray-900">${queryType}</div>
            </div>
        `;
        
        // DNS特性
        const dnsFeatures = document.createElement('div');
        dnsFeatures.className = 'col-span-1 md:col-span-2 space-y-1';
        dnsFeatures.innerHTML = `
            <div class="text-xs text-gray-500">DNS特性</div>
            <div class="text-sm font-medium text-gray-900">
                ${dnssec ? '<i class="fa fa-lock text-green-500 mr-1" title="DNSSEC已启用"></i>DNSSEC ' : ''}
                ${edns ? '<i class="fa fa-exchange text-blue-500 mr-1" title="EDNS已启用"></i>EDNS' : ''}
                ${!dnssec && !edns ? '无' : ''}
            </div>
        `;
        
        // 跟踪器信息
        const trackerDiv = document.createElement('div');
        trackerDiv.className = 'col-span-1 md:col-span-2 space-y-1';
        trackerDiv.innerHTML = `
            <div class="text-xs text-gray-500">跟踪器信息</div>
            <div class="text-sm font-medium text-gray-900">
                ${isTracker ? `
                    <div class="flex items-center">
                        <i class="fa fa-eye text-red-500 mr-1"></i>
                        <span>${trackerInfo.name} (${trackersDatabase.categories[trackerInfo.categoryId] || '未知'})</span>
                    </div>
                ` : '无'}
            </div>
        `;
        
        // 解析记录
        const recordsDiv = document.createElement('div');
        recordsDiv.className = 'col-span-1 md:col-span-2 space-y-1';
        recordsDiv.innerHTML = `
            <div class="text-xs text-gray-500">解析记录</div>
            <div class="text-sm font-medium text-gray-900 whitespace-pre-wrap break-all bg-gray-50 p-3 rounded-md border border-gray-200">
                ${dnsRecords}
            </div>
        `;
        
        // DNS服务器
        const dnsServerDiv = document.createElement('div');
        dnsServerDiv.className = 'col-span-1 md:col-span-2 space-y-1';
        dnsServerDiv.innerHTML = `
            <div class="text-xs text-gray-500">DNS服务器</div>
            <div class="text-sm font-medium text-gray-900">${dnsServer}</div>
        `;
        
        // DNSSEC专用服务器
        const dnssecServerDiv = document.createElement('div');
        dnssecServerDiv.className = 'col-span-1 md:col-span-2 space-y-1';
        dnssecServerDiv.innerHTML = `
            <div class="text-xs text-gray-500">DNSSEC专用服务器</div>
            <div class="text-sm font-medium text-gray-900">${dnssecServer}</div>
        `;
        
        basicInfoGrid.appendChild(dnsFeatures);
        basicInfoGrid.appendChild(trackerDiv);
        basicInfoGrid.appendChild(recordsDiv);
        basicInfoGrid.appendChild(dnsServerDiv);
        basicInfoGrid.appendChild(dnssecServerDiv);
        
        basicInfo.appendChild(basicInfoTitle);
        basicInfo.appendChild(basicInfoGrid);
        
        // 响应细节部分
        const responseDetails = document.createElement('div');
        responseDetails.className = 'space-y-4 pt-4 border-t border-gray-200';
        
        const responseDetailsTitle = document.createElement('h4');
        responseDetailsTitle.className = 'text-sm font-medium text-gray-700 uppercase tracking-wider';
        responseDetailsTitle.textContent = '响应细节';
        
        const responseGrid = document.createElement('div');
        responseGrid.className = 'grid grid-cols-1 md:grid-cols-2 gap-4';
        responseGrid.innerHTML = `
            <div class="space-y-1">
                <div class="text-xs text-gray-500">响应时间</div>
                <div class="text-sm font-medium text-gray-900">${responseTime}毫秒</div>
            </div>
            <div class="space-y-1">
                <div class="text-xs text-gray-500">规则</div>
                <div class="text-sm font-medium text-gray-900">${blockRule}</div>
            </div>
            <div class="space-y-1">
                <div class="text-xs text-gray-500">响应代码</div>
                <div class="text-sm font-medium text-gray-900">${getResponseCodeText(log.responseCode)}</div>
            </div>
            <div class="space-y-1">
                <div class="text-xs text-gray-500">缓存状态</div>
                <div class="text-sm font-medium ${fromCache ? 'text-primary' : 'text-gray-500'}">
                    ${fromCache ? '缓存' : '非缓存'}
                </div>
            </div>
        `;
        
        responseDetails.appendChild(responseDetailsTitle);
        responseDetails.appendChild(responseGrid);
        
        // 客户端详情部分
        const clientDetails = document.createElement('div');
        clientDetails.className = 'space-y-4 pt-4 border-t border-gray-200';
        
        const clientDetailsTitle = document.createElement('h4');
        clientDetailsTitle.className = 'text-sm font-medium text-gray-700 uppercase tracking-wider';
        clientDetailsTitle.textContent = '客户端详情';
        
        const clientIPDiv = document.createElement('div');
        clientIPDiv.className = 'space-y-1';
        clientIPDiv.innerHTML = `
            <div class="text-xs text-gray-500">IP地址</div>
            <div class="text-sm font-medium text-gray-900">${clientIP} (${location})</div>
        `;
        
        clientDetails.appendChild(clientDetailsTitle);
        clientDetails.appendChild(clientIPDiv);
        
        // 组装内容
        content.appendChild(basicInfo);
        content.appendChild(responseDetails);
        content.appendChild(clientDetails);
        
        // 组装模态框
        modalContent.appendChild(header);
        modalContent.appendChild(content);
        modalContainer.appendChild(modalContent);
        
        // 添加到页面
        document.body.appendChild(modalContainer);
        
        // 关闭模态框函数
        function closeModal() {
            modalContainer.classList.add('animate-fade-out');
            modalContent.classList.add('animate-slide-out');
            
            // 等待动画结束后移除元素
            setTimeout(() => {
                document.body.removeChild(modalContainer);
            }, 300);
        }
        
        // 点击外部关闭
        modalContainer.addEventListener('click', (e) => {
            if (e.target === modalContainer) {
                closeModal();
            }
        });
        
        // ESC键关闭
        const handleEsc = (e) => {
            if (e.key === 'Escape') {
                closeModal();
                document.removeEventListener('keydown', handleEsc);
            }
        };
        document.addEventListener('keydown', handleEsc);
        
    } catch (error) {
        console.error('Error showing log detail modal:', error);
    }
}