Browse Source

feat(dashboard): 重构界面布局并添加侧边栏币对列表

- 使用flex布局重构整体页面结构
- 添加侧边栏显示币对列表,替换原有的下拉选择框
- 优化移动端响应式布局
- 添加币对选中状态样式
skyfffire 1 tuần trước cách đây
mục cha
commit
17c7e84eee
1 tập tin đã thay đổi với 158 bổ sung55 xóa
  1. 158 55
      src/dashboard/static/index.html

+ 158 - 55
src/dashboard/static/index.html

@@ -27,6 +27,9 @@
             border-radius: 0;
             box-shadow: none;
             overflow: hidden;
+            display: flex;
+            flex-direction: column;
+            height: 100vh;
         }
 
         .header {
@@ -47,10 +50,75 @@
             opacity: 0.9;
         }
 
+        .main-content {
+            display: flex;
+            flex: 1;
+            overflow: hidden;
+        }
+
+        .sidebar {
+            width: 250px;
+            background: #f8f9fa;
+            border-right: 1px solid #e9ecef;
+            overflow-y: auto;
+            flex-shrink: 0;
+        }
+
+        .sidebar-header {
+            padding: 20px;
+            background: #e9ecef;
+            border-bottom: 1px solid #dee2e6;
+        }
+
+        .sidebar-header h3 {
+            margin: 0;
+            font-size: 1.1em;
+            color: #495057;
+            font-weight: 600;
+        }
+
+        .symbol-list {
+            padding: 0;
+            margin: 0;
+            list-style: none;
+        }
+
+        .symbol-item {
+            padding: 12px 20px;
+            cursor: pointer;
+            border-bottom: 1px solid #e9ecef;
+            transition: all 0.2s ease;
+            color: #495057;
+            font-weight: 500;
+        }
+
+        .symbol-item:hover {
+            background: #e9ecef;
+            color: #2c3e50;
+        }
+
+        .symbol-item.active {
+            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+            color: white;
+            font-weight: 600;
+        }
+
+        .symbol-item.active:hover {
+            background: linear-gradient(135deg, #5a6fd8 0%, #6a4190 100%);
+        }
+
+        .content-area {
+            flex: 1;
+            display: flex;
+            flex-direction: column;
+            overflow: hidden;
+        }
+
         .controls {
-            padding: 30px;
+            padding: 20px 30px;
             background: #f8f9fa;
             border-bottom: 1px solid #e9ecef;
+            flex-shrink: 0;
         }
 
         .control-group {
@@ -58,6 +126,7 @@
             gap: 20px;
             align-items: center;
             flex-wrap: wrap;
+            justify-content: flex-end;
         }
 
         .control-item {
@@ -113,6 +182,8 @@
 
         .content {
             padding: 30px;
+            flex: 1;
+            overflow-y: auto;
         }
 
         .stats-grid {
@@ -209,9 +280,21 @@
         }
 
         @media (max-width: 768px) {
+            .main-content {
+                flex-direction: column;
+            }
+
+            .sidebar {
+                width: 100%;
+                height: 200px;
+                border-right: none;
+                border-bottom: 1px solid #e9ecef;
+            }
+
             .control-group {
                 flex-direction: column;
                 align-items: stretch;
+                justify-content: center;
             }
 
             .stats-grid {
@@ -231,49 +314,56 @@
             <p>Lighter vs Binance 价格差异分析</p>
         </div>
 
-        <div class="controls">
-            <div class="control-group">
-            <div class="control-item">
-                <label for="symbolSelect">选择币对:</label>
-                <select id="symbolSelect">
-                    <option value="">请选择币对...</option>
-                </select>
+        <div class="main-content">
+            <div class="sidebar">
+                <div class="sidebar-header">
+                    <h3>选择币对</h3>
+                </div>
+                <ul id="symbolList" class="symbol-list">
+                    <li class="symbol-item loading-item">正在加载币对...</li>
+                </ul>
             </div>
-            <button class="btn" onclick="loadData()">刷新数据</button>
-        </div>
-        </div>
 
-        <div class="content">
-            <div id="loading" class="loading">请选择币对以查看数据</div>
-            <div id="error" class="error" style="display: none;"></div>
-            
-            <!-- 数据卡片已移除 -->
-
-            <div id="chartsContainer" style="display: none;">
-                <!-- 24小时缩略图 -->
-                <div class="chart-container">
-                    <h3>24小时价格缩略图 (点击查看详情)</h3>
-                    <div class="chart-wrapper" style="height: 200px;">
-                        <canvas id="thumbnailChart"></canvas>
+            <div class="content-area">
+                <div class="controls">
+                    <div class="control-group">
+                        <button class="btn" onclick="loadData()">刷新数据</button>
                     </div>
                 </div>
 
-                <div class="chart-container">
-                    <h3>价格对比图</h3>
-                    <div class="chart-wrapper">
-                        <canvas id="priceChart"></canvas>
+                <div class="content">
+                    <div id="loading" class="loading">请选择币对以查看数据</div>
+                    <div id="error" class="error" style="display: none;"></div>
+                    
+                    <!-- 数据卡片已移除 -->
+
+                    <div id="chartsContainer" style="display: none;">
+                        <!-- 24小时缩略图 -->
+                        <div class="chart-container">
+                            <h3>24小时价格缩略图 (点击查看详情)</h3>
+                            <div class="chart-wrapper" style="height: 200px;">
+                                <canvas id="thumbnailChart"></canvas>
+                            </div>
+                        </div>
+
+                        <div class="chart-container">
+                            <h3>价格对比图</h3>
+                            <div class="chart-wrapper">
+                                <canvas id="priceChart"></canvas>
+                            </div>
+                        </div>
+
+                        <div class="chart-container">
+                            <h3>价格差异图</h3>
+                            <div class="chart-wrapper">
+                                <canvas id="diffChart"></canvas>
+                            </div>
+                        </div>
                     </div>
-                </div>
 
-                <div class="chart-container">
-                    <h3>价格差异图</h3>
-                    <div class="chart-wrapper">
-                        <canvas id="diffChart"></canvas>
-                    </div>
+                    <div id="lastUpdate" class="last-update" style="display: none;"></div>
                 </div>
             </div>
-
-            <div id="lastUpdate" class="last-update" style="display: none;"></div>
         </div>
     </div>
 
@@ -283,6 +373,8 @@
         let thumbnailChart = null;
         let thumbnailData = null;
         let autoRefreshInterval = null;
+        let selectedSymbol = null;
+        
         // 动态设置API基础URL
         let API_BASE = '';
         
@@ -300,15 +392,25 @@
         // 初始化
         document.addEventListener('DOMContentLoaded', function() {
             loadSymbols();
-            setupEventListeners();
         });
 
-        function setupEventListeners() {
-            document.getElementById('symbolSelect').addEventListener('change', function() {
-                if (this.value) {
-                    loadData();
+        function selectSymbol(symbol) {
+            // 移除之前选中的样式
+            const previousActive = document.querySelector('.symbol-item.active');
+            if (previousActive) {
+                previousActive.classList.remove('active');
+            }
+            
+            // 添加新的选中样式
+            const symbolItems = document.querySelectorAll('.symbol-item');
+            symbolItems.forEach(item => {
+                if (item.textContent === symbol) {
+                    item.classList.add('active');
                 }
             });
+            
+            selectedSymbol = symbol;
+            loadData();
         }
 
         async function loadSymbols() {
@@ -316,24 +418,25 @@
                 const response = await axios.get(`${API_BASE}/symbols`);
                 const symbols = response.data.symbols;
                 
-                const select = document.getElementById('symbolSelect');
-                select.innerHTML = '<option value="">请选择币对...</option>';
+                const symbolList = document.getElementById('symbolList');
+                symbolList.innerHTML = '';
                 
                 symbols.forEach(symbol => {
-                    const option = document.createElement('option');
-                    option.value = symbol;
-                    option.textContent = symbol;
-                    select.appendChild(option);
+                    const listItem = document.createElement('li');
+                    listItem.className = 'symbol-item';
+                    listItem.textContent = symbol;
+                    listItem.onclick = () => selectSymbol(symbol);
+                    symbolList.appendChild(listItem);
                 });
             } catch (error) {
+                const symbolList = document.getElementById('symbolList');
+                symbolList.innerHTML = '<li class="symbol-item error-item">加载币对列表失败</li>';
                 showError('加载币对列表失败: ' + error.message);
             }
         }
 
         async function loadData() {
-            const symbol = document.getElementById('symbolSelect').value;
-            
-            if (!symbol) {
+            if (!selectedSymbol) {
                 showError('请先选择币对');
                 return;
             }
@@ -343,18 +446,18 @@
             try {
                 // 并行加载数据、统计信息和24小时缩略图
                 const [dataResponse, statsResponse, latestResponse, thumbnailResponse] = await Promise.all([
-                    axios.get(`${API_BASE}/data/${symbol}?hours=24&limit=1000`),
-                    axios.get(`${API_BASE}/stats/${symbol}?hours=24`),
-                    axios.get(`${API_BASE}/latest/${symbol}`),
-                    axios.get(`${API_BASE}/thumbnail/${symbol}`)
+                    axios.get(`${API_BASE}/data/${selectedSymbol}?hours=24&limit=1000`),
+                    axios.get(`${API_BASE}/stats/${selectedSymbol}?hours=24`),
+                    axios.get(`${API_BASE}/latest/${selectedSymbol}`),
+                    axios.get(`${API_BASE}/thumbnail/${selectedSymbol}`)
                 ]);
 
                 const data = dataResponse.data.data;
                 thumbnailData = thumbnailResponse.data.data;
                 // 数据卡片相关代码已移除
                 
-                updateThumbnailChart(thumbnailData, symbol);
-                updateCharts(data, symbol);
+                updateThumbnailChart(thumbnailData, selectedSymbol);
+                updateCharts(data, selectedSymbol);
                 updateLastUpdateTime();
                 
                 document.getElementById('chartsContainer').style.display = 'block';