pages_asset_transfer_chart.tsx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import React from 'react';
  2. import {
  3. Table, Card, Typography
  4. } from 'antd';
  5. import {
  6. useQuery,
  7. } from '@tanstack/react-query';
  8. import { Pie } from "@ant-design/plots";
  9. import 'dayjs/locale/zh-cn';
  10. import type {
  11. StateChartDataWithPercent,
  12. } from '../share/monitorTypes.ts';
  13. import { MonitorChartsAPI } from './api/index.ts';
  14. interface ChartTooltipInfo {
  15. items: Array<Record<string, any>>;
  16. title: string;
  17. }
  18. // 资产流转状态图表页面
  19. export const AssetTransferChartPage = () => {
  20. const { data: stateData, isLoading } = useQuery({
  21. queryKey: ['adminZichanState'],
  22. queryFn: MonitorChartsAPI.fetchStateData
  23. });
  24. const { Title } = Typography;
  25. return (
  26. <div>
  27. <Title level={2}>资产流转状态分布</Title>
  28. <Card loading={isLoading}>
  29. <div style={{ height: '500px' }}>
  30. {stateData && (
  31. <Pie
  32. data={stateData}
  33. angleField="设备数"
  34. colorField="资产流转"
  35. radius={0.9}
  36. innerRadius={0.8}
  37. label={{
  38. position: 'outside',
  39. text: ({ 资产流转, 设备数, 百分比, percent }: StateChartDataWithPercent & { percent: number }) => {
  40. // 只有占比超过5%的项才显示标签
  41. if (percent < 0.05) return null;
  42. return `${资产流转}\n(${设备数})`;
  43. },
  44. style: {
  45. fill: '#000',
  46. fontSize: 12,
  47. fontWeight: 500,
  48. },
  49. transform: [{ type: 'overlapDodgeY' }],
  50. }}
  51. theme={{
  52. colors10: ['#36cfc9', '#ff4d4f', '#ffa940', '#73d13d', '#4096ff'],
  53. }}
  54. interactions={[
  55. { type: 'element-active' },
  56. { type: 'element-selected' }
  57. ]}
  58. interaction={{
  59. tooltip: {
  60. render: (_: unknown, { items, title }: ChartTooltipInfo) => {
  61. if (!items || items.length === 0) return '';
  62. // 获取当前选中项的数据
  63. const item = items[0];
  64. // 根据value找到对应的完整数据项
  65. const fullData = stateData?.find(d => d['设备数'] === item.value);
  66. if (!fullData) return '';
  67. return `<div class="bg-white p-2 rounded">
  68. <div class="flex items-center">
  69. <div class="w-3 h-3 rounded-full mr-2" style="background:${item.color}"></div>
  70. <span class="font-semibold text-gray-900">${fullData['资产流转']}</span>
  71. </div>
  72. <p class="text-sm text-gray-800">数量: ${item.value}</p>
  73. <p class="text-sm text-gray-800">占比: ${fullData['百分比']}%</p>
  74. </div>`;
  75. }
  76. }
  77. }}
  78. />
  79. )}
  80. </div>
  81. </Card>
  82. <Card style={{ marginTop: '16px' }}>
  83. <Title level={4}>数据明细</Title>
  84. <Table
  85. dataSource={stateData}
  86. rowKey={(record) => record['资产流转']}
  87. columns={[
  88. {
  89. title: '资产流转状态',
  90. dataIndex: '资产流转',
  91. key: '资产流转',
  92. },
  93. {
  94. title: '设备数量',
  95. dataIndex: '设备数',
  96. key: '设备数',
  97. sorter: (a, b) => a['设备数'] - b['设备数'],
  98. },
  99. {
  100. title: '占比',
  101. dataIndex: '百分比',
  102. key: '百分比',
  103. render: (text) => `${text}%`,
  104. sorter: (a, b) => parseFloat(a['百分比']) - parseFloat(b['百分比']),
  105. }
  106. ]}
  107. pagination={false}
  108. />
  109. </Card>
  110. </div>
  111. );
  112. };