init
This commit is contained in:
150
templates/admin_dashboard.html
Normal file
150
templates/admin_dashboard.html
Normal file
@@ -0,0 +1,150 @@
|
||||
<!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 rel="stylesheet" href="/static/css/ui-components.css?v=3">
|
||||
<link rel="stylesheet" href="/static/css/admin.css">
|
||||
</head>
|
||||
|
||||
<body class="admin-layout">
|
||||
<header class="admin-header">
|
||||
<div class="header-container">
|
||||
<a href="/admin/dashboard" class="brand">
|
||||
<span style="font-size: 1.5rem;">⚡</span> JieXi Admin
|
||||
</a>
|
||||
<nav class="nav-links">
|
||||
<a href="/admin/dashboard" class="nav-item active">仪表板</a>
|
||||
<a href="/admin/users" class="nav-item">用户管理</a>
|
||||
<a href="/admin/apis" class="nav-item">接口管理</a>
|
||||
<a href="/admin/config" class="nav-item">系统配置</a>
|
||||
<a href="/admin/logs" class="nav-item">日志审计</a>
|
||||
</nav>
|
||||
<div class="user-actions">
|
||||
<a href="/admin/profile" class="ui-btn ui-btn-secondary ui-btn-sm">账号设置</a>
|
||||
<button class="ui-btn ui-btn-secondary ui-btn-sm" onclick="logout()">退出登录</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="main-container">
|
||||
<div class="page-header">
|
||||
<h1 class="page-title">仪表板</h1>
|
||||
<div class="actions">
|
||||
<a href="/" target="_blank" class="ui-btn ui-btn-primary ui-btn-sm">
|
||||
访问前台
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">今日解析总数</div>
|
||||
<div class="stat-value" id="todayTotal">-</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">今日成功解析</div>
|
||||
<div class="stat-value" id="todaySuccess" style="color: var(--success);">-</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">总注册用户</div>
|
||||
<div class="stat-value" id="totalUsers">-</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">活跃接口节点</div>
|
||||
<div class="stat-value" id="activeApis" style="color: var(--warning);">-</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ui-card">
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<h3 class="text-lg font-bold">实时解析动态</h3>
|
||||
<a href="/admin/logs" class="text-sm text-muted" style="text-decoration: none;">查看全部 →</a>
|
||||
</div>
|
||||
|
||||
<div class="table-container">
|
||||
<table id="logsTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>时间</th>
|
||||
<th>平台</th>
|
||||
<th>状态</th>
|
||||
<th>耗时</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="4" style="text-align: center; color: var(--text-muted);">加载中...</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script src="/static/js/ui-components.js"></script>
|
||||
<script>
|
||||
async function loadDashboard() {
|
||||
try {
|
||||
const response = await fetch('/admin/api/dashboard');
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
const data = result.data;
|
||||
document.getElementById('todayTotal').textContent = data.today.total.toLocaleString();
|
||||
document.getElementById('todaySuccess').textContent = data.today.success.toLocaleString();
|
||||
document.getElementById('totalUsers').textContent = data.total_users.toLocaleString();
|
||||
document.getElementById('activeApis').textContent = data.active_apis;
|
||||
}
|
||||
} catch (error) {
|
||||
UI.notify('加载数据失败: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async function loadRecentLogs() {
|
||||
try {
|
||||
const response = await fetch('/admin/api/logs?page=1&per_page=10');
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success && result.data.length > 0) {
|
||||
const tbody = document.querySelector('#logsTable tbody');
|
||||
tbody.innerHTML = result.data.map(log => {
|
||||
let badgeClass = 'badge-neutral';
|
||||
if (log.status === 'success') badgeClass = 'badge-success';
|
||||
else if (log.status === 'failed') badgeClass = 'badge-error';
|
||||
|
||||
return `
|
||||
<tr>
|
||||
<td>${new Date(log.created_at).toLocaleString('zh-CN')}</td>
|
||||
<td><span class="font-medium">${log.platform}</span></td>
|
||||
<td><span class="badge ${badgeClass}">${log.status}</span></td>
|
||||
<td class="text-muted">${log.response_time ? (log.response_time / 1000).toFixed(2) + 's' : '-'}</td>
|
||||
</tr>
|
||||
`;
|
||||
}).join('');
|
||||
} else {
|
||||
document.querySelector('#logsTable tbody').innerHTML =
|
||||
'<tr><td colspan="4" style="text-align: center; padding: 2rem; color: var(--text-muted);">暂无记录</td></tr>';
|
||||
}
|
||||
} catch (error) {
|
||||
UI.notify('加载日志失败', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async function logout() {
|
||||
try {
|
||||
await fetch('/admin/logout', { method: 'POST' });
|
||||
window.location.href = '/admin/login';
|
||||
} catch (error) {
|
||||
UI.notify('退出失败', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
loadDashboard();
|
||||
loadRecentLogs();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user