Files
pdf-translate-web/templates/admin/stats.html.bak
coder 2ef5e6da87 V2.0.0: 新增用户权限动态配置、会员套餐配置、数据包购买功能
新功能:
- 用户权限动态配置(翻译次数、页数限制)
- 会员套餐动态配置(名称、价格、周期)
- 数据包购买套餐管理
- 收入统计功能
- 数据包销售排行

技术更新:
- 新增 DynamicConfig 模型支持动态配置
- 新增 DataPackage 和 UserPackage 模型
- 后台管理增加数据包管理模块
2026-04-07 23:26:53 +08:00

160 lines
7.5 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>统计报表 - 后台管理</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
body { background-color: #f5f5f5; }
.sidebar { position: fixed; top: 0; left: 0; height: 100vh; width: 250px; background: #343a40; padding-top: 60px; }
.sidebar .nav-link { color: #adb5bd; padding: 12px 20px; }
.sidebar .nav-link:hover, .sidebar .nav-link.active { color: #fff; background: rgba(255,255,255,0.1); }
.main-content { margin-left: 250px; padding: 20px; }
</style>
</head>
<body>
<nav class="sidebar">
<div class="position-absolute top-0 w-100 p-3 border-bottom border-secondary">
<h5 class="text-white mb-0"><i class="bi bi-gear-fill"></i> 后台管理</h5>
</div>
<ul class="nav flex-column">
<li class="nav-item"><a class="nav-link" href="{{ url_for('admin.dashboard') }}"><i class="bi bi-speedometer2"></i> 数据概览</a></li>
<li class="nav-item"><a class="nav-link" href="{{ url_for('admin.users') }}"><i class="bi bi-people"></i> 用户管理</a></li>
<li class="nav-item"><a class="nav-link" href="{{ url_for('admin.translations') }}"><i class="bi bi-file-text"></i> 翻译记录</a></li>
<li class="nav-item"><a class="nav-link" href="{{ url_for('admin.cache_list') }}"><i class="bi bi-database"></i> 缓存管理</a></li>
<li class="nav-item"><a class="nav-link active" href="{{ url_for('admin.stats') }}"><i class="bi bi-bar-chart"></i> 统计报表</a></li>
<li class="nav-item"><a class="nav-link" href="{{ url_for('admin.logs') }}"><i class="bi bi-list-check"></i> 操作日志</a></li>
<li class="nav-item"><a class="nav-link" href="{{ url_for('admin.settings') }}"><i class="bi bi-sliders"></i> 系统配置</a></li>
</ul>
<div class="position-absolute bottom-0 w-100 p-3 border-top border-secondary">
<a href="/" class="btn btn-outline-light btn-sm w-100"><i class="bi bi-house"></i> 返回前台</a>
</div>
</nav>
<main class="main-content">
<div class="row mb-4">
<!-- 用户增长趋势 -->
<div class="col-md-6">
<div class="card">
<div class="card-header"><h6 class="mb-0"><i class="bi bi-people"></i> 用户增长趋势30天</h6></div>
<div class="card-body">
<canvas id="userChart" height="150"></canvas>
</div>
</div>
</div>
<!-- 翻译量趋势 -->
<div class="col-md-6">
<div class="card">
<div class="card-header"><h6 class="mb-0"><i class="bi bi-file-text"></i> 翻译量趋势30天</h6></div>
<div class="card-body">
<canvas id="transChart" height="150"></canvas>
</div>
</div>
</div>
</div>
<div class="row mb-4">
<!-- 用户类型分布 -->
<div class="col-md-4">
<div class="card">
<div class="card-header"><h6 class="mb-0"><i class="bi bi-pie-chart"></i> 用户类型分布</h6></div>
<div class="card-body">
<canvas id="userTypeChart" height="200"></canvas>
</div>
</div>
</div>
<!-- 翻译状态分布 -->
<div class="col-md-4">
<div class="card">
<div class="card-header"><h6 class="mb-0"><i class="bi bi-pie-chart"></i> 翻译状态分布</h6></div>
<div class="card-body">
<canvas id="statusChart" height="200"></canvas>
</div>
</div>
</div>
<!-- Top用户 -->
<div class="col-md-4">
<div class="card">
<div class="card-header"><h6 class="mb-0"><i class="bi bi-trophy"></i> 活跃用户Top10</h6></div>
<div class="card-body p-0">
<table class="table table-sm mb-0">
<thead class="table-light">
<tr><th>排名</th><th>用户</th><th>翻译数</th></tr>
</thead>
<tbody>
{% for name, count in top_users %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ name }}</td>
<td><span class="badge bg-primary">{{ count }}</span></td>
</tr>
{% else %}
<tr><td colspan="3" class="text-center text-muted">暂无数据</td></tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</main>
<script>
// 用户增长趋势
new Chart(document.getElementById('userChart'), {
type: 'line',
data: {
labels: {{ user_growth | map(attribute='date') | list | tojson }},
datasets: [{
label: '新增用户',
data: {{ user_growth | map(attribute='count') | list | tojson }},
borderColor: '#0d6efd',
backgroundColor: 'rgba(13, 110, 253, 0.1)',
fill: true, tension: 0.3
}]
},
options: { responsive: true, plugins: { legend: { display: false } } }
});
// 翻译量趋势
new Chart(document.getElementById('transChart'), {
type: 'bar',
data: {
labels: {{ translation_growth | map(attribute='date') | list | tojson }},
datasets: [{
label: '翻译次数',
data: {{ translation_growth | map(attribute='count') | list | tojson }},
backgroundColor: 'rgba(25, 135, 84, 0.7)'
}]
},
options: { responsive: true, plugins: { legend: { display: false } } }
});
// 用户类型分布
new Chart(document.getElementById('userTypeChart'), {
type: 'doughnut',
data: {
labels: {{ user_distribution | map(attribute=0) | list | tojson }},
datasets: [{
data: {{ user_distribution | map(attribute=1) | list | tojson }},
backgroundColor: ['#6c757d', '#ffc107', '#fd7e14', '#0d6efd', '#198754']
}]
}
});
// 翻译状态分布
new Chart(document.getElementById('statusChart'), {
type: 'doughnut',
data: {
labels: {{ status_distribution | map(attribute=0) | list | tojson }},
datasets: [{
data: {{ status_distribution | map(attribute=1) | list | tojson }},
backgroundColor: ['#198754', '#ffc107', '#dc3545', '#6c757d']
}]
}
});
</script>
</body>
</html>