From 8ee1d944719b1d5949a201dd8db21a4baf84a53a Mon Sep 17 00:00:00 2001 From: Alex Yang Date: Thu, 27 Nov 2025 15:51:55 +0800 Subject: [PATCH] =?UTF-8?q?web=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...DNS请求趋势图表展开后影响主页面图表的问题.md | 18 ++ .../修复DNS请求趋势图表展开后的响应式问题.md | 15 ++ ...DNS请求趋势图表展开后超出显示范围的问题.md | 21 ++ .../调整DNS趋势图表默认显示和浮窗独立性.md | 44 +++ static/index.html | 2 +- static/js/dashboard.js | 255 +++--------------- 6 files changed, 132 insertions(+), 223 deletions(-) create mode 100644 .trae/documents/修复DNS请求趋势图表展开后影响主页面图表的问题.md create mode 100644 .trae/documents/修复DNS请求趋势图表展开后的响应式问题.md create mode 100644 .trae/documents/修复DNS请求趋势图表展开后超出显示范围的问题.md create mode 100644 .trae/documents/调整DNS趋势图表默认显示和浮窗独立性.md diff --git a/.trae/documents/修复DNS请求趋势图表展开后影响主页面图表的问题.md b/.trae/documents/修复DNS请求趋势图表展开后影响主页面图表的问题.md new file mode 100644 index 0000000..e6d76eb --- /dev/null +++ b/.trae/documents/修复DNS请求趋势图表展开后影响主页面图表的问题.md @@ -0,0 +1,18 @@ +## 问题分析 +当前实现中,详细图表(浮窗)的时间范围切换会影响到主页面的图表显示,这是因为它们共享了全局变量`currentTimeRange`和`isMixedView`。当用户在浮窗内切换时间范围时,这些全局变量会被修改,导致主页面的图表也随之改变。 + +## 解决方案 +1. 为详细图表创建独立的变量,用于存储其时间范围和混合视图状态 +2. 修改`initDetailedTimeRangeToggle`函数,使其使用这些独立的变量,而不是全局变量 +3. 修改`drawDetailedDNSRequestsChart`函数,使用独立的变量来控制图表显示 +4. 确保主图表默认显示混合视图 + +## 修复步骤 +1. 在`dashboard.js`文件中添加详细图表专用的全局变量 +2. 修改`initDetailedTimeRangeToggle`函数,使用详细图表专用变量 +3. 修改`drawDetailedDNSRequestsChart`函数,使用详细图表专用变量 +4. 确保主图表默认显示混合视图 +5. 测试修复效果,确保浮窗内的时间范围切换不会影响主页面图表 + +## 预期效果 +修复后,DNS请求趋势图表默认显示混合内容视图不变,当用户点击展开按钮查看详细数据时,浮窗内的时间范围切换不会影响到主页面的图表内容,提供更好的用户体验。 \ No newline at end of file diff --git a/.trae/documents/修复DNS请求趋势图表展开后的响应式问题.md b/.trae/documents/修复DNS请求趋势图表展开后的响应式问题.md new file mode 100644 index 0000000..c86530f --- /dev/null +++ b/.trae/documents/修复DNS请求趋势图表展开后的响应式问题.md @@ -0,0 +1,15 @@ +## 问题分析 +DNS请求趋势图表展开后不能随页面放大缩小自动调整大小。通过代码分析,发现`window.addEventListener('resize')`事件监听器只处理了侧边栏的显示/隐藏,没有处理图表的调整大小。 + +## 解决方案 +1. 修改`window.addEventListener('resize')`事件监听器,添加对所有图表(包括详细图表)的更新调用 +2. 确保在模态框显示时,图表能够正确响应窗口大小变化 + +## 修复步骤 +1. 打开`/root/dns/static/js/dashboard.js`文件 +2. 找到`window.addEventListener('resize')`事件监听器 +3. 修改该事件监听器,添加对`dnsRequestsChart`和`detailedDnsRequestsChart`的更新调用 +4. 确保图表实例存在时才调用update方法 + +## 预期效果 +修复后,当用户展开DNS请求趋势图表并调整浏览器窗口大小时,图表会自动调整大小以适应新的窗口尺寸。 \ No newline at end of file diff --git a/.trae/documents/修复DNS请求趋势图表展开后超出显示范围的问题.md b/.trae/documents/修复DNS请求趋势图表展开后超出显示范围的问题.md new file mode 100644 index 0000000..b0a7eec --- /dev/null +++ b/.trae/documents/修复DNS请求趋势图表展开后超出显示范围的问题.md @@ -0,0 +1,21 @@ +## 问题分析 +展开图表超出了显示范围,没有按照展开浮窗大小显示内容。通过代码分析,发现以下问题: + +1. 图表容器使用了固定高度 `h-[600px]`,这可能导致在某些屏幕尺寸下图表超出显示范围 +2. 浮窗容器设置了 `max-h-[90vh]`,但图表容器的固定高度可能超过这个限制 +3. 当图表初始化时,可能没有正确计算容器的实际可用空间 + +## 解决方案 +1. 修改图表容器的高度设置,使其更灵活,能够适应不同屏幕尺寸 +2. 确保图表容器的高度不超过浮窗的最大高度限制 +3. 在图表显示时,确保正确计算容器大小并更新图表 + +## 修复步骤 +1. 打开 `index.html` 文件,修改图表容器的高度设置 +2. 将固定高度 `h-[600px]` 改为相对高度或最大高度 +3. 确保图表容器的高度能够适应浮窗的可用空间 +4. 在 `drawDetailedDNSRequestsChart` 函数中,添加对图表容器大小的检查和调整 +5. 确保在图表显示时,正确计算容器大小并更新图表 + +## 预期效果 +修复后,当用户展开DNS请求趋势图表时,图表会根据浮窗的可用空间自动调整大小,不会超出显示范围,提供更好的用户体验。 \ No newline at end of file diff --git a/.trae/documents/调整DNS趋势图表默认显示和浮窗独立性.md b/.trae/documents/调整DNS趋势图表默认显示和浮窗独立性.md new file mode 100644 index 0000000..0062ca5 --- /dev/null +++ b/.trae/documents/调整DNS趋势图表默认显示和浮窗独立性.md @@ -0,0 +1,44 @@ +# 调整DNS趋势图表默认显示和浮窗独立性 + +## 问题分析 +1. **DNS趋势图表默认显示**:当前代码中`isMixedView`变量默认设置为`true`,但在`initTimeRangeToggle`函数中,默认选中第一个按钮后会将`isMixedView`设置为`false`,导致实际默认显示的是24小时视图而非混合视图。 +2. **浮窗图表独立性**:当前代码中详细图表(浮窗)已有独立变量`detailedCurrentTimeRange`和`detailedIsMixedView`,但需要确保初始化时正确设置,避免与主图表冲突。 + +## 实现计划 + +### 1. 修改DNS趋势图表默认显示为混合内容 +- **文件**:`/root/dns/static/js/dashboard.js` +- **函数**:`initTimeRangeToggle` +- **修改点**: + - 在函数末尾,默认选中第一个按钮后,将`isMixedView`设置为`true` + - 将`currentTimeRange`设置为`'mixed'` + - 更新按钮样式,添加混合视图标记 + +### 2. 确保浮窗图表初始化正确 +- **文件**:`/root/dns/static/js/dashboard.js` +- **函数**:`initDetailedTimeRangeToggle` +- **修改点**: + - 确保初始化时`detailedIsMixedView`默认值与主图表保持一致 + - 确保点击浮窗中的时间范围按钮时,只修改详细图表的变量,不影响主图表 + +### 3. 验证功能完整性 +- 检查`drawDNSRequestsChart`函数,确保它使用主图表变量 +- 检查`drawDetailedDNSRequestsChart`函数,确保它使用详细图表变量 +- 确保两个函数的实现逻辑一致,但使用不同的变量 + +## 预期效果 +1. DNS趋势图表默认显示混合内容(24小时、7天、30天数据同时显示) +2. 展开浮窗后,切换浮窗中的时间范围或视图模式,不会影响主页图表的显示 +3. 主页图表和浮窗图表可以独立显示不同的时间范围和视图模式 + +## 实现步骤 +1. 修改`initTimeRangeToggle`函数,设置默认混合视图 +2. 优化`initDetailedTimeRangeToggle`函数,确保浮窗图表初始化正确 +3. 验证两个图表函数的变量使用是否正确 +4. 测试功能完整性 + +## 代码修改点 +1. **第1250-1256行**:修改默认按钮选中逻辑,添加混合视图设置 +2. **第1475-1507行**:优化浮窗图表时间范围切换逻辑 +3. **第1716-1912行**:确保主图表函数使用正确变量 +4. **第1509-1714行**:确保浮窗图表函数使用正确变量 \ No newline at end of file diff --git a/static/index.html b/static/index.html index 94ea7cf..116d54c 100644 --- a/static/index.html +++ b/static/index.html @@ -518,7 +518,7 @@
-
+
diff --git a/static/js/dashboard.js b/static/js/dashboard.js index 53ebee2..3b713e9 100644 --- a/static/js/dashboard.js +++ b/static/js/dashboard.js @@ -1106,9 +1106,13 @@ function updateTopDomainsTable(domains) { // 当前选中的时间范围 let currentTimeRange = '24h'; // 默认为24小时 -let isMixedView = false; // 是否为混合视图 +let isMixedView = true; // 是否为混合视图 - 默认显示混合视图 let lastSelectedIndex = 0; // 最后选中的按钮索引 +// 详细图表专用变量 +let detailedCurrentTimeRange = '24h'; // 详细图表当前时间范围 +let detailedIsMixedView = false; // 详细图表是否为混合视图 + // 初始化时间范围切换 function initTimeRangeToggle() { console.log('初始化时间范围切换'); @@ -1252,218 +1256,7 @@ function initTimeRangeToggle() { } } -// 初始化展开按钮功能 -function initExpandButton() { - const expandBtn = document.getElementById('expand-chart-btn'); - const chartModal = document.getElementById('chart-modal'); - const closeBtn = document.getElementById('close-modal-btn'); - - if (!expandBtn || !chartModal || !closeBtn) { - console.error('未找到展开按钮或浮窗元素'); - return; - } - - // 展开按钮点击事件 - expandBtn.addEventListener('click', () => { - console.log('展开按钮被点击'); - chartModal.classList.remove('hidden'); - // 初始化详细图表 - drawDetailedDNSRequestsChart(); - }); - - // 关闭按钮点击事件 - closeBtn.addEventListener('click', () => { - console.log('关闭浮窗'); - chartModal.classList.add('hidden'); - }); - - // 点击浮窗外部关闭 - chartModal.addEventListener('click', (event) => { - if (event.target === chartModal) { - chartModal.classList.add('hidden'); - } - }); - - // 初始化详细图表的时间范围切换 - initDetailedTimeRangeToggle(); -} - -// 初始化详细图表的时间范围切换 -function initDetailedTimeRangeToggle() { - const timeRangeBtns = document.querySelectorAll('.time-range-btn[data-range]'); - - if (!timeRangeBtns.length) { - console.warn('未找到详细图表的时间范围按钮'); - return; - } - - // 详细图表的当前时间范围 - let detailedCurrentTimeRange = '24h'; - let detailedIsMixedView = false; - - // 为所有时间范围按钮添加点击事件 - timeRangeBtns.forEach(btn => { - btn.addEventListener('click', () => { - const range = btn.getAttribute('data-range'); - - if (range === 'mixed') { - detailedIsMixedView = !detailedIsMixedView; - } else { - detailedCurrentTimeRange = range; - detailedIsMixedView = false; - } - - // 更新按钮样式 - updateTimeRangeButtonStyles(timeRangeBtns, range, detailedIsMixedView); - - // 重新绘制详细图表 - drawDetailedDNSRequestsChart(detailedCurrentTimeRange, detailedIsMixedView); - }); - }); -} - -// 更新时间范围按钮样式 -function updateTimeRangeButtonStyles(buttons, activeRange, isMixedView) { - buttons.forEach(btn => { - const btnRange = btn.getAttribute('data-range'); - - if (btnRange === activeRange && (btnRange !== 'mixed' || isMixedView)) { - btn.classList.add('bg-primary', 'text-white'); - btn.classList.remove('bg-gray-200', 'text-gray-700'); - } else { - btn.classList.remove('bg-primary', 'text-white'); - btn.classList.add('bg-gray-200', 'text-gray-700'); - } - }); -} - -// 绘制详细DNS请求图表 -function drawDetailedDNSRequestsChart(timeRange = '24h', isMixedView = false) { - const chartElement = document.getElementById('detailed-dns-requests-chart'); - if (!chartElement) { - console.error('未找到详细DNS请求图表元素'); - return; - } - - const chartContext = chartElement.getContext('2d'); - - // 这里可以复用或修改现有的drawDNSRequestsChart函数的逻辑 - // 为详细图表使用与原始图表相同的数据获取逻辑 - let apiFunction; - let count; - - if (isMixedView) { - // 混合视图 - 不同时间范围的数据 - apiFunction = () => Promise.resolve({ - labels: ['0h', '6h', '12h', '18h', '24h', '48h', '72h', '96h', '120h', '144h', '168h'], - data: generateMockData(11, 1000, 5000) - }); - } else { - // 普通视图 - 基于时间范围 - if (timeRange === '24h') { - count = 24; - apiFunction = () => Promise.resolve({ - labels: generateTimeLabels(count), - data: generateMockData(count, 100, 500) - }); - } else if (timeRange === '7d') { - count = 7; - apiFunction = () => Promise.resolve({ - labels: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'], - data: generateMockData(count, 1000, 5000) - }); - } else if (timeRange === '30d') { - count = 30; - apiFunction = () => Promise.resolve({ - labels: Array(count).fill(''), - data: generateMockData(count, 10000, 50000) - }); - } - } - - // 获取数据并绘制图表 - if (apiFunction) { - apiFunction().then(data => { - // 创建或更新图表 - if (detailedDnsRequestsChart) { - detailedDnsRequestsChart.data.labels = data.labels; - detailedDnsRequestsChart.data.datasets = [{ - label: 'DNS请求数量', - data: data.data, - borderColor: '#3b82f6', - backgroundColor: 'rgba(59, 130, 246, 0.1)', - tension: 0.4, - fill: true - }]; - detailedDnsRequestsChart.options.plugins.legend.display = false; - // 使用平滑过渡动画更新图表 - detailedDnsRequestsChart.update({ - duration: 800, - easing: 'easeInOutQuart' - }); - } else { - detailedDnsRequestsChart = new Chart(chartContext, { - type: 'line', - data: { - labels: data.labels, - datasets: [{ - label: 'DNS请求数量', - data: data.data, - borderColor: '#3b82f6', - backgroundColor: 'rgba(59, 130, 246, 0.1)', - tension: 0.4, - fill: true - }] - }, - options: { - responsive: true, - maintainAspectRatio: false, - animation: { - duration: 800, - easing: 'easeInOutQuart' - }, - plugins: { - legend: { - display: false - }, - tooltip: { - mode: 'index', - intersect: false - } - }, - scales: { - y: { - beginAtZero: true, - grid: { - color: 'rgba(0, 0, 0, 0.1)' - } - }, - x: { - grid: { - display: false - } - } - } - } - }); - } - }).catch(error => { - console.error('绘制详细DNS请求图表失败:', error); - // 错误处理:使用空数据 - const count = timeRange === '24h' ? 24 : (timeRange === '7d' ? 7 : 30); - const emptyData = { - labels: Array(count).fill(''), - data: Array(count).fill(0) - }; - - if (detailedDnsRequestsChart) { - detailedDnsRequestsChart.data.labels = emptyData.labels; - detailedDnsRequestsChart.data.datasets[0].data = emptyData.data; - detailedDnsRequestsChart.update(); - } - }); - } -} +// 注意:这个函数已被后面的实现覆盖,请使用后面的drawDetailedDNSRequestsChart函数 // 初始化图表 function initCharts() { @@ -1642,6 +1435,13 @@ function initExpandButton() { // 初始化浮窗中的时间范围切换 initDetailedTimeRangeToggle(); + + // 延迟更新图表大小,确保容器大小已计算 + setTimeout(() => { + if (detailedDnsRequestsChart) { + detailedDnsRequestsChart.resize(); + } + }, 100); }); // 关闭按钮点击事件 @@ -1673,7 +1473,9 @@ function initExpandButton() { // 初始化详细图表的时间范围切换 function initDetailedTimeRangeToggle() { - const detailedTimeRangeButtons = document.querySelectorAll('.time-range-btn'); + // 只选择图表模态框内的时间范围按钮,避免与主视图冲突 + const chartModal = document.getElementById('chart-modal'); + const detailedTimeRangeButtons = chartModal ? chartModal.querySelectorAll('.time-range-btn') : []; console.log('初始化详细图表时间范围切换,找到按钮数量:', detailedTimeRangeButtons.length); @@ -1696,9 +1498,9 @@ function initDetailedTimeRangeToggle() { } }); - // 更新详细图表 - currentTimeRange = timeRange; - isMixedView = isMixedMode; + // 更新详细图表专用变量 + detailedCurrentTimeRange = timeRange; + detailedIsMixedView = isMixedMode; drawDetailedDNSRequestsChart(); }); }); @@ -1706,7 +1508,7 @@ function initDetailedTimeRangeToggle() { // 绘制详细的DNS请求趋势图表 function drawDetailedDNSRequestsChart() { - console.log('绘制详细DNS请求趋势图表,时间范围:', currentTimeRange, '混合视图:', isMixedView); + console.log('绘制详细DNS请求趋势图表,时间范围:', detailedCurrentTimeRange, '混合视图:', detailedIsMixedView); const ctx = document.getElementById('detailed-dns-requests-chart'); if (!ctx) { @@ -1724,7 +1526,7 @@ function drawDetailedDNSRequestsChart() { ]; // 检查是否为混合视图 - if (isMixedView || currentTimeRange === 'mixed') { + if (detailedIsMixedView || detailedCurrentTimeRange === 'mixed') { console.log('渲染混合视图详细图表'); // 显示图例 @@ -1808,9 +1610,9 @@ function drawDetailedDNSRequestsChart() { }); } else { // 普通视图 - // 根据当前时间范围选择API函数 + // 根据详细视图时间范围选择API函数 let apiFunction; - switch (currentTimeRange) { + switch (detailedCurrentTimeRange) { case '7d': apiFunction = (api && api.getDailyStats) || (() => Promise.resolve({ labels: [], data: [] })); break; @@ -1896,7 +1698,7 @@ function drawDetailedDNSRequestsChart() { }).catch(error => { console.error('绘制详细DNS请求图表失败:', error); // 错误处理:使用空数据 - const count = currentTimeRange === '24h' ? 24 : (currentTimeRange === '7d' ? 7 : 30); + const count = detailedCurrentTimeRange === '24h' ? 24 : (detailedCurrentTimeRange === '7d' ? 7 : 30); const emptyData = { labels: Array(count).fill(''), data: Array(count).fill(0) @@ -2731,6 +2533,15 @@ function handleResponsive() { if (window.innerWidth >= 1024) { sidebar.classList.remove('-translate-x-full'); } + + // 更新图表大小 + if (dnsRequestsChart) { + dnsRequestsChart.update(); + } + + if (detailedDnsRequestsChart) { + detailedDnsRequestsChart.update(); + } }); }