List.js 14 KB

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