CommitAuditModal.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. import React, { useEffect, useState, useRef, useMemo, useCallback } from 'react';
  2. import '@ant-design/compatible/assets/index.css';
  3. import {
  4. Modal,
  5. Input,
  6. Select,
  7. message,
  8. Cascader,
  9. Form,
  10. Tabs,
  11. Row,
  12. Col,
  13. Empty,
  14. Button,
  15. Steps,
  16. Popover,
  17. Upload,
  18. Table,
  19. Divider,
  20. Collapse,
  21. } from 'antd';
  22. import { PlusOutlined, UploadOutlined } from '@ant-design/icons';
  23. import { connect } from 'dva';
  24. import { isArray, result, set } from 'lodash';
  25. import { useForm } from 'rc-field-form';
  26. import { async } from '@antv/x6/lib/registry/marker/async';
  27. import AuditDetailed from './AuditDetailed';
  28. import AuditFlow from './AuditFlow';
  29. import {
  30. queryDingSchema,
  31. queryGetBomForm,
  32. queryProcessFlows,
  33. querySaveBomForm,
  34. } from '@/services/boom';
  35. import { Form as Form3x } from '@ant-design/compatible';
  36. import { getCurrentUser } from '@/utils/authority';
  37. import DDCode from '@/components/DDComponents/DDCode';
  38. import { uploadFile, queryUserListByRoleID } from '@/services/boom';
  39. import ApprovalProcess from './ApprovalProcess';
  40. import { uuidv4 } from '@antv/xflow';
  41. import AliyunOSSUpload from '@/components/OssUpload/AliyunOssUploader';
  42. import AttachmentTable from '@/components/AttachmentTable';
  43. const { TextArea } = Input;
  44. const { Option } = Select;
  45. const { TabPane } = Tabs;
  46. const { Step } = Steps;
  47. // 提交
  48. function CommitAuditModal(props) {
  49. const {
  50. dispatch,
  51. visible,
  52. onClose,
  53. loading,
  54. version,
  55. versionList,
  56. flowDetail,
  57. currentUser,
  58. luckysheet,
  59. userList,
  60. templateId,
  61. OSSData,
  62. } = props;
  63. // console.log(loading);
  64. const [auditId, setAuditId] = useState();
  65. const [data, setData] = useState([]);
  66. const [length, setLength] = useState(1);
  67. const [formData, setFromData] = useState({});
  68. const [auditList, setAuditList] = useState([]); //用于创建Tabs表单
  69. const [formComponentValues, setFormComponentValues] = useState({}); //用于创建Tabs表单
  70. const [form] = Form.useForm();
  71. const [approvalProcess, setApprovalProcess] = useState({});
  72. const [selectUserList, setSelectUserList] = useState([]);
  73. const [curNodeIdx, setCurNodeIdx] = useState(-1);
  74. const [dataSource, setDataSource] = useState([]);
  75. const uploadList = useRef([]);
  76. useEffect(() => {
  77. if (!visible) return;
  78. const { edges, nodes } = flowDetail;
  79. // initFormList().then(approvalProcess => {
  80. let Id = version.template_node_id;
  81. const currentId = flowDetail.nodes.find?.(item => item.Id == Id)?.node_id;
  82. const data = treeData(currentId);
  83. console.log('===============审批节点======', data);
  84. if (data.length <= 0) {
  85. setAuditId(currentId);
  86. } else {
  87. let defaultValues = {};
  88. if (data.length == 1) {
  89. let value = getDataValue(data[0]);
  90. defaultValues[`circle`] = value;
  91. } else {
  92. data.forEach((item, index) => {
  93. let value = getDataValue(item);
  94. defaultValues[`circle${index}`] = value;
  95. });
  96. }
  97. // 设置延迟,等待组件渲染
  98. setTimeout(async () => {
  99. form.setFieldsValue(defaultValues);
  100. const approvalProcess = await initFormList();
  101. Object.values(defaultValues).forEach(value => onChange(value, approvalProcess || {}));
  102. }, 200);
  103. }
  104. setData(data);
  105. // });
  106. }, [version.template_node_id, visible]);
  107. useEffect(() => {
  108. if (!visible) return;
  109. dispatch({
  110. type: 'detail/getChartOSSData',
  111. payload: {
  112. projectId: version.project_id,
  113. },
  114. });
  115. }, [visible]);
  116. useEffect(() => {
  117. form.resetFields();
  118. setAuditList([]);
  119. }, [visible]);
  120. // const OnModelFileDone = file => {
  121. // var path = OSSData.host + '/' + file.url;
  122. // uploadList.current = [...uploadList.current, path];
  123. // console.log(uploadList.current);
  124. // };
  125. const setUploadList = files => {
  126. uploadList.current = files.map(file => OSSData.host + '/' + file.url);
  127. console.log(uploadList.current);
  128. };
  129. const OnUploading = file => {};
  130. const uploadProps = {
  131. OSSData: OSSData,
  132. // onDone: OnModelFileDone,
  133. onUploading: OnUploading,
  134. noStyle: false,
  135. onChange: setUploadList,
  136. // showUploadList: false,
  137. };
  138. const initFormList = async () => {
  139. const res = await queryGetBomForm({
  140. project_id: version.project_id,
  141. node_id: version.template_node_id,
  142. });
  143. if (res.data) {
  144. const formList = JSON.parse(res.data.json);
  145. setApprovalProcess(formList.approvalProcess || {});
  146. return formList.approvalProcess;
  147. // setFormComponentValues(defaultFormData);
  148. }
  149. };
  150. const treeData = currentId => {
  151. const list = getNextNodes(currentId, 'custom-circle');
  152. const fun = nodes => {
  153. const re = nodes?.forEach((item, idx) => {
  154. const data = getNextNodes(item.Id, 'custom-circle');
  155. if (data || data.length > 0) list.push(...data);
  156. fun(data);
  157. });
  158. };
  159. fun(list);
  160. const fun2 = list => {
  161. const parents = list.filter(item => list.findIndex(node => node.Id == item.parentId) == -1);
  162. let translator = (parents, children) => {
  163. setLength(length + 1);
  164. parents.forEach(parent => {
  165. children.forEach((current, index) => {
  166. if (current.parentId === parent.Id) {
  167. let temp = JSON.parse(JSON.stringify(children));
  168. temp.splice(index, 1);
  169. translator([current], temp);
  170. if (!parent.children.find(item => item.Id == current.Id))
  171. parent.children.push(current);
  172. }
  173. });
  174. });
  175. };
  176. translator(parents, list);
  177. return parents;
  178. };
  179. return fun2(list);
  180. };
  181. const currentNodeId = useMemo(() => {
  182. let Id = version.template_node_id;
  183. setAuditId(currentNodeId);
  184. return flowDetail.nodes.find?.(item => item.Id == Id)?.node_id;
  185. }, [flowDetail, version]);
  186. /**
  187. *
  188. * @param {*} currentId 当前节点
  189. * @param {*} type 下一个节点的类型 custom-circle: 审批节点 custom-rect: 业务节点
  190. * @returns
  191. */
  192. const getNextNodes = (currentId, type) => {
  193. const { edges, nodes } = flowDetail;
  194. if (!currentId) return [];
  195. //删除虚线通向的节点
  196. // let targetIds = edges
  197. // .filter(edge => {
  198. // let line = edge.attrs?.line?.strokeDasharray?.split(' ');
  199. // return edge.source.cell == currentId && line && line[0] == '0';
  200. // })
  201. // .map(item => item.target.cell);
  202. let targetIds = edges
  203. .filter(edge => edge.source.cell == currentId)
  204. .map(item => item.target.cell);
  205. edges.filter(edge => edge.source.cell == currentId);
  206. let auditNodes = nodes.filter(node => {
  207. if (type && node.name != type) {
  208. return false;
  209. }
  210. return targetIds.indexOf(node.id) != -1;
  211. });
  212. const result = auditNodes.map(item => {
  213. return {
  214. label: item.label,
  215. value: item.Id,
  216. Id: item.node_id,
  217. parentId: currentId,
  218. children: [],
  219. };
  220. });
  221. return result || [];
  222. };
  223. const nextNodesList = useMemo(() => {
  224. if (!auditId && !currentNodeId) return [];
  225. return getNextNodes(auditId || currentNodeId, 'custom-rect');
  226. }, [auditId, currentNodeId, flowDetail]);
  227. const changeAudit = id => {
  228. let node = flowDetail.nodes.find?.(item => item.Id == id);
  229. setAuditId(node?.node_id);
  230. };
  231. const onChange = (value, approvalProcess) => {
  232. if (value) {
  233. changeAudit(value[value.length - 1]);
  234. setAuditListFun(approvalProcess);
  235. } else {
  236. changeAudit('');
  237. setAuditList([]);
  238. setApprovalProcess({});
  239. }
  240. form.setFieldValue('next_template_node_id', '');
  241. };
  242. const getReComputeAudit = (items, changedValues) => {
  243. const id = Object.keys(changedValues)[0];
  244. const formItem = items?.find(item => item.props.id == id);
  245. if (formItem && formItem.props?.required) return true;
  246. return false;
  247. };
  248. //填写表单实时计算审批流程
  249. const advanceSubmit = async () => {
  250. console.log('重重新计算审批流程');
  251. var fieldsValue = await form.validateFields();
  252. let hasFlowId = true; //是否都绑定审批节点
  253. let result = Object.values(fieldsValue)
  254. .map(item => {
  255. if (item && Array.isArray(item)) return item;
  256. })
  257. .filter(item => item);
  258. const formList = await getFromData(result);
  259. let params = {
  260. desc: fieldsValue.desc,
  261. // 审核流程id
  262. flow_id: 0,
  263. node_level_id: 0,
  264. id: version.id,
  265. project_id: version.project_id,
  266. cur_template_node_id: version.template_node_id * 1, // 当前节点
  267. next_template_node_id: 0, // 审核完成后的业务节点
  268. template_node_id: null, // 将要流转的节点审批节点
  269. flow_path: null, //审批节点数组
  270. // 模板id.一致就行
  271. template_id: version.template_id,
  272. cur_template_id: version.template_id,
  273. next_template_id: version.template_id,
  274. form_list: formList,
  275. };
  276. dispatch({
  277. type: 'detail/advanceSubmitNextNode',
  278. payload: params, //values,
  279. callback: data => {
  280. if (data) {
  281. setApprovalProcess(data);
  282. }
  283. },
  284. });
  285. };
  286. //处理tabs页
  287. const setAuditListFun = async (approvalProcess = {}) => {
  288. var fieldsValue = await form.validateFields();
  289. let addAuditList = [];
  290. let result = Object.values(fieldsValue)
  291. .map(item => {
  292. if (item && Array.isArray(item)) return item;
  293. })
  294. .filter(item => item)
  295. .flat(Infinity);
  296. let nodeList = [...new Set(result)]
  297. .map(Id => {
  298. return flowDetail.nodes.find?.(item => item.Id == Id);
  299. })
  300. .filter(item => item);
  301. let flowIds = [...new Set(nodeList.map(item => item.flow_id))].join(',');
  302. let data = await queryProcessFlows({ ids: flowIds });
  303. if (data && data?.length > 0) {
  304. let newlist = nodeList.map(node => {
  305. let curData = data.find(item => item.id == node.flow_id);
  306. let newItem = {
  307. name: curData?.name,
  308. nodeId: node.Id,
  309. items: JSON.parse(curData.form_json || '[]'),
  310. };
  311. return newItem;
  312. });
  313. addAuditList = [...addAuditList, ...newlist];
  314. }
  315. addAuditList.forEach((item, index) => {
  316. let Components = Form3x.create({
  317. onValuesChange: (props, changedValues, allValues) => {
  318. const { items } = props;
  319. formComponentValues[item.nodeId] = items
  320. .map(item => {
  321. const itemProps = item.props;
  322. let val = allValues[itemProps.id];
  323. if (!itemProps.label || val === '') return;
  324. if (val instanceof Object) {
  325. return {
  326. name: itemProps.label,
  327. id: itemProps.id,
  328. value: [...val],
  329. };
  330. } else if (allValues[itemProps.id]) {
  331. return {
  332. name: itemProps.label,
  333. id: itemProps.id,
  334. value: [allValues[itemProps.id]] || undefined,
  335. };
  336. }
  337. })
  338. .filter(item => item);
  339. if (getReComputeAudit(items, changedValues)) advanceSubmit();
  340. setFormComponentValues({ ...formComponentValues });
  341. },
  342. })(AuditDetailed);
  343. item.FormComponents = <Components items={item.items} />;
  344. });
  345. setAuditList(addAuditList);
  346. if (Object.keys(approvalProcess).length == 0) advanceSubmit();
  347. };
  348. const getFromData = async idList => {
  349. const data = formComponentValues;
  350. const result = [];
  351. //获取流转节点的层级关系
  352. let len = 0;
  353. let list = [];
  354. idList.forEach(item => {
  355. if (len < item.length) len = item.length;
  356. });
  357. for (let i = 0; i < len; i++) {
  358. idList.forEach(item => {
  359. if (item && item[i]) list.push(item[i]);
  360. });
  361. }
  362. let firstList = [...new Set(list)];
  363. // let attachment = await upload();
  364. firstList.forEach(id => {
  365. let approvalNode = flowDetail.nodes.find?.(item => item.Id == id);
  366. if (!approvalNode) return;
  367. let values = data[approvalNode.Id] || [];
  368. let audit_list = [],
  369. cc_list = [];
  370. approvalProcess[approvalNode.Id]?.forEach(item => {
  371. let arr = item[0].is_cc == 1 ? cc_list : audit_list;
  372. if (item[0].type == 'role') return arr.push(item[0].nowValue);
  373. return arr.push(item[0].value);
  374. });
  375. const formItem = {
  376. flow_id: approvalNode.flow_id,
  377. template_node_id: approvalNode.Id,
  378. formComponentValues: [...values], //{ name: '附件', value: JSON.stringify(attachment) }
  379. audit_list,
  380. cc_list,
  381. };
  382. result.push(JSON.stringify(formItem));
  383. });
  384. return result;
  385. };
  386. const getFlowPath = node => {
  387. //[134, 135]
  388. let itemData = {};
  389. const Function = (curId, index) => {
  390. if (!curId) return;
  391. let data = {};
  392. let approvalNode = flowDetail.nodes.find?.(item => item.Id == curId);
  393. data.template_id = version.template_id;
  394. data.flow_id = approvalNode?.flow_id || 0;
  395. data.node_level_id = approvalNode?.flow_id ? 1 : 0;
  396. data.template_node_id = approvalNode?.Id;
  397. index++;
  398. if (approvalNode?.Id) {
  399. if (!approvalNode?.flow_id) {
  400. hasFlowId = false;
  401. }
  402. }
  403. const res = Function(node[index], index);
  404. if (res) {
  405. data.flow_path = [res];
  406. }
  407. return data;
  408. };
  409. itemData = Function(node[0], 0);
  410. return itemData;
  411. };
  412. const onFinish = async () => {
  413. const isOk = Object.values(approvalProcess).every(item => {
  414. return item.every(cur => {
  415. if (cur[0].type == 'role') return cur[0].nowValue;
  416. return true;
  417. });
  418. });
  419. if (!isOk) {
  420. message.error('请选择审批人。');
  421. return;
  422. }
  423. var fieldsValue = await form.validateFields();
  424. let hasFlowId = true; //是否都绑定审批节点
  425. const getFlowPath = node => {
  426. //[134, 135]
  427. let itemData = {};
  428. const Function = (curId, index) => {
  429. if (!curId) return;
  430. let data = {};
  431. let approvalNode = flowDetail.nodes.find?.(item => item.Id == curId);
  432. data.template_id = version.template_id;
  433. data.flow_id = approvalNode?.flow_id || 0;
  434. data.node_level_id = approvalNode?.flow_id ? 1 : 0;
  435. data.template_node_id = approvalNode?.Id;
  436. index++;
  437. if (approvalNode?.Id) {
  438. if (!approvalNode?.flow_id) {
  439. hasFlowId = false;
  440. }
  441. }
  442. const res = Function(node[index], index);
  443. if (res) {
  444. data.flow_path = [res];
  445. }
  446. return data;
  447. };
  448. itemData = Function(node[0], 0);
  449. return itemData;
  450. };
  451. let result = Object.values(fieldsValue)
  452. .map(item => {
  453. if (item && Array.isArray(item)) return item;
  454. })
  455. .filter(item => item);
  456. let serviceNode = flowDetail.nodes.find?.(item => item.Id == fieldsValue.next_template_node_id);
  457. if (!serviceNode) {
  458. message.error('请选择需要流转的业务节点。');
  459. return;
  460. }
  461. const flowPath = result.map(item => getFlowPath(item));
  462. const formList = await getFromData(result);
  463. let params = {
  464. desc: fieldsValue.desc,
  465. // 审核流程id
  466. // flow_id: approvalNode?.flow_id || 0,
  467. // node_level_id: approvalNode?.flow_id ? 1 : 0,
  468. id: version.id,
  469. project_id: version.project_id,
  470. cur_template_node_id: version.template_node_id * 1, // 当前节点
  471. next_template_node_id: serviceNode.Id * 1, // 审核完成后的业务节点
  472. // template_node_id: result[0][0], // 将要流转的节点审批节点
  473. // flow_path:flow_path, //审批节点数组
  474. // 模板id.一致就行
  475. template_id: version.template_id,
  476. cur_template_id: version.template_id,
  477. next_template_id: version.template_id,
  478. };
  479. if (result.length <= 0) {
  480. //直接走业务节点
  481. } else if (result.length <= 1 && result[0]?.length <= 1) {
  482. //单个审批节点
  483. let approvalNode = flowDetail.nodes.find?.(item => item.Id == result[0][0]);
  484. params.flow_id = approvalNode?.flow_id || 0;
  485. params.node_level_id = approvalNode?.flow_id ? 1 : 0;
  486. params.template_node_id = result[0][0]; // 将要流转的节点审批节点
  487. params.form_list = formList; //创建钉钉表单所需数据
  488. if (approvalNode?.Id) {
  489. if (!approvalNode?.flow_id) {
  490. hasFlowId = false;
  491. }
  492. }
  493. } else {
  494. //多节点审批
  495. params.template_node_id = result[0][0]; // 将要流转的节点审批节点
  496. params.flow_path = flowPath;
  497. params.form_list = formList; //创建钉钉表单所需数据
  498. }
  499. if (!hasFlowId) {
  500. message.error('当前存在审批节点未绑定审批流程!请联系管理员。');
  501. return;
  502. }
  503. await querySaveBomForm({
  504. project_id: version.project_id,
  505. node_id: version.template_node_id,
  506. json: JSON.stringify({ approvalProcess }),
  507. });
  508. params.audit_series = uuidv4();
  509. params.files = uploadList.current.join(',');
  510. console.log(params);
  511. onSubmitNextNode(params);
  512. };
  513. const onSubmitNextNode = values => {
  514. dispatch({
  515. type: 'detail/submitNextNode',
  516. payload: values,
  517. callback: newVersion => {
  518. onClose();
  519. // 更新flow流程图
  520. dispatch({
  521. type: 'xflow/queryBoomFlowDetail',
  522. payload: {
  523. id: templateId,
  524. },
  525. });
  526. },
  527. });
  528. };
  529. const CascaderNode = index => {
  530. return (
  531. <Form.Item
  532. labelCol={{ span: 7 }}
  533. wrapperCol={{ span: 15 }}
  534. label={`审批节点${index + 1}`}
  535. name={`circle${index}`}
  536. key={`circle${index}`}
  537. >
  538. <Cascader style={{ width: '100%' }} options={data} onChange={onChange} />
  539. </Form.Item>
  540. );
  541. };
  542. const upload = async () => {
  543. let blob = await luckysheet.current.getExcelBolb();
  544. let formData = new FormData();
  545. formData.append('userid', currentUser.DingUserId);
  546. formData.append('file', new File([blob], `${version.version_name}_${version.version_no}.xlsx`));
  547. try {
  548. let res = await uploadFile(formData);
  549. let data = JSON.parse(res.dentry);
  550. return [
  551. {
  552. spaceId: String(data.spaceId),
  553. fileName: data.name,
  554. fileSize: String(data.spaceId),
  555. fileType: data.extension,
  556. fileId: data.id,
  557. },
  558. ];
  559. } catch (error) {
  560. message.error('附件上传失败');
  561. }
  562. };
  563. const columns = [
  564. {
  565. title: '文件名称',
  566. dataIndex: 'name',
  567. key: 'name',
  568. },
  569. {
  570. title: '操作',
  571. render: record => <a>删除</a>,
  572. },
  573. ];
  574. useEffect(() => {
  575. if (!visible) {
  576. // 清空数据
  577. uploadList.current = [];
  578. }
  579. }, [visible]);
  580. return (
  581. <Modal
  582. confirmLoading={loading.global}
  583. destroyOnClose
  584. title="提交流转目标"
  585. width={1000}
  586. visible={visible}
  587. onCancel={() => {
  588. setAuditId();
  589. onClose();
  590. }}
  591. onOk={onFinish}
  592. >
  593. <Form form={form}>
  594. {data.map((item, idx) => (data.length == 1 ? CascaderNode('') : CascaderNode(idx)))}
  595. <Form.Item
  596. labelCol={{ span: 7 }}
  597. wrapperCol={{ span: 15 }}
  598. label="业务节点"
  599. name="next_template_node_id"
  600. // rules={[{ required: true, message: '请选择业务节点' }]}
  601. >
  602. <Select style={{ width: '100%' }}>
  603. {nextNodesList.map(item => (
  604. <Option key={item.value}>{item.label}</Option>
  605. ))}
  606. </Select>
  607. </Form.Item>
  608. <Form.Item labelCol={{ span: 7 }} wrapperCol={{ span: 15 }} label="备注信息" name="desc">
  609. <Input.TextArea />
  610. </Form.Item>
  611. <Form.Item labelCol={{ span: 7 }} wrapperCol={{ span: 15 }} label="附件">
  612. {OSSData.host && <AliyunOSSUpload {...uploadProps} directory={false} label="上传文件" />}
  613. </Form.Item>
  614. </Form>
  615. <Collapse style={{ marginTop: 20 }}>
  616. <Collapse.Panel header="已上传附件" key="1">
  617. <AttachmentTable version={version} canDelete={version.last_version == 0} />
  618. </Collapse.Panel>
  619. </Collapse>
  620. <Tabs defaultActiveKey="1">
  621. {auditList.map((item, idx) => (
  622. <TabPane tab={item.name} key={`${idx}_${item.title}`}>
  623. <Row>
  624. <Col span={17}>{item.FormComponents}</Col>
  625. <Col offset={1} span={6}>
  626. {!approvalProcess[item.nodeId] ? ( //!formComponentValues[item.nodeId] ||
  627. <Empty description="请先填写表单" />
  628. ) : (
  629. <ApprovalProcess
  630. id={item.nodeId}
  631. approvalProcess={approvalProcess}
  632. onChange={setApprovalProcess}
  633. />
  634. )}
  635. </Col>
  636. </Row>
  637. </TabPane>
  638. ))}
  639. </Tabs>
  640. </Modal>
  641. );
  642. }
  643. function getDataValue(item) {
  644. let arr = [];
  645. arr.push(item.value);
  646. if (item.children?.length > 0) {
  647. let res = getDataValue(item.children[0]);
  648. arr = arr.concat(res);
  649. }
  650. return arr;
  651. }
  652. export default connect(({ xflow, detail, user, loading }) => ({
  653. flowDetail: xflow.flowDetail,
  654. versionList: detail.versionList,
  655. currentUser: user.currentUser,
  656. userList: user.list,
  657. OSSData: detail.OSSData,
  658. loading,
  659. }))(CommitAuditModal);