CommitAuditModal.js 24 KB

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