MandateDetail.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  1. import { queryMandate } from '@/services/SmartOps';
  2. import { UnityAction } from '@/utils/utils';
  3. import { connect, useRequest } from '@umijs/max';
  4. import {
  5. Button,
  6. Checkbox,
  7. Col,
  8. ConfigProvider,
  9. DatePicker,
  10. Divider,
  11. Form,
  12. Input,
  13. Modal,
  14. Row,
  15. Select,
  16. Table,
  17. message,
  18. } from 'antd';
  19. import dayjs from 'dayjs';
  20. import { useEffect, useState } from 'react';
  21. import {
  22. MandateClass,
  23. MandateStatus,
  24. MandateType,
  25. OrderStatus,
  26. OrderType,
  27. ignoreReason,
  28. } from '../constent';
  29. import styles from './MandateDetail.less';
  30. import zhCN from 'antd/es/locale/zh_CN';
  31. const MandateDetail = (props) => {
  32. const {
  33. projectID,
  34. mandateID,
  35. userList,
  36. ignoreTask,
  37. dispatchTask,
  38. autoHandleTask,
  39. dispatch,
  40. } = props;
  41. useEffect(() => {
  42. if (userList.length === 0) {
  43. dispatch({
  44. type: 'taskUser/fetchUserList',
  45. payload: { project_id: projectID },
  46. });
  47. }
  48. }, []);
  49. const [mandateDetail, setMandateDetail] = useState();
  50. const [mandateChild, setMandateChild] = useState([]);
  51. const [handledWorkOrder, setHandledWorkOrder] = useState([]);
  52. const [ignoreModalOpen, setIgnoreModalOpen] = useState(false);
  53. const [autoHandleModalOpen, setAutoHandleModalOpen] = useState(false);
  54. const [mandateSelectModalOpen, setMandateSelectModalOpen] = useState(false);
  55. const [selectedTask, setSelectedTask] = useState([]);
  56. const [dispatchModalOpen, setDispatchModalOpen] = useState(false);
  57. const columns = [
  58. {
  59. title: '参数',
  60. dataIndex: 'Title',
  61. },
  62. {
  63. title: '调整内容',
  64. dataIndex: 'Content',
  65. },
  66. ];
  67. const { run: getMandateInfo } = useRequest(queryMandate, {
  68. manual: true,
  69. formatResult: (result) => {
  70. if (result?.data) {
  71. const tempMandate = {
  72. ...result.data,
  73. Status: MandateStatus.find(
  74. (item) => item.value === result.data.Status,
  75. ),
  76. MandateClass: MandateClass.find(
  77. (item) => item.value === result.data.MandateClass,
  78. ),
  79. MandateType: MandateType.find(
  80. (item) => item.value === result.data.MandateType,
  81. ),
  82. ResponsiblePeople: userList.find(
  83. (item) => item.ID === result.data.ResponsiblePeople,
  84. ),
  85. CreateTime: dayjs(result.data.CreateTime).format('YYYY-MM-DD HH:mm'),
  86. };
  87. const workOrder = result.data.Records.map((item) => {
  88. return {
  89. ...item,
  90. CreateTime: dayjs(item.CreateTime).format('YYYY-MM-DD HH:mm'),
  91. Status: OrderStatus.find((status) => status.value === item.Status),
  92. RecordType: OrderType.find(
  93. (type) => type.value === item.RecordType,
  94. ),
  95. Responsible: userList.find((user) => user.ID === item.Responsible),
  96. };
  97. });
  98. setMandateDetail(tempMandate);
  99. setMandateChild(tempMandate.MandateChild);
  100. setHandledWorkOrder(workOrder);
  101. }
  102. },
  103. });
  104. // 打开指定弹窗
  105. const openSpecifiedModal = (type) => {
  106. switch (type) {
  107. case 'ignore':
  108. setIgnoreModalOpen(true);
  109. break;
  110. case 'manual':
  111. UnityAction.sendMsg('menuItem', '工艺监控');
  112. break;
  113. case 'auto':
  114. setAutoHandleModalOpen(true);
  115. break;
  116. case 'dispatch':
  117. setMandateSelectModalOpen(true);
  118. break;
  119. }
  120. };
  121. // 忽略
  122. const onIgnoreConfirm = async (reason) => {
  123. const result = await ignoreTask(mandateID, reason);
  124. if (result) {
  125. setIgnoreModalOpen(false);
  126. getMandateInfo({ mandate_id: mandateID });
  127. }
  128. };
  129. const onAutoHandleConfirm = async (pw) => {
  130. const result = await autoHandleTask(pw, mandateDetail);
  131. if (result) {
  132. setAutoHandleModalOpen(false);
  133. getMandateInfo({ mandate_id: mandateID });
  134. }
  135. };
  136. const onManualHandleConfirm = () => {
  137. console.log('manual handle Confirm');
  138. };
  139. const onMandateSelected = (records) => {
  140. // 打开派单Form弹窗将选中的任务进行派遣
  141. if (records?.length === 0) {
  142. message.warning('请先选择要派遣的任务');
  143. return;
  144. }
  145. setSelectedTask(records);
  146. setDispatchModalOpen(true);
  147. };
  148. const onDispatchConfirm = async (value) => {
  149. const params = {
  150. ...value,
  151. m_id: Number(mandateID),
  152. mc_id: selectedTask.join(),
  153. plan_end_time: dayjs(value.plan_end_time).format('YYYY-MM-DD HH:mm:ss'),
  154. };
  155. if (params.type === 5) {
  156. if (params.mc_id.split(',').length > 1) {
  157. message.warning('加药工单不可批量派遣');
  158. return;
  159. }
  160. params.note = `${
  161. mandateChild
  162. .find((mandate) => mandate.Id === Number(params.mc_id))
  163. ?.Title?.split(':')[1] + ',请及时加药'
  164. }`;
  165. } else {
  166. params.note = mandateDetail.Summary;
  167. }
  168. const result = await dispatchTask(params);
  169. if (result) {
  170. setDispatchModalOpen(false);
  171. getMandateInfo({ mandate_id: mandateID });
  172. }
  173. };
  174. const openWorkOrderModal = (record) => {
  175. UnityAction.sendMsg(
  176. 'OpenWorkOrderModal',
  177. `order_id=${record.Id}&order_type=${record.RecordType.value}`,
  178. );
  179. };
  180. useEffect(() => {
  181. getMandateInfo({ mandate_id: mandateID });
  182. }, []);
  183. return (
  184. <div>
  185. <div className={styles.mandate}>
  186. <Row>
  187. <Col className={styles.fontS28}>任务内容:</Col>
  188. <Col className={styles.fontS28} span={21}>
  189. <Table
  190. columns={columns}
  191. dataSource={mandateChild}
  192. pagination={false}
  193. />
  194. </Col>
  195. </Row>
  196. <Row>
  197. <Col className={styles.fontS28} span={14}>
  198. 任务时间:{mandateDetail?.CreateTime || '-'}
  199. </Col>
  200. <Col className={styles.fontS28}>
  201. 任务类别:{mandateDetail?.MandateClass?.label || '-'}
  202. </Col>
  203. </Row>
  204. <Row>
  205. <Col className={styles.fontS28} span={14}>
  206. 任务状态:{' '}
  207. <span style={{ color: ' #5697e4' }}>
  208. {mandateDetail?.Status.label}
  209. </span>
  210. </Col>
  211. <Col className={styles.fontS28}>
  212. 任务负责人:{mandateDetail?.ResponsiblePeople?.CName || '-'}
  213. </Col>
  214. </Row>
  215. </div>
  216. {handledWorkOrder?.length > 0 && <Divider />}
  217. {handledWorkOrder?.map((item) => {
  218. return (
  219. <div key={item.Id} className={styles.relatedOrder}>
  220. <div className={styles.leftInfo}>
  221. <Row>
  222. <Col span={12} className={styles.fontS28}>
  223. 工单类型:{item?.RecordType?.label}
  224. </Col>
  225. <Col className={styles.fontS28}>时间:{item?.CreateTime}</Col>
  226. </Row>
  227. <Row>
  228. <Col span={12} className={styles.fontS28}>
  229. 工单状态:
  230. <span style={{ color: ' #5697e4' }}>
  231. {item?.Status?.label}
  232. </span>
  233. </Col>
  234. <Col className={styles.fontS28}>
  235. 工单负责人:{item?.Responsible?.CName}
  236. </Col>
  237. </Row>
  238. </div>
  239. <Divider type="vertical" style={{ height: '40px' }} />
  240. <div
  241. className={styles.rightButton}
  242. onClick={() => openWorkOrderModal(item)}
  243. >
  244. 查看工单
  245. </div>
  246. </div>
  247. );
  248. })}
  249. {mandateDetail?.Status?.value === 0 && <Divider />}
  250. {mandateDetail?.Status?.value === 0 && (
  251. <div className={styles.footerConstainer}>
  252. <Button
  253. className={styles.footerBtn}
  254. shape="round"
  255. onClick={() => {
  256. openSpecifiedModal('ignore');
  257. }}
  258. >
  259. 忽略
  260. </Button>
  261. {(mandateDetail?.MandateClass?.value === 1 ||
  262. mandateDetail?.MandateClass?.value === 2) &&
  263. mandateDetail?.Status?.value === 0 && (
  264. <>
  265. <Button
  266. className={styles.footerBtn}
  267. shape="round"
  268. onClick={() => {
  269. openSpecifiedModal('manual');
  270. }}
  271. >
  272. 手动处理
  273. </Button>
  274. <Button
  275. className={styles.footerBtn}
  276. shape="round"
  277. onClick={() => {
  278. openSpecifiedModal('auto');
  279. }}
  280. >
  281. 自动处理
  282. </Button>
  283. </>
  284. )}
  285. <Button
  286. className={styles.footerBtn}
  287. shape="round"
  288. onClick={() => {
  289. openSpecifiedModal('dispatch');
  290. }}
  291. >
  292. 派单
  293. </Button>
  294. </div>
  295. )}
  296. {/* 弹窗 */}
  297. <ConfigProvider locale={zhCN}>
  298. <IgnoreTaskModal
  299. open={ignoreModalOpen}
  300. onCancel={() => setIgnoreModalOpen(false)}
  301. onOk={onIgnoreConfirm}
  302. />
  303. <AutoHandleModal
  304. open={autoHandleModalOpen}
  305. onCancel={() => setAutoHandleModalOpen(false)}
  306. onOk={onAutoHandleConfirm}
  307. />
  308. <MandateSelectModal
  309. open={mandateSelectModalOpen}
  310. onCancel={() => setMandateSelectModalOpen(false)}
  311. selectedTask={selectedTask}
  312. setSelectedTask={setSelectedTask}
  313. onOk={onMandateSelected}
  314. list={mandateChild}
  315. />
  316. <DispatchTaskModal
  317. open={dispatchModalOpen}
  318. userList={userList}
  319. onCancel={() => {
  320. setDispatchModalOpen(false);
  321. }}
  322. onOK={onDispatchConfirm}
  323. />
  324. </ConfigProvider>
  325. </div>
  326. );
  327. };
  328. export default connect(({ taskUser }) => {
  329. return {
  330. userList: taskUser.userList,
  331. };
  332. })(MandateDetail);
  333. const IgnoreTaskModal = (params) => {
  334. const { open, onCancel, onOk } = params;
  335. const [ignoreReasonText, setIgnoreReasonText] = useState('');
  336. const [selectedReason, setSelectedReason] = useState({});
  337. const [showInput, setShowInput] = useState(false);
  338. const onReasonChange = (reason, option) => {
  339. if (reason !== 4) {
  340. setSelectedReason(option);
  341. setShowInput(false);
  342. } else {
  343. setShowInput(true);
  344. }
  345. };
  346. const onReasonTextChange = (e) => {
  347. setIgnoreReasonText(e.target.value);
  348. };
  349. const confirmIgnore = () => {
  350. if (showInput) {
  351. if (!ignoreReasonText.length) {
  352. message.warning('请输入忽略理由');
  353. } else {
  354. onOk(ignoreReasonText);
  355. }
  356. } else {
  357. if (selectedReason?.label) {
  358. onOk(selectedReason.label);
  359. } else {
  360. message.warning('请选择忽略理由');
  361. }
  362. }
  363. };
  364. return (
  365. <Modal
  366. title="忽略"
  367. open={open}
  368. onCancel={onCancel}
  369. onOk={confirmIgnore}
  370. destroyOnClose
  371. >
  372. <div style={{ padding: '15px' }}>
  373. <Form layout="vertical">
  374. <Form.Item label="忽略理由:">
  375. <Select
  376. className={styles.fontS28}
  377. options={ignoreReason}
  378. onChange={onReasonChange}
  379. allowClear
  380. />
  381. </Form.Item>
  382. {showInput && (
  383. <Form.Item label="输入理由:">
  384. <Input placeholder="请输入理由" onChange={onReasonTextChange} />
  385. </Form.Item>
  386. )}
  387. </Form>
  388. </div>
  389. </Modal>
  390. );
  391. };
  392. const AutoHandleModal = (props) => {
  393. const { open, onCancel, onOk } = props;
  394. const [automation, setAutomation] = useState();
  395. const confirmAutoHandle = () => {
  396. if (automation.length) {
  397. onOk(automation);
  398. } else {
  399. message.warning('请输入口令');
  400. }
  401. };
  402. return (
  403. <Modal
  404. title="自动处理"
  405. open={open}
  406. onCancel={onCancel}
  407. onOk={confirmAutoHandle}
  408. destroyOnClose
  409. >
  410. <div style={{ padding: '15px' }}>
  411. <Form layout="vertical">
  412. <Form.Item label="口令:">
  413. {
  414. <Input
  415. autoFocus
  416. style={{ width: '100%' }}
  417. placeholder="请输入口令"
  418. onChange={(e) => {
  419. setAutomation(e.target.value);
  420. }}
  421. />
  422. }
  423. </Form.Item>
  424. </Form>
  425. </div>
  426. </Modal>
  427. );
  428. };
  429. const MandateSelectModal = (props) => {
  430. const { open, onCancel, list, onOk, selectedTask, setSelectedTask } = props;
  431. const [checkOptions, setCheckOptions] = useState([]);
  432. useEffect(() => {
  433. setCheckOptions(
  434. list.map((mandate, index) => {
  435. return {
  436. label: (
  437. <Row className={styles.taskCheckItem}>
  438. <span
  439. style={{
  440. textDecoration: `${
  441. mandate.Status === 0 ? '' : 'line-through'
  442. }`,
  443. }}
  444. >
  445. {`${index + 1}. ${mandate.Title}为${mandate.Content}`}
  446. </span>
  447. </Row>
  448. ),
  449. value: mandate.Id,
  450. disabled: mandate.Status !== 0,
  451. };
  452. }),
  453. );
  454. }, [list]);
  455. const onDispatchClick = () => {
  456. onOk(selectedTask);
  457. };
  458. const handleCheckChange = (checkedValue) => {
  459. setSelectedTask(checkedValue);
  460. };
  461. return (
  462. <Modal
  463. title={<span className={styles.fontS28}>选择任务</span>}
  464. open={open}
  465. onCancel={onCancel}
  466. width={'95%'}
  467. destroyOnClose
  468. footer={[
  469. <Button key="back" onClick={onCancel}>
  470. 取消
  471. </Button>,
  472. <Button key="dispatch" type="primary" onClick={onDispatchClick}>
  473. 派单
  474. </Button>,
  475. ]}
  476. >
  477. <Checkbox.Group
  478. className={styles.taskCheckBox}
  479. options={checkOptions}
  480. onChange={handleCheckChange}
  481. />
  482. </Modal>
  483. );
  484. };
  485. const DispatchTaskModal = (props) => {
  486. const { open, onCancel, onOK, userList } = props;
  487. const [form] = Form.useForm();
  488. useEffect(() => {
  489. if (!open) {
  490. form.resetFields();
  491. }
  492. }, [open]);
  493. const handleDispatchConfirm = async () => {
  494. const value = await form.validateFields().catch((err) =>
  495. err.errorFields.forEach((item) => {
  496. message.error(item.errors);
  497. }),
  498. );
  499. if (!value) {
  500. return;
  501. }
  502. onOK(value);
  503. };
  504. return (
  505. <Modal
  506. title={<span className={styles.fontS28}>派遣任务</span>}
  507. onCancel={onCancel}
  508. open={open}
  509. destroyOnClose
  510. style={{ padding: '20px 0' }}
  511. onOk={handleDispatchConfirm}
  512. >
  513. <Form
  514. form={form}
  515. layout="horizontal"
  516. labelCol={{ span: 6 }}
  517. wrapperCol={{ span: 18 }}
  518. >
  519. <Form.Item
  520. label="工单类型"
  521. name="type"
  522. rules={[{ required: true, message: '请选择工单类型' }]}
  523. >
  524. <Select options={OrderType} placeholder="请选择工单类型" />
  525. </Form.Item>
  526. <Form.Item
  527. label="操作人"
  528. name="operator_id"
  529. rules={[{ required: true, message: '请选择操作人' }]}
  530. >
  531. <Select
  532. options={userList.map((item) => {
  533. return {
  534. label: item.CName,
  535. value: item.ID,
  536. };
  537. })}
  538. placeholder="请选择操作人"
  539. />
  540. </Form.Item>
  541. <Form.Item
  542. label="计划完成时间"
  543. name="plan_end_time"
  544. rules={[{ required: true, message: '请选择完成时间' }]}
  545. >
  546. <DatePicker style={{ width: '100%' }} placeholder="请选择完成时间" />
  547. </Form.Item>
  548. </Form>
  549. </Modal>
  550. );
  551. };