skyffire hace 6 meses
padre
commit
a66cfa2b6e
Se han modificado 1 ficheros con 124 adiciones y 52 borrados
  1. 124 52
      templates/index.html

+ 124 - 52
templates/index.html

@@ -4,7 +4,9 @@
     <meta charset="UTF-8">
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <title>价格与价差监控 MUBARAK/USDT</title>
     <title>价格与价差监控 MUBARAK/USDT</title>
-    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <!-- 引入 Chart.js -->
+    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
+    <!-- 引入 chartjs-plugin-zoom 插件 -->
+    <script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom@2.0.1/dist/chartjs-plugin-zoom.min.js"></script>
     <style>
     <style>
         body { font-family: Arial, sans-serif; margin: 20px; background-color: #f4f4f4; color: #333; }
         body { font-family: Arial, sans-serif; margin: 20px; background-color: #f4f4f4; color: #333; }
         .container { background-color: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 0 10px rgba(0,0,0,0.1); margin-bottom: 20px; }
         .container { background-color: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 0 10px rgba(0,0,0,0.1); margin-bottom: 20px; }
@@ -14,22 +16,52 @@
         th { background-color: #e9e9e9; }
         th { background-color: #e9e9e9; }
         .price-up { color: green; }
         .price-up { color: green; }
         .price-down { color: red; }
         .price-down { color: red; }
-        .error-message { color: #c00; font-style: italic; font-size: 0.9em; } /* Renamed from .error */
+        .error-message { color: #c00; font-style: italic; font-size: 0.9em; }
         .status-cell { /* For status messages, not just errors */ }
         .status-cell { /* For status messages, not just errors */ }
         .timestamp { font-size: 0.9em; color: #666; text-align: right; margin-top: 15px; }
         .timestamp { font-size: 0.9em; color: #666; text-align: right; margin-top: 15px; }
         .chart-container {
         .chart-container {
             position: relative;
             position: relative;
-            height: 40vh; /* Responsive height */
-            width: 80vw;  /* Responsive width */
-            margin: auto; /* Center the chart */
-            margin-bottom: 30px;
+            height: 45vh; /* Slightly increased height for better zoom interaction */
+            width: 90vw;
+            margin: auto;
+            margin-bottom: 10px; /* Reduced bottom margin */
+        }
+        .controls-container { /* Container for buttons */
+            text-align: center;
+            margin-bottom: 20px;
+            margin-top: 5px;
+        }
+        .control-button {
+            background-color: #007bff;
+            color: white;
+            border: none;
+            padding: 8px 15px;
+            text-align: center;
+            text-decoration: none;
+            display: inline-block;
+            font-size: 14px;
+            border-radius: 5px;
+            cursor: pointer;
+            margin: 0 5px;
+        }
+        .control-button:hover {
+            background-color: #0056b3;
+        }
+        .pause-button-active {
+            background-color: #ffc107; /* Yellow when active (paused) */
+            color: #333;
+        }
+        .pause-button-active:hover {
+            background-color: #e0a800;
         }
         }
     </style>
     </style>
 </head>
 </head>
 <body>
 <body>
     <div class="container">
     <div class="container">
         <h1>MUBARAK/USDT 价格监控</h1>
         <h1>MUBARAK/USDT 价格监控</h1>
-
+        <div class="controls-container">
+            <button id="pause-resume-button" class="control-button">暂停刷新</button>
+        </div>
         <table>
         <table>
             <thead>
             <thead>
                 <tr>
                 <tr>
@@ -63,6 +95,9 @@
         <div class="chart-container">
         <div class="chart-container">
             <canvas id="priceHistoryChart"></canvas>
             <canvas id="priceHistoryChart"></canvas>
         </div>
         </div>
+        <div class="controls-container">
+            <button id="reset-price-zoom-button" class="control-button">重置缩放</button>
+        </div>
     </div>
     </div>
 
 
     <div class="container">
     <div class="container">
@@ -70,12 +105,20 @@
         <div class="chart-container">
         <div class="chart-container">
             <canvas id="diffHistoryChart"></canvas>
             <canvas id="diffHistoryChart"></canvas>
         </div>
         </div>
+        <div class="controls-container">
+            <button id="reset-diff-zoom-button" class="control-button">重置缩放</button>
+        </div>
     </div>
     </div>
 
 
     <script>
     <script>
         let priceChartInstance = null;
         let priceChartInstance = null;
         let diffChartInstance = null;
         let diffChartInstance = null;
-        const MAX_CHART_POINTS = 60; // 与后端 MAX_HISTORY_POINTS 对应或稍小
+        // const MAX_CHART_POINTS = 60; // MAX_HISTORY_POINTS is defined in backend
+
+        let dataUpdateIntervalID = null;
+        let isPaused = false;
+        const REFRESH_INTERVAL_MS = 5000; // 5 seconds
+        const pauseResumeButton = document.getElementById('pause-resume-button');
 
 
         function formatPrice(priceStr) {
         function formatPrice(priceStr) {
             if (priceStr === null || priceStr === undefined || priceStr === "N/A") return "N/A";
             if (priceStr === null || priceStr === undefined || priceStr === "N/A") return "N/A";
@@ -87,14 +130,14 @@
             return new Chart(ctx, {
             return new Chart(ctx, {
                 type: 'line',
                 type: 'line',
                 data: {
                 data: {
-                    labels: initialLabels, // 时间戳
-                    datasets: datasetsConfig // e.g., [{ label: 'OpenOcean', data: [], borderColor: 'rgb(75, 192, 192)', tension: 0.1, fill: false }, ...]
+                    labels: initialLabels,
+                    datasets: datasetsConfig
                 },
                 },
                 options: {
                 options: {
                     responsive: true,
                     responsive: true,
                     maintainAspectRatio: false,
                     maintainAspectRatio: false,
                     animation: {
                     animation: {
-                        duration: 200 // 平滑过渡
+                        duration: 150 // slightly faster animation
                     },
                     },
                     scales: {
                     scales: {
                         x: {
                         x: {
@@ -102,17 +145,35 @@
                         },
                         },
                         y: {
                         y: {
                             title: { display: true, text: chartType === 'price' ? '价格 (USDT)' : '价差 (%)' },
                             title: { display: true, text: chartType === 'price' ? '价格 (USDT)' : '价差 (%)' },
-                            beginAtZero: chartType === 'diff' ? false : undefined // 价差可能为负
+                            beginAtZero: chartType === 'diff' ? false : undefined
                         }
                         }
                     },
                     },
                     plugins: {
                     plugins: {
                         legend: { position: 'top' },
                         legend: { position: 'top' },
-                        title: { display: true, text: titleText }
+                        title: { display: true, text: titleText },
+                        zoom: { // Zoom plugin configuration
+                            pan: {
+                                enabled: true,
+                                mode: 'xy', // Allow panning in x and y directions
+                                threshold: 5, // Pixels before pan starts
+                            },
+                            zoom: {
+                                wheel: {
+                                    enabled: true, // Enable zooming with mouse wheel
+                                },
+                                pinch: {
+                                    enabled: true // Enable zooming with pinch gesture (touch devices)
+                                },
+                                drag: { // Enable drag-to-zoom (box select)
+                                    enabled: true,
+                                    backgroundColor: 'rgba(0,123,255,0.25)'
+                                },
+                                mode: 'xy', // Allow zooming in x and y directions
+                            }
+                        }
                     },
                     },
                     elements: {
                     elements: {
-                        point:{
-                            radius: 2 // Smaller points
-                        }
+                        point:{ radius: 2 }
                     }
                     }
                 }
                 }
             });
             });
@@ -123,14 +184,16 @@
             newDatasetsData.forEach((datasetData, index) => {
             newDatasetsData.forEach((datasetData, index) => {
                 chartInstance.data.datasets[index].data = datasetData;
                 chartInstance.data.datasets[index].data = datasetData;
             });
             });
-            chartInstance.update('quiet'); // 'quiet' to prevent re-animation on every update
+            chartInstance.update('quiet');
         }
         }
 
 
         function updateDisplayAndCharts() {
         function updateDisplayAndCharts() {
+            // If paused by user, don't fetch new data unless it's an initial call or manual resume
+            // This check is implicitly handled by not having setInterval running when paused.
+
             fetch('/data')
             fetch('/data')
                 .then(response => response.json())
                 .then(response => response.json())
                 .then(data => {
                 .then(data => {
-                    // --- 更新表格数据 ---
                     const current = data.current;
                     const current = data.current;
                     document.getElementById('oo-price').textContent = formatPrice(current.oo_price);
                     document.getElementById('oo-price').textContent = formatPrice(current.oo_price);
                     document.getElementById('gate-price').textContent = formatPrice(current.gate_price);
                     document.getElementById('gate-price').textContent = formatPrice(current.gate_price);
@@ -139,7 +202,7 @@
                     if (current.difference_percentage && current.difference_percentage !== "N/A") {
                     if (current.difference_percentage && current.difference_percentage !== "N/A") {
                         diffEl.textContent = current.difference_percentage;
                         diffEl.textContent = current.difference_percentage;
                         const diffValue = parseFloat(current.difference_percentage.replace('%', ''));
                         const diffValue = parseFloat(current.difference_percentage.replace('%', ''));
-                        if (!isNaN(diffValue)) { // Ensure it's a number before comparing
+                        if (!isNaN(diffValue)) {
                            if (diffValue > 0) diffEl.className = 'price-up';
                            if (diffValue > 0) diffEl.className = 'price-up';
                            else if (diffValue < 0) diffEl.className = 'price-down';
                            else if (diffValue < 0) diffEl.className = 'price-down';
                            else diffEl.className = '';
                            else diffEl.className = '';
@@ -161,26 +224,12 @@
 
 
                     document.getElementById('last-updated').textContent = current.last_updated || "N/A";
                     document.getElementById('last-updated').textContent = current.last_updated || "N/A";
 
 
-                    // --- 初始化或更新图表 ---
                     const history = data.history;
                     const history = data.history;
 
 
-                    // 价格历史图表
                     const priceCtx = document.getElementById('priceHistoryChart').getContext('2d');
                     const priceCtx = document.getElementById('priceHistoryChart').getContext('2d');
                     const priceDatasets = [
                     const priceDatasets = [
-                        {
-                            label: 'OpenOcean',
-                            data: history.prices.oo,
-                            borderColor: 'rgb(75, 192, 192)',
-                            tension: 0.1,
-                            fill: false
-                        },
-                        {
-                            label: 'Gate.io',
-                            data: history.prices.gate,
-                            borderColor: 'rgb(255, 99, 132)',
-                            tension: 0.1,
-                            fill: false
-                        }
+                        { label: 'OpenOcean', data: history.prices.oo, borderColor: 'rgb(75, 192, 192)', tension: 0.1, fill: false },
+                        { label: 'Gate.io', data: history.prices.gate, borderColor: 'rgb(255, 99, 132)', tension: 0.1, fill: false }
                     ];
                     ];
                     if (!priceChartInstance) {
                     if (!priceChartInstance) {
                         priceChartInstance = initializeChart(priceCtx, 'price', priceDatasets, history.prices.labels, '价格历史 (MUBARAK/USDT)');
                         priceChartInstance = initializeChart(priceCtx, 'price', priceDatasets, history.prices.labels, '价格历史 (MUBARAK/USDT)');
@@ -188,37 +237,60 @@
                         updateChartData(priceChartInstance, history.prices.labels, [history.prices.oo, history.prices.gate]);
                         updateChartData(priceChartInstance, history.prices.labels, [history.prices.oo, history.prices.gate]);
                     }
                     }
 
 
-                    // 价差历史图表
                     const diffCtx = document.getElementById('diffHistoryChart').getContext('2d');
                     const diffCtx = document.getElementById('diffHistoryChart').getContext('2d');
-                    const diffDatasets = [
-                        {
-                            label: '价差百分比 (OO vs Gate)',
-                            data: history.difference.values,
-                            borderColor: 'rgb(54, 162, 235)',
-                            tension: 0.1,
-                            fill: false
-                        }
-                    ];
-                     if (!diffChartInstance) {
+                    const diffDatasets = [{ label: '价差百分比 (OO vs Gate)', data: history.difference.values, borderColor: 'rgb(54, 162, 235)', tension: 0.1, fill: false }];
+                    if (!diffChartInstance) {
                         diffChartInstance = initializeChart(diffCtx, 'diff', diffDatasets, history.difference.labels, '价差百分比历史');
                         diffChartInstance = initializeChart(diffCtx, 'diff', diffDatasets, history.difference.labels, '价差百分比历史');
                     } else {
                     } else {
                          updateChartData(diffChartInstance, history.difference.labels, [history.difference.values]);
                          updateChartData(diffChartInstance, history.difference.labels, [history.difference.values]);
                     }
                     }
-
                 })
                 })
                 .catch(error => {
                 .catch(error => {
                     console.error('Error fetching data:', error);
                     console.error('Error fetching data:', error);
-                    // Handle display errors if fetch fails
                     document.getElementById('oo-price').textContent = '错误';
                     document.getElementById('oo-price').textContent = '错误';
                     document.getElementById('gate-price').textContent = '错误';
                     document.getElementById('gate-price').textContent = '错误';
                     document.getElementById('diff-percentage').textContent = '无法获取数据';
                     document.getElementById('diff-percentage').textContent = '无法获取数据';
                 });
                 });
         }
         }
 
 
-        // 首次加载数据并初始化图表
+        function togglePauseResume() {
+            isPaused = !isPaused;
+            if (isPaused) {
+                clearInterval(dataUpdateIntervalID);
+                dataUpdateIntervalID = null; // Clear the ID
+                pauseResumeButton.textContent = '继续刷新';
+                pauseResumeButton.classList.add('pause-button-active');
+                console.log("Data refresh PAUSED");
+            } else {
+                pauseResumeButton.textContent = '暂停刷新';
+                pauseResumeButton.classList.remove('pause-button-active');
+                updateDisplayAndCharts(); // Refresh immediately upon resuming
+                dataUpdateIntervalID = setInterval(updateDisplayAndCharts, REFRESH_INTERVAL_MS);
+                console.log("Data refresh RESUMED");
+            }
+        }
+
+        // --- Event Listeners ---
+        pauseResumeButton.addEventListener('click', togglePauseResume);
+
+        document.getElementById('reset-price-zoom-button').addEventListener('click', () => {
+            if (priceChartInstance) {
+                priceChartInstance.resetZoom();
+            }
+        });
+
+        document.getElementById('reset-diff-zoom-button').addEventListener('click', () => {
+            if (diffChartInstance) {
+                diffChartInstance.resetZoom();
+            }
+        });
+
+        // Initial data load and start interval
         updateDisplayAndCharts();
         updateDisplayAndCharts();
-        // 每5秒更新一次数据和图表 (与后端更新频率匹配)
-        setInterval(updateDisplayAndCharts, 5000);
+        if (!isPaused) { // Start interval only if not initially paused (though it's false by default)
+            dataUpdateIntervalID = setInterval(updateDisplayAndCharts, REFRESH_INTERVAL_MS);
+        }
+
     </script>
     </script>
 </body>
 </body>
-</html>
+</html>