Index.js 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132
  1. import React, { useEffect, useState, useRef, useMemo } from 'react';
  2. import { UnorderedListOutlined, PlusOutlined } from '@ant-design/icons';
  3. import { Button, Modal, message, Alert, Avatar, Spin, Select, Menu, Dropdown } from 'antd';
  4. import { connect } from 'dva';
  5. import styles from './Index.less';
  6. import LuckySheet from './LuckySheet';
  7. import router from 'umi/router';
  8. import AuditModal from './AuditModal';
  9. // import CommentDrawer from './CommentDrawer';
  10. import RightDrawer from './RightDrawer';
  11. import CommitModal from './CommitModal';
  12. import CompareModal from './CompareModal';
  13. import ExportModal from './ExportModal';
  14. import FlowModal from './FlowModal';
  15. import HistoryModal from './HistoryModal';
  16. import TimeNode from './TimeNode';
  17. import FilesModal from './FilesModal';
  18. import VersionModal from './VersionModal';
  19. import CommitAuditModal from './CommitAuditModal';
  20. import CommentContent from '@/components/CommentContent';
  21. import MergeModal from './MergeModal';
  22. import { GetTokenFromUrl, getToken } from '@/utils/utils';
  23. import { queryDetail } from '@/services/boom';
  24. const LocalData = localStorage.luckysheet;
  25. const { Option } = Select;
  26. function Detail(props) {
  27. const {
  28. // flow,
  29. dispatch,
  30. comment,
  31. history,
  32. loading,
  33. currentUser,
  34. fileList,
  35. roleList,
  36. template,
  37. versionList,
  38. auditList,
  39. flowDetail,
  40. match: { params },
  41. } = props;
  42. // const audit_status = 0
  43. const [commentVisible, setCommentVisible] = useState(false);
  44. const [mergeVisible, setMergeVisible] = useState(false);
  45. const [compareVisible, setCompareVisible] = useState(false);
  46. const [exportVisible, setExportVisible] = useState(false);
  47. const [commitVisible, setCommitVisible] = useState(false);
  48. const [auditVisible, setAuditVisible] = useState(false);
  49. const [flowVisible, setFlowVisible] = useState(false);
  50. const [versionVisible, setVersionVisible] = useState(false);
  51. const [commitAuditVisible, setCommitAuditVisible] = useState(false);
  52. const [sheet, setSheet] = useState({});
  53. const [compareList, setCompareList] = useState([]);
  54. const [edit, setEdit] = useState(false);
  55. const [isMerge, setIsMerge] = useState(false);
  56. const [version, setVersion] = useState({});
  57. const [user, setUser] = useState([]);
  58. const [updateCount, setUpdateCount] = useState({
  59. diff: 0,
  60. add: 0,
  61. });
  62. const [fileVisible, setFileVisible] = useState(false);
  63. const [exportDate, setExportData] = useState([]);
  64. // const [dataSource, setDataSource] = useState(DataSource);
  65. // const [lastCommit, setLastCommit] = useState({ data: [] });
  66. const sheetRef = useRef();
  67. const sheetRef2 = useRef();
  68. const sheetRef3 = useRef();
  69. const fileRef = useRef();
  70. const statusRef = useRef({
  71. edit: false,
  72. compare: false,
  73. });
  74. const cellPosition = useRef({});
  75. // const [excelId, setExcelId] = useState(parseInt(params.excelId));
  76. // const excelId = parseInt(params.excelId);
  77. const projectId = parseInt(params.projectId);
  78. const templateId = parseInt(params.templateId);
  79. const flow = useMemo(() => {
  80. let data = {
  81. active: 0,
  82. active_id: null,
  83. current: 0,
  84. currentNode: {},
  85. list: {
  86. FlowNodes: [],
  87. },
  88. };
  89. if (version?.flow_id && auditList?.length > 0) {
  90. let item = auditList.find(item => item.list.id == version.flow_id);
  91. if (!item) return data;
  92. // 合并同审批级别项
  93. let nodes = {};
  94. item.list.FlowNodes.map(item => {
  95. if (!nodes[item.seq]) nodes[item.seq] = { ...item, user: [] };
  96. nodes[item.seq].user.push(item.AuditorUser);
  97. });
  98. item.list.FlowNodes = Object.values(nodes);
  99. // 查询当前节点
  100. let current = item.list.FlowNodes.findIndex(node => node.seq == item.active);
  101. item.current = current == -1 ? 0 : current;
  102. // 保存当前所处节点
  103. item.currentNode = item.list.FlowNodes[item.current];
  104. data = item;
  105. }
  106. return data;
  107. }, [auditList, version]);
  108. const audit_status = flow.active_audit;
  109. const isAuditor = useMemo(() => {
  110. const getUserRole = () => {
  111. let item = flow.currentNode?.user?.find?.(item => item.ID == currentUser.ID);
  112. if (item) return true;
  113. return false;
  114. };
  115. return audit_status == 1 && getUserRole();
  116. }, [audit_status, flow, currentUser]);
  117. // const audit_status = 1;
  118. const onSave = () => {
  119. let sheet1 = compareList[0];
  120. Modal.confirm({
  121. title: '提示',
  122. content: `是否确认保存【${sheet1.version_name || sheet1.name}】`,
  123. okText: '确定',
  124. cancelText: '取消',
  125. onOk() {
  126. let sheetData = sheetRef3.current.getSheetJson().data;
  127. sheetData.forEach(sheet => {
  128. delete sheet.data;
  129. });
  130. let params = {
  131. ...sheet1,
  132. data: JSON.stringify(sheetData),
  133. };
  134. dispatch({
  135. type: 'detail/commitSheet',
  136. payload: params,
  137. callback: () => {
  138. onCompare(false);
  139. },
  140. });
  141. },
  142. });
  143. };
  144. const onCompare = async checkSheets => {
  145. if (checkSheets) {
  146. const [sheet1, sheet2] = checkSheets;
  147. if (!sheet1.data) {
  148. sheet1.data = (
  149. await queryDetail({
  150. excel_id: sheet1.id,
  151. })
  152. ).data;
  153. }
  154. if (!sheet2.data) {
  155. sheet2.data = (
  156. await queryDetail({
  157. excel_id: sheet2.id,
  158. })
  159. ).data;
  160. }
  161. setCompareList(checkSheets);
  162. statusRef.current.compare = true;
  163. } else {
  164. let index = compareList.findIndex(item => item.id == sheet.id);
  165. // 退出比对模式
  166. if (index == 0) {
  167. sheetRef3.current.toggleCompare(false);
  168. } else if (index == 1) {
  169. sheetRef2.current.toggleCompare(false);
  170. }
  171. setIsMerge(false);
  172. setCompareList([]);
  173. setSheet({
  174. ...sheet,
  175. });
  176. setUpdateCount({
  177. diff: 0,
  178. add: 0,
  179. });
  180. statusRef.current.compare = false;
  181. }
  182. setCommentVisible(false);
  183. };
  184. // const exportSheet = async item => {
  185. // console.log(item);
  186. // var sheets = await queryHistoryDetail(item);
  187. // sheets.id = sheets.sheet_id;
  188. // setSheet({
  189. // ...item,
  190. // name: item.version_name,
  191. // data: sheets,
  192. // });
  193. // };
  194. const renderSheetDom = (item, index) => {
  195. return (
  196. <div key={item?.id || 'temp'} className={styles.sheetItem}>
  197. <h3>
  198. {item?.name}
  199. {item.version_name && `(${item.version_name})`}
  200. </h3>
  201. <LuckySheet
  202. className={styles.sheet}
  203. ref={!index ? sheetRef3 : sheetRef2}
  204. data={item.data || null}
  205. // onClickCell={onClickCell}
  206. />
  207. </div>
  208. );
  209. };
  210. const onClickCell = (cell, position, s) => {
  211. console.log(cell);
  212. if (cell?.cid && !statusRef.current.edit) {
  213. let payload = {
  214. sheet_id: s.order || '0',
  215. excel_id: version.id,
  216. cid: cell.cid,
  217. };
  218. dispatch({
  219. type: 'detail/queryComment',
  220. payload,
  221. });
  222. cellPosition.current = {
  223. ...payload,
  224. sheet_index: (s.seq || 0) + '',
  225. };
  226. // setCommentVisible(true);
  227. }
  228. // 比对模式下双excl同步选中
  229. // if (statusRef.current.compare) {
  230. // sheetRef3.current.selectCell(position.r, position.c, s.order);
  231. // sheetRef2.current.selectCell(position.r, position.c, s.order);
  232. // }
  233. };
  234. const onCommit = (values, id) => {
  235. let currentData = sheetRef.current.getSheetJson().data;
  236. let sheets = JSON.parse(JSON.stringify(currentData));
  237. sheets.forEach(item => {
  238. delete item.data;
  239. });
  240. console.log(sheets);
  241. let params = {
  242. ...values,
  243. id: id,
  244. project_id: version.project_id,
  245. name: version.name,
  246. guid: version.guid,
  247. audit_status: version.audit_status,
  248. template_id: version.template_id,
  249. template_node_id: version.template_node_id,
  250. flow_id: version.flow_id,
  251. node_id: version.node_id,
  252. new_version: '0',
  253. data: JSON.stringify(sheets),
  254. };
  255. dispatch({
  256. type: 'detail/commitSheet',
  257. payload: params,
  258. callback: sheets => {
  259. onCompare(false);
  260. setCommitVisible(false);
  261. setVersionVisible(false);
  262. // setSheet(sheets);
  263. // localStorage.luckysheet = JSON.stringify(sheets);
  264. },
  265. });
  266. };
  267. const onUpdate = () => {
  268. let currentData = sheetRef.current.getSheetJson().data;
  269. let sheets = JSON.parse(JSON.stringify(currentData));
  270. sheets.forEach(item => {
  271. delete item.data;
  272. });
  273. console.log(sheets);
  274. let params = {
  275. ...version,
  276. data: JSON.stringify(sheets),
  277. };
  278. dispatch({
  279. type: 'detail/saveSheet',
  280. payload: params,
  281. });
  282. };
  283. // const onCommit = values => {
  284. // var flowNode = flow.currentNode;
  285. // // 获取最新sheet页信息
  286. // dispatch({
  287. // type: 'detail/querySheet',
  288. // payload: {
  289. // project_id: projectId,
  290. // flow_id: flowNode.flow_id,
  291. // node_id: flowNode.id,
  292. // },
  293. // callback: sheets => {
  294. // let currentData = sheetRef.current.getSheetJson().data;
  295. // currentData.forEach((item, index) => {
  296. // // 使用最新的sheetId 防止多次创建sheet
  297. // item.id = sheets.data[index]?.id;
  298. // console.log(item.data.celldata);
  299. // });
  300. // let newSheet = {
  301. // ...values,
  302. // data: JSON.stringify(currentData),
  303. // id: excelId,
  304. // flow_id: flowNode.flow_id,
  305. // node_id: flowNode.id,
  306. // project_id: projectId,
  307. // };
  308. // dispatch({
  309. // type: 'detail/commitSheet',
  310. // payload: newSheet,
  311. // callback: sheets => {
  312. // onCompare(false);
  313. // setCommitVisible(false);
  314. // setSheet(sheets);
  315. // localStorage.luckysheet = JSON.stringify(sheets);
  316. // },
  317. // });
  318. // },
  319. // });
  320. // };
  321. const onAudit = ({ audit_comment }) => {
  322. var flowNode = flow.currentNode;
  323. dispatch({
  324. type: 'detail/approve',
  325. payload: {
  326. id: version.id,
  327. project_id: projectId,
  328. audit_status: 2,
  329. flow_id: flowNode.flow_id,
  330. node_id: flowNode.seq,
  331. audit_comment,
  332. },
  333. callback: () => {
  334. setAuditVisible(false);
  335. },
  336. });
  337. };
  338. const onSubmitAudit = () => {
  339. Modal.confirm({
  340. title: '提示',
  341. content: '是否确认提交审批。',
  342. okText: '确定',
  343. cancelText: '取消',
  344. onOk() {
  345. var flowNode = flow.currentNode;
  346. dispatch({
  347. type: 'detail/submitAudit',
  348. payload: {
  349. id: version.id,
  350. flow_id: flowNode.flow_id,
  351. node_id: flowNode.id,
  352. projectId,
  353. },
  354. });
  355. },
  356. });
  357. };
  358. const onApprove = flag => {
  359. if (!flag) {
  360. setAuditVisible(true);
  361. return;
  362. }
  363. Modal.confirm({
  364. title: '提示',
  365. content: `是否${flag ? '通过' : '拒绝'}审批。`,
  366. okText: '确定',
  367. cancelText: '取消',
  368. onOk: () => {
  369. var flowNode = flow.currentNode;
  370. dispatch({
  371. type: 'detail/approve',
  372. payload: {
  373. id: flow.active_id,
  374. project_id: projectId,
  375. audit_status: flag ? 3 : 2,
  376. flow_id: flowNode.flow_id,
  377. node_id: flowNode.seq,
  378. },
  379. callback: newVersion => {
  380. // 更新flow流程图
  381. dispatch({
  382. type: 'xflow/queryBoomFlowDetail',
  383. payload: {
  384. id: templateId,
  385. },
  386. });
  387. if (flow.current == flow.list.FlowNodes.length - 1) {
  388. // 最后一个审核节点通过后 需要更新version id
  389. localStorage.excelId = newVersion.id;
  390. setVersion({
  391. ...version,
  392. id: newVersion.id,
  393. });
  394. }
  395. },
  396. });
  397. },
  398. });
  399. };
  400. const onMerge = () => {
  401. const [sheet1, sheet2] = compareList;
  402. Modal.confirm({
  403. title: '提示',
  404. content: `是否确认将【${sheet2.version_name}】改动的内容同步至【${sheet1.version_name ||
  405. sheet1.name}】`,
  406. okText: '确定',
  407. cancelText: '取消',
  408. onOk() {
  409. // let sheet2Data = sheetRef2.current.getSheetJson()
  410. sheetRef3.current.mergeExcl(sheetRef2.current.updateCell);
  411. // setCompareList([...compareList]);
  412. // let currentData = sheetRef3.current.getSheetJson()
  413. // // 更新后重新比对
  414. // sheetRef2.current.toggleCompare(false);
  415. // sheetRef2.current.toggleCompare(true, currentData);
  416. },
  417. });
  418. };
  419. const onMergeVersion = async sheet2 => {
  420. // const [sheet1, sheet2] = checkSheets;
  421. const sheet1 = version;
  422. if (!sheet1.data) {
  423. sheet1.data = (
  424. await queryDetail({
  425. excel_id: sheet1.id,
  426. })
  427. ).data;
  428. }
  429. if (!sheet2.data) {
  430. sheet2.data = (
  431. await queryDetail({
  432. excel_id: sheet2.id,
  433. })
  434. ).data;
  435. }
  436. setIsMerge(true);
  437. setCompareList([sheet1, sheet2]);
  438. // setTimeout(() => {
  439. // sheetRef3.current.mergeExcl(sheet.data);
  440. // }, 400);
  441. };
  442. // const handleClickCommit = async () => {
  443. // const { list } = await queryHistory();
  444. // let lastCommit = list[0];
  445. // // 判断当前版本是否为最新版本
  446. // if (lastCommit && sheet.guid != lastCommit.guid) {
  447. // Modal.confirm({
  448. // title: '提示',
  449. // content: '当前版本与最新版本不匹配,将进入比对模式确认版本差异。',
  450. // okText: '比对',
  451. // cancelText: '返回',
  452. // onOk() {
  453. // dispatch({
  454. // type: 'detail/queryHistoryDetail',
  455. // payload: {
  456. // excel_id: lastCommit.excel_id,
  457. // history_id: lastCommit.id,
  458. // },
  459. // callback: sheets => {
  460. // setIsMerge(true);
  461. // let currentSheet = {
  462. // ...sheet,
  463. // name: '当前版本',
  464. // };
  465. // let lastSheet = {
  466. // ...lastCommit,
  467. // name: `线上最新版本(${lastCommit.version_name})`,
  468. // data: sheets,
  469. // };
  470. // onCompare([currentSheet, lastSheet]);
  471. // },
  472. // });
  473. // },
  474. // });
  475. // } else {
  476. // setCommitVisible(true);
  477. // }
  478. // setCommentVisible(false);
  479. // };
  480. // const handleEdit = status => {
  481. // if (!status) {
  482. // // 还原数据
  483. // sheetRef.current.renderSheet(sheet.data);
  484. // }
  485. // setCommentVisible(false);
  486. // setEdit(status);
  487. // statusRef.current.edit = status;
  488. // sheetRef.current.toggleEdit(status);
  489. // };
  490. const handleClickFile = () => {
  491. fileRef.current.click();
  492. };
  493. const handleMenuClick = e => {
  494. console.log('click', e);
  495. switch (e.key) {
  496. case 'back':
  497. // 返回
  498. router.push(`/home`);
  499. break;
  500. // case 'version':
  501. // // 版本
  502. // queryHistory();
  503. // setCommentVisible(false);
  504. // setHistoryVisible(true);
  505. // break;
  506. case 'bomDetail':
  507. // 版本
  508. setCommentVisible(true);
  509. break;
  510. case 'export':
  511. // 导出
  512. handleExportClick();
  513. break;
  514. case 'commitAudit':
  515. // 提交流转
  516. setCommitAuditVisible(true);
  517. break;
  518. case 'flow':
  519. // 查看流程
  520. setFlowVisible(true);
  521. break;
  522. case 'compare':
  523. // 比对
  524. setCompareVisible(true);
  525. break;
  526. case 'template':
  527. // 模板
  528. handleClickFile();
  529. break;
  530. // case 'auditSuccess':
  531. // // 审核通过
  532. // onApprove(true);
  533. // break;
  534. // case 'auditFailed':
  535. // // 审核拒绝
  536. // onApprove(false);
  537. // break;
  538. // case 'edit':
  539. // // 编辑
  540. // handleEdit(true);
  541. case 'merge':
  542. // 同步版本
  543. setMergeVisible(true);
  544. break;
  545. case 'commit':
  546. // 提交
  547. // handleClickCommit();
  548. setCommitVisible(true);
  549. setCommentVisible(false);
  550. break;
  551. case 'approval':
  552. // 申请审批
  553. onSubmitAudit();
  554. break;
  555. case 'attachment':
  556. // 附件
  557. setFileVisible(true);
  558. queryFiles();
  559. break;
  560. }
  561. };
  562. const renderBtns = () => {
  563. // if (edit) {
  564. // return (
  565. // <>
  566. // <Button type="primary" onClick={onSave}>
  567. // 保存
  568. // </Button>
  569. // <Button onClick={() => handleEdit(false)}>取消</Button>
  570. // </>
  571. // );
  572. // }
  573. // 判断是否为比对模式
  574. if (compareList.length == 2) {
  575. // 判断是否为同步最新版本的比对
  576. if (isMerge) {
  577. return (
  578. <>
  579. <Button type="primary" onClick={() => onSave()}>
  580. 保存
  581. </Button>
  582. <Button onClick={() => onMerge()}>同步新增内容</Button>
  583. {/* <Button onClick={() => setCommitVisible(true)}>确认提交</Button> */}
  584. <Button onClick={() => onCompare(false)}>取消比对</Button>
  585. </>
  586. );
  587. } else {
  588. return <Button onClick={() => onCompare(false)}>取消比对</Button>;
  589. }
  590. }
  591. const menuList = [
  592. <Menu.Item key="back">返回</Menu.Item>,
  593. <Menu.Item key="bomDetail">详情</Menu.Item>,
  594. <Menu.Item key="export">导出</Menu.Item>,
  595. <Menu.Item key="commitAudit">提交流转</Menu.Item>,
  596. <Menu.Item key="flow">查看流程</Menu.Item>,
  597. <Menu.Item key="compare">比对</Menu.Item>,
  598. <Menu.Item key="attachment">附件</Menu.Item>,
  599. ];
  600. // if (audit_status != 1) {
  601. // menuList.push(<Menu.Item key="version">历史提交</Menu.Item>);
  602. // // menuList.push(<Menu.Item key="template">模板</Menu.Item>);
  603. // }
  604. if (!isAuditor && canEdit()) {
  605. // menuList.push(<Menu.Item key="edit">编辑</Menu.Item>);
  606. menuList.push(<Menu.Item key="merge">同步</Menu.Item>);
  607. // menuList.push(<Menu.Item key="commit">提交</Menu.Item>);
  608. // if (history.list.length > 0) {
  609. // menuList.push(<Menu.Item key="approval">申请审批</Menu.Item>);
  610. // }
  611. }
  612. return (
  613. <>
  614. <Dropdown overlay={<Menu onClick={handleMenuClick}>{menuList}</Menu>}>
  615. {/* <Button type="primary">
  616. 其他操作 <DownOutlined />
  617. </Button> */}
  618. <UnorderedListOutlined style={{ fontSize: 30, cursor: 'pointer' }} />
  619. </Dropdown>
  620. </>
  621. );
  622. };
  623. const canEdit = () => {
  624. if (flow.list.FlowNodes.length - 1 == flow.current && audit_status == 3) return false;
  625. return audit_status != 1;
  626. };
  627. const renderAlert = () => {
  628. const audit_comment = history.list[0]?.audit_comment;
  629. let item = '';
  630. switch (audit_status) {
  631. case 0:
  632. return;
  633. case 1:
  634. item = <Alert message="等待审核中" type="info" />;
  635. break;
  636. case 2:
  637. item = (
  638. <Alert
  639. message={`审批被拒绝${
  640. audit_comment ? `,拒绝原因:${audit_comment}` : ''
  641. }。请修改后重新提交`}
  642. type="error"
  643. />
  644. );
  645. break;
  646. case 3:
  647. item = <Alert message="审批通过" type="success" />;
  648. break;
  649. }
  650. return <div style={{ marginTop: 20 }}>{item}</div>;
  651. };
  652. const exportExcl = files => {
  653. sheetRef.current.uploadExcel(files, () => {
  654. fileRef.current.value = null;
  655. });
  656. };
  657. const getRowOneList = () => {
  658. const obj = sheetRef.current.getSheetJson();
  659. console.log(obj);
  660. const list = [];
  661. obj.data.forEach(item => {
  662. list.push(item.data[0]);
  663. });
  664. return list;
  665. };
  666. //点击导出弹出选择导出列弹框
  667. const handleExportClick = () => {
  668. setExportData(sheetRef.current.getSheetJson());
  669. setExportVisible(true);
  670. };
  671. const downloadExcel = checkValue => {
  672. sheetRef.current.downloadExcel(checkValue);
  673. setExportVisible(false);
  674. };
  675. const queryHistory = id => {
  676. return new Promise(reslove => {
  677. dispatch({
  678. type: 'detail/queryHistory',
  679. payload: {
  680. // excel_id: id || excelId,
  681. project_id: projectId,
  682. },
  683. callback: reslove,
  684. });
  685. });
  686. };
  687. const queryFiles = () => {
  688. dispatch({
  689. type: 'detail/queryFiles',
  690. payload: {
  691. // excel_id: id || excelId,
  692. excel_id: version.id,
  693. },
  694. });
  695. };
  696. const getUploadProps = () => {
  697. const token = getToken() || GetTokenFromUrl();
  698. const uploadProps = {
  699. name: 'file',
  700. showUploadList: false,
  701. action: `/api/v1/purchase/attachment/${version.id}`,
  702. headers: {
  703. 'JWT-TOKEN': token,
  704. },
  705. onChange(info) {
  706. if (info.file.status !== 'uploading') {
  707. console.log(info.file, info.fileList);
  708. }
  709. if (info.file.status === 'done') {
  710. message.success(`${info.file.name} 文件上传成功`);
  711. queryFiles();
  712. } else if (info.file.status === 'error') {
  713. message.error(`${info.file.name} 文件上传失败`);
  714. }
  715. },
  716. };
  717. return uploadProps;
  718. };
  719. const deleteFile = id => {
  720. dispatch({
  721. type: 'detail/deleteFiles',
  722. id: id,
  723. callback: () => {
  724. queryFiles();
  725. },
  726. });
  727. };
  728. const queryHistoryDetail = async item => {
  729. return new Promise(resolve => {
  730. dispatch({
  731. type: 'detail/queryHistoryDetail',
  732. payload: {
  733. excel_id: item.excel_id,
  734. history_id: item.id,
  735. },
  736. callback: sheet => {
  737. resolve(sheet);
  738. },
  739. });
  740. });
  741. };
  742. const getLoading = () => {
  743. let effects = loading.effects;
  744. return !loading.effects['detail/queryComment'] && loading.models.detail;
  745. };
  746. const getFilesLoading = () => {
  747. let effects = loading.effects;
  748. return loading.effects['detail/queryFiles'];
  749. };
  750. const downloadFile = record => {
  751. window.location.href = `${record.url}`;
  752. };
  753. const changeVersion = id => {
  754. let version = versionList.find(item => item.id == id);
  755. if (!version) return;
  756. localStorage.excelId = id;
  757. setVersion(version);
  758. // 查询excel内容
  759. // dispatch({
  760. // type: 'detail/queryRecord',
  761. // payload: {
  762. // project_id: projectId,
  763. // template_id: version.template_id,
  764. // template_node_id: version.template_node_id,
  765. // version_id: version.id,
  766. // },
  767. // callback: sheets => {
  768. // console.log(sheets);
  769. // setSheet(sheets);
  770. // // sheetRef.current.renderSheet(sheets.data);
  771. // },
  772. // });
  773. // // 查询历史修改
  774. // dispatch({
  775. // type: 'detail/queryHistoryList',
  776. // payload: {
  777. // version_id: version.id,
  778. // },
  779. // });
  780. // 判断是否审批节点
  781. if (version.flow_id) {
  782. dispatch({
  783. type: 'detail/queryAuditList',
  784. payload: {
  785. template_id: version.template_id,
  786. template_node_id: version.template_node_id,
  787. flow_id: version.flow_id,
  788. version_id: version.id,
  789. },
  790. });
  791. }
  792. };
  793. const onSubmitNextNode = values => {
  794. dispatch({
  795. type: 'detail/submitNextNode',
  796. payload: values,
  797. callback: () => {
  798. setCommitAuditVisible(false);
  799. },
  800. });
  801. };
  802. const getUser = user => {
  803. setUser(user);
  804. };
  805. const renderNode = () => {
  806. const nodeId = version.template_node_id;
  807. if (!flowDetail?.nodes || !nodeId) return;
  808. const node = flowDetail.nodes.find(item => item.Id == nodeId);
  809. return `当前节点:${node?.label || '-'}`;
  810. };
  811. const handleSubmitCell = (value, callback) => {
  812. if (!value) return;
  813. dispatch({
  814. type: 'detail/addComment',
  815. payload: {
  816. ...cellPosition.current,
  817. comment: value,
  818. },
  819. callback,
  820. });
  821. };
  822. useEffect(() => {
  823. dispatch({
  824. type: 'detail/queryProjectRecord',
  825. payload: {
  826. project_id: projectId,
  827. },
  828. });
  829. dispatch({
  830. type: 'xflow/queryBoomFlowDetail',
  831. payload: {
  832. id: templateId,
  833. },
  834. });
  835. dispatch({
  836. type: 'user/fetchUserList',
  837. });
  838. // 审批流程
  839. // dispatch({
  840. // type: 'detail/queryAuditList',
  841. // });
  842. // 查询节点
  843. // dispatch({
  844. // type: 'detail/queryFlowInfo',
  845. // payload: {
  846. // projectId,
  847. // },
  848. // callback: async ({ currentNode }, sheets) => {
  849. // if (sheets.id != excelId) {
  850. // // 更新excel id
  851. // router.push(`/home/detail/${sheets.id}/${projectId}`);
  852. // }
  853. // let { list } = await queryHistory(sheets.id);
  854. // let sheet = JSON.parse(LocalData || '{}');
  855. // if (
  856. // LocalData &&
  857. // sheet.excel_id == sheets.id &&
  858. // currentNode.id == sheet.node_id &&
  859. // list[0]?.audit_status != 1
  860. // ) {
  861. // // 显示缓存数据
  862. // setSheet(sheet);
  863. // } else {
  864. // sheets.excel_id = sheets.id;
  865. // sheets.name = sheets.version_name;
  866. // delete sheets.id;
  867. // setSheet(sheets);
  868. // }
  869. // sheetRef.current.renderSheet(sheets.data);
  870. // },
  871. // });
  872. // dispatch({
  873. // type: 'detail/getRoleList',
  874. // payload: {
  875. // ID: projectId,
  876. // },
  877. // });
  878. }, []);
  879. useEffect(() => {
  880. if (compareList.length == 2) {
  881. const callback = ({ diff, add }) => {
  882. setUpdateCount(updateCount => {
  883. return {
  884. diff: diff.length,
  885. add: updateCount.add + add.length,
  886. };
  887. });
  888. };
  889. var update1 = sheetRef3.current.toggleCompare(true, compareList[1].data, callback);
  890. var update2 = sheetRef2.current.toggleCompare(true, compareList[0].data, callback);
  891. }
  892. }, [compareList]);
  893. useEffect(() => {
  894. if (versionList.length == 0) return;
  895. if (!version.id) {
  896. const excelId = localStorage.excelId;
  897. changeVersion(excelId);
  898. } else {
  899. changeVersion(version.id);
  900. }
  901. // else if (version.id != params.excelId) {
  902. // changeVersion(version.id);
  903. // }
  904. }, [versionList]);
  905. return (
  906. <Spin spinning={false}>
  907. {/* <Spin spinning={getLoading()}> */}
  908. <div className={styles.top}>
  909. <div>
  910. {/* 当前节点: {version.template_node_id}
  911. <br />
  912. 当前状态:{version.audit_status} */}
  913. <Select
  914. style={{ width: 140, marginLeft: 10 }}
  915. value={version.id}
  916. onChange={changeVersion}
  917. >
  918. {versionList.map(item => (
  919. <Option value={item.id} key={item.id}>
  920. {item.version_name}
  921. </Option>
  922. ))}
  923. </Select>
  924. {flow?.active == 0 && (
  925. <Button
  926. type="primary"
  927. icon={<PlusOutlined />}
  928. onClick={() => setVersionVisible(true)}
  929. ></Button>
  930. )}
  931. <span style={{ marginLeft: 20 }}>{renderNode()}</span>
  932. </div>
  933. <div className={styles.btns}>
  934. <Avatar.Group style={{ marginRight: 20 }}>
  935. {user.map(item => (
  936. <Avatar
  937. // style={{ backgroundColor: item.id == currentUser.ID ? '#008dff' : '' }}
  938. size="large"
  939. >
  940. {item.Name}
  941. </Avatar>
  942. ))}
  943. </Avatar.Group>
  944. {renderBtns()}
  945. </div>
  946. <input
  947. type="file"
  948. ref={fileRef}
  949. style={{ display: 'none' }}
  950. onChange={e => exportExcl(e.target.files)}
  951. />
  952. </div>
  953. <TimeNode flow={flow} isAuditor={isAuditor} onApprove={onApprove}></TimeNode>
  954. {renderAlert()}
  955. {/* 判断是否为比对模式 */}
  956. {compareList.length == 2 ? (
  957. <>
  958. <Alert
  959. message={`比对结果:${updateCount.diff}项差异。${updateCount.add}项新增`}
  960. type="info"
  961. />
  962. <div className={styles.sheetBox}>{compareList.map(renderSheetDom)}</div>
  963. </>
  964. ) : (
  965. <div className={styles.sheetBox}>
  966. {version.id && (
  967. <LuckySheet
  968. className={styles.sheet}
  969. ref={sheetRef}
  970. onClickCell={onClickCell}
  971. version={version}
  972. templateId={templateId}
  973. getUser={getUser}
  974. onUpdate={onUpdate}
  975. />
  976. )}
  977. </div>
  978. )}
  979. <CommentContent
  980. title="单元格沟通记录"
  981. comment={comment}
  982. onSubmit={handleSubmitCell}
  983. loading={loading.effects['detail/queryComment'] || loading.effects['detail/addComment']}
  984. />
  985. <RightDrawer
  986. version={version}
  987. visible={commentVisible}
  988. onClose={() => setCommentVisible(false)}
  989. />
  990. {/* <HistoryModal
  991. visible={historyVisible}
  992. version={version}
  993. // onChange={queryHistory}
  994. onClose={() => setHistoryVisible(false)}
  995. onSelect={item => exportSheet(item)}
  996. /> */}
  997. <CompareModal
  998. visible={compareVisible}
  999. version={version}
  1000. onClose={() => setCompareVisible(false)}
  1001. onOk={onCompare}
  1002. />
  1003. <MergeModal
  1004. visible={mergeVisible}
  1005. version={version}
  1006. onClose={() => setMergeVisible(false)}
  1007. onOk={onMergeVersion}
  1008. />
  1009. <ExportModal
  1010. visible={exportVisible}
  1011. sheet={exportDate.data}
  1012. onClose={() => setExportVisible(false)}
  1013. onOk={downloadExcel}
  1014. />
  1015. {/* <CommitModal
  1016. loading={getLoading()}
  1017. visible={commitVisible}
  1018. version={version}
  1019. onClose={() => setCommitVisible(false)}
  1020. onOk={values => onCommit(values, version.id)}
  1021. /> */}
  1022. <FlowModal
  1023. visible={flowVisible}
  1024. onClose={() => setFlowVisible(false)}
  1025. version={version}
  1026. // onOk={onCommit}
  1027. onChangeVersion={version => changeVersion(version.id)}
  1028. />
  1029. <AuditModal
  1030. loading={getLoading()}
  1031. visible={auditVisible}
  1032. onClose={() => setAuditVisible(false)}
  1033. onOk={onAudit}
  1034. />
  1035. <FilesModal
  1036. loading={getFilesLoading()}
  1037. visible={fileVisible}
  1038. onClose={() => setFileVisible(false)}
  1039. uploadProps={getUploadProps()}
  1040. DeleteFile={deleteFile}
  1041. downloadFile={downloadFile}
  1042. data={fileList}
  1043. />
  1044. <VersionModal
  1045. loading={getLoading()}
  1046. visible={versionVisible}
  1047. onClose={() => setVersionVisible(false)}
  1048. onOk={values => onCommit(values)}
  1049. />
  1050. <CommitAuditModal
  1051. loading={getLoading()}
  1052. visible={commitAuditVisible}
  1053. version={version}
  1054. onClose={() => setCommitAuditVisible(false)}
  1055. onOk={onSubmitNextNode}
  1056. />
  1057. </Spin>
  1058. );
  1059. }
  1060. export default connect(({ detail, user, xflow, loading }) => ({
  1061. flow: detail.flow,
  1062. flowDetail: xflow.flowDetail,
  1063. auditList: detail.auditList,
  1064. fileList: detail.fileList,
  1065. history: detail.history,
  1066. comment: detail.comment,
  1067. currentUser: user.currentUser,
  1068. roleList: detail.roleList,
  1069. versionList: detail.versionList,
  1070. loading,
  1071. }))(Detail);