Files
NetworkAuth/web/template/admin/dashboard.html
2025-10-24 00:09:45 +08:00

236 lines
8.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.
{{ define "dashboard.html" }}
<section>
<h2>系统信息</h2>
<div class="layui-row layui-col-space15" style="margin-top:12px">
<div class="layui-col-md6">
<div class="layui-card">
<div class="layui-card-header">基本信息</div>
<div class="layui-card-body">
<div class="system-info-grid">
<div class="system-info-item">
<div class="system-info-label">版本</div>
<div class="system-info-value">{{ .Version }}</div>
</div>
<div class="system-info-item">
<div class="system-info-label">运行模式</div>
<div class="system-info-value">{{ .Mode }}</div>
</div>
</div>
</div>
</div>
</div>
<div class="layui-col-md6">
<div class="layui-card">
<div class="layui-card-header">运行状态</div>
<div class="layui-card-body">
<div class="system-info-grid">
<div class="system-info-item">
<div class="system-info-label">数据库</div>
<div class="system-info-value">{{ .DBType }}</div>
</div>
<div class="system-info-item">
<div class="system-info-label">运行时长</div>
<div class="system-info-value">{{ .Uptime }}</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- 卡密统计区域 -->
<section style="margin-top:16px">
<div class="layui-row layui-col-space15">
<!-- 当日卡密统计 -->
<div class="layui-col-md6">
<div class="layui-card">
<div class="layui-card-header">当日卡密统计 <span class="layui-badge layui-bg-blue" style="margin-left:8px">总数:<span id="today-total">-</span></span></div>
<div class="layui-card-body">
<div id="chart-today-by-status" style="width:100%;height:320px"></div>
</div>
</div>
</div>
<!-- 所有卡密统计 -->
<div class="layui-col-md6">
<div class="layui-card">
<div class="layui-card-header">所有卡密统计 <span class="layui-badge layui-bg-blue" style="margin-left:8px">总数:<span id="all-total">-</span></span></div>
<div class="layui-card-body">
<div id="chart-all-by-status" style="width:100%;height:320px"></div>
</div>
</div>
</div>
</div>
<!-- 30天走势图 -->
<div class="layui-row layui-col-space15" style="margin-top:16px">
<div class="layui-col-md12">
<div class="layui-card">
<div class="layui-card-header">近30天卡密走势</div>
<div class="layui-card-body">
<div id="chart-trend-30days" style="width:100%;height:360px"></div>
</div>
</div>
</div>
</div>
</section>
<script>
// 仪表盘统计脚本(采用箭头函数与中文注释)
layui.use(['layer', 'util'], function(){
const layer = layui.layer;
const util = layui.util;
const $ = layui.$;
// 全局引用ECharts CDN 地址
const echartsCdn = 'https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js';
// 工具函数:加载 ECharts 库(若已加载则直接回调)
// 功能:通过全局的 loadScript 方法按需加载图表库,避免重复加载
const ensureECharts = (cb) => {
if (window.echarts) { cb && cb(); return; }
if (typeof loadScript === 'function') {
loadScript(echartsCdn, () => cb && cb());
} else {
// 兜底:直接插入 <script>
const s = document.createElement('script');
s.src = echartsCdn;
s.onload = () => cb && cb();
document.head.appendChild(s);
}
};
// 工具函数:状态码 -> 名称 映射
// 说明卡密状态映射0=未使用1=已使用2=禁用
const getStatusText = (s) => {
const map = {0:'未使用',1:'已使用',2:'禁用'};
const k = Number(s);
return map[k] ?? String(s);
};
// 工具函数:状态码 -> 颜色 映射(与徽章风格一致,尽量贴近 Layui 配色)
const getStatusColor = (s) => {
switch (Number(s)) {
case 0: return '#1E9FFF'; // 蓝色 - 未使用
case 1: return '#5FB878'; // 绿色 - 已使用
case 2: return '#FF5722'; // 红色 - 禁用
default: return '#909399'; // 灰色 - 默认
}
};
// 函数:渲染饼图
// 说明:接收状态分布对象(键为状态码,值为数量),绘制环形图
const renderPie = (domId, byStatus) => {
const el = document.getElementById(domId);
if (!el) return;
const chart = echarts.init(el);
const codes = [0,1,2]; // 卡密状态0=未使用1=已使用2=禁用
const data = codes.map(code => ({
name: getStatusText(code),
value: Number((byStatus && byStatus[code]) || 0),
itemStyle: { color: getStatusColor(code) }
}));
chart.setOption({
tooltip: { trigger: 'item' },
legend: { top: 'bottom' },
series: [{
name: '按状态分布',
type: 'pie',
radius: ['38%', '68%'],
avoidLabelOverlap: true,
label: { formatter: '{b}: {c} ({d}%)' },
data
}]
});
// 自适应
window.addEventListener('resize', () => chart.resize());
return chart;
};
// 函数:渲染 30 天折线图
// 说明三条序列total/used/unused对应后台返回的数组
const renderTrend = (domId, trend) => {
const el = document.getElementById(domId);
if (!el) return;
const chart = echarts.init(el);
const dates = (trend && trend.dates) || [];
const total = (trend && trend.total) || [];
const used = (trend && trend.used) || [];
const unused = (trend && trend.unused) || [];
chart.setOption({
tooltip: { trigger: 'axis' },
legend: { data: ['总数', '已使用', '未使用'] },
grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
xAxis: { type: 'category', boundaryGap: false, data: dates },
yAxis: { type: 'value' },
series: [
{ name: '总数', type: 'line', smooth: true, data: total, itemStyle: { color: '#909399' } },
{ name: '已使用', type: 'line', smooth: true, data: used, itemStyle: { color: getStatusColor(1) } },
{ name: '未使用', type: 'line', smooth: true, data: unused, itemStyle: { color: getStatusColor(0) } }
]
});
window.addEventListener('resize', () => chart.resize());
return chart;
};
// 函数:拉取概览并渲染
// 说明:请求 /admin/api/cards/stats_overview更新总数文本并渲染两个饼图
const loadAndRenderOverview = () => {
$.get('/admin/api/cards/stats_overview', (res) => {
if (!res || res.code !== 0) { layer.msg(res && res.msg ? res.msg : '获取统计概览失败'); return; }
const data = res.data || {};
$('#today-total').text((data.today && data.today.total) ?? '-');
$('#all-total').text((data.all && data.all.total) ?? '-');
// 渲染饼图
renderPie('chart-today-by-status', data.today ? data.today.by_status : {});
renderPie('chart-all-by-status', data.all ? data.all.by_status : {});
});
};
// 函数:拉取 30 天数据并渲染折线图
// 说明:请求 /admin/api/cards/trend_30days渲染趋势图
const loadAndRenderTrend = () => {
$.get('/admin/api/cards/trend_30days', (res) => {
if (!res || res.code !== 0) { layer.msg(res && res.msg ? res.msg : '获取30天趋势失败'); return; }
renderTrend('chart-trend-30days', res.data || {});
});
};
// 函数:刷新基本信息和运行状态
// 说明:请求后台获取最新的系统信息并更新页面显示
const refreshSystemInfo = () => {
$.get('/admin/api/system/info', (res) => {
if (res && res.code === 0 && res.data) {
const data = res.data;
// 更新运行时长
if (data.uptime) {
$('.system-info-item').each(function() {
const label = $(this).find('.system-info-label').text();
if (label === '运行时长') {
$(this).find('.system-info-value').text(data.uptime);
}
});
}
}
}).fail(() => {
console.log('获取系统信息失败');
});
};
// 入口:确保 ECharts 已加载后开始渲染
ensureECharts(() => {
loadAndRenderOverview();
loadAndRenderTrend();
// 立即刷新一次系统信息
refreshSystemInfo();
});
});
</script>
{{ end }}