<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>仪表板 - 后台管理系统</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.2/font/bootstrap-icons.css" rel="stylesheet"> <style> .sidebar { position: fixed; top: 60px; bottom: 0; left: 0; z-index: 100; padding: 0; box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1); background-color: #f8f9fa; } .sidebar-sticky { position: relative; top: 0; height: calc(100vh - 60px); padding-top: .5rem; overflow-x: hidden; overflow-y: auto; } .navbar { box-shadow: 0 2px 4px rgba(0,0,0,.1); height: 60px; } .main-content { margin-left: 240px; padding: 20px; margin-top: 60px; } .nav-link { color: #333; padding: 10px 20px; } .nav-link:hover { background-color: #e9ecef; } .nav-link.active { color: #0d6efd; background-color: #e9ecef; } .card { margin-bottom: 20px; box-shadow: 0 0 10px rgba(0,0,0,0.1); } .stat-card { text-align: center; padding: 20px; } .stat-card i { font-size: 2rem; margin-bottom: 10px; color: #0d6efd; } </style> </head> <body> <nav class="navbar navbar-expand-lg navbar-light bg-white fixed-top"> <div class="container-fluid"> <a class="navbar-brand" href="#">后台管理系统</a> <div class="d-flex"> <button class="btn btn-outline-danger" id="logoutBtn">退出登录</button> </div> </div> </nav> <div class="container-fluid"> <div class="row"> <nav class="col-md-3 col-lg-2 d-md-block sidebar"> <div class="sidebar-sticky"> <ul class="nav flex-column"> <li class="nav-item"> <a class="nav-link active" href="/admin/views/dashboard.html" data-page="dashboard"> <i class="bi bi-speedometer2"></i> 仪表板 </a> </li> <li class="nav-item"> <a class="nav-link" href="/admin/views/groups.html" data-page="groups"> <i class="bi bi-people"></i> 群组管理 </a> </li> <li class="nav-item"> <a class="nav-link" href="/admin/views/transactions.html" data-page="transactions"> <i class="bi bi-cash-stack"></i> 交易记录 </a> </li> <!-- <li class="nav-item"> <a class="nav-link" href="/admin/views/statistics.html" data-page="statistics"> <i class="bi bi-graph-up"></i> 统计报表 </a> </li> --> <li class="nav-item"> <a class="nav-link" href="/admin/views/settings.html" data-page="settings"> <i class="bi bi-gear"></i> 系统设置 </a> </li> </ul> </div> </nav> <main class="col-md-9 ms-sm-auto col-lg-10 px-md-4 main-content"> <div id="dashboardContent"> <h2 class="mb-4">仪表板</h2> <div class="row"> <div class="col-md-3"> <div class="card stat-card"> <i class="bi bi-people"></i> <h3 id="totalGroups">0</h3> <p>总群组数</p> </div> </div> <div class="col-md-3"> <div class="card stat-card"> <i class="bi bi-cash-stack"></i> <h3 id="totalTransactions">0</h3> <p>总交易数</p> </div> </div> <div class="col-md-3"> <div class="card stat-card"> <i class="bi bi-currency-yen"></i> <h3 id="totalAmount">¥0</h3> <p>总金额</p> </div> </div> <div class="col-md-3"> <div class="card stat-card"> <i class="bi bi-graph-up"></i> <h3 id="todayTransactions">0</h3> <p>今日交易</p> </div> </div> </div> <div class="row mt-4"> <div class="col-md-6"> <div class="card"> <div class="card-header"> <h5 class="card-title mb-0">最近交易</h5> </div> <div class="card-body"> <div class="table-responsive"> <table class="table"> <thead> <tr> <th>时间</th> <th>类型</th> <th>金额</th> <th>群组</th> </tr> </thead> <tbody id="recentTransactions"> </tbody> </table> </div> </div> </div> </div> <div class="col-md-6"> <div class="card"> <div class="card-header"> <h5 class="card-title mb-0">活跃群组</h5> </div> <div class="card-body"> <div class="table-responsive"> <table class="table"> <thead> <tr> <th>群组名称</th> <th>今日交易</th> <th>总交易</th> </tr> </thead> <tbody id="activeGroups"> </tbody> </table> </div> </div> </div> </div> </div> </div> </main> </div> </div> <script> // 检查登录状态 function checkAuth() { const token = localStorage.getItem('token'); console.log('检查登录状态,token:', token ? '存在' : '不存在'); if (!token) { console.log('未找到token,跳转到登录页'); window.location.href = '/admin/views/login.html'; return; } // 验证token是否有效 fetch('/api/users/profile', { headers: { 'Authorization': `Bearer ${token}` } }) .then(response => { if (!response.ok) { throw new Error('Token无效'); } return response.json(); }) .then(data => { console.log('用户信息:', data); // 可以在这里保存用户信息到全局变量 window.currentUser = data; }) .catch(error => { console.error('验证token时出错:', error); localStorage.removeItem('token'); window.location.href = '/admin/views/login.html'; }); } // 加载仪表板数据 async function loadDashboardData() { try { const token = localStorage.getItem('token'); const response = await fetch('/api/transactions/dashboard', { headers: { 'Authorization': `Bearer ${token}` } }); if (response.ok) { const data = await response.json(); updateDashboardStats(data); } else { if (response.status === 401) { window.location.href = '/'; } } } catch (error) { console.error('加载数据失败:', error); } } // 更新仪表板统计数据 function updateDashboardStats(data) { document.getElementById('totalGroups').textContent = data.totalGroups || 0; document.getElementById('totalTransactions').textContent = data.totalTransactions || 0; document.getElementById('totalAmount').textContent = `¥${(data.totalAmount || 0).toFixed(2)}`; document.getElementById('todayTransactions').textContent = data.todayTransactions || 0; // 更新最近交易 const recentTransactionsHtml = (data.recentTransactions || []).map(t => ` <tr> <td>${new Date(t.time).toLocaleString('zh-CN')}</td> <td> <span class="badge ${t.type === 'deposit' ? 'bg-success' : 'bg-danger'}"> ${t.type === 'deposit' ? '入款' : '出款'} </span> </td> <td>¥${parseFloat(t.amount).toFixed(2)}</td> <td>${t.group_name || '-'}</td> </tr> `).join('') || '<tr><td colspan="4" class="text-center">暂无数据</td></tr>'; document.getElementById('recentTransactions').innerHTML = recentTransactionsHtml; // 更新活跃群组 const activeGroupsHtml = (data.activeGroups || []).map(g => ` <tr> <td>${g.group_name || '-'}</td> <td>${g.todayTransactions || 0}</td> <td>${g.totalTransactions || 0}</td> </tr> `).join('') || '<tr><td colspan="3" class="text-center">暂无数据</td></tr>'; document.getElementById('activeGroups').innerHTML = activeGroupsHtml; } // 退出登录 document.getElementById('logoutBtn').addEventListener('click', () => { localStorage.removeItem('token'); window.location.href = '/'; }); // 页面加载时检查登录状态并加载数据 checkAuth(); loadDashboardData(); // 每5分钟刷新一次数据 setInterval(loadDashboardData, 5 * 60 * 1000); </script> </body> </html>