index.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. import React, { useEffect, useMemo, useState } from 'react'
  2. import Helmet from 'react-helmet'
  3. import Container, { ContainerBody } from 'components/Container'
  4. import Box from 'components/Box'
  5. import { Button, DatePicker, message, Progress, Select, Table } from 'antd'
  6. import { ColumnProps } from 'antd/lib/table'
  7. import { IReport } from 'containers/DataGovernanceAuaitAnalysis/types'
  8. import api from 'utils/api'
  9. import request from 'utils/request'
  10. import styles from './index.less'
  11. import { AnalysisReportDetailModal } from 'containers/DataGovernanceAuaitAnalysis/AnalysisReportDetailModal'
  12. import { IClassification } from 'containers/DataGovernanceQualityAudit/types'
  13. import moment, { Moment } from 'moment'
  14. export default function DataGovernanceAuaitAnalysis() {
  15. const [tableLoading, setTableLoading] = useState(false)
  16. const [detailVisible, setDetailVisible] = useState(false)
  17. const [detailForm, setDetailForm] = useState<IReport>()
  18. const [reports, setReports] = useState<IReport[]>([])
  19. const [classifications, setClassifications] = useState<IClassification[]>([])
  20. const [systemId, setSystemId] = useState<number>(null)
  21. const [time, setTime] = useState<Moment>(moment())
  22. const workbench = useMemo(() => {
  23. const total = reports
  24. .map(
  25. (item) =>
  26. item.accuracyCorrect ??
  27. 0 + item.accuracyError ??
  28. 0 + item.integrityCorrect ??
  29. 0 + item.integrityError ??
  30. 0 + item.normativeCorrect ??
  31. 0 + item.normativeError ??
  32. 0 + item.uniformityCorrect ??
  33. 0 + item.uniformityError ??
  34. 0
  35. )
  36. .reduce((c, n) => c + n, 0)
  37. const totalCorrect = reports
  38. .map(
  39. (item) =>
  40. item.accuracyCorrect ??
  41. 0 + item.integrityCorrect ??
  42. 0 + item.normativeCorrect ??
  43. 0 + item.uniformityCorrect ??
  44. 0
  45. )
  46. .reduce((c, n) => c + n, 0)
  47. // 完整性
  48. const integrityCorrect = reports
  49. .map((item) => item.integrityCorrect ?? 0)
  50. .reduce((c, n) => c + n, 0)
  51. const integrityTotal = reports
  52. .map((item) => item.integrityCorrect ?? 0 + item.integrityError)
  53. .reduce((c, n) => c + n, 0)
  54. // 一致性
  55. const uniformityCorrect = reports
  56. .map((item) => item.uniformityCorrect ?? 0)
  57. .reduce((c, n) => c + n, 0)
  58. const uniformityTotal = reports
  59. .map((item) => item.uniformityCorrect ?? 0 + item.uniformityError)
  60. .reduce((c, n) => c + n, 0)
  61. // 规范性
  62. const normativeCorrect = reports
  63. .map((item) => item.normativeCorrect ?? 0)
  64. .reduce((c, n) => c + n, 0)
  65. const normativeTotal = reports
  66. .map((item) => item.normativeCorrect ?? 0 + item.normativeError)
  67. .reduce((c, n) => c + n, 0)
  68. // 准确性
  69. const accuracyCorrect = reports
  70. .map((item) => item.accuracyCorrect ?? 0)
  71. .reduce((c, n) => c + n, 0)
  72. const accuracyTotal = reports
  73. .map((item) => item.accuracyCorrect ?? 0 + item.accuracyError)
  74. .reduce((c, n) => c + n, 0)
  75. return [
  76. {
  77. title: '总概率',
  78. rateLabel: '正确率',
  79. rateValue: ((totalCorrect / total || 0) * 100).toFixed(2) ?? '',
  80. countLabel: '正确数量',
  81. countValue: totalCorrect ?? 0,
  82. totalLabel: '总数据量',
  83. totalValue: total ?? 0,
  84. color: '#1890ff'
  85. },
  86. {
  87. title: '完整性',
  88. rateLabel: '正确率',
  89. rateValue:
  90. ((integrityCorrect / integrityTotal || 0) * 100).toFixed(2) ?? '',
  91. countLabel: '正确数量',
  92. countValue: integrityCorrect,
  93. totalLabel: '总数据量',
  94. totalValue: integrityTotal,
  95. color: '#52c41a'
  96. },
  97. {
  98. title: '一致性',
  99. rateLabel: '正确率',
  100. rateValue:
  101. ((uniformityCorrect / uniformityTotal || 0) * 100).toFixed(2) ?? '',
  102. countLabel: '正确数量',
  103. countValue: uniformityCorrect,
  104. totalLabel: '总数据量',
  105. totalValue: uniformityTotal,
  106. color: '#fa8c16'
  107. },
  108. {
  109. title: '规范性',
  110. rateLabel: '正确率',
  111. rateValue:
  112. ((normativeCorrect / normativeTotal || 0) * 100).toFixed(2) ?? '',
  113. countLabel: '正确数量',
  114. countValue: normativeCorrect,
  115. totalLabel: '总数据量',
  116. totalValue: normativeTotal,
  117. color: '#1890ff'
  118. },
  119. {
  120. title: '准确性',
  121. rateLabel: '正确率',
  122. rateValue:
  123. ((accuracyCorrect / accuracyTotal || 0) * 100).toFixed(2) ?? '',
  124. countLabel: '正确数量',
  125. countValue: accuracyCorrect,
  126. totalLabel: '总数据量',
  127. totalValue: accuracyTotal,
  128. color: '#722ed1'
  129. }
  130. ]
  131. }, [reports])
  132. const tableColumns: Array<ColumnProps<IReport>> = [
  133. {
  134. title: '任务名称',
  135. dataIndex: 'taskName'
  136. },
  137. {
  138. title: '稽查时间',
  139. dataIndex: 'auditorTime'
  140. },
  141. {
  142. title: '系统名称',
  143. dataIndex: 'typeName'
  144. },
  145. {
  146. title: '元数据名称',
  147. dataIndex: 'metadataName'
  148. },
  149. {
  150. title: '完整性',
  151. children: [
  152. {
  153. title: '正确数量',
  154. dataIndex: 'integrityCorrect'
  155. },
  156. {
  157. title: '错误数量',
  158. dataIndex: 'integrityError'
  159. },
  160. {
  161. title: '正确率',
  162. dataIndex: 'integrityCorrectProbability'
  163. },
  164. {
  165. title: '错误率',
  166. dataIndex: 'integrityErrorProbability'
  167. }
  168. ]
  169. },
  170. {
  171. title: '一致性',
  172. children: [
  173. {
  174. title: '正确数量',
  175. dataIndex: 'uniformityCorrect'
  176. },
  177. {
  178. title: '错误数量',
  179. dataIndex: 'uniformityError'
  180. },
  181. {
  182. title: '正确率',
  183. dataIndex: 'uniformityCorrectProbability'
  184. },
  185. {
  186. title: '错误率',
  187. dataIndex: 'uniformityErrorProbability'
  188. }
  189. ]
  190. },
  191. {
  192. title: '规范性',
  193. children: [
  194. {
  195. title: '正确数量',
  196. dataIndex: 'normativeCorrect'
  197. },
  198. {
  199. title: '错误数量',
  200. dataIndex: 'normativeError'
  201. },
  202. {
  203. title: '正确率',
  204. dataIndex: 'normativeCorrectProbability'
  205. },
  206. {
  207. title: '错误率',
  208. dataIndex: 'normativeErrorProbability'
  209. }
  210. ]
  211. },
  212. {
  213. title: '准确性',
  214. children: [
  215. {
  216. title: '正确数量',
  217. dataIndex: 'accuracyCorrect'
  218. },
  219. {
  220. title: '错误数量',
  221. dataIndex: 'accuracyError'
  222. },
  223. {
  224. title: '正确率',
  225. dataIndex: 'accuracyCorrectProbability'
  226. },
  227. {
  228. title: '错误率',
  229. dataIndex: 'accuracyErrorProbability'
  230. }
  231. ]
  232. },
  233. {
  234. title: '操作',
  235. fixed: 'right',
  236. width: 50,
  237. render: (_, data) => (
  238. <span
  239. onClick={() => {
  240. setDetailVisible(true)
  241. setDetailForm(data)
  242. }}
  243. >
  244. 详情
  245. </span>
  246. )
  247. }
  248. ]
  249. const queryReports = async () => {
  250. if (!systemId || !time) {
  251. return
  252. }
  253. try {
  254. setTableLoading(true)
  255. const data = await request(
  256. `${api.qualityReport}?systemId=${systemId}&time=${time.format(
  257. 'YYYY-MM-DD'
  258. )}`,
  259. {
  260. method: 'GET'
  261. }
  262. )
  263. // @ts-ignore
  264. setReports(data?.payload ?? [])
  265. } finally {
  266. setTableLoading(false)
  267. }
  268. }
  269. const querySystem = async () => {
  270. try {
  271. setTableLoading(true)
  272. const data = await request(`${api.getAuditClassification}`, {
  273. method: 'GET'
  274. })
  275. // @ts-ignore
  276. setClassifications(data?.payload ?? [])
  277. // @ts-ignore
  278. setSystemId(data?.payload?.[0].id)
  279. } finally {
  280. setTableLoading(false)
  281. }
  282. }
  283. const handleQuery = () => {
  284. if (!systemId || !time) {
  285. message.info({ content: '请输入主题或时间' })
  286. return
  287. }
  288. queryReports()
  289. }
  290. useEffect(() => {
  291. async function query() {
  292. await querySystem()
  293. await queryReports()
  294. }
  295. query()
  296. }, [])
  297. return (
  298. <Container>
  299. <Helmet title="稽核分析" />
  300. <ContainerBody>
  301. <Box>
  302. <Box.Header>
  303. <Box.Title>稽核分析</Box.Title>
  304. </Box.Header>
  305. <div style={{ padding: 20 }} />
  306. <Box.Body>
  307. <div className={styles['audit-analysiss-search-content']}>
  308. <div>
  309. <span>系统选择:</span>
  310. <Select
  311. value={systemId}
  312. style={{ width: 200 }}
  313. onChange={(e) => setSystemId(e)}
  314. >
  315. {classifications.map((c) => (
  316. <Select.Option key={c.id} value={c.id}>
  317. {c.name}
  318. </Select.Option>
  319. ))}
  320. </Select>
  321. </div>
  322. <div>
  323. <span>时间选择:</span>
  324. <DatePicker
  325. onChange={(e) => setTime(e)}
  326. value={time}
  327. format="YYYY-MM-DD"
  328. />
  329. </div>
  330. <Button onClick={handleQuery}>查询</Button>
  331. </div>
  332. <div className={styles['audit-analysiss-card-content']}>
  333. {workbench?.map((item, idx) => (
  334. <div
  335. key={item.title}
  336. className={styles['audit-analysiss-card-item']}
  337. >
  338. <div className={styles['audit-analysiss-card-item-title']}>
  339. {item.title}
  340. </div>
  341. <div className={styles['audit-analysiss-card-item-rate']}>
  342. <div
  343. className={styles['audit-analysiss-card-item-rate-label']}
  344. >
  345. <span>正确率</span>
  346. <span>{item.rateValue ?? '-'}%</span>
  347. </div>
  348. <Progress
  349. showInfo={false}
  350. strokeColor={item.color}
  351. percent={Number(item.rateValue ?? 0)}
  352. />
  353. </div>
  354. <div className={styles['audit-analysiss-card-item-number']}>
  355. <div
  356. className={
  357. styles['audit-analysiss-card-item-number-count']
  358. }
  359. >
  360. <span>正确数量</span>
  361. <span>{item.countValue ?? '-'}</span>
  362. </div>
  363. <div
  364. className={
  365. styles['audit-analysiss-card-item-number-total']
  366. }
  367. >
  368. <span>总数据量</span>
  369. <span>{item.totalValue ?? '-'}</span>
  370. </div>
  371. </div>
  372. </div>
  373. ))}
  374. </div>
  375. <Table
  376. style={{ flex: 1 }}
  377. bordered
  378. rowKey="id"
  379. loading={tableLoading}
  380. dataSource={reports}
  381. columns={tableColumns}
  382. pagination={false}
  383. />
  384. <div style={{ padding: 20 }} />
  385. <AnalysisReportDetailModal
  386. visible={detailVisible}
  387. tableColumns={tableColumns}
  388. formView={detailForm}
  389. />
  390. </Box.Body>
  391. </Box>
  392. </ContainerBody>
  393. </Container>
  394. )
  395. }