List.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. import React, { useState, useEffect } from 'react';
  2. import { Table, Button, Form, Select, Divider, Modal, Popover, Input, Checkbox } from 'antd';
  3. import moment from 'moment';
  4. import router from 'umi/router';
  5. import styles from './List.less';
  6. import ApprovalModal from './ApprovalModal';
  7. import DetailModal from './DetailModal';
  8. import ExecutionModal from './ExecutionModal';
  9. import MemberModal from './MemberModal';
  10. import QualityOperateModal from './QualityOperateModal';
  11. import { connect } from 'dva';
  12. const { Option } = Select;
  13. //状态
  14. const STATUS = [
  15. {
  16. value: 0,
  17. label: '售前',
  18. },
  19. {
  20. value: 1,
  21. label: '转执行',
  22. },
  23. {
  24. value: 2,
  25. label: '转运营',
  26. },
  27. {
  28. value: 3,
  29. label: '转质保',
  30. },
  31. ];
  32. function List(props) {
  33. const {
  34. industryList,
  35. typeList,
  36. data,
  37. flowList,
  38. currentUser,
  39. dispatch,
  40. loading,
  41. depUserTree,
  42. member,
  43. } = props;
  44. const [form] = Form.useForm();
  45. const [addVisible, setAddVisible] = useState(false);
  46. const [detailVisible, setDetailVisible] = useState(false);
  47. const [executionVisible, setExecutionVisible] = useState(false);
  48. const [qualityOperateVisible, setQualityOperateVisible] = useState(false);
  49. const [memberVisible, setMemberVisible] = useState(false);
  50. const [selfItems, setSelfItems] = useState(false);
  51. const [currentItem, setCurrentItem] = useState({});
  52. const [qualityOperate, setQualityOperate] = useState(0);
  53. const columns = [
  54. {
  55. title: '项目编号',
  56. dataIndex: 'project_full_code',
  57. },
  58. {
  59. title: '项目名称',
  60. dataIndex: 'project_name',
  61. },
  62. {
  63. title: '分类',
  64. dataIndex: 'TypeInfo',
  65. render: TypeInfo => (TypeInfo ? `${TypeInfo.name}(${TypeInfo.code})` : '-'),
  66. },
  67. /*
  68. {
  69. title: '名称',
  70. dataIndex: 'name',
  71. },
  72. {
  73. title: '行业',
  74. dataIndex: 'IndustryInfo',
  75. render: IndustryInfo => `${IndustryInfo.name}(${IndustryInfo.code})`,
  76. },
  77. {
  78. title: '所在地',
  79. dataIndex: 'location',
  80. render: (location, record) => `${location}(${record.location_code})`,
  81. },
  82. {
  83. title: '期数',
  84. dataIndex: 'version',
  85. render: version => `${version}期`,
  86. },
  87. */
  88. {
  89. title: '流程',
  90. dataIndex: ['FlowInfo', 'name'],
  91. },
  92. {
  93. title: '状态',
  94. dataIndex: 'project_status',
  95. render: project_status => {
  96. // return project_status === 0 ? <>售前</> : <>转执行</>;
  97. //若添加其他状态则启用以下switch case:
  98. switch (project_status) {
  99. case 0:
  100. return <>售前</>;
  101. case 1:
  102. return <>转执行</>;
  103. case 2:
  104. return <>转运营</>;
  105. case 3:
  106. return <>转质保</>;
  107. }
  108. },
  109. },
  110. {
  111. title: '节点',
  112. dataIndex: 'NodeInfo',
  113. render: (nodeInfo, item) => {
  114. let statusDom;
  115. switch (item.audit_status) {
  116. case 0:
  117. statusDom = '待提交';
  118. break;
  119. case 1:
  120. statusDom = <span style={{ color: '#1890ff' }}>审核中</span>;
  121. break;
  122. case 2:
  123. statusDom = (
  124. <Popover content={`拒绝原因: ${item.audit_comment}`}>
  125. <span style={{ color: '#f5222d' }}>审核拒绝</span>
  126. </Popover>
  127. );
  128. break;
  129. case 3:
  130. statusDom = <span style={{ color: '#a0d911' }}>审核通过</span>;
  131. break;
  132. }
  133. return (
  134. <>
  135. {nodeInfo.node}({statusDom})
  136. </>
  137. );
  138. },
  139. },
  140. {
  141. title: '售前项目经理',
  142. dataIndex: 'AuthorUser',
  143. render: AuthorUser => (AuthorUser ? AuthorUser.CName : '-'),
  144. },
  145. {
  146. title: '创建时间',
  147. dataIndex: 'c_time',
  148. render: c_time => moment(c_time).format('YYYY.MM.DD'),
  149. },
  150. {
  151. title: '执行经理',
  152. dataIndex: 'Leader',
  153. render: Leader => (Leader ? Leader.CName : '-'),
  154. },
  155. {
  156. title: '操作',
  157. render: record => renderEditBtns(record),
  158. },
  159. ];
  160. const handleSearch = () => {
  161. const { projectName, projectCode, projectStatus } = form.getFieldsValue();
  162. let params = {};
  163. params.project_name = projectName;
  164. params.project_code = projectCode?.toUpperCase();
  165. params.project_status = projectStatus;
  166. params.currentPage = 1;
  167. dispatch({
  168. type: 'approval/queryApproval',
  169. payload: params,
  170. });
  171. };
  172. const checkSelf = e => {
  173. let checked = e.target.checked;
  174. setCurrentItem({});
  175. setSelfItems(checked);
  176. dispatch({
  177. type: 'approval/queryApproval',
  178. payload: {
  179. filter_type: Number(checked),
  180. currentPage: 1,
  181. },
  182. });
  183. };
  184. const renderSearch = () => {
  185. return (
  186. <Form
  187. form={form}
  188. layout="inline"
  189. initialValues={{ projectName: null, projectCode: null, projectStatus: null }}
  190. >
  191. <Form.Item label="项目名称" name="projectName">
  192. <Input style={{ width: 200 }} />
  193. </Form.Item>
  194. <Form.Item label="项目编号" name="projectCode">
  195. <Input style={{ width: 200 }} />
  196. </Form.Item>
  197. <Form.Item label="状态" name="projectStatus">
  198. <Select
  199. showSearch
  200. style={{ width: 120 }}
  201. filterOption={(input, option) =>
  202. option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
  203. }
  204. >
  205. <Option value={null}>全部</Option>
  206. {STATUS.map(item => (
  207. <Option key={item.value}>{item.label}</Option>
  208. ))}
  209. </Select>
  210. </Form.Item>
  211. <Form.Item>
  212. <Button type="primary" loading={loading} onClick={handleSearch}>
  213. 查询
  214. </Button>
  215. </Form.Item>
  216. </Form>
  217. );
  218. };
  219. const onOk = values => {
  220. if (values.id) {
  221. dispatch({
  222. type: 'approval/updateApproval',
  223. payload: values,
  224. callback: () => setAddVisible(false),
  225. });
  226. } else {
  227. dispatch({
  228. type: 'approval/createApproval',
  229. payload: values,
  230. callback: () => setAddVisible(false),
  231. });
  232. }
  233. };
  234. const onDelete = item => {
  235. Modal.confirm({
  236. title: '删除',
  237. content: '是否确认删除该项目',
  238. okText: '删除',
  239. okType: 'danger',
  240. cancelText: '取消',
  241. onOk() {
  242. dispatch({
  243. type: 'approval/deleteApproval',
  244. payload: item,
  245. });
  246. },
  247. });
  248. };
  249. const onSubmitAuth = item => {
  250. Modal.confirm({
  251. title: '提交审核',
  252. content: '是否确认提交审核',
  253. okText: '提审',
  254. cancelText: '取消',
  255. onOk() {
  256. dispatch({
  257. type: 'approval/submitAudit',
  258. payload: {
  259. id: item.id,
  260. flow_id: item.flow_id,
  261. node_id: item.node_id,
  262. },
  263. });
  264. },
  265. });
  266. };
  267. const queryList = page => {
  268. dispatch({
  269. type: 'approval/queryApproval',
  270. payload: {
  271. currentPage: page.current,
  272. },
  273. });
  274. };
  275. const renderEditBtns = record => {
  276. let dividerPush = (item, list) => {
  277. if (list.length === 0) list.push(item);
  278. else {
  279. list.push(<Divider type="vertical" />);
  280. list.push(item);
  281. }
  282. };
  283. let detailBtn = (
  284. <a
  285. onClick={() => {
  286. setCurrentItem(record);
  287. setDetailVisible(true);
  288. }}
  289. >
  290. 项目详情
  291. </a>
  292. );
  293. let memberBtn = (
  294. <a
  295. onClick={() => {
  296. setCurrentItem(record);
  297. setMemberVisible(true);
  298. dispatch({
  299. type: 'approval/queryMember',
  300. payload: { project_code_id: record.id },
  301. });
  302. }}
  303. >
  304. 成员管理
  305. </a>
  306. );
  307. let executionBtn = (
  308. <a
  309. onClick={() => {
  310. setCurrentItem(record);
  311. setExecutionVisible(true);
  312. }}
  313. >
  314. 转执行
  315. </a>
  316. );
  317. let editBtn = (
  318. <>
  319. <a
  320. onClick={() => {
  321. setCurrentItem(record);
  322. setAddVisible(true);
  323. }}
  324. >
  325. 编辑
  326. </a>
  327. <Divider type="vertical" />
  328. <a
  329. onClick={() => {
  330. onDelete(record);
  331. }}
  332. >
  333. 删除
  334. </a>
  335. <Divider type="vertical" />
  336. <a
  337. onClick={() => {
  338. onSubmitAuth(record);
  339. }}
  340. >
  341. 提交审核
  342. </a>
  343. </>
  344. );
  345. let statusBtn = (
  346. <>
  347. <a
  348. onClick={() => {
  349. setCurrentItem(record);
  350. setQualityOperateVisible(true);
  351. setQualityOperate(0);
  352. }}
  353. >
  354. 转质保
  355. </a>
  356. <Divider type="vertical" />
  357. <a
  358. onClick={() => {
  359. setCurrentItem(record);
  360. setQualityOperateVisible(true);
  361. setQualityOperate(1);
  362. }}
  363. >
  364. 转运营
  365. </a>
  366. </>
  367. );
  368. let { audit_status, project_status, type_id } = record;
  369. //权限审核
  370. let canEdit = () => {
  371. if (currentUser.IsSuper) return true;
  372. switch (audit_status) {
  373. case 0:
  374. return currentUser.ID == record.author;
  375. case 1:
  376. return false;
  377. case 2:
  378. if (project_status == 0) return currentUser.ID == record.author;
  379. if (project_status == 1) return currentUser.ID == record.LeaderId;
  380. return false;
  381. case 3:
  382. switch (project_status) {
  383. case 0:
  384. return currentUser.ID == record.author;
  385. case 1:
  386. return currentUser.ID == record.LeaderId;
  387. case 2:
  388. return currentUser.ID == record.LeaderId || currentUser.ID == record.opt_manager_id;
  389. case 3:
  390. return currentUser.ID == record.LeaderId || currentUser.ID == record.wty_manager_id;
  391. }
  392. return false;
  393. }
  394. };
  395. let toReturn = [];
  396. dividerPush(detailBtn, toReturn);
  397. switch (audit_status) {
  398. //未提交
  399. case 0:
  400. canEdit() && dividerPush(editBtn, toReturn);
  401. break;
  402. //审核中
  403. case 1:
  404. break;
  405. //审核拒绝
  406. case 2:
  407. if (project_status == 0 && canEdit()) dividerPush(editBtn, toReturn);
  408. else if (project_status == 1 && canEdit()) {
  409. dividerPush(memberBtn, toReturn);
  410. dividerPush(statusBtn, toReturn);
  411. }
  412. break;
  413. //审核通过
  414. case 3:
  415. switch (project_status) {
  416. //售前
  417. case 0:
  418. if (canEdit()) {
  419. dividerPush(memberBtn, toReturn);
  420. dividerPush(executionBtn, toReturn);
  421. }
  422. break;
  423. //转执行
  424. case 1:
  425. if (canEdit()) {
  426. dividerPush(memberBtn, toReturn);
  427. dividerPush(statusBtn, toReturn);
  428. }
  429. break;
  430. //转运营
  431. case 2:
  432. canEdit() && dividerPush(memberBtn, toReturn);
  433. break;
  434. //转质保
  435. case 3:
  436. canEdit() && dividerPush(memberBtn, toReturn);
  437. break;
  438. }
  439. break;
  440. }
  441. return toReturn;
  442. };
  443. useEffect(() => {
  444. dispatch({
  445. type: 'approval/queryFlow',
  446. });
  447. dispatch({
  448. type: 'approval/queryType',
  449. });
  450. dispatch({
  451. type: 'approval/queryIndustry',
  452. });
  453. dispatch({
  454. type: 'approval/queryApproval',
  455. });
  456. dispatch({
  457. type: 'approval/fetchDepV2',
  458. });
  459. }, []);
  460. return (
  461. <div>
  462. {renderSearch()}
  463. <div className={styles.btns}>
  464. <Button
  465. onClick={() => {
  466. setCurrentItem({});
  467. setAddVisible(true);
  468. }}
  469. >
  470. 新增项目
  471. </Button>
  472. <Checkbox checked={selfItems} onChange={checkSelf}>
  473. 只看自己
  474. </Checkbox>
  475. </div>
  476. <Table
  477. loading={loading}
  478. rowKey="id"
  479. dataSource={data.list}
  480. pagination={data.pagination}
  481. columns={columns}
  482. onChange={queryList}
  483. />
  484. <ApprovalModal
  485. currentUser={currentUser}
  486. depUserTree={depUserTree}
  487. loading={loading}
  488. industryList={industryList}
  489. flowList={flowList}
  490. typeList={typeList}
  491. visible={addVisible}
  492. onOk={onOk}
  493. data={currentItem}
  494. total={data.pagination.total}
  495. onClose={() => setAddVisible(false)}
  496. />
  497. <DetailModal
  498. industryList={industryList}
  499. flowList={flowList}
  500. typeList={typeList}
  501. visible={detailVisible}
  502. data={currentItem}
  503. onClose={() => setDetailVisible(false)}
  504. />
  505. <ExecutionModal
  506. depUserTree={depUserTree}
  507. loading={loading}
  508. visible={executionVisible}
  509. currentItem={currentItem}
  510. onOk={() => setExecutionVisible(false)}
  511. onClose={() => setExecutionVisible(false)}
  512. />
  513. <MemberModal
  514. depUserTree={depUserTree}
  515. loading={loading}
  516. visible={memberVisible}
  517. onClose={() => setMemberVisible(false)}
  518. currentItem={currentItem}
  519. dataSource={member}
  520. />
  521. <QualityOperateModal
  522. depUserTree={depUserTree}
  523. loading={loading}
  524. visible={qualityOperateVisible}
  525. currentItem={currentItem}
  526. onOk={() => setQualityOperateVisible(false)}
  527. onClose={() => setQualityOperateVisible(false)}
  528. qualityOperate={qualityOperate}
  529. />
  530. </div>
  531. );
  532. }
  533. export default connect(({ approval, user, loading }) => ({
  534. data: approval.list,
  535. typeList: approval.typeList,
  536. flowList: approval.flowList,
  537. industryList: approval.industryList,
  538. currentUser: user.currentUser,
  539. loading: loading.models.approval,
  540. depUserTree: approval.depUserTree,
  541. member: approval.member,
  542. }))(List);