Index.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  1. import React, { useEffect, useState, useRef, useMemo } from 'react';
  2. import { UnorderedListOutlined, PlusOutlined, InfoOutlined } from '@ant-design/icons';
  3. import { Button, Modal, message, Alert, Avatar } from 'antd';
  4. import { connect } from 'dva';
  5. import styles from './Index.less';
  6. import LuckySheet from './LuckySheet';
  7. import AuditModal from './AuditModal';
  8. // import CommentDrawer from './CommentDrawer';
  9. import RightDrawer from './RightDrawer';
  10. import CompareModal from './CompareModal';
  11. import ExportModal from './ExportModal';
  12. import FlowModal from './FlowModal';
  13. import TimeNode from './TimeNode';
  14. import VersionModal from './VersionModal';
  15. import CommitAuditModal from './CommitAuditModal';
  16. import CommentContent from '@/components/CommentContent';
  17. import MergeModal from './MergeModal';
  18. import { GetTokenFromUrl, getToken } from '@/utils/utils';
  19. import {
  20. getAuditDetail,
  21. getVersionDetail,
  22. queryDelSheetRecord,
  23. queryDetail,
  24. queryDingInstanceExecute,
  25. setLastVersion,
  26. } from '@/services/boom';
  27. import HistoryDrawer from './HistoryDrawer';
  28. import AuditFlow from './AuditFlow';
  29. import { getCurrentUser } from '@/utils/authority';
  30. import { async } from '@antv/x6/es/registry/marker/async';
  31. import FileViewerModal from '@/components/FileViewer';
  32. import PreviewFile from '@/components/PreviewFile';
  33. import FormAndFilesNode from './FormAndFilesNode';
  34. import DropdownMenu from './DropdownMenu';
  35. import CurrentInfo from './CurrentInfo';
  36. import moment from 'moment';
  37. import PsrControl from './PsrControl';
  38. function Detail(props) {
  39. const {
  40. dispatch,
  41. loading,
  42. currentUser,
  43. versionList,
  44. auditList,
  45. flowDetail,
  46. versionTree,
  47. match: { params },
  48. location: { query },
  49. instanceDetail,
  50. typeOptions,
  51. classifyList,
  52. excelFileList,
  53. comment,
  54. } = props;
  55. const [versionTreeVisible, setVersionTreeVisible] = useState(false);
  56. const [commentVisible, setCommentVisible] = useState(false);
  57. const [mergeVisible, setMergeVisible] = useState(false);
  58. const [compareVisible, setCompareVisible] = useState(false);
  59. const [exportVisible, setExportVisible] = useState(false);
  60. const [commitVisible, setCommitVisible] = useState(false);
  61. // false 关闭 1=审批通过 2=审批拒绝
  62. const [auditVisible, setAuditVisible] = useState(false);
  63. const [flowVisible, setFlowVisible] = useState(false);
  64. const [versionVisible, setVersionVisible] = useState(false);
  65. const [commitAuditVisible, setCommitAuditVisible] = useState(false);
  66. const [sheet, setSheet] = useState({});
  67. const [compareList, setCompareList] = useState([]);
  68. const [isMerge, setIsMerge] = useState(false);
  69. const [version, setVersion] = useState({});
  70. const [user, setUser] = useState([]);
  71. const [updateCount, setUpdateCount] = useState({
  72. diff: 0,
  73. add: 0,
  74. });
  75. const [saveTime, setSaveTime] = useState();
  76. const [exportDate, setExportData] = useState([]);
  77. const sheetRef = useRef();
  78. const sheetRef2 = useRef();
  79. const sheetRef3 = useRef();
  80. const fileRef = useRef();
  81. const userRef = useRef();
  82. const statusRef = useRef({
  83. edit: false,
  84. compare: false,
  85. });
  86. const cellPosition = useRef({});
  87. useEffect(() => {
  88. // if (!version.id) return
  89. // 不请求excelFileList 时清空excelFileList,否则会出现清单切换后如果attachment_id不存在,附件信息没有更新
  90. if (!version.attachment_id) {
  91. dispatch({
  92. type: 'detail/save',
  93. payload: {
  94. excelFileList: [],
  95. },
  96. });
  97. } else {
  98. dispatch({
  99. type: 'detail/QueryExcelFiles',
  100. payload: {
  101. excel_id: version.attachment_id,
  102. },
  103. });
  104. }
  105. }, [version.id]);
  106. const projectId = parseInt(params.projectId);
  107. const templateId = parseInt(params.templateId);
  108. const excelID = parseInt(query.excel_id);
  109. const TOKEN = query['JWT-TOKEN'];
  110. if (!localStorage.getItem('JWT-TOKEN')) {
  111. localStorage['JWT-TOKEN'] = TOKEN;
  112. }
  113. const node = useMemo(() => {
  114. if (version.template_node_id && flowDetail.nodes.length > 0) {
  115. return flowDetail.nodes.find(item => item.Id == version.template_node_id);
  116. }
  117. return null;
  118. }, [flowDetail, version.template_node_id]);
  119. const flow = useMemo(() => {
  120. let data = {
  121. active: 0,
  122. active_id: null,
  123. current: 0,
  124. currentNode: {},
  125. list: {
  126. FlowNodes: [],
  127. },
  128. };
  129. if (version?.flow_id && auditList?.length > 0) {
  130. let item = auditList.find(item => item.list.id == version.flow_id);
  131. if (!item) return data;
  132. // 查询当前节点
  133. let current = item.list.FlowNodes.findIndex(node => node.seq == item.active);
  134. item.current = current == -1 ? 0 : current;
  135. // 保存当前所处节点
  136. item.currentNode = item.list.FlowNodes[item.current];
  137. data = item;
  138. }
  139. return data;
  140. }, [auditList, version]);
  141. const active_audit = flow.active_audit;
  142. const isAuditor = useMemo(() => {
  143. return active_audit == 1 && flow.currentNode?.auditor == currentUser.ID;
  144. }, [active_audit, flow, currentUser]);
  145. const onCompare = async checkSheets => {
  146. if (checkSheets) {
  147. const [sheet1, sheet2] = checkSheets;
  148. sheet1.data = (
  149. await queryDetail({
  150. excel_id: sheet1.id,
  151. })
  152. ).data;
  153. sheet2.data = (
  154. await queryDetail({
  155. excel_id: sheet2.id,
  156. })
  157. ).data;
  158. setCompareList(checkSheets);
  159. statusRef.current.compare = true;
  160. } else {
  161. let index = compareList.findIndex(item => item.id == sheet.id);
  162. // 退出比对模式
  163. if (index == 0) {
  164. sheetRef3.current.toggleCompare(false);
  165. } else if (index == 1) {
  166. sheetRef2.current.toggleCompare(false);
  167. }
  168. setIsMerge(false);
  169. setCompareList([]);
  170. setSheet({
  171. ...sheet,
  172. });
  173. setUpdateCount({
  174. diff: 0,
  175. add: 0,
  176. });
  177. statusRef.current.compare = false;
  178. }
  179. setCommentVisible(false);
  180. };
  181. const renderSheetDom = (item, index) => {
  182. return (
  183. <div key={item?.id || 'temp'} className={styles.sheetItem}>
  184. <h3>{item.version_name || item?.name}</h3>
  185. <LuckySheet
  186. className={styles.sheet}
  187. ref={!index ? sheetRef3 : sheetRef2}
  188. data={item.data || null}
  189. />
  190. </div>
  191. );
  192. };
  193. const onClickCell = (cell, position, s) => {
  194. if (cell?.cid && !statusRef.current.edit) {
  195. let payload = {
  196. sheet_id: s.order || '0',
  197. excel_id: version.id,
  198. cid: cell.cid,
  199. sheet_index: String(s.seq || 0),
  200. };
  201. cellPosition.current = {
  202. ...payload,
  203. };
  204. dispatch({
  205. type: 'detail/queryComment',
  206. payload,
  207. });
  208. }
  209. };
  210. const onCommit = params => {
  211. let currentData = sheetRef.current.getSheetJson().data;
  212. let sheets = JSON.parse(JSON.stringify(currentData));
  213. sheets.forEach(item => {
  214. delete item.data;
  215. });
  216. dispatch({
  217. type: 'detail/commitSheet',
  218. payload: {
  219. ...params,
  220. data: JSON.stringify(sheets),
  221. },
  222. callback: newVersion => {
  223. onCompare(false);
  224. setCommitVisible(false);
  225. setVersionVisible(false);
  226. changeVersion(newVersion);
  227. // 更新flow流程图
  228. dispatch({
  229. type: 'xflow/queryBoomFlowDetail',
  230. payload: {
  231. id: templateId,
  232. },
  233. });
  234. },
  235. });
  236. };
  237. // 更新表单,flag为true时不判断是否属于审批,强制更新
  238. const onUpdate = flag => {
  239. if (!flag && flow.active != 0) return;
  240. let currentData = sheetRef.current.getSheetJson().data;
  241. let sheets = JSON.parse(JSON.stringify(currentData));
  242. sheets.forEach(item => {
  243. delete item.data;
  244. });
  245. let params = {
  246. ...version,
  247. data: JSON.stringify(sheets),
  248. };
  249. dispatch({
  250. type: 'detail/saveSheet',
  251. payload: params,
  252. callback: () => {
  253. setSaveTime(moment().format('HH:mm:ss'));
  254. },
  255. });
  256. };
  257. const onDelSheet = async id => {
  258. const params = {
  259. excel_id: version.id,
  260. sheet_id: id,
  261. };
  262. await queryDelSheetRecord(params);
  263. };
  264. const onAudit = data => {
  265. const flowNode = flow.currentNode;
  266. dispatch({
  267. type: 'detail/approve',
  268. payload: {
  269. id: flow.active_id,
  270. project_id: projectId,
  271. flow_id: flowNode.flow_id,
  272. node_id: flowNode.seq,
  273. ...data,
  274. },
  275. callback: newVersion => {
  276. setAuditVisible(false);
  277. // 更新flow流程图
  278. dispatch({
  279. type: 'xflow/queryBoomFlowDetail',
  280. payload: {
  281. id: templateId,
  282. },
  283. });
  284. if (data.audit_status == 3) {
  285. // 更新审批流
  286. dispatch({
  287. type: 'detail/queryAuditList',
  288. payload: {
  289. template_id: version.template_id,
  290. template_node_id: version.template_node_id,
  291. flow_id: version.flow_id,
  292. version_id: version.version_id,
  293. audit_series: version.audit_series,
  294. },
  295. });
  296. } else {
  297. dispatch({
  298. type: 'authList/queryAuthList',
  299. payloda: { user_id: currentUser.ID },
  300. });
  301. localStorage.excelId = newVersion.id;
  302. setVersion({
  303. ...version,
  304. flow_id: newVersion.flow_id,
  305. id: newVersion.id,
  306. });
  307. }
  308. //更新未审批列表
  309. dispatch({
  310. type: 'authList/queryAuthList',
  311. payloda: { user_id: currentUser.ID },
  312. });
  313. },
  314. });
  315. };
  316. const onMergeVersion = async sheet2 => {
  317. const sheet1 = version;
  318. if (!sheet1.data) {
  319. sheet1.data = (
  320. await queryDetail({
  321. excel_id: sheet1.id,
  322. })
  323. ).data;
  324. }
  325. if (!sheet2.data) {
  326. sheet2.data = (
  327. await queryDetail({
  328. excel_id: sheet2.id,
  329. })
  330. ).data;
  331. }
  332. setIsMerge(true);
  333. setCompareList([sheet1, sheet2]);
  334. };
  335. const handleMenuClick = e => {
  336. switch (e.key) {
  337. case 'bomDetail':
  338. // 清单
  339. setCommentVisible(true);
  340. break;
  341. case 'export':
  342. // 导出
  343. handleExportClick();
  344. break;
  345. case 'commitAudit':
  346. // 提交流转
  347. setCommitAuditVisible(true);
  348. break;
  349. case 'compare':
  350. // 比对
  351. setCompareVisible(true);
  352. break;
  353. case 'merge':
  354. // 同步清单
  355. setMergeVisible(true);
  356. break;
  357. case 'compare':
  358. // 同步
  359. onCompare(e.data);
  360. break;
  361. }
  362. };
  363. const exportExcl = files => {
  364. sheetRef.current.uploadExcel(files, () => {
  365. fileRef.current.value = null;
  366. });
  367. };
  368. //点击导出弹出选择导出列弹框
  369. const handleExportClick = () => {
  370. setExportData(sheetRef.current.getSheetJson());
  371. setExportVisible(true);
  372. };
  373. const downloadExcel = checkValue => {
  374. sheetRef.current.downloadExcel(checkValue);
  375. setExportVisible(false);
  376. };
  377. const getLoading = () => {
  378. let effects = loading.effects;
  379. return !loading.effects['detail/queryComment'] && loading.models.detail;
  380. };
  381. const changeVersion = async id => {
  382. let version;
  383. if (typeof id === 'object') {
  384. version = id;
  385. localStorage.excelId = version.id;
  386. localStorage.excelItem = JSON.stringify(version);
  387. } else {
  388. version = await getVersionDetail({ excelID });
  389. if (!version) {
  390. const excelId = localStorage.excelItem
  391. ? JSON.parse(localStorage.excelItem)
  392. : localStorage.excelId;
  393. if (typeof excelId === 'object') {
  394. changeVersion(excelId);
  395. return;
  396. }
  397. }
  398. localStorage.excelId = id;
  399. }
  400. setVersion(version);
  401. setSaveTime(null);
  402. //请求历史版本
  403. dispatch({
  404. type: 'detail/queryVersionsTree',
  405. payload: {
  406. excel_id: version.id || localStorage.excelId,
  407. },
  408. });
  409. // 判断是否审批节点
  410. if (version.flow_id) {
  411. dispatch({
  412. type: 'detail/queryAuditList',
  413. payload: {
  414. template_id: version.template_id,
  415. template_node_id: version.template_node_id,
  416. flow_id: version.flow_id,
  417. version_id: version.version_id,
  418. audit_series: version.audit_series,
  419. },
  420. });
  421. }
  422. };
  423. // console.log('0--------------', currentUser);
  424. //是否展示psr表上面的按钮
  425. const showPsrBtns = useMemo(() => {
  426. if (node?.node_type_psr == 3 || node?.node_type_psr == 4) return true;
  427. return false;
  428. }, [node]);
  429. const getUser = newUser => {
  430. try {
  431. if (JSON.stringify(newUser) != JSON.stringify(userRef.current)) {
  432. userRef.current = newUser;
  433. setUser(newUser);
  434. }
  435. } catch (error) {}
  436. };
  437. const handleSubmitCell = (value, callback) => {
  438. if (!value) return;
  439. dispatch({
  440. type: 'detail/addComment',
  441. payload: {
  442. ...cellPosition.current,
  443. comment: value,
  444. },
  445. callback,
  446. });
  447. };
  448. useEffect(() => {
  449. dispatch({
  450. type: 'detail/queryProjectRecord',
  451. payload: {
  452. project_id: projectId,
  453. },
  454. });
  455. dispatch({
  456. type: 'xflow/queryBoomFlowDetail',
  457. payload: {
  458. id: templateId,
  459. },
  460. });
  461. dispatch({
  462. type: 'user/getRoleList',
  463. });
  464. dispatch({
  465. type: 'user/fetch',
  466. });
  467. dispatch({
  468. type: 'user/fetchDepV2',
  469. });
  470. dispatch({
  471. type: 'detail/queryClassify',
  472. });
  473. dispatch({
  474. type: 'detail/queryBindClassify',
  475. payload: {
  476. project_id: projectId,
  477. },
  478. });
  479. dispatch({
  480. type: 'detail/queryProject',
  481. });
  482. // dispatch({
  483. // type: 'detail/queryListParentByUser',
  484. // payload: {
  485. // userid: currentUser.DingUserId || getCurrentUser()?.DingUserId,
  486. // },
  487. // });
  488. }, []);
  489. useEffect(() => {
  490. if (compareList.length == 2) {
  491. const callback = ({ diff, add }) => {
  492. setUpdateCount(updateCount => {
  493. return {
  494. diff: diff.length,
  495. add: updateCount.add + add.length,
  496. };
  497. });
  498. };
  499. var update1 = sheetRef3.current.toggleCompare(true, compareList[1].data, callback);
  500. var update2 = sheetRef2.current.toggleCompare(true, compareList[0].data, callback);
  501. }
  502. }, [compareList]);
  503. useEffect(() => {
  504. // if (versionList.length == 0) return;
  505. if (!currentUser.ID) return;
  506. if (!version.id) {
  507. changeVersion(excelID);
  508. } else {
  509. changeVersion(version.id);
  510. }
  511. }, [versionList, currentUser]);
  512. return (
  513. <>
  514. <div className={styles.top}>
  515. <div>
  516. <Button type="primary" style={{ marginRight: 20 }} onClick={() => setFlowVisible(true)}>
  517. 查看流程
  518. </Button>
  519. {/* 非审批节点可以创建清单 */}
  520. {flow?.active == 0 && (
  521. <Button type="primary" onClick={() => setVersionVisible(true)}>
  522. 新建清单
  523. </Button>
  524. )}
  525. <CurrentInfo version={version} flowDetail={flowDetail} />
  526. </div>
  527. <div className={styles.btns}>
  528. {saveTime && <span style={{ color: '#333', fontSize: 14 }}>上次保存时间 {saveTime}</span>}
  529. {version.audit_status === 0 && (
  530. <Button type="primary" loading={loading.effects['detail/saveSheet']} onClick={onUpdate}>
  531. 保存
  532. </Button>
  533. )}
  534. <Button
  535. type="primary"
  536. style={{ marginRight: 20 }}
  537. onClick={() => setVersionTreeVisible(true)}
  538. >
  539. 历史版本
  540. </Button>
  541. <Avatar.Group style={{ marginRight: 20 }}>
  542. {user.map((item, id) => (
  543. <Avatar
  544. key={`${id}-${item.name}`}
  545. style={{ backgroundColor: '#008dff' }}
  546. size="large"
  547. >
  548. {item.Name}
  549. </Avatar>
  550. ))}
  551. </Avatar.Group>
  552. <DropdownMenu
  553. compareList={compareList}
  554. isMerge={isMerge}
  555. version={version}
  556. flowDetail={flowDetail}
  557. classifyList={classifyList}
  558. currentUser={currentUser}
  559. isAuditor={isAuditor}
  560. flow={flow}
  561. sheetRef3={sheetRef3}
  562. onClick={handleMenuClick}
  563. setVersion={setVersion}
  564. />
  565. </div>
  566. <input
  567. type="file"
  568. ref={fileRef}
  569. style={{ display: 'none' }}
  570. onChange={e => exportExcl(e.target.files)}
  571. />
  572. </div>
  573. {showPsrBtns && <PsrControl sheetRef={sheetRef} />}
  574. <div style={{ display: 'flex' }}>
  575. <div
  576. className={styles.content}
  577. style={{
  578. width: '100%',
  579. // 合同清单先显示附件再显示清单详情
  580. flexDirection: version?.TemplateNodeInfo?.flow_id == 9 ? 'column-reverse' : 'column',
  581. }}
  582. >
  583. {/* 判断是否为比对模式 */}
  584. {compareList.length == 2 ? (
  585. <>
  586. <Alert
  587. message={`比对结果:${updateCount.diff}项差异。${updateCount.add}项新增`}
  588. type="info"
  589. />
  590. <div className={styles.sheetBox}>{compareList.map(renderSheetDom)}</div>
  591. </>
  592. ) : (
  593. <div className={styles.sheetBox}>
  594. {version.id && (
  595. <LuckySheet
  596. className={styles.sheet}
  597. ref={sheetRef}
  598. onClickCell={onClickCell}
  599. permissions={currentUser.Permission}
  600. version={version}
  601. templateId={templateId}
  602. node={node}
  603. getUser={getUser}
  604. onUpdate={onUpdate}
  605. onDelSheet={onDelSheet}
  606. />
  607. )}
  608. </div>
  609. )}
  610. <FormAndFilesNode
  611. formData={version?.formStr || version?.ding_schema}
  612. excelFileList={excelFileList}
  613. version={version}
  614. />
  615. </div>
  616. <TimeNode
  617. flow={flow}
  618. flowDetail={flowDetail}
  619. isAuditor={isAuditor}
  620. version={version}
  621. templateId={templateId}
  622. projectId={projectId}
  623. setAuditVisible={setAuditVisible}
  624. stepDirection="vertical"
  625. style={{
  626. maxWidth: '20%',
  627. display: 'inline',
  628. marginLeft: '20px',
  629. }}
  630. />
  631. </div>
  632. <CommentContent
  633. title="单元格沟通记录"
  634. comment={comment}
  635. onSubmit={handleSubmitCell}
  636. loading={loading.effects['detail/queryComment'] || loading.effects['detail/addComment']}
  637. />
  638. <HistoryDrawer
  639. versionTree={versionTree}
  640. version={version}
  641. visible={versionTreeVisible}
  642. onChangeVersion={version => changeVersion(version)}
  643. onClose={() => setVersionTreeVisible(false)}
  644. />
  645. <RightDrawer
  646. version={version}
  647. visible={commentVisible}
  648. onClose={() => setCommentVisible(false)}
  649. />
  650. <CompareModal
  651. visible={compareVisible}
  652. version={version}
  653. onClose={() => setCompareVisible(false)}
  654. onOk={onCompare}
  655. />
  656. <MergeModal
  657. visible={mergeVisible}
  658. version={version}
  659. onClose={() => setMergeVisible(false)}
  660. onOk={onMergeVersion}
  661. />
  662. <ExportModal
  663. visible={exportVisible}
  664. sheet={exportDate.data}
  665. onClose={() => setExportVisible(false)}
  666. onOk={downloadExcel}
  667. />
  668. <FlowModal
  669. typeOptions={typeOptions}
  670. flowDetail={flowDetail}
  671. visible={flowVisible}
  672. templateId={templateId}
  673. onClose={() => setFlowVisible(false)}
  674. version={version}
  675. onChangeVersion={version => changeVersion(version)}
  676. />
  677. <AuditModal
  678. loading={getLoading()}
  679. visible={auditVisible}
  680. sheetRef={sheetRef}
  681. onClose={() => setAuditVisible(false)}
  682. onOk={onAudit}
  683. flow={flow}
  684. flowDetail={flowDetail}
  685. version={version}
  686. versionList={versionList}
  687. />
  688. <VersionModal
  689. typeOptions={typeOptions}
  690. visible={versionVisible}
  691. flowDetail={flowDetail}
  692. versionList={versionList}
  693. version={version}
  694. onClose={() => setVersionVisible(false)}
  695. onOk={values => onCommit(values)}
  696. loading={getLoading()}
  697. />
  698. <CommitAuditModal
  699. visible={commitAuditVisible}
  700. version={version}
  701. onClose={() => setCommitAuditVisible(false)}
  702. luckysheet={sheetRef}
  703. templateId={templateId}
  704. />
  705. </>
  706. );
  707. }
  708. export default connect(({ detail, user, xflow, loading }) => ({
  709. flowDetail: xflow.flowDetail,
  710. auditList: detail.auditList,
  711. instanceDetail: detail.dingInstanceDetail,
  712. currentUser: user.currentUser,
  713. versionList: detail.versionList,
  714. versionTree: detail.versionTree,
  715. typeOptions: detail.typeOptions,
  716. classifyList: detail.classifyList,
  717. excelFileList: detail.excelFileList,
  718. comment: detail.comment,
  719. loading,
  720. }))(Detail);