2
0

pages_chart.tsx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. import React from 'react';
  2. import {
  3. Card, Spin, Row, Col, Statistic,
  4. } from 'antd';
  5. import {
  6. useQuery,
  7. } from '@tanstack/react-query';
  8. import { Line , Pie, Column} from "@ant-design/plots";
  9. import 'dayjs/locale/zh-cn';
  10. import { ChartAPI } from './api/index.ts';
  11. import { useTheme } from './hooks_sys.tsx';
  12. // 用户活跃度图表组件
  13. const UserActivityChart: React.FC = () => {
  14. const { isDark } = useTheme();
  15. const { data: activityData, isLoading } = useQuery({
  16. queryKey: ['userActivity'],
  17. queryFn: async () => {
  18. const response = await ChartAPI.getUserActivity();
  19. return response.data;
  20. }
  21. });
  22. if (isLoading) return <Spin />;
  23. const config = {
  24. data: activityData || [],
  25. xField: 'date',
  26. yField: 'count',
  27. smooth: true,
  28. theme: isDark ? 'dark' : 'light',
  29. color: '#1890ff',
  30. areaStyle: {
  31. fill: 'l(270) 0:#1890ff10 1:#1890ff',
  32. },
  33. };
  34. return (
  35. <Card title="用户活跃度趋势" variant="borderless">
  36. <Line {...config} />
  37. </Card>
  38. );
  39. };
  40. // 文件上传统计图表组件
  41. const FileUploadsChart: React.FC = () => {
  42. const { isDark } = useTheme();
  43. const { data: uploadsData, isLoading } = useQuery({
  44. queryKey: ['fileUploads'],
  45. queryFn: async () => {
  46. const response = await ChartAPI.getFileUploads();
  47. return response.data;
  48. }
  49. });
  50. if (isLoading) return <Spin />;
  51. const config = {
  52. data: uploadsData || [],
  53. xField: 'month',
  54. yField: 'count',
  55. theme: isDark ? 'dark' : 'light',
  56. color: '#52c41a',
  57. label: {
  58. position: 'middle',
  59. style: {
  60. fill: '#FFFFFF',
  61. opacity: 0.6,
  62. },
  63. },
  64. meta: {
  65. month: {
  66. alias: '月份',
  67. },
  68. count: {
  69. alias: '上传数量',
  70. },
  71. },
  72. };
  73. return (
  74. <Card title="文件上传统计" variant="borderless">
  75. <Column {...config} />
  76. </Card>
  77. );
  78. };
  79. // 文件类型分布图表组件
  80. const FileTypesChart: React.FC = () => {
  81. const { isDark } = useTheme();
  82. const { data: typesData, isLoading } = useQuery({
  83. queryKey: ['fileTypes'],
  84. queryFn: async () => {
  85. const response = await ChartAPI.getFileTypes();
  86. return response.data;
  87. }
  88. });
  89. if (isLoading) return <Spin />;
  90. const config = {
  91. data: typesData || [],
  92. angleField: 'value',
  93. colorField: 'type',
  94. radius: 0.8,
  95. theme: isDark ? 'dark' : 'light',
  96. label: {
  97. type: 'spider',
  98. labelHeight: 28,
  99. content: '{name}\n{percentage}',
  100. },
  101. interactions: [
  102. {
  103. type: 'element-active',
  104. },
  105. ],
  106. };
  107. return (
  108. <Card title="文件类型分布" variant="borderless">
  109. <Pie {...config} />
  110. </Card>
  111. );
  112. };
  113. // 仪表盘概览组件
  114. const DashboardOverview: React.FC = () => {
  115. const { data: overviewData, isLoading } = useQuery({
  116. queryKey: ['dashboardOverview'],
  117. queryFn: async () => {
  118. const response = await ChartAPI.getDashboardOverview();
  119. return response.data;
  120. }
  121. });
  122. if (isLoading) return <Spin />;
  123. return (
  124. <Row gutter={[16, 16]}>
  125. <Col xs={12} sm={12} md={6}>
  126. <Card variant="borderless">
  127. <Statistic
  128. title="用户总数"
  129. value={overviewData?.userCount || 0}
  130. valueStyle={{ color: '#1890ff' }}
  131. />
  132. </Card>
  133. </Col>
  134. <Col xs={12} sm={12} md={6}>
  135. <Card variant="borderless">
  136. <Statistic
  137. title="文件总数"
  138. value={overviewData?.fileCount || 0}
  139. valueStyle={{ color: '#52c41a' }}
  140. />
  141. </Card>
  142. </Col>
  143. <Col xs={12} sm={12} md={6}>
  144. <Card variant="borderless">
  145. <Statistic
  146. title="文章总数"
  147. value={overviewData?.articleCount || 0}
  148. valueStyle={{ color: '#faad14' }}
  149. />
  150. </Card>
  151. </Col>
  152. <Col xs={12} sm={12} md={6}>
  153. <Card variant="borderless">
  154. <Statistic
  155. title="今日登录"
  156. value={overviewData?.todayLoginCount || 0}
  157. valueStyle={{ color: '#722ed1' }}
  158. />
  159. </Card>
  160. </Col>
  161. </Row>
  162. );
  163. };
  164. // 图表仪表盘页面组件
  165. export const ChartDashboardPage: React.FC = () => {
  166. return (
  167. <div className="chart-dashboard">
  168. <DashboardOverview />
  169. <div style={{ height: 24 }} />
  170. <Row gutter={[16, 16]}>
  171. <Col xs={24} lg={12}>
  172. <UserActivityChart />
  173. </Col>
  174. <Col xs={24} lg={12}>
  175. <FileUploadsChart />
  176. </Col>
  177. <Col xs={24}>
  178. <FileTypesChart />
  179. </Col>
  180. </Row>
  181. </div>
  182. );
  183. };