index.tsx 12 KB

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