AuditFlow.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. import React, { useMemo, useEffect, useState, useRef } from 'react';
  2. import { Steps, Popover, Alert, Button, Spin } from 'antd';
  3. import styles from './Index.less';
  4. import { queryDDProcessesForecast } from '@/services/boom';
  5. import { connect } from 'dva';
  6. const { Step } = Steps;
  7. function AuditFlow(props) {
  8. const {
  9. processCode,
  10. deptId,
  11. userId,
  12. formComponentValues,
  13. // activityId,
  14. direction,
  15. status,
  16. tasks,
  17. userList,
  18. cc_userids = [],
  19. canShowAudit = false,
  20. onApprove,
  21. } = props;
  22. const [flow, setFlow] = useState({ workflowActivityRules: [] });
  23. const [loading, setLoading] = useState(false);
  24. const timerRef = useRef({
  25. id: '',
  26. status: false,
  27. });
  28. const current = useMemo(() => {
  29. if (!tasks || tasks.length == 0) {
  30. return false;
  31. } else {
  32. let current = 0;
  33. flow.workflowActivityRules.forEach((item, index) => {
  34. let task = tasks.find(task => task.activity_id == item.activityId);
  35. if (task) {
  36. if (task.task_status == 'COMPLETED') {
  37. // 完成时节点为下一级
  38. current = index + 1;
  39. } else {
  40. // 未完成则为当前节点
  41. current = index;
  42. }
  43. }
  44. });
  45. return current;
  46. }
  47. }, [tasks, flow]);
  48. const showAduit = useMemo(() => {
  49. if (!canShowAudit) return false;
  50. //当前处理中的审批人和登录人是一个人显示审批通过和拒绝
  51. if (!tasks || tasks.length == 0) {
  52. return false;
  53. } else {
  54. // 查询处于RUNNING的task activityId
  55. const runningTask = tasks.filter(item => item.task_status == 'RUNNING');
  56. // const task = tasks.find(task => task.activity_id == activityId);
  57. if (runningTask.length == 0) return false;
  58. // if (task.task_status == 'RUNNING' && task.userid == userId) return true;
  59. return runningTask.find(task => task.userid == userId);
  60. }
  61. }, [tasks, userId]);
  62. const getTaskId = () => {
  63. const runningTask = tasks.find(item => item.task_status == 'RUNNING' && item.userid == userId);
  64. if (runningTask) return runningTask.taskid;
  65. };
  66. const getDesc = item => {
  67. const { activityId } = item;
  68. if (!tasks || tasks.length == 0) return '';
  69. if (item.activityName == '抄送人') {
  70. let names = cc_userids
  71. .map(userId => {
  72. let user = userList.find(u => u.DingUserId == userId);
  73. return user?.CName;
  74. })
  75. .filter(item => item);
  76. return names.join(',');
  77. } else {
  78. const task = tasks.find(task => task.activity_id == activityId);
  79. if (!task) return;
  80. const user = userList.find(user => task.userid == user.DingUserId);
  81. let result = null;
  82. if (task.task_result !== 'NONE') {
  83. result = (
  84. <>
  85. <br />
  86. 审批结果: {TASK_RESULT[task.task_result]}
  87. <br />
  88. </>
  89. );
  90. }
  91. return (
  92. <>
  93. {user?.CName || '未知操作人'}({TASK_STATUS[task.task_status]}){result}
  94. </>
  95. );
  96. }
  97. };
  98. const renderAlert = () => {
  99. // const audit_comment = history.list[0]?.audit_comment;
  100. let item = '';
  101. switch (status) {
  102. case -1:
  103. item = <Alert message="已失效" type="error" />;
  104. break;
  105. case 0:
  106. if (!flow.list || flow.list.FlowNodes?.length == 0) return;
  107. item = <Alert message="审批拒绝" type="error" />;
  108. break;
  109. case 1:
  110. item = <Alert message="等待审核中" type="info" />;
  111. break;
  112. case 2:
  113. item = <Alert message={`审批被拒绝`} type="error" />;
  114. break;
  115. case 3:
  116. item = <Alert message="审批通过" type="success" />;
  117. break;
  118. case -1:
  119. item = <Alert message="已失效" type="error" />;
  120. break;
  121. }
  122. return <div style={{ margin: '20px auto' }}>{item}</div>;
  123. };
  124. const customDot = (dot, { status, index }) => {
  125. let item = flow.workflowActivityRules[index];
  126. return (
  127. <Popover
  128. content={
  129. <div>
  130. 节点类型:{ACTIVITY_TYPE[item.activityType]}
  131. <br />
  132. 操作人类型:{ACTOR_TYPE[item.workflowActor?.actorType]}
  133. <br />
  134. 审批类型:{APPROVAL_TYPE[item.workflowActor?.approvalType]}
  135. <br />
  136. 审批方式:{APPROVAL_METHOD[item.workflowActor?.approvalMethod]}
  137. </div>
  138. }
  139. >
  140. {dot}
  141. </Popover>
  142. );
  143. };
  144. const getDetail = async () => {
  145. if (!deptId || !userId) {
  146. console.log('depId或userId不存在!');
  147. return;
  148. }
  149. if (!timerRef.current.status) {
  150. // 上锁
  151. timerRef.current.status = true;
  152. setLoading(true);
  153. try {
  154. let flow = await queryDDProcessesForecast({
  155. processCode,
  156. deptId,
  157. userId,
  158. formComponentValues,
  159. });
  160. setFlow(flow);
  161. console.log(flow);
  162. } catch (error) {}
  163. setLoading(false);
  164. setTimeout(() => {
  165. // 延时解锁
  166. timerRef.current.status = false;
  167. }, 2000);
  168. } else {
  169. clearTimeout(timerRef.current.id);
  170. // 延迟调用
  171. timerRef.current.id = setTimeout(() => {
  172. getDetail();
  173. }, 2000);
  174. }
  175. };
  176. useEffect(() => {
  177. if (!processCode || !formComponentValues) return;
  178. getDetail();
  179. }, [processCode, formComponentValues]);
  180. return (
  181. <Spin spinning={loading}>
  182. <div className={styles.top}>
  183. <Steps current={current} progressDot={customDot} direction={direction}>
  184. {flow.workflowActivityRules.map(item => (
  185. <Step key={item.activityId} title={item?.activityName} description={getDesc(item)} />
  186. ))}
  187. {/* <Step key={item.activityId} title={item?.activityName} description={renderDesc(item)} /> */}
  188. </Steps>
  189. {showAduit && status != -1 && (
  190. <div className={styles.btns} style={{ marginLeft: 80 }}>
  191. <Button type="primary" onClick={() => onApprove(true, getTaskId())}>
  192. 审批通过
  193. </Button>
  194. <Button onClick={() => onApprove(false, getTaskId())} danger>
  195. 审批拒绝
  196. </Button>
  197. </div>
  198. )}
  199. </div>
  200. {status !== undefined && renderAlert()}
  201. </Spin>
  202. );
  203. }
  204. const ACTOR_TYPE = {
  205. approver: '审批人',
  206. notifier: '抄送人',
  207. audit: '办理人',
  208. };
  209. const APPROVAL_TYPE = {
  210. MANUAL: '人工审批',
  211. AUTO_AGREE: '自动通过',
  212. AUTO_REFUSE: '自动拒绝',
  213. };
  214. const APPROVAL_METHOD = {
  215. ONE_BY_ONE: '依次审批',
  216. AND: '会签审批',
  217. OR: '或签审批',
  218. };
  219. const ACTIVITY_TYPE = {
  220. target_select: '自选审批人',
  221. target_approval: '指定审批人',
  222. };
  223. const OPERATION_RESULT = {
  224. AGREE: '同意',
  225. REFUSE: '拒绝',
  226. NONE: '未处理',
  227. };
  228. const OPERATION_TYPE = {
  229. EXECUTE_TASK_NORMAL: '正常执行任务',
  230. EXECUTE_TASK_AGENT: '代理人执行任务',
  231. APPEND_TASK_BEFORE: '前加签任务',
  232. APPEND_TASK_AFTER: '后加签任务',
  233. REDIRECT_TASK: '转交任务',
  234. START_PROCESS_INSTANCE: '发起流程实例',
  235. TERMINATE_PROCESS_INSTANCE: '终止(撤销)流程实例',
  236. FINISH_PROCESS_INSTANCE: '结束流程实例',
  237. ADD_REMARK: '添加评论',
  238. REDIRECT_PROCESS: '审批退回',
  239. PROCESS_CC: '抄送',
  240. };
  241. const TASK_STATUS = {
  242. NEW: '未启动',
  243. RUNNING: '处理中',
  244. PAUSED: '暂停',
  245. CANCELED: '取消',
  246. COMPLETED: '完成',
  247. TERMINATED: '终止',
  248. };
  249. const TASK_RESULT = {
  250. AGREE: '同意',
  251. REFUSE: '拒绝',
  252. REDIRECTED: '转交',
  253. NONE: '未处理',
  254. };
  255. export default connect(({ user }) => ({
  256. userList: user.list,
  257. }))(AuditFlow);