index.jsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. import React, { useState, useRef, useEffect } from 'react';
  2. import {
  3. Button,
  4. DatePicker,
  5. Input,
  6. Select,
  7. Space,
  8. Table,
  9. message,
  10. Modal,
  11. } from 'antd';
  12. import styles from './index.less';
  13. import ContractModal, { Type } from './component/Modal';
  14. import { PageContainer } from '@ant-design/pro-components';
  15. import { useRequest, useModel } from '@umijs/max';
  16. import { connect } from 'umi';
  17. import {
  18. queryApproval,
  19. queryCompany,
  20. queryContract,
  21. queryContractCancel,
  22. queryContractCancelCheck,
  23. queryContractDownload,
  24. queryGetContractList,
  25. } from '../../services/contract';
  26. import dayjs from 'dayjs';
  27. import FileViewerModal from '@/components/FileViewerNew';
  28. import { getToken } from '@/utils/utils';
  29. import PageContent from '@/components/PageContent';
  30. import EllipsisText from './component/EllipsisText';
  31. const ConteactManager = (props) => {
  32. const { dispatch } = props;
  33. const [searchData, setSearchData] = useState({
  34. effect_on: '',
  35. project_name: '',
  36. status: '',
  37. page_size: 10,
  38. current: 1,
  39. name: '',
  40. });
  41. const {
  42. initialState: { user },
  43. } = useModel('@@initialState');
  44. const [visible, setVisible] = useState(false);
  45. const [detail, setDetail] = useState({});
  46. const [data, setData] = useState([]);
  47. const [pagination, setPagination] = useState({ current: 1 });
  48. const typeRef = useRef();
  49. const parentIdRef = useRef(0);
  50. const [fileViewerVisible, setFileViewerVisible] = useState(false);
  51. const [fileViewerData, setFileViewerData] = useState();
  52. const [modal, contextHolder] = Modal.useModal();
  53. const showBtn = (record, type) => {
  54. let bool = false;
  55. switch (type) {
  56. case 'download':
  57. if (user?.Permission['menu-001-audit'] || record.created_by == user.ID)
  58. bool = true;
  59. break;
  60. // case 'addOrCal':
  61. // if (record.created_by == user.ID) bool = true;
  62. // break;
  63. }
  64. return bool;
  65. };
  66. const columns = [
  67. {
  68. title: '合同编号',
  69. dataIndex: 'code',
  70. key: 'code',
  71. align: 'center',
  72. width: 160,
  73. },
  74. {
  75. title: '合同签订时间',
  76. dataIndex: 'effect_on',
  77. key: 'effect_on',
  78. align: 'center',
  79. width: 120,
  80. },
  81. {
  82. title: '合同名称',
  83. dataIndex: 'name',
  84. key: 'name',
  85. align: 'center',
  86. },
  87. {
  88. title: '甲方',
  89. dataIndex: 'party_a',
  90. key: 'party_a',
  91. align: 'center',
  92. render: (text) => <EllipsisText text={text} width={120} />,
  93. },
  94. {
  95. title: '乙方',
  96. dataIndex: 'party_b',
  97. key: 'party_b',
  98. align: 'center',
  99. render: (text) => <EllipsisText text={text} width={120} />,
  100. },
  101. {
  102. title: '丙方',
  103. dataIndex: 'party_c',
  104. key: 'party_c',
  105. align: 'center',
  106. render: (text) => {
  107. let str = text;
  108. try {
  109. str = JSON.parse(text).join('、');
  110. } catch (error) {}
  111. return <EllipsisText text={str} width={120} />;
  112. },
  113. },
  114. {
  115. title: '所属部门/子公司',
  116. dataIndex: 'dep_name',
  117. key: 'dep_name',
  118. align: 'center',
  119. width: 160,
  120. },
  121. {
  122. title: '项目名称',
  123. dataIndex: 'project_name',
  124. key: 'project_name',
  125. align: 'center',
  126. width: 120,
  127. },
  128. {
  129. title: '合同总价(万元)',
  130. dataIndex: 'amount',
  131. key: 'amount',
  132. align: 'center',
  133. width: 160,
  134. },
  135. {
  136. title: '经办人',
  137. dataIndex: 'deal_by',
  138. key: 'deal_by',
  139. align: 'center',
  140. width: 80,
  141. },
  142. {
  143. title: '状态',
  144. dataIndex: 'status',
  145. key: 'status',
  146. align: 'center',
  147. width: 100,
  148. render: (status) => {
  149. let str = '';
  150. switch (status) {
  151. case 1:
  152. str = '待审核';
  153. break;
  154. case 2:
  155. str = '审核拒绝';
  156. break;
  157. case 3:
  158. str = '已存档';
  159. break;
  160. case 4:
  161. str = '作废待审核';
  162. break;
  163. case 5:
  164. str = '作废拒绝';
  165. break;
  166. case 6:
  167. str = '已作废';
  168. break;
  169. }
  170. return <div>{str}</div>;
  171. },
  172. },
  173. {
  174. title: '操作',
  175. width: '210px',
  176. align: 'center',
  177. render: (record) => {
  178. return (
  179. <Space>
  180. <a
  181. onClick={() => {
  182. typeRef.current = Type.detail;
  183. parentIdRef.current = 0;
  184. setDetail(record);
  185. setVisible(true);
  186. }}
  187. >
  188. 详情
  189. </a>
  190. <a onClick={() => handlePreView(record)}>预览</a>
  191. {showBtn(record, 'download') && (
  192. <a onClick={() => handleUpload(record)}>下载</a>
  193. )}
  194. {/* {showBtn(record, 'addOrCal') && !record.parent_id && (
  195. <a
  196. onClick={() => {
  197. typeRef.current = Type.add;
  198. parentIdRef.current = record.id;
  199. setDetail({});
  200. setVisible(true);
  201. }}
  202. >
  203. 增补
  204. </a>
  205. )} */}
  206. {record.status == 3 && (
  207. <a
  208. onClick={() => {
  209. typeRef.current = Type.cancel;
  210. setDetail(record);
  211. setVisible(true);
  212. }}
  213. >
  214. 作废
  215. </a>
  216. )}
  217. </Space>
  218. );
  219. },
  220. },
  221. ];
  222. const config = {
  223. title: '添加成功!',
  224. content: (
  225. <>
  226. 将合同(含附件)的原件和相关资料交给集团档案管理部门或分子公司合同专员才能完成合同存档,请注意及时存档。
  227. </>
  228. ),
  229. };
  230. useEffect(() => {
  231. dispatch({
  232. type: 'user/fetch',
  233. });
  234. }, []);
  235. //请求列表
  236. const { run, loading } = useRequest((data) => queryGetContractList(data), {
  237. defaultParams: [searchData],
  238. onSuccess: (data) => {
  239. let resultData = data?.list?.map((item) => {
  240. return item.sub_num > 0 ? { ...item, children: [] } : item;
  241. });
  242. setData(resultData);
  243. setPagination(data?.pagination);
  244. },
  245. });
  246. //编辑新增接口
  247. const { run: editRun } = useRequest((data) => queryContract(data), {
  248. manual: true,
  249. onSuccess: () => {
  250. // message.success('添加成功');
  251. setVisible(false);
  252. run(searchData);
  253. modal.info(config);
  254. },
  255. onError: () => {
  256. message.success('添加失败');
  257. },
  258. });
  259. //作废发起
  260. const { run: calRun } = useRequest((data) => queryContractCancel(data), {
  261. manual: true,
  262. onSuccess: () => {
  263. message.success('发起作废成功');
  264. setVisible(false);
  265. run(searchData);
  266. },
  267. onError: () => {
  268. message.success('发起作废失败');
  269. },
  270. });
  271. //作废审核
  272. const { run: calCheckRun } = useRequest(
  273. (data) => queryContractCancelCheck(data),
  274. {
  275. manual: true,
  276. onSuccess: () => {
  277. message.success('审核成功');
  278. setVisible(false);
  279. run(searchData);
  280. },
  281. onError: () => {
  282. message.success('审核失败');
  283. },
  284. },
  285. );
  286. //请求项目列表
  287. const { data: projectData } = useRequest(queryApproval, {
  288. defaultParams: [{ pageSize: 99999 }],
  289. });
  290. const handlePreView = (record) => {
  291. if (!record.attach) return;
  292. const attach = JSON.parse(record.attach);
  293. setFileViewerData(attach);
  294. setFileViewerVisible(true);
  295. };
  296. const handleUpload = (record) => {
  297. const token = getToken();
  298. window.downloadFile(
  299. `/api/contract/v1/contract/download?id=${record.id}&JWT-TOKEN=${token}`,
  300. record.name,
  301. false,
  302. );
  303. };
  304. const handleSearch = () => {
  305. run(searchData);
  306. };
  307. const handleExport = () => {};
  308. const handleQueryChildren = async (req) => {
  309. const res = await queryGetContractList(req);
  310. if (res?.data?.list) {
  311. let resultData = [...data];
  312. let idx = data.findIndex((item) => item.id == req.is_parent);
  313. if (idx > -1) {
  314. resultData[idx].children = res?.data?.list;
  315. setData(resultData);
  316. setPagination(res.data?.pagination);
  317. // setData({ list: resultData, pagination: res.data?.pagination });
  318. }
  319. }
  320. };
  321. const handleOk = (data) => {
  322. if (typeRef.current == Type.add) {
  323. editRun(data);
  324. } else if (typeRef.current == Type.cancel) {
  325. calRun(data);
  326. } else {
  327. calCheckRun(data);
  328. }
  329. };
  330. const onPageChange = (page) => {
  331. run({ ...searchData, current: page });
  332. };
  333. return (
  334. <PageContent>
  335. <div className={styles.searchContent}>
  336. <div className={styles.itemFlex}>
  337. <div>合同签订日期:</div>
  338. <DatePicker
  339. onChange={(e) => {
  340. setSearchData({
  341. ...searchData,
  342. effect_on: e ? dayjs(e).format('YYYY-MM-DD') : null,
  343. });
  344. }}
  345. />
  346. </div>
  347. <div className={styles.itemFlex}>
  348. <div>项目名称:</div>
  349. <Select
  350. style={{ width: 200 }}
  351. placeholder="请选择"
  352. onChange={(e) => {
  353. setSearchData({
  354. ...searchData,
  355. project_name: e,
  356. });
  357. }}
  358. options={projectData?.list?.map((item) => {
  359. return {
  360. value: item.project_name,
  361. label: item.project_name,
  362. };
  363. })}
  364. />
  365. </div>
  366. <div className={styles.itemFlex}>
  367. <div>状态:</div>
  368. <Select
  369. style={{ width: 150 }}
  370. placeholder="请选择"
  371. allowClear
  372. onChange={(e) => {
  373. setSearchData({
  374. ...searchData,
  375. status: e,
  376. });
  377. }}
  378. options={[
  379. { value: 3, label: '已归档' },
  380. { value: 1, label: '归档审核中' },
  381. { value: 4, label: '作废审核中' },
  382. { value: 6, label: '已作废' },
  383. { value: 2, label: '归档拒绝' },
  384. { value: 5, label: '作废拒绝' },
  385. ]}
  386. />
  387. </div>
  388. <Input
  389. style={{ width: 150 }}
  390. className={styles.inputSty}
  391. placeholder="请输入合同名称/编号"
  392. allowClear
  393. onChange={(e) => {
  394. setSearchData({
  395. ...searchData,
  396. name: e.target.value,
  397. });
  398. }}
  399. />
  400. <Button
  401. type="primary"
  402. className={styles.searchBtnSty}
  403. onClick={handleSearch}
  404. >
  405. 查询
  406. </Button>
  407. <Button
  408. type="primary"
  409. onClick={() => {
  410. typeRef.current = Type.add;
  411. setDetail({});
  412. setVisible(true);
  413. }}
  414. >
  415. 新增
  416. </Button>
  417. <Button
  418. type="primary"
  419. className={styles.exportBtnSty}
  420. onClick={handleExport}
  421. >
  422. 导出
  423. </Button>
  424. </div>
  425. <Table
  426. rowKey="code"
  427. loading={loading}
  428. columns={columns}
  429. dataSource={data}
  430. indentSize={70}
  431. onExpand={(expanded, record) => {
  432. console.log(expanded, record);
  433. if (expanded) handleQueryChildren({ is_parent: record.id });
  434. }}
  435. pagination={{ ...pagination, onChange: onPageChange }}
  436. />
  437. <ContractModal
  438. detail={detail}
  439. type={typeRef.current}
  440. parent_id={parentIdRef.current}
  441. projectList={projectData?.list}
  442. visible={visible}
  443. handleOk={handleOk}
  444. handleCancel={() => setVisible(false)}
  445. />
  446. <FileViewerModal
  447. data={fileViewerData}
  448. visible={fileViewerVisible}
  449. downloadFile={() => {}}
  450. onCancel={() => {
  451. setFileViewerVisible(false);
  452. }}
  453. />
  454. {contextHolder}
  455. </PageContent>
  456. );
  457. };
  458. export default connect(({ user, loading }) => ({
  459. userList: user.list,
  460. }))(ConteactManager);