148 lines
5.2 KiB
JavaScript
148 lines
5.2 KiB
JavaScript
// app/static/js/user_activity.js
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
let activityChart = null;
|
||
|
||
// 初始加载
|
||
loadUserActivity();
|
||
|
||
function loadUserActivity() {
|
||
// 显示加载状态
|
||
document.getElementById('user-table-body').innerHTML = `
|
||
<tr class="loading-row">
|
||
<td colspan="4">加载中...</td>
|
||
</tr>
|
||
`;
|
||
|
||
// 调用API获取数据
|
||
fetch('/statistics/api/user-activity')
|
||
.then(response => {
|
||
if (!response.ok) {
|
||
throw new Error(`HTTP error! status: ${response.status}`);
|
||
}
|
||
return response.json();
|
||
})
|
||
.then(data => {
|
||
updateUserTable(data);
|
||
updateUserChart(data);
|
||
})
|
||
.catch(error => {
|
||
console.error('加载用户活跃度数据失败:', error);
|
||
document.getElementById('user-table-body').innerHTML = `
|
||
<tr class="error-row">
|
||
<td colspan="4">加载数据失败,请稍后重试</td>
|
||
</tr>
|
||
`;
|
||
// 也可以考虑清除或提示图表加载失败
|
||
if (activityChart) {
|
||
activityChart.destroy();
|
||
activityChart = null;
|
||
}
|
||
const canvas = document.getElementById('user-activity-chart');
|
||
const ctx = canvas.getContext('2d');
|
||
ctx.clearRect(0, 0, canvas.width, canvas.height); // 清除画布
|
||
// 可以在画布上显示错误信息,但这比较复杂,通常表格的错误提示已足够
|
||
});
|
||
}
|
||
|
||
function updateUserTable(data) {
|
||
const tableBody = document.getElementById('user-table-body');
|
||
|
||
if (!data || data.length === 0) { // 增加了对 data 本身的检查
|
||
tableBody.innerHTML = `
|
||
<tr class="no-data-row">
|
||
<td colspan="4">暂无数据</td>
|
||
</tr>
|
||
`;
|
||
return;
|
||
}
|
||
|
||
let tableHtml = '';
|
||
|
||
data.forEach((user, index) => {
|
||
tableHtml += `
|
||
<tr>
|
||
<td class="rank">${index + 1}</td>
|
||
<td>${user.username || 'N/A'}</td>
|
||
<td>${user.nickname || 'N/A'}</td>
|
||
<td class="borrow-count">${user.borrow_count}</td>
|
||
</tr>
|
||
`;
|
||
});
|
||
|
||
tableBody.innerHTML = tableHtml;
|
||
}
|
||
|
||
function updateUserChart(data) {
|
||
// 销毁旧图表
|
||
if (activityChart) {
|
||
activityChart.destroy();
|
||
activityChart = null; // 确保旧实例被完全清除
|
||
}
|
||
|
||
const canvas = document.getElementById('user-activity-chart');
|
||
const ctx = canvas.getContext('2d');
|
||
|
||
if (!data || data.length === 0) {
|
||
// 如果没有数据,清除画布,避免显示旧图表或空白图表框架
|
||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||
// 也可以在这里显示 "暂无数据" 的文本到 canvas 上,如果需要
|
||
// 例如:
|
||
// ctx.textAlign = 'center';
|
||
// ctx.fillText('暂无图表数据', canvas.width / 2, canvas.height / 2);
|
||
return;
|
||
}
|
||
|
||
// 准备图表数据
|
||
const labels = data.map(user => user.nickname || user.username || '未知用户');
|
||
const borrowCounts = data.map(user => user.borrow_count);
|
||
|
||
// 创建图表
|
||
activityChart = new Chart(ctx, {
|
||
type: 'bar',
|
||
data: {
|
||
labels: labels,
|
||
datasets: [{
|
||
label: '借阅次数',
|
||
data: borrowCounts,
|
||
backgroundColor: 'rgba(153, 102, 255, 0.6)',
|
||
borderColor: 'rgba(153, 102, 255, 1)',
|
||
borderWidth: 1
|
||
}]
|
||
},
|
||
options: {
|
||
responsive: true,
|
||
maintainAspectRatio: false,
|
||
scales: {
|
||
y: {
|
||
beginAtZero: true,
|
||
title: {
|
||
display: true,
|
||
text: '借阅次数'
|
||
}
|
||
},
|
||
x: {
|
||
title: {
|
||
display: true,
|
||
text: '用户' // 这个标题现在应该有空间显示了
|
||
}
|
||
}
|
||
},
|
||
plugins: {
|
||
legend: {
|
||
display: false // 保持不显示图例
|
||
},
|
||
title: {
|
||
display: true, // 如果HTML中已有h3标题,这里可以设为 false
|
||
text: '最活跃用户排行' // 这个是图表内部的标题
|
||
}
|
||
},
|
||
layout: { // <--- 这是添加的部分
|
||
padding: {
|
||
bottom: 30 // 为X轴标题和标签留出足够的底部空间,可以根据实际显示效果调整此数值
|
||
}
|
||
}
|
||
}
|
||
});
|
||
}
|
||
});
|