Files
gemini-banlancer/web/static/js/dashboard-chart.js
2025-11-20 12:24:05 +08:00

92 lines
3.5 KiB
JavaScript
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.
// Filename: public/static/js/dashboard-chart.js (V2.0 - 兼容全局授权版)
// export default function initializeDashboardChart() {
// ========================================================================= //
// Dashboard Chart Module //
// ========================================================================= //
/** @type {import('chart.js').Chart | null} 专属的图表实例 */
let historicalChartInstance = null;
// 使用 DOMContentLoaded 确保页面结构加载完毕后再执行
document.addEventListener('DOMContentLoaded', main);
function main() {
setupChartEventListeners();
fetchChartData();
// [新增] 监听来自主程序的刷新命令
window.addEventListener('refresh-chart', () => fetchChartData(document.getElementById('chartGroupFilter')?.value));
}
function setupChartEventListeners() {
const chartGroupFilter = document.getElementById('chartGroupFilter');
if (chartGroupFilter) {
chartGroupFilter.addEventListener('change', (e) => fetchChartData(e.target.value));
}
}
function handleFilterChange(groupId) {
fetchChartData(groupId);
}
async function fetchChartData(groupId = '') {
const url = groupId ? `/admin/dashboard/chart?group_id=${groupId}` : '/admin/dashboard/chart';
try {
const response = await apiFetch(url, { noCache: true }); // 图表数据总是获取最新的
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
const chartData = await response.json();
renderHistoricalChart(chartData);
} catch (error) {
if (error.message !== 'Unauthorized') {
console.error('Failed to fetch chart data:', error);
renderHistoricalChart(null);
}
}
}
function renderHistoricalChart(chartData) {
const canvas = document.getElementById('historicalChart');
if (!canvas) return;
// [关键] 我们不再需要 setTimeout 检查!
// 因为HTML的加载顺序保证了当这个脚本执行时`Chart` 对象必然存在。
const ctx = canvas.getContext('2d');
if (historicalChartInstance) {
historicalChartInstance.destroy();
}
if (!chartData || !chartData.labels || chartData.labels.length === 0) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.font = "16px Inter, sans-serif";
ctx.fillStyle = "#9ca3af";
ctx.textAlign = "center";
ctx.fillText("暂无图表数据", canvas.width / 2, canvas.height / 2);
return;
}
// 创建新图表
historicalChartInstance = new Chart(ctx, {
type: 'line',
data: {
labels: chartData.labels,
datasets: chartData.datasets.map(dataset => ({
label: dataset.label, data: dataset.data, borderColor: dataset.color,
backgroundColor: `${dataset.color}33`, pointBackgroundColor: dataset.color,
pointBorderColor: '#fff', pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: dataset.color, fill: true, tension: 0.4
}))
},
options: {
responsive: true, maintainAspectRatio: false,
scales: {
y: { beginAtZero: true, grid: { color: 'rgba(0, 0, 0, 0.05)' } },
x: { grid: { display: false } }
},
plugins: {
legend: { position: 'top', align: 'end', labels: { usePointStyle: true, boxWidth: 8, padding: 20 } }
},
interaction: { intersect: false, mode: 'index' }
}
});
}