index.tsx 13 KB

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