index.tsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. import React, { useEffect, useState } from 'react'
  2. import Container, { ContainerBody } from 'components/Container'
  3. import Helmet from 'react-helmet'
  4. import Box from 'components/Box'
  5. import styles from 'containers/DataManagerView/index.less'
  6. import {
  7. Button,
  8. Divider,
  9. Dropdown,
  10. Icon,
  11. Menu,
  12. message,
  13. Popconfirm,
  14. Spin,
  15. Table
  16. } from 'antd'
  17. import classnames from 'classnames'
  18. import request from 'utils/request'
  19. import api from 'utils/api'
  20. import { ColumnProps } from 'antd/lib/table'
  21. import {
  22. IClassification,
  23. IQualityTask
  24. } from 'containers/DataGovernanceQualityAudit/types'
  25. import ClassificationsFormModal from 'containers/DataGovernanceQualityAudit/components/ClassificationsFormModal'
  26. import QualityTaskFormModal from 'containers/DataGovernanceQualityAudit/components/QualityTaskFormModal'
  27. import ScheduleFormModal from 'containers/DataGovernanceQualityAudit/components/ScheduleFormModal'
  28. // import header from 'containers/Display/Editor/Header'
  29. import { RouteComponentProps, withRouter } from 'react-router-dom'
  30. function DataGovernanceQualityAudit(props: RouteComponentProps) {
  31. const { history, match } = props
  32. const [tableLoading, setTableLoading] = useState(false)
  33. const [treeLoading, setTreeLoading] = useState(false)
  34. const [selectedKey, setSelectedKey] = useState<number>()
  35. const [qualityTasks, setQualityTasks] = useState<IQualityTask[]>([])
  36. const [qtVisible, setQtVisible] = useState(false)
  37. const [qtLoading, setQtLoading] = useState(false)
  38. // eslint-disable-next-line no-undef
  39. const [qtForm, setQtForm] = useState<Partial<IQualityTask>>({})
  40. const [classifications, setClassifications] = useState<IClassification[]>([])
  41. const [cfVisible, setCfVisible] = useState(false)
  42. const [cfLoading, setCfLoading] = useState(false)
  43. const [cfForm, setCfForm] = useState<IClassification>({})
  44. const [scVisible, setScVisible] = useState(false)
  45. const [scLoading, setSCLoading] = useState(false)
  46. const [scForm, setSCForm] = useState<IClassification>({})
  47. const tableColumns: Array<ColumnProps<IQualityTask>> = [
  48. {
  49. title: '任务名称',
  50. dataIndex: 'taskName'
  51. },
  52. {
  53. title: '元数据名称',
  54. dataIndex: 'metadataName'
  55. },
  56. {
  57. title: '稽核字段个数',
  58. dataIndex: 'auditorCount'
  59. },
  60. {
  61. title: '操作',
  62. render: (_, data) => (
  63. <>
  64. <a
  65. onClick={() => {
  66. setQtVisible(true)
  67. setQtForm(data)
  68. }}
  69. >
  70. 编辑
  71. </a>
  72. <Divider type='vertical' />
  73. <Dropdown
  74. overlay={
  75. <Menu>
  76. <Menu.Item
  77. key='00'
  78. onClick={() => {
  79. // eslint-disable-next-line react/prop-types
  80. history.push(`/project/${match.params.projectId}/dataGovernance/auditAnalysiss?systemId=${data.pId}&starTime=${data.startTime}&endTime=${data.endTime}`)
  81. }}
  82. >
  83. 稽查历史
  84. </Menu.Item>
  85. <Menu.Item
  86. key='0'
  87. onClick={() => {
  88. setQtForm(data)
  89. setScVisible(true)
  90. }}
  91. >
  92. 设置调度
  93. </Menu.Item>
  94. <Menu.Item key='1'>
  95. <Popconfirm
  96. title='确定立即稽查吗?'
  97. placement='bottom'
  98. onConfirm={() => handleSetDispatchRightNow(data)}
  99. >
  100. <a>立即稽查</a>
  101. </Popconfirm>
  102. </Menu.Item>
  103. <Menu.Item key='3'>
  104. <Popconfirm
  105. title='确定删除?'
  106. placement='bottom'
  107. onConfirm={() => handleDeleteTask(data.id)}
  108. >
  109. <a>删除</a>
  110. </Popconfirm>
  111. </Menu.Item>
  112. </Menu>
  113. }
  114. >
  115. <a>
  116. {' '}
  117. 更多 <Icon type='down' />
  118. </a>
  119. </Dropdown>
  120. </>
  121. )
  122. }
  123. ]
  124. const handleEditTreeItem = (form: IClassification) => {
  125. setCfForm(form)
  126. setCfVisible(true)
  127. }
  128. const handleDeleteTreeItem = async(c: IClassification) => {
  129. try {
  130. setTreeLoading(true)
  131. const data = await request(`${api.deleteAuditClassification}${c.id}`, {
  132. method: 'DELETE'
  133. })
  134. // @ts-ignore
  135. if (data?.header?.code === 200) {
  136. message.success({ content: '删除成功' })
  137. await queryClassifications()
  138. } else {
  139. // @ts-ignore
  140. // tslint:disable-next-line:no-unused-expression
  141. data?.header?.msg && message.error({ content: data?.header?.msg })
  142. }
  143. } finally {
  144. setTreeLoading(false)
  145. }
  146. }
  147. const renderTree = (catalogues: IClassification[]) => (
  148. <>
  149. {catalogues.map((c, idx) => (
  150. <div
  151. key={c.id ?? idx}
  152. className={classnames(styles.treeNode, {
  153. [styles.treeNodeSelected]: selectedKey === c.id
  154. })}
  155. >
  156. <span
  157. className={styles.treeNodeLeft}
  158. onClick={() => {
  159. setSelectedKey(c.id)
  160. }}
  161. >
  162. <Icon type='file' />
  163. {c.name}
  164. </span>
  165. <Dropdown
  166. overlay={() => (
  167. <Menu>
  168. <Menu.Item key='0' onClick={() => handleEditTreeItem(c)}>
  169. 编辑
  170. </Menu.Item>
  171. <Menu.Item key='1'>
  172. <Popconfirm
  173. title='确定删除?'
  174. placement='bottom'
  175. onConfirm={() => handleDeleteTreeItem(c)}
  176. >
  177. <a>删除</a>
  178. </Popconfirm>
  179. </Menu.Item>
  180. </Menu>
  181. )}
  182. trigger={['click']}
  183. >
  184. <Icon type='more' />
  185. </Dropdown>
  186. </div>
  187. ))}
  188. </>
  189. )
  190. const handleSetDispatchRightNow = async(data: IQualityTask) => {
  191. try {
  192. setTableLoading(true)
  193. const result = await request(`${api.setDispatchRightNow}${data.id}`, {
  194. method: 'GET'
  195. }).catch((err) => {
  196. if (err?.response?.data?.header?.msg) {
  197. message.error({ content: err?.response?.data?.header?.msg })
  198. }
  199. })
  200. // @ts-ignore
  201. if (result?.header?.code === 200) {
  202. message.success({ content: '立即稽核完成' })
  203. }
  204. } finally {
  205. setTableLoading(false)
  206. }
  207. }
  208. const handleDispatch = async(form) => {
  209. try {
  210. setSCLoading(true)
  211. const result = await request(`${api.setDispatch}${qtForm.id}`, {
  212. method: 'PUT',
  213. data: {
  214. // @ts-ignore
  215. projectId: match.params?.projectId,
  216. name: qtForm.taskName,
  217. // taskName: qtForm.taskName,
  218. cronExpression: form.cronExpression,
  219. startDate: form.startDate[0].format('YYYY-MM-DD hh:mm:ss'),
  220. endDate: form.startDate[1].format('YYYY-MM-DD hh:mm:ss'),
  221. periodUnit: form.periodUnit,
  222. jobStatus: form.jobStatus ? 'started' : 'new',
  223. jobType: 'auditor'
  224. }
  225. })
  226. // @ts-ignore
  227. if (result.header.code === 200) {
  228. setScVisible(false);
  229. message.success({ content: '设置调度成功' })
  230. queryQualityTasks()
  231. }
  232. } finally {
  233. setSCLoading(false)
  234. }
  235. }
  236. const queryClassifications = async() => {
  237. try {
  238. setTreeLoading(true)
  239. const data = await request(api.getAuditClassification, { method: 'GET' })
  240. // @ts-ignore
  241. setClassifications(data?.payload ?? [])
  242. // @ts-ignore
  243. setSelectedKey(data?.payload?.[0]?.id)
  244. } finally {
  245. setTreeLoading(false)
  246. }
  247. }
  248. const queryQualityTasks = async() => {
  249. try {
  250. setTableLoading(true)
  251. const data = await request(`${api.getQualityTask}?pId=${selectedKey}`, {
  252. method: 'GET'
  253. })
  254. // @ts-ignore
  255. setQualityTasks(data?.payload ?? [])
  256. } finally {
  257. setTableLoading(false)
  258. }
  259. }
  260. const handleSaveCfForm = async(form: IClassification) => {
  261. try {
  262. setCfLoading(true)
  263. const url = cfForm.id
  264. ? api.updateAuditClassification + cfForm.id
  265. : api.createAuditClassification
  266. const result = await request(url, {
  267. method: cfForm.id ? 'PUT' : 'POST',
  268. data: { ...cfForm, ...form }
  269. })
  270. // @ts-ignore
  271. if (result?.header?.code === 200) {
  272. setCfVisible(false)
  273. await queryClassifications()
  274. }
  275. } finally {
  276. setCfLoading(false)
  277. }
  278. }
  279. const handleSaveQtForm = async(view) => {
  280. try {
  281. setQtLoading(true)
  282. const url = qtForm?.id
  283. ? api.updateQualityTask + qtForm?.id
  284. : api.createQualityTask
  285. const result = await request(url, {
  286. method: qtForm?.id ? 'PUT' : 'POST',
  287. data: { ...qtForm, ...view }
  288. })
  289. // @ts-ignore
  290. if (result?.header?.code === 200) {
  291. setQtVisible(false)
  292. await queryQualityTasks()
  293. }
  294. } finally {
  295. setQtLoading(false)
  296. }
  297. }
  298. const handleDeleteTask = async(id: number) => {
  299. try {
  300. setTableLoading(true)
  301. const data = await request(`${api.deleteQualityTask}${id}`, {
  302. method: 'DELETE'
  303. })
  304. // @ts-ignore
  305. if (data.header.code === 200) {
  306. message.success({ content: '删除成功' })
  307. queryQualityTasks()
  308. }
  309. } finally {
  310. setTableLoading(false)
  311. }
  312. }
  313. useEffect(() => {
  314. queryClassifications()
  315. }, [])
  316. useEffect(() => {
  317. if (selectedKey) {
  318. queryQualityTasks()
  319. }
  320. }, [selectedKey])
  321. return (
  322. <Container>
  323. <Helmet title='质量稽核' />
  324. <ContainerBody>
  325. <Box>
  326. <Box.Header>
  327. <Box.Title>质量稽核</Box.Title>
  328. </Box.Header>
  329. <Box.Body>
  330. <div className={styles.treeTableContainer}>
  331. <div className={styles.treeContainer}>
  332. <div className={styles.treeTitle}>
  333. <h6>数据质量</h6>
  334. <div
  335. className={styles.treePlusNode}
  336. onClick={() => {
  337. setCfForm({})
  338. setCfVisible(true)
  339. }}
  340. >
  341. <Icon type='plus' />
  342. </div>
  343. </div>
  344. <div className={styles.treeContent}>
  345. <Spin spinning={treeLoading}>
  346. {renderTree(classifications)}
  347. </Spin>
  348. </div>
  349. </div>
  350. <div style={{ flex: 1 }}>
  351. <div style={{ padding: '0 0 20px' }}>
  352. <Button
  353. type='primary'
  354. icon='plus'
  355. onClick={() => {
  356. setQtVisible(true)
  357. setQtForm(null)
  358. }}
  359. >
  360. 新增
  361. </Button>
  362. </div>
  363. <Table
  364. style={{ flex: 1 }}
  365. bordered
  366. rowKey='id'
  367. loading={tableLoading}
  368. dataSource={qualityTasks}
  369. columns={tableColumns}
  370. pagination={false}
  371. // onChange={this.tableChange}
  372. />
  373. </div>
  374. </div>
  375. <br />
  376. </Box.Body>
  377. </Box>
  378. </ContainerBody>
  379. <ClassificationsFormModal
  380. visible={cfVisible}
  381. formView={cfForm}
  382. onSave={handleSaveCfForm}
  383. loading={cfLoading}
  384. onCancel={() => setCfVisible(false)}
  385. />
  386. <QualityTaskFormModal
  387. pId={selectedKey}
  388. visible={qtVisible}
  389. formView={qtForm}
  390. onSave={handleSaveQtForm}
  391. loading={qtLoading}
  392. onCancel={() => setQtVisible(false)}
  393. />
  394. <ScheduleFormModal
  395. visible={scVisible}
  396. loading={scLoading}
  397. formView={scForm}
  398. onSave={handleDispatch}
  399. onCancel={() => setScVisible(false)}
  400. />
  401. </Container>
  402. )
  403. }
  404. export default withRouter(DataGovernanceQualityAudit)