index.jsx 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. import { useState, useRef, useMemo } from 'react'
  2. import BasicTable from '@/components/Table'
  3. import { DatePicker, Table, Typography } from 'antd'
  4. import { querySoftwareUsageList } from '@/services/statistic'
  5. import consts from '@/consts'
  6. import dayjs from 'dayjs'
  7. import { Pie } from '@ant-design/charts'
  8. import OptionSelect from '../../components/OptionSelect'
  9. const { Text } = Typography
  10. const colLabelValToZH = {
  11. giftsCount: '赠送',
  12. lendCount: '借出',
  13. salesCount: '销售'
  14. }
  15. const Usage = () => {
  16. const tRef = useRef(null)
  17. const [state, setState] = useState({
  18. params: {
  19. optionType: 'staff',
  20. dataIds: [],
  21. startMonth: [dayjs(new Date()), dayjs(new Date())]
  22. }
  23. })
  24. const pieData = useMemo(() => {
  25. if (!state.chart || !state.sum) return {}
  26. const leftKeys = Object.keys(state.chart)
  27. const pieLeft = []
  28. leftKeys.forEach(item => {
  29. const v = state.chart[item]
  30. pieLeft.push({ label: item === 'unused' ? '未使用' : '已使用', value: v })
  31. })
  32. const rightKeys = Object.keys(state.sum)
  33. const pieRight = []
  34. rightKeys.forEach(item => {
  35. const v = state.sum[item]
  36. if (!['receiveCount', 'createCount'].includes(item)) {
  37. pieRight.push({ label: colLabelValToZH[item], value: v })
  38. }
  39. })
  40. return { pieLeft, pieRight }
  41. }, [state.chart])
  42. const columns = [
  43. {
  44. title: '名称',
  45. dataIndex: 'name',
  46. key: 'name',
  47. width: 100,
  48. fixed: 'left',
  49. align: 'center'
  50. },
  51. {
  52. title: '未使用',
  53. children: [
  54. {
  55. title: '生成',
  56. key: 'create',
  57. dataIndex: 'create',
  58. align: 'center'
  59. },
  60. {
  61. title: '接收',
  62. key: 'receive',
  63. dataIndex: 'receive',
  64. align: 'center'
  65. }
  66. ]
  67. },
  68. {
  69. title: '已使用',
  70. children: [
  71. {
  72. title: '借出',
  73. key: 'lend',
  74. dataIndex: 'lend',
  75. align: 'center'
  76. },
  77. {
  78. title: '销售',
  79. key: 'sales',
  80. dataIndex: 'sales',
  81. align: 'center'
  82. },
  83. {
  84. title: '赠送',
  85. key: 'gifts',
  86. dataIndex: 'gifts',
  87. align: 'center'
  88. }
  89. ]
  90. }
  91. ]
  92. const leftConfig = {
  93. appendPadding: 10,
  94. data: pieData.pieLeft,
  95. angleField: 'value',
  96. colorField: 'label',
  97. radius: 0.9,
  98. color: ['#40B7E6', '#79CE67'],
  99. interactions: [{ type: 'element-active' }]
  100. }
  101. const rightConfig = {
  102. appendPadding: 10,
  103. data: pieData.pieRight,
  104. angleField: 'value',
  105. colorField: 'label',
  106. radius: 0.9,
  107. color: ['#40B7E6', '#79CE67', '#FBD743'],
  108. interactions: [{ type: 'element-active' }]
  109. }
  110. const optionChange = (type, ids) =>
  111. setState({ ...state, params: { ...state.params, optionType: type, dataIds: ids } })
  112. return (
  113. <div className="flex flex-col">
  114. <div className="flex flex-row justify-between mb-4">
  115. <div className="card-transition w-1/2 bg-white mr-2">
  116. {pieData.pieLeft ? <Pie {...leftConfig} /> : null}
  117. </div>
  118. <div className="card-transition w-1/2 bg-white ml-2">
  119. {pieData.pieRight ? <Pie {...rightConfig} /> : null}
  120. </div>
  121. </div>
  122. <BasicTable
  123. // manualRequest
  124. search={false}
  125. columns={columns}
  126. actionRef={tRef}
  127. rowkey="id"
  128. toolbar={{
  129. title: <OptionSelect onChange={optionChange} type="SoftwareUsage" />,
  130. actions: [
  131. <DatePicker.RangePicker
  132. picker="month"
  133. key="DatePicker"
  134. disabled={[false, true]}
  135. value={state.startMonth}
  136. onChange={val => setState({ ...state, params: { ...state.params, startMonth: val } })}
  137. />
  138. ]
  139. }}
  140. params={state.params}
  141. pagination={false}
  142. bordered
  143. request={async (params, sort, filter) => {
  144. const {
  145. code = -1,
  146. data: { list, sum, chart, create }
  147. } = await querySoftwareUsageList({ ...params, ...sort, ...filter })
  148. setState({ ...state, sum, chart, create })
  149. return {
  150. data: list,
  151. success: code === consts.RET_CODE.SUCCESS,
  152. total: list?.length || 0
  153. }
  154. }}
  155. summary={data =>
  156. data?.length ? (
  157. <>
  158. <Table.Summary.Row>
  159. <Table.Summary.Cell className="text-center">小计</Table.Summary.Cell>
  160. <Table.Summary.Cell className="text-center">
  161. {state.sum?.createCount}
  162. </Table.Summary.Cell>
  163. <Table.Summary.Cell className="text-center">
  164. {state.sum?.receiveCount}
  165. </Table.Summary.Cell>
  166. <Table.Summary.Cell className="text-center">
  167. {state.sum?.lendCount}
  168. </Table.Summary.Cell>
  169. <Table.Summary.Cell className="text-center">
  170. {state.sum?.salesCount}
  171. </Table.Summary.Cell>
  172. <Table.Summary.Cell className="text-center">
  173. {state.sum?.giftsCount}
  174. </Table.Summary.Cell>
  175. </Table.Summary.Row>
  176. <Table.Summary.Row>
  177. <Table.Summary.Cell className="text-center">总计</Table.Summary.Cell>
  178. <Table.Summary.Cell colSpan={2} className="text-center">
  179. <Text type="danger">
  180. {(state.sum?.createCount || 0) + state.sum?.receiveCount}
  181. </Text>
  182. </Table.Summary.Cell>
  183. <Table.Summary.Cell colSpan={3} className="text-center">
  184. <Text type="danger">
  185. {state.sum?.lendCount + state.sum?.salesCount + state.sum?.giftsCount}
  186. </Text>
  187. </Table.Summary.Cell>
  188. </Table.Summary.Row>
  189. </>
  190. ) : null
  191. }
  192. />
  193. </div>
  194. )
  195. }
  196. export default Usage