statistics.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /**
  2. * 统计分析页面的JavaScript功能
  3. */
  4. // 初始化所有图表
  5. function initCharts() {
  6. // 各图表初始化逻辑在页面内已实现
  7. // 添加图表交互功能
  8. enableChartInteractions();
  9. // 初始化数据表格排序功能
  10. initDataTableSorting();
  11. }
  12. // 为图表添加交互功能
  13. function enableChartInteractions() {
  14. // 为所有图表添加下载功能
  15. addChartDownloadButtons();
  16. // 为折线图添加时间范围选择功能
  17. addTimeRangeSelectors();
  18. }
  19. // 添加图表下载按钮
  20. function addChartDownloadButtons() {
  21. const chartContainers = document.querySelectorAll('.chart-container');
  22. chartContainers.forEach(container => {
  23. const canvas = container.querySelector('canvas');
  24. if (!canvas) return;
  25. const header = container.querySelector('.chart-header');
  26. const downloadBtn = document.createElement('button');
  27. downloadBtn.className = 'btn btn-sm';
  28. downloadBtn.innerHTML = '下载图表';
  29. downloadBtn.onclick = function() {
  30. const chartInstance = Chart.getChart(canvas);
  31. if (!chartInstance) return;
  32. // 创建临时链接并触发下载
  33. const a = document.createElement('a');
  34. a.href = chartInstance.toBase64Image();
  35. a.download = (container.querySelector('.chart-title').textContent || 'chart') + '.png';
  36. document.body.appendChild(a);
  37. a.click();
  38. document.body.removeChild(a);
  39. };
  40. header.appendChild(downloadBtn);
  41. });
  42. }
  43. // 添加时间范围选择器
  44. function addTimeRangeSelectors() {
  45. // 为具有时间轴的图表添加缩放功能
  46. // 这个功能需要Chart.js的Zoom插件,如果需要可以进一步实现
  47. }
  48. // 初始化数据表格排序
  49. function initDataTableSorting() {
  50. const tables = document.querySelectorAll('.data-table');
  51. tables.forEach(table => {
  52. const headers = table.querySelectorAll('th');
  53. headers.forEach((header, index) => {
  54. // 排除不需要排序的列
  55. if (header.classList.contains('no-sort')) return;
  56. header.style.cursor = 'pointer';
  57. header.dataset.sortDirection = 'none'; // none, asc, desc
  58. // 添加排序图标
  59. const sortIcon = document.createElement('span');
  60. sortIcon.className = 'sort-icon';
  61. sortIcon.innerHTML = ' ⇅';
  62. header.appendChild(sortIcon);
  63. // 添加点击事件
  64. header.addEventListener('click', () => {
  65. // 重置其他列的排序状态
  66. headers.forEach(h => {
  67. if (h !== header) h.dataset.sortDirection = 'none';
  68. });
  69. // 切换当前列的排序方向
  70. const currentDirection = header.dataset.sortDirection;
  71. if (currentDirection === 'none' || currentDirection === 'desc') {
  72. header.dataset.sortDirection = 'asc';
  73. } else {
  74. header.dataset.sortDirection = 'desc';
  75. }
  76. // 执行排序
  77. sortTable(table, index, header.dataset.sortDirection);
  78. });
  79. });
  80. });
  81. }
  82. // 执行表格排序
  83. function sortTable(table, columnIndex, direction) {
  84. const tbody = table.querySelector('tbody');
  85. const rows = Array.from(tbody.querySelectorAll('tr'));
  86. // 排序行
  87. rows.sort((a, b) => {
  88. const aValue = a.querySelectorAll('td')[columnIndex].textContent.trim();
  89. const bValue = b.querySelectorAll('td')[columnIndex].textContent.trim();
  90. // 检测是否为数值(包括货币符号)
  91. const aNum = parseFloat(aValue.replace(/[¥,]/g, ''));
  92. const bNum = parseFloat(bValue.replace(/[¥,]/g, ''));
  93. if (!isNaN(aNum) && !isNaN(bNum)) {
  94. return direction === 'asc' ? aNum - bNum : bNum - aNum;
  95. }
  96. // 字符串比较
  97. return direction === 'asc'
  98. ? aValue.localeCompare(bValue, 'zh-CN')
  99. : bValue.localeCompare(aValue, 'zh-CN');
  100. });
  101. // 重新添加排序后的行
  102. rows.forEach(row => tbody.appendChild(row));
  103. }
  104. // 页面加载完成后初始化
  105. document.addEventListener('DOMContentLoaded', initCharts);