routes_charts.ts 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. import { Hono } from "hono";
  2. import debug from "debug";
  3. import {
  4. DeleteStatus,
  5. } from "../client/share/types.ts";
  6. import type { Variables, WithAuth } from "./middlewares.ts";
  7. const log = {
  8. api: debug("api:sys"),
  9. };
  10. // 创建图表数据路由
  11. export function createChartRoutes(withAuth: WithAuth) {
  12. const chartRoutes = new Hono<{ Variables: Variables }>();
  13. // 获取用户活跃度图表数据
  14. chartRoutes.get("/user-activity", withAuth, async (c) => {
  15. try {
  16. const apiClient = c.get('apiClient');
  17. // 获取过去30天的数据
  18. const days = 30;
  19. const result = [];
  20. // 当前日期
  21. const currentDate = new Date();
  22. // 生成过去30天的日期范围
  23. for (let i = days - 1; i >= 0; i--) {
  24. const date = new Date();
  25. date.setDate(currentDate.getDate() - i);
  26. // 格式化日期为 YYYY-MM-DD
  27. const formattedDate = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
  28. // 查询当天的登录次数
  29. const loginCount = await apiClient.database
  30. .table('login_history')
  31. .whereRaw(`DATE(login_time) = ?`, [formattedDate])
  32. .count();
  33. result.push({
  34. date: formattedDate,
  35. count: Number(loginCount),
  36. });
  37. }
  38. return c.json({
  39. message: "获取用户活跃度数据成功",
  40. data: result,
  41. });
  42. } catch (error) {
  43. log.api("获取用户活跃度数据失败:", error);
  44. return c.json({ error: "获取用户活跃度数据失败" }, 500);
  45. }
  46. });
  47. // 获取文件上传统计图表数据
  48. chartRoutes.get("/file-uploads", withAuth, async (c) => {
  49. try {
  50. const apiClient = c.get('apiClient');
  51. // 获取过去12个月的数据
  52. const months = 12;
  53. const result = [];
  54. // 当前日期
  55. const currentDate = new Date();
  56. // 生成过去12个月的月份范围
  57. for (let i = months - 1; i >= 0; i--) {
  58. const date = new Date();
  59. date.setMonth(currentDate.getMonth() - i);
  60. // 获取年月
  61. const year = date.getFullYear();
  62. const month = date.getMonth() + 1;
  63. // 月份标签
  64. const monthLabel = `${year}-${String(month).padStart(2, '0')}`;
  65. // 查询当月的文件上传数量
  66. const fileCount = await apiClient.database
  67. .table('file_library')
  68. .whereRaw(`YEAR(created_at) = ? AND MONTH(created_at) = ?`, [year, month])
  69. .count();
  70. result.push({
  71. month: monthLabel,
  72. count: Number(fileCount),
  73. });
  74. }
  75. return c.json({
  76. message: "获取文件上传统计数据成功",
  77. data: result,
  78. });
  79. } catch (error) {
  80. log.api("获取文件上传统计数据失败:", error);
  81. return c.json({ error: "获取文件上传统计数据失败" }, 500);
  82. }
  83. });
  84. // 获取文件类型分布图表数据
  85. chartRoutes.get("/file-types", withAuth, async (c) => {
  86. try {
  87. const apiClient = c.get('apiClient');
  88. // 查询不同文件类型的数量
  89. const fileTypeStats = await apiClient.database
  90. .table('file_library')
  91. .select('file_type',apiClient.database.raw('count(id) as count'))
  92. .where('is_deleted', DeleteStatus.NOT_DELETED)
  93. .groupBy('file_type');
  94. // 将结果转换为饼图所需格式
  95. const result = fileTypeStats.map(item => ({
  96. type: item.file_type || '未知',
  97. value: Number(item.count),
  98. }));
  99. return c.json({
  100. message: "获取文件类型分布数据成功",
  101. data: result,
  102. });
  103. } catch (error) {
  104. log.api("获取文件类型分布数据失败:", error);
  105. return c.json({ error: "获取文件类型分布数据失败" }, 500);
  106. }
  107. });
  108. // 获取仪表盘概览数据
  109. chartRoutes.get("/dashboard-overview", withAuth, async (c) => {
  110. try {
  111. const apiClient = c.get('apiClient');
  112. // 获取用户总数
  113. const userCount = await apiClient.database
  114. .table('users')
  115. .where('is_deleted', DeleteStatus.NOT_DELETED)
  116. .count();
  117. // 获取文件总数
  118. const fileCount = await apiClient.database
  119. .table('file_library')
  120. .where('is_deleted', DeleteStatus.NOT_DELETED)
  121. .count();
  122. // 获取知识库文章总数
  123. const articleCount = await apiClient.database
  124. .table('know_info')
  125. .where('is_deleted', DeleteStatus.NOT_DELETED)
  126. .count();
  127. // 获取今日登录次数
  128. const today = new Date().toISOString().split('T')[0];
  129. const todayLoginCount = await apiClient.database
  130. .table('login_history')
  131. .whereRaw(`DATE(login_time) = ?`, [today])
  132. .count();
  133. return c.json({
  134. message: "获取仪表盘概览数据成功",
  135. data: {
  136. userCount: Number(userCount),
  137. fileCount: Number(fileCount),
  138. articleCount: Number(articleCount),
  139. todayLoginCount: Number(todayLoginCount),
  140. },
  141. });
  142. } catch (error) {
  143. log.api("获取仪表盘概览数据失败:", error);
  144. return c.json({ error: "获取仪表盘概览数据失败" }, 500);
  145. }
  146. });
  147. return chartRoutes;
  148. }