Forráskód Böngészése

流程功能测试

wangliang 1 éve
szülő
commit
7a1987a36c

+ 88 - 0
sop-business/src/main/java/com/qmth/sop/business/activiti/service/ActivitiService.java

@@ -0,0 +1,88 @@
+package com.qmth.sop.business.activiti.service;
+
+import com.qmth.sop.business.bean.bean.FormPropertyBean;
+import com.qmth.sop.common.enums.FlowApprovePassEnum;
+import com.qmth.sop.common.enums.TFCustomTypeEnum;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Description: activiti service
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2021/7/12
+ */
+public interface ActivitiService {
+
+    /**
+     * 根据deploymentId查找processDefinitionId
+     *
+     * @param deploymentId
+     * @return
+     */
+    String findProcessDefinitionIdByDeploymentId(String deploymentId);
+
+    /**
+     * 部署流程
+     *
+     * @param tfCustomTypeEnumList
+     * @return
+     */
+    public Map<String, Object> createDeployment(List<TFCustomTypeEnum> tfCustomTypeEnumList) throws IOException;
+
+    /**
+     * 审批任务
+     *
+     * @param flowDeploymentId
+     * @param approve
+     * @param taskId
+     * @param formProperties
+     * @param approveUserIds
+     * @param approveRemark
+     * @param map
+     * @return
+     */
+    public Map<String, Object> taskApprove(String flowDeploymentId,
+                                           FlowApprovePassEnum approve,
+                                           Long taskId,
+                                           String formProperties,
+                                           List<Long> approveUserIds,
+                                           String approveRemark,
+                                           Map<String, Object> map);
+
+    /**
+     * 获取流程表单属性接口
+     *
+     * @param flowDeploymentId
+     * @param flowId
+     * @param taskId
+     * @return
+     */
+    public Map<String, Object> formPropertiesGet(String flowDeploymentId, Long flowId, Long taskId);
+
+    /**
+     * 获取用户待办
+     *
+     * @param userId
+     * @return
+     */
+    public List<FormPropertyBean> getTaskList(Long userId);
+
+    /**
+     * 流程节点转他人审批
+     *
+     * @param userId
+     * @param taskId
+     */
+    public void taskApproverExchange(Long userId, Long taskId);
+
+    /**
+     * 流程终止
+     *
+     * @param flowId
+     */
+    public void flowEnd(Long flowId);
+}

+ 672 - 0
sop-business/src/main/java/com/qmth/sop/business/activiti/service/impl/ActivitiServiceImpl.java

@@ -0,0 +1,672 @@
+package com.qmth.sop.business.activiti.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.qmth.boot.api.exception.ApiException;
+import com.qmth.sop.business.activiti.service.ActivitiService;
+import com.qmth.sop.business.bean.bean.FormPropertyBean;
+import com.qmth.sop.business.bean.result.FlowResult;
+import com.qmth.sop.business.bean.result.FlowTaskResult;
+import com.qmth.sop.business.entity.TFCustomFlow;
+import com.qmth.sop.business.entity.TFCustomFlowEntity;
+import com.qmth.sop.business.entity.TFFlowApprove;
+import com.qmth.sop.business.entity.TFFlowLog;
+import com.qmth.sop.business.mapper.SysUserMapper;
+import com.qmth.sop.business.service.TFCustomFlowEntityService;
+import com.qmth.sop.business.service.TFCustomFlowService;
+import com.qmth.sop.business.service.TFFlowApproveService;
+import com.qmth.sop.business.service.TFFlowLogService;
+import com.qmth.sop.common.contant.SystemConstant;
+import com.qmth.sop.common.enums.*;
+import com.qmth.sop.common.lock.MemoryLock;
+import com.qmth.sop.common.util.GsonUtil;
+import com.qmth.sop.common.util.JacksonUtil;
+import com.qmth.sop.common.util.ResultUtil;
+import org.activiti.bpmn.model.BpmnModel;
+import org.activiti.bpmn.model.FlowNode;
+import org.activiti.bpmn.model.UserTask;
+import org.activiti.engine.HistoryService;
+import org.activiti.engine.RepositoryService;
+import org.activiti.engine.RuntimeService;
+import org.activiti.engine.TaskService;
+import org.activiti.engine.history.HistoricTaskInstance;
+import org.activiti.engine.impl.bpmn.behavior.MultiInstanceActivityBehavior;
+import org.activiti.engine.repository.DeploymentBuilder;
+import org.activiti.engine.runtime.ProcessInstance;
+import org.activiti.engine.task.Task;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import javax.annotation.Resource;
+import java.io.IOException;
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.zip.ZipInputStream;
+
+/**
+ * @Description: activiti service impl
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2021/7/12
+ */
+@Service
+public class ActivitiServiceImpl implements ActivitiService {
+    private final static Logger log = LoggerFactory.getLogger(ActivitiServiceImpl.class);
+
+    @Resource
+    RepositoryService repositoryService;
+
+    @Resource
+    TaskService taskService;
+
+    @Resource
+    TFCustomFlowService tfCustomFlowService;
+
+    @Resource
+    RuntimeService runtimeService;
+
+    @Resource
+    TFCustomFlowEntityService tfCustomFlowEntityService;
+
+    @Resource
+    SysUserMapper sysUserMapper;
+
+    @Resource
+    MemoryLock memoryLock;
+
+    @Resource
+    HistoryService historyService;
+
+    @Resource
+    TFFlowApproveService tfFlowApproveService;
+
+    @Resource
+    TFFlowLogService tfFlowLogService;
+
+    /**
+     * 根据deploymentId查找processDefinitionId
+     *
+     * @param deploymentId
+     * @return
+     */
+    @Override
+    public String findProcessDefinitionIdByDeploymentId(String deploymentId) {
+        return sysUserMapper.findProcessDefinitionIdByDeploymentId(deploymentId);
+    }
+
+    /**
+     * 部署流程
+     *
+     * @param tfCustomTypeEnumList
+     * @return
+     */
+    @Override
+    public Map<String, Object> createDeployment(List<TFCustomTypeEnum> tfCustomTypeEnumList) throws IOException {
+        Map<String, Object> map = new HashMap<>();
+        for (TFCustomTypeEnum tfCustomTypeEnum : tfCustomTypeEnumList) {
+            DeploymentBuilder builder = repositoryService.createDeployment();
+            ClassPathResource resource = new ClassPathResource(tfCustomTypeEnum.getFileName());
+            ZipInputStream zip = new ZipInputStream(resource.getInputStream());
+            builder.addZipInputStream(zip);
+            Map<String, Object> mapData = formPropertiesGet(builder.deploy().getId(), null, null);
+            map.put(tfCustomTypeEnum.name(), mapData);
+        }
+        return map;
+    }
+
+    /**
+     * 审批任务
+     *
+     * @param flowDeploymentId
+     * @param approve
+     * @param taskId
+     * @param formProperties
+     * @param approveUserIds
+     * @param approveRemark
+     * @param map
+     * @return
+     */
+    @Override
+    public Map<String, Object> taskApprove(String flowDeploymentId,
+                                           FlowApprovePassEnum approve,
+                                           Long taskId,
+                                           String formProperties,
+                                           List<Long> approveUserIds,
+                                           String approveRemark,
+                                           Map<String, Object> map) {
+        List<String> approveIdList = new ArrayList<>();
+        if (!CollectionUtils.isEmpty(approveUserIds)) {
+            approveIdList = approveUserIds.stream().map(s -> String.valueOf(s)).collect(Collectors.toList());
+        } else {
+            if (approve == FlowApprovePassEnum.START || approve == FlowApprovePassEnum.DRAFT || approve == FlowApprovePassEnum.PASS) {
+                approveIdList.add("123");//否则是当前登录用户
+            }
+        }
+        String processFlowId = null;
+        TFCustomFlowEntity tfCustomFlowEntity = null;
+        TFFlowApprove tfFlowApprove = null;
+        Task taskTemp = null;
+        FlowResult flowResult = null;
+        if (Objects.nonNull(flowDeploymentId) && Objects.isNull(taskId)) {
+            TFCustomFlow tfCustomFlow = tfCustomFlowService.getOne(new QueryWrapper<TFCustomFlow>().lambda().eq(TFCustomFlow::getFlowDeploymentId, flowDeploymentId));
+            Optional.ofNullable(tfCustomFlow.getFlowProcessVar()).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程没有部署数据!"));
+
+            map.put(SystemConstant.DEFAULT_ASSIGNEE_LIST + 1, approveIdList);
+            ProcessInstance processInstance = runtimeService.startProcessInstanceById(tfCustomFlow.getFlowDefinitionId(), map);
+            processFlowId = processInstance.getId();
+            tfCustomFlowEntity = new TFCustomFlowEntity(tfCustomFlow.getId(), null);
+            tfFlowApprove = new TFFlowApprove(null, Long.parseLong(approveIdList.get(approveIdList.size() - 1)), FlowStatusEnum.valueOf(approve.name()), null);
+            flowResult = JSONObject.parseObject(tfCustomFlow.getFlowProcessVar(), FlowResult.class);
+        } else if (Objects.nonNull(taskId)) {
+            taskTemp = taskService.createTaskQuery().taskId(String.valueOf(taskId)).singleResult();
+            Optional.ofNullable(taskTemp).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程任务数据为空!"));
+            processFlowId = taskTemp.getProcessInstanceId();
+        }
+
+        boolean lock = memoryLock.lock(SystemConstant.LOCK_FLOW_TASK_PREFIX + processFlowId, processFlowId, SystemConstant.LOCK_FLOW_TIME_OUT);
+        if (!lock) {
+            throw ExceptionResultEnum.ERROR.exception("正在审批中,请稍候再试!");
+        }
+        try {
+            List<Task> taskList = new ArrayList<>();
+            if (Objects.isNull(taskTemp)) {
+                taskList = taskService.createTaskQuery().processInstanceId(processFlowId).list();
+            } else {
+                tfCustomFlowEntity = tfCustomFlowEntityService.getOne(new QueryWrapper<TFCustomFlowEntity>().lambda().eq(TFCustomFlowEntity::getFlowId, Long.parseLong(processFlowId)));
+                Optional.ofNullable(tfCustomFlowEntity).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程没有实例数据!"));
+                flowResult = JSONObject.parseObject(tfCustomFlowEntity.getFlowProcessVar(), FlowResult.class);
+
+                tfFlowApprove = tfFlowApproveService.getOne(new QueryWrapper<TFFlowApprove>().lambda().eq(TFFlowApprove::getFlowId, Long.parseLong(processFlowId)));
+                Optional.ofNullable(tfFlowApprove).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程没有审批数据!"));
+                taskList.add(taskTemp);
+            }
+            List<TFFlowLog> tfFlowLogList = new ArrayList<>();
+            LinkedHashMap<String, FlowTaskResult> setupMap = flowResult.getSetupMap();
+
+            tfCustomFlowEntity.setFlowId(Long.parseLong(processFlowId));
+            tfFlowApprove.setFlowId(Long.parseLong(processFlowId));
+            tfFlowApprove.setApproveMaxSetup(setupMap.size());
+            for (Task task : taskList) {
+                BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
+                FlowNode currFlow = (FlowNode) bpmnModel.getMainProcess().getFlowElement(task.getTaskDefinitionKey());
+                FlowTaskResult currFlowTaskResult = null, nextFlowTaskResult = null, formDataFlowTaskResult = null;
+                Integer nrOfCompletedInstances = null, nrOfInstances = null;
+                boolean multiInstance = false;
+                if (currFlow instanceof UserTask) {
+                    if (currFlow.getBehavior() instanceof MultiInstanceActivityBehavior) {
+                        nrOfCompletedInstances = (Integer) taskService.getVariable(task.getId(), SystemConstant.NR_OF_COMPLETED_INSTANCES);
+                        nrOfCompletedInstances++;
+                        nrOfInstances = (Integer) taskService.getVariable(task.getId(), SystemConstant.NR_OF_INSTANCES);
+                        multiInstance = true;
+                    }
+                    currFlowTaskResult = GsonUtil.fromJson(GsonUtil.toJson(setupMap.get(task.getTaskDefinitionKey())), FlowTaskResult.class);
+                    if (Objects.nonNull(formProperties)) {
+                        formDataFlowTaskResult = JSONObject.parseObject(formProperties, FlowTaskResult.class);
+                    }
+                    int currSetup = currFlowTaskResult.getSetup().intValue();
+                    if (currSetup != 1 && approve == FlowApprovePassEnum.START) {
+                        throw ExceptionResultEnum.ERROR.exception("只有流程第一步才需要提交!");
+                    }
+                    if (currSetup != 2 && approve == FlowApprovePassEnum.CANCEL) {
+                        throw ExceptionResultEnum.ERROR.exception("只有流程第二步才能撤回!");
+                    }
+                    //流程流水日志
+                    TFFlowLog tfFlowLog = new TFFlowLog(null, Long.parseLong(task.getAssignee()), null,
+                            currFlowTaskResult.getSetup(), Long.parseLong(processFlowId),
+                            Long.parseLong(task.getId()), tfCustomFlowEntity.getId(), approveIdList.toString().replaceAll("\\[", "").replaceAll("\\]", ""));
+                    if (approve == FlowApprovePassEnum.PASS || approve == FlowApprovePassEnum.DRAFT || approve == FlowApprovePassEnum.START) {
+                        currSetup = currSetup == setupMap.size() - 1 ? 0 : currSetup + 1;
+                        nextFlowTaskResult = this.getNextFlowTaskResult(nrOfCompletedInstances,
+                                nrOfInstances,
+                                currFlowTaskResult,
+                                nextFlowTaskResult,
+                                currSetup,
+                                setupMap,
+                                approve);
+
+                        this.approvePass(currFlowTaskResult,
+                                setupMap,
+                                multiInstance,
+                                nrOfCompletedInstances,
+                                nrOfInstances,
+                                tfFlowApprove,
+                                tfFlowLog,
+                                nextFlowTaskResult,
+                                map,
+                                approve,
+                                approveRemark);
+                        map.put(SystemConstant.DEFAULT_ASSIGNEE_LIST + nextFlowTaskResult.getSetup(), approveIdList);
+                    } else if (approve == FlowApprovePassEnum.REJECT || approve == FlowApprovePassEnum.CANCEL) {
+                        currSetup = currSetup - 1;
+                        nextFlowTaskResult = this.getNextFlowTaskResult(nrOfCompletedInstances,
+                                nrOfInstances,
+                                currFlowTaskResult,
+                                nextFlowTaskResult,
+                                currSetup,
+                                setupMap,
+                                approve);
+
+                        this.approveReject(multiInstance,
+                                map,
+                                currFlowTaskResult,
+                                nextFlowTaskResult,
+                                tfFlowApprove,
+                                tfFlowLog,
+                                approve,
+                                approveRemark);
+                    }
+                    map.put(SystemConstant.APPROVE, nextFlowTaskResult.getTaskKey());
+                    map.put(SystemConstant.DEFAULT_ASSIGNEE_LIST + nextFlowTaskResult.getSetup(), approveIdList);
+                    if (Objects.nonNull(formDataFlowTaskResult) && Objects.equals(task.getTaskDefinitionKey(), formDataFlowTaskResult.getTaskKey())) {
+                        setupMap.put(task.getTaskDefinitionKey(), formDataFlowTaskResult);
+                    }
+                    flowResult.setSetupMap(setupMap);
+                    tfCustomFlowEntity.setFlowProcessVar(JacksonUtil.parseJson(flowResult));
+                    if (approve == FlowApprovePassEnum.START || approve == FlowApprovePassEnum.PASS
+                            || approve == FlowApprovePassEnum.CANCEL || approve == FlowApprovePassEnum.REJECT) {
+                        if (approve == FlowApprovePassEnum.CANCEL || approve == FlowApprovePassEnum.REJECT) {
+                            List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery()
+                                    .processInstanceId(task.getProcessInstanceId()).orderByHistoricTaskInstanceEndTime().desc().list();
+                            if (!CollectionUtils.isEmpty(historicTaskInstanceList)) {
+                                Set<String> approveIdSet = new LinkedHashSet<>();
+                                for (int i = historicTaskInstanceList.size() - 1; i >= 0; i--) {
+                                    HistoricTaskInstance historicTaskInstance = historicTaskInstanceList.get(i);
+                                    if (Objects.equals(historicTaskInstance.getTaskDefinitionKey(), nextFlowTaskResult.getTaskKey())) {
+                                        approveIdSet.add(historicTaskInstance.getAssignee());
+                                    }
+                                }
+                                map.put(SystemConstant.DEFAULT_ASSIGNEE_LIST + nextFlowTaskResult.getSetup(), new ArrayList<>(approveIdSet));
+                            }
+                        }
+                        taskService.complete(task.getId(), map);
+                    }
+//                    if (approve != FlowApprovePassEnum.DRAFT && approve != FlowApprovePassEnum.REJECT) {
+//                        taskService.complete(task.getId(), map);
+//                    } else if (approve == FlowApprovePassEnum.REJECT) {
+//                        ((TaskServiceImpl) taskService).getCommandExecutor().execute(new ProcessEventRejectCmd(task.getId(), nextFlowTaskResult.getTaskKey(), map));
+//                        if (Objects.nonNull(map.get(SystemConstant.DEFAULT_ASSIGNEE_LIST + nextFlowTaskResult.getSetup()))) {
+//                            List<String> rejectApproveIdList = (List<String>) map.get(SystemConstant.DEFAULT_ASSIGNEE_LIST + nextFlowTaskResult.getSetup());
+//                            tfFlowLog.setPendApproveId(rejectApproveIdList.toString().replaceAll("\\[", "").replaceAll("\\]", ""));
+//                        }
+//                    }
+                    tfFlowLogList.add(tfFlowLog);
+                }
+            }
+            tfCustomFlowEntityService.saveOrUpdate(tfCustomFlowEntity);
+            tfFlowApproveService.saveOrUpdate(tfFlowApprove);
+            tfFlowLogService.saveBatch(tfFlowLogList);
+        } catch (Exception e) {
+            log.error(SystemConstant.LOG_ERROR, e);
+            if (e instanceof ApiException) {
+                ResultUtil.error((ApiException) e, e.getMessage());
+            } else {
+                ResultUtil.error(e.getMessage());
+            }
+        } finally {
+            memoryLock.unlock(SystemConstant.LOCK_FLOW_TASK_PREFIX + processFlowId);
+        }
+        return map;
+    }
+
+    /**
+     * 获取流程表单属性接口
+     *
+     * @param flowDeploymentId
+     * @param flowId
+     * @param taskId
+     * @return
+     */
+    @Override
+    public Map<String, Object> formPropertiesGet(String flowDeploymentId,
+                                                 Long flowId,
+                                                 Long taskId) {
+        Map<String, Object> map = new HashMap<>();
+        FlowResult flowResult = null;
+        TFCustomFlow tfCustomFlow = null;
+        List<Task> taskList = null;
+        if (Objects.nonNull(flowDeploymentId)) {
+            tfCustomFlow = tfCustomFlowService.getOne(new QueryWrapper<TFCustomFlow>().lambda().eq(TFCustomFlow::getFlowDeploymentId, flowDeploymentId));
+            Optional.ofNullable(tfCustomFlow).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程没有部署数据!"));
+            if (Objects.isNull(tfCustomFlow.getFlowDefinitionId())) {
+                String processDefinitionId = this.findProcessDefinitionIdByDeploymentId(flowDeploymentId);
+                tfCustomFlow.setFlowDefinitionId(processDefinitionId);
+                tfCustomFlowService.updateById(tfCustomFlow);
+            }
+            flowResult = JSONObject.parseObject(tfCustomFlow.getFlowProcessVar(), FlowResult.class);
+            map = this.getFlowFormPropertie(flowResult, map, 1);
+            map.put(SystemConstant.FLOW_DEPLOYMENT_ID, tfCustomFlow.getFlowDeploymentId());
+            map.put(SystemConstant.ID, tfCustomFlow.getId());
+        } else if (Objects.nonNull(flowId)) {
+            taskList = taskService.createTaskQuery().processInstanceId(String.valueOf(flowId)).list();
+            map = this.getFlowFormPropertie(map, taskList, flowResult, tfCustomFlow);
+        } else {
+            taskList = taskService.createTaskQuery().taskId(String.valueOf(taskId)).list();
+            map = this.getFlowFormPropertie(map, taskList, flowResult, tfCustomFlow);
+        }
+        return map;
+    }
+
+    /**
+     * 获取用户待办
+     *
+     * @param userId
+     * @return
+     */
+    @Override
+    public List<FormPropertyBean> getTaskList(Long userId) {
+        Map<String, Object> map = new HashMap<>();
+        List<FormPropertyBean> formPropertyList = new LinkedList<>();
+        List<Task> taskList = taskService.createTaskQuery().taskAssignee(String.valueOf(userId)).list();
+        if (!CollectionUtils.isEmpty(taskList)) {
+            for (Task t : taskList) {
+                TFCustomFlowEntity tfCustomFlowEntity = tfCustomFlowEntityService.getOne(new QueryWrapper<TFCustomFlowEntity>().lambda().eq(TFCustomFlowEntity::getFlowId, Long.parseLong(t.getProcessInstanceId())));
+                Optional.ofNullable(tfCustomFlowEntity).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程没有实例数据!"));
+                TFCustomFlow tfCustomFlow = tfCustomFlowService.getById(tfCustomFlowEntity.gettFCustomFlowId());
+                Optional.ofNullable(tfCustomFlow).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程没有部署数据!"));
+
+                FlowResult flowResult = JSONObject.parseObject(tfCustomFlowEntity.getFlowProcessVar(), FlowResult.class);
+                LinkedHashMap<String, FlowTaskResult> setupMap = flowResult.getSetupMap();
+                for (Task task : taskList) {
+                    FlowTaskResult currFlowTaskResult = GsonUtil.fromJson(GsonUtil.toJson(setupMap.get(task.getTaskDefinitionKey())), FlowTaskResult.class);
+                    map = this.getFlowFormPropertie(flowResult, map, currFlowTaskResult.getSetup());
+                }
+                formPropertyList.add(new FormPropertyBean(Long.parseLong(t.getProcessInstanceId()), Long.parseLong(t.getId()), userId, (FlowTaskResult) map.get(SystemConstant.FORM_PROPERTIES)));
+            }
+        }
+        return formPropertyList;
+    }
+
+    /**
+     * 流程节点转他人审批
+     *
+     * @param userId
+     * @param taskId
+     */
+    @Override
+    public void taskApproverExchange(Long userId, Long taskId) {
+        boolean lock = memoryLock.lock(SystemConstant.LOCK_FLOW_EXCHANGE_PREFIX + taskId, taskId, SystemConstant.LOCK_FLOW_TIME_OUT);
+        if (!lock) {
+            throw ExceptionResultEnum.ERROR.exception("正在转审中,请稍候再试!");
+        }
+        try {
+            Task task = taskService.createTaskQuery().taskId(String.valueOf(taskId)).singleResult();
+            Optional.ofNullable(task).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程任务数据为空!"));
+
+            if (Objects.equals(task.getAssignee(), String.valueOf(userId))) {
+                throw ExceptionResultEnum.ERROR.exception("不能转给自己!");
+            } else {
+                List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery()
+                        .processInstanceId(task.getProcessInstanceId()).orderByHistoricTaskInstanceEndTime().desc().list();
+                if (!CollectionUtils.isEmpty(historicTaskInstanceList)) {
+                    Set<String> approveIdSet = new LinkedHashSet<>();
+                    for (int i = historicTaskInstanceList.size() - 1; i >= 0; i--) {
+                        HistoricTaskInstance historicTaskInstance = historicTaskInstanceList.get(i);
+                        if (Objects.equals(historicTaskInstance.getTaskDefinitionKey(), task.getTaskDefinitionKey())) {
+                            approveIdSet.add(historicTaskInstance.getAssignee());
+                        }
+                    }
+                    if (approveIdSet.contains(String.valueOf(userId))) {
+                        throw ExceptionResultEnum.ERROR.exception("该审批人已有审批权限!");
+                    }
+                }
+            }
+            taskService.setAssignee(String.valueOf(taskId), String.valueOf(userId));
+
+            TFCustomFlowEntity tfCustomFlowEntity = tfCustomFlowEntityService.getOne(new QueryWrapper<TFCustomFlowEntity>().lambda().eq(TFCustomFlowEntity::getFlowId, Long.parseLong(task.getProcessInstanceId())));
+            Optional.ofNullable(tfCustomFlowEntity).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程没有实例数据!"));
+
+            FlowResult flowResult = JSONObject.parseObject(tfCustomFlowEntity.getFlowProcessVar(), FlowResult.class);
+            LinkedHashMap<String, FlowTaskResult> setupMap = flowResult.getSetupMap();
+            FlowTaskResult currFlowTaskResult = GsonUtil.fromJson(GsonUtil.toJson(setupMap.get(task.getTaskDefinitionKey())), FlowTaskResult.class);
+            TFFlowLog tfFlowLog = new TFFlowLog(null, Long.parseLong(task.getAssignee()), null,
+                    currFlowTaskResult.getSetup(), Long.parseLong(task.getProcessInstanceId()),
+                    Long.parseLong(task.getId()), tfCustomFlowEntity.getId(), String.valueOf(userId));
+            tfFlowLog.setApproveOperation(FlowApproveOperationEnum.EXCHANGE);
+            tfFlowLog.setApproveRemark(task.getAssignee() + "转" + userId + "审批");
+            tfFlowLogService.save(tfFlowLog);
+        } catch (Exception e) {
+            log.error(SystemConstant.LOG_ERROR, e);
+            if (e instanceof ApiException) {
+                ResultUtil.error((ApiException) e, e.getMessage());
+            } else {
+                ResultUtil.error(e.getMessage());
+            }
+        } finally {
+            memoryLock.unlock(SystemConstant.LOCK_FLOW_EXCHANGE_PREFIX + taskId);
+        }
+    }
+
+    /**
+     * 流程终止
+     *
+     * @param flowId
+     */
+    @Override
+    public void flowEnd(Long flowId) {
+        boolean lock = memoryLock.lock(SystemConstant.LOCK_FLOW_TASK_PREFIX + flowId, flowId, SystemConstant.LOCK_FLOW_TIME_OUT);
+        if (!lock) {
+            throw ExceptionResultEnum.ERROR.exception("正在终止中,请稍候再试!");
+        }
+        try {
+            runtimeService.deleteProcessInstance(String.valueOf(flowId), "结束");
+        } catch (Exception e) {
+            log.error(SystemConstant.LOG_ERROR, e);
+            if (e instanceof ApiException) {
+                ResultUtil.error((ApiException) e, e.getMessage());
+            } else {
+                ResultUtil.error(e.getMessage());
+            }
+        } finally {
+            memoryLock.unlock(SystemConstant.LOCK_FLOW_TASK_PREFIX + flowId);
+        }
+    }
+
+    /**
+     * 获取表单属性
+     *
+     * @param map
+     * @param taskList
+     * @param flowResult
+     * @param tfCustomFlow
+     * @return
+     */
+    protected Map<String, Object> getFlowFormPropertie(Map<String, Object> map,
+                                                       List<Task> taskList,
+                                                       FlowResult flowResult,
+                                                       TFCustomFlow tfCustomFlow) {
+        if (CollectionUtils.isEmpty(taskList)) {
+            throw ExceptionResultEnum.ERROR.exception("流程任务数据为空!");
+        }
+        Long flowId = Long.parseLong(taskList.get(0).getProcessInstanceId());
+        TFCustomFlowEntity tfCustomFlowEntity = tfCustomFlowEntityService.getOne(new QueryWrapper<TFCustomFlowEntity>().lambda().eq(TFCustomFlowEntity::getFlowId, flowId));
+        Optional.ofNullable(tfCustomFlowEntity).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程没有实例数据!"));
+        tfCustomFlow = tfCustomFlowService.getById(tfCustomFlowEntity.gettFCustomFlowId());
+        Optional.ofNullable(tfCustomFlow).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程没有部署数据!"));
+
+        flowResult = JSONObject.parseObject(tfCustomFlowEntity.getFlowProcessVar(), FlowResult.class);
+        LinkedHashMap<String, FlowTaskResult> setupMap = flowResult.getSetupMap();
+        for (Task task : taskList) {
+            FlowTaskResult currFlowTaskResult = GsonUtil.fromJson(GsonUtil.toJson(setupMap.get(task.getTaskDefinitionKey())), FlowTaskResult.class);
+            map = this.getFlowFormPropertie(flowResult, map, currFlowTaskResult.getSetup());
+        }
+        map.put(SystemConstant.FLOW_DEPLOYMENT_ID, tfCustomFlow.getFlowDeploymentId());
+        map.put(SystemConstant.ID, tfCustomFlow.getId());
+        return map;
+    }
+
+    /**
+     * 获取表单属性
+     *
+     * @param flowResult
+     * @param map
+     * @param setup
+     * @return
+     */
+    protected Map<String, Object> getFlowFormPropertie(FlowResult flowResult, Map<String, Object> map, int setup) {
+        Map<String, FlowTaskResult> setupMap = flowResult.getSetupMap();
+        for (Map.Entry<String, FlowTaskResult> entry : setupMap.entrySet()) {
+            FlowTaskResult flowTaskResultTemp = GsonUtil.fromJson(GsonUtil.toJson(entry.getValue()), FlowTaskResult.class);
+            if (flowTaskResultTemp.getSetup().intValue() == setup) {
+                map.put(SystemConstant.FORM_PROPERTIES, flowTaskResultTemp);
+                break;
+            }
+        }
+        return map;
+    }
+
+    /**
+     * 获取流程下一节点
+     *
+     * @param nrOfCompletedInstances
+     * @param nrOfInstances
+     * @param currFlowTaskResult
+     * @param nextFlowTaskResult
+     * @param currSetup
+     * @param setupMap
+     * @param approvePass
+     * @return
+     */
+    protected FlowTaskResult getNextFlowTaskResult(Integer nrOfCompletedInstances,
+                                                   Integer nrOfInstances,
+                                                   FlowTaskResult currFlowTaskResult,
+                                                   FlowTaskResult nextFlowTaskResult,
+                                                   int currSetup,
+                                                   Map<String, FlowTaskResult> setupMap,
+                                                   FlowApprovePassEnum approvePass) {
+        if (approvePass == FlowApprovePassEnum.PASS || approvePass == FlowApprovePassEnum.START || approvePass == FlowApprovePassEnum.DRAFT) {
+            if (Objects.nonNull(nrOfCompletedInstances)
+                    && Objects.nonNull(nrOfInstances)
+                    && nrOfCompletedInstances.intValue() != nrOfInstances.intValue() || approvePass == FlowApprovePassEnum.DRAFT) {
+                nextFlowTaskResult = currFlowTaskResult;
+            } else {
+                nextFlowTaskResult = this.getNextFlowTaskResult(setupMap, currSetup, nextFlowTaskResult);
+            }
+        } else if (approvePass == FlowApprovePassEnum.REJECT || approvePass == FlowApprovePassEnum.CANCEL) {
+            nextFlowTaskResult = this.getNextFlowTaskResult(setupMap, currSetup, nextFlowTaskResult);
+        }
+        Optional.ofNullable(nextFlowTaskResult).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("该节点不能审批通过"));
+        return nextFlowTaskResult;
+    }
+
+    /**
+     * 获取下级审核节点
+     *
+     * @param setupMap
+     * @param currSetup
+     * @param nextFlowTaskResult
+     * @return
+     */
+    protected FlowTaskResult getNextFlowTaskResult(Map<String, FlowTaskResult> setupMap,
+                                                   int currSetup,
+                                                   FlowTaskResult nextFlowTaskResult) {
+        for (Map.Entry<String, FlowTaskResult> entry : setupMap.entrySet()) {
+            FlowTaskResult flowTaskResultTemp = GsonUtil.fromJson(GsonUtil.toJson(entry.getValue()), FlowTaskResult.class);
+            if (flowTaskResultTemp.getSetup().intValue() == currSetup) {
+                nextFlowTaskResult = flowTaskResultTemp;
+                break;
+            }
+        }
+        return nextFlowTaskResult;
+    }
+
+    /**
+     * 审批通过
+     *
+     * @param currFlowTaskResult
+     * @param setupMap
+     * @param multiInstance
+     * @param nrOfCompletedInstances
+     * @param nrOfInstances
+     * @param tfFlowApprove
+     * @param tfFlowLog
+     * @param nextFlowTaskResult
+     * @param map
+     * @param approvePass
+     * @param approveRemark
+     */
+    public void approvePass(FlowTaskResult currFlowTaskResult,
+                            Map<String, FlowTaskResult> setupMap,
+                            boolean multiInstance,
+                            Integer nrOfCompletedInstances,
+                            Integer nrOfInstances,
+                            TFFlowApprove tfFlowApprove,
+                            TFFlowLog tfFlowLog,
+                            FlowTaskResult nextFlowTaskResult,
+                            Map<String, Object> map,
+                            FlowApprovePassEnum approvePass,
+                            String approveRemark) {
+        if (multiInstance) {
+            map.computeIfAbsent(FlowApproveOperationEnum.REJECT.getId() + currFlowTaskResult.getSetup(), v -> 0);
+        }
+        if (currFlowTaskResult.getSetup().intValue() == setupMap.size() - 1) {
+            if (multiInstance && Objects.nonNull(nrOfCompletedInstances)
+                    && Objects.nonNull(nrOfInstances)
+                    && nrOfCompletedInstances.intValue() == nrOfInstances.intValue()) {
+                tfFlowApprove.setStatus(FlowStatusEnum.FINISH);
+                tfFlowApprove.setSetup(FlowApproveSetupEnum.FINISH.getSetup());
+            } else if (!multiInstance) {
+                tfFlowApprove.setStatus(FlowStatusEnum.FINISH);
+                tfFlowApprove.setSetup(FlowApproveSetupEnum.FINISH.getSetup());
+            } else {
+                tfFlowApprove.setStatus(FlowStatusEnum.AUDITING);
+                tfFlowApprove.setSetup(nextFlowTaskResult.getSetup());
+            }
+        } else {
+            if (approvePass == FlowApprovePassEnum.DRAFT || approvePass == FlowApprovePassEnum.START) {
+                tfFlowApprove.setStatus(FlowStatusEnum.valueOf(approvePass.name()));
+            } else {
+                tfFlowApprove.setStatus(FlowStatusEnum.AUDITING);
+            }
+            tfFlowApprove.setSetup(nextFlowTaskResult.getSetup());
+        }
+        if (tfFlowApprove.getStatus() == FlowStatusEnum.START) {
+            tfFlowLog.setApproveOperation(FlowApproveOperationEnum.START);
+        } else if (tfFlowApprove.getStatus() == FlowStatusEnum.DRAFT) {
+            tfFlowLog.setApproveOperation(FlowApproveOperationEnum.DRAFT);
+        } else {
+            tfFlowLog.setApproveOperation(FlowApproveOperationEnum.APPROVE);
+        }
+        if (Objects.nonNull(approveRemark)) {
+            tfFlowLog.setApproveRemark(approveRemark);
+        } else {
+            tfFlowLog.setApproveRemark(tfFlowLog.getApproveOperation().getTitle());
+        }
+    }
+
+    /**
+     * 审批驳回
+     *
+     * @param multiInstance
+     * @param map
+     * @param currFlowTaskResult
+     * @param nextFlowTaskResult
+     * @param tfFlowApprove
+     * @param tfFlowLog
+     * @param approvePass
+     * @param approveRemark
+     */
+    protected void approveReject(boolean multiInstance,
+                                 Map<String, Object> map,
+                                 FlowTaskResult currFlowTaskResult,
+                                 FlowTaskResult nextFlowTaskResult,
+                                 TFFlowApprove tfFlowApprove,
+                                 TFFlowLog tfFlowLog,
+                                 FlowApprovePassEnum approvePass,
+                                 String approveRemark) {
+        if (multiInstance) {
+            map.computeIfAbsent(FlowApproveOperationEnum.REJECT.getId() + currFlowTaskResult.getSetup(), v -> 1);
+        }
+        tfFlowApprove.setSetup(nextFlowTaskResult.getSetup());
+        tfFlowApprove.setStatus(FlowStatusEnum.convertToEnum(approvePass.name()));
+        tfFlowLog.setApproveOperation(FlowApproveOperationEnum.convertToEnum(approvePass.name()));
+        if (Objects.nonNull(approveRemark)) {
+            tfFlowLog.setApproveRemark(approveRemark);
+        } else {
+            tfFlowLog.setApproveRemark(tfFlowLog.getApproveOperation().getTitle());
+        }
+    }
+}

+ 8 - 1
sop-business/src/main/java/com/qmth/sop/business/bean/FormPropertyBean.java → sop-business/src/main/java/com/qmth/sop/business/bean/bean/FormPropertyBean.java

@@ -1,4 +1,4 @@
-package com.qmth.sop.business.bean;
+package com.qmth.sop.business.bean.bean;
 
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
@@ -8,6 +8,13 @@ import io.swagger.annotations.ApiModelProperty;
 
 import java.io.Serializable;
 
+/**
+ * @Description: 流程表单属性bean
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2023/7/24
+ */
 @JsonInclude(JsonInclude.Include.NON_NULL)
 public class FormPropertyBean implements Serializable {
 

+ 0 - 21
sop-business/src/main/java/com/qmth/sop/business/service/ActivitiConsumerService.java

@@ -1,21 +0,0 @@
-package com.qmth.sop.business.service;
-
-public interface ActivitiConsumerService {
-    boolean createDeployment();
-
-    boolean startActivityDemo(String key);
-
-    boolean getTaskList();
-
-    boolean complete(String taskId);
-
-    boolean deleteProcessInstance(String runId);
-
-    /**
-     * 根据deploymentId查找processDefinitionId
-     *
-     * @param deploymentId
-     * @return
-     */
-    String findProcessDefinitionIdByDeploymentId(String deploymentId);
-}

+ 0 - 116
sop-business/src/main/java/com/qmth/sop/business/service/impl/ActivitiConsumerServiceImpl.java

@@ -1,116 +0,0 @@
-package com.qmth.sop.business.service.impl;
-
-import com.qmth.sop.business.mapper.SysUserMapper;
-import com.qmth.sop.business.service.ActivitiConsumerService;
-import org.activiti.engine.RepositoryService;
-import org.activiti.engine.RuntimeService;
-import org.activiti.engine.TaskService;
-import org.activiti.engine.repository.DeploymentBuilder;
-import org.activiti.engine.runtime.ProcessInstance;
-import org.activiti.engine.task.Task;
-import org.springframework.stereotype.Service;
-
-import javax.annotation.Resource;
-import java.util.List;
-
-@Service
-public class ActivitiConsumerServiceImpl implements ActivitiConsumerService {
-
-    @Resource
-    private RuntimeService runtimeService;
-
-    @Resource
-    private TaskService taskService;
-
-    @Resource
-    private RepositoryService repositoryService;
-
-    @Resource
-    SysUserMapper sysUserMapper;
-
-    /**
-     * 注册一个流程
-     *
-     * @return
-     */
-    @Override
-    public boolean createDeployment() {
-        DeploymentBuilder builder = repositoryService.createDeployment();
-        builder.addClasspathResource("test1.bpmn");
-        builder.deploy();
-        return true;
-    }
-
-    /**
-     * 查询待办
-     *
-     * @return
-     */
-    @Override
-    public boolean getTaskList() {
-        //获取待办的一些信息,这里可以传入需要查询的用户,
-        //我这里查询的所有待办
-        List<Task> tasks = taskService.createTaskQuery().list();
-        for (Task t : tasks) {
-            System.out.println(t.getCreateTime());
-            System.out.println(t.getId());
-            System.out.println(t.getName());
-            System.out.println(t.getProcessInstanceId());
-            System.out.println(t.getTaskDefinitionKey());
-            System.out.println(t.getParentTaskId());
-        }
-        return true;
-    }
-
-
-    /**
-     * 根据流程key开启一个流程
-     *
-     * @param key
-     * @return
-     */
-    @Override
-    public boolean startActivityDemo(String key) {
-        ProcessInstance test01 = runtimeService.startProcessInstanceByKey(key);
-        String id = test01.getId();
-        System.out.println("流程id=" + id);
-        /*  */
-        /*    String assignee = "abc";*/
-        return true;
-    }
-
-    /**
-     * 根据任务id提交任务
-     *
-     * @param taskId
-     * @return
-     */
-    @Override
-    public boolean complete(String taskId) {
-        taskService.complete(taskId);
-        return true;
-    }
-
-    /**
-     * 根据流程id直接结束流程
-     *
-     * @param runId
-     * @return
-     */
-    @Override
-    public boolean deleteProcessInstance(String runId) {
-        runtimeService.deleteProcessInstance(runId, "结束");
-        return true;
-    }
-
-    /**
-     * 根据deploymentId查找processDefinitionId
-     *
-     * @param deploymentId
-     * @return
-     */
-    @Override
-    public String findProcessDefinitionIdByDeploymentId(String deploymentId) {
-        return sysUserMapper.findProcessDefinitionIdByDeploymentId(deploymentId);
-    }
-}

+ 3 - 1
sop-common/src/main/java/com/qmth/sop/common/contant/SystemConstant.java

@@ -126,8 +126,10 @@ public class SystemConstant {
      * 锁
      */
     public static final String LOCK_FLOW_TASK_PREFIX = "lock:flow:task:";//流程节点锁
+    public static final String LOCK_FLOW_END_PREFIX = "lock:flow:end:";//流程节点锁
+    public static final String LOCK_FLOW_EXCHANGE_PREFIX = "lock:flow:exchange:";//流程节点锁
 
-    public static final Long LOCK_FLOW_TASK_TIME_OUT = 60L * 2 * 1000;
+    public static final Long LOCK_FLOW_TIME_OUT = 60L * 2 * 1000;
 
     /**
      * 获取数据库uuid

+ 10 - 3
sop-common/src/main/java/com/qmth/sop/common/enums/TFCustomTypeEnum.java

@@ -11,9 +11,9 @@ import java.util.Objects;
  */
 public enum TFCustomTypeEnum {
 
-    OFFICE_SOP_FLOW("教务处SOP", null, "officeSopFlow"),
+    OFFICE_SOP_FLOW("教务处SOP", null, "officeSopFlow", "testform1.zip"),
 
-    CLOUD_MARK_SOP_FLOW("云阅卷SOP", null, "cloudMarkSopFlow");
+    CLOUD_MARK_SOP_FLOW("云阅卷SOP", null, "cloudMarkSopFlow", null);
 
     private String title;
 
@@ -21,10 +21,13 @@ public enum TFCustomTypeEnum {
 
     private String code;
 
-    private TFCustomTypeEnum(String title, String table, String code) {
+    private String fileName;
+
+    private TFCustomTypeEnum(String title, String table, String code, String fileName) {
         this.title = title;
         this.table = table;
         this.code = code;
+        this.fileName = fileName;
     }
 
     public String getTable() {
@@ -39,6 +42,10 @@ public enum TFCustomTypeEnum {
         return code;
     }
 
+    public String getFileName() {
+        return fileName;
+    }
+
     /**
      * 状态转换 toName
      *

+ 21 - 501
sop-server/src/main/java/com/qmth/sop/server/api/ActivitiFromHtmlController.java

@@ -1,38 +1,15 @@
 package com.qmth.sop.server.api;
 
-import com.alibaba.fastjson.JSONObject;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.qmth.boot.api.exception.ApiException;
-import com.qmth.sop.business.bean.FormPropertyBean;
-import com.qmth.sop.business.bean.result.FlowResult;
-import com.qmth.sop.business.bean.result.FlowTaskResult;
-import com.qmth.sop.business.entity.TFCustomFlow;
-import com.qmth.sop.business.entity.TFCustomFlowEntity;
-import com.qmth.sop.business.entity.TFFlowApprove;
-import com.qmth.sop.business.entity.TFFlowLog;
-import com.qmth.sop.business.service.*;
-import com.qmth.sop.common.contant.SystemConstant;
-import com.qmth.sop.common.enums.*;
-import com.qmth.sop.common.lock.MemoryLock;
-import com.qmth.sop.common.util.GsonUtil;
-import com.qmth.sop.common.util.JacksonUtil;
+import com.qmth.sop.business.activiti.service.ActivitiService;
+import com.qmth.sop.business.service.TFCustomFlowService;
+import com.qmth.sop.common.enums.FlowApprovePassEnum;
+import com.qmth.sop.common.enums.TFCustomTypeEnum;
 import com.qmth.sop.common.util.Result;
 import com.qmth.sop.common.util.ResultUtil;
 import io.swagger.annotations.*;
-import org.activiti.bpmn.model.BpmnModel;
-import org.activiti.bpmn.model.FlowNode;
-import org.activiti.bpmn.model.UserTask;
-import org.activiti.engine.*;
-import org.activiti.engine.history.HistoricTaskInstance;
-import org.activiti.engine.impl.bpmn.behavior.MultiInstanceActivityBehavior;
-import org.activiti.engine.repository.DeploymentBuilder;
-import org.activiti.engine.runtime.ProcessInstance;
-import org.activiti.engine.task.Task;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.core.io.ClassPathResource;
 import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RequestParam;
@@ -42,58 +19,25 @@ import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 import java.io.IOException;
 import java.util.*;
-import java.util.stream.Collectors;
-import java.util.zip.ZipInputStream;
 
 @Api(tags = "测试流程表单htmlController")
 @RestController
-@RequestMapping("/flow")
+@RequestMapping("/test/flow")
 public class ActivitiFromHtmlController {
     private final static Logger log = LoggerFactory.getLogger(ActivitiFromHtmlController.class);
 
     @Resource
-    ActivitiConsumerService activitiConsumerService;
-
-    @Resource
-    RepositoryService repositoryService;
-
-    @Resource
-    FormService formService;
-
-    @Resource
-    TaskService taskService;
+    ActivitiService activitiService;
 
     @Resource
     TFCustomFlowService tfCustomFlowService;
 
-    @Resource
-    RuntimeService runtimeService;
-
-    @Resource
-    TFCustomFlowEntityService tfCustomFlowEntityService;
-
-    @Resource
-    TFFlowApproveService tfFlowApproveService;
-
-    @Resource
-    TFFlowLogService tfFlowLogService;
-
-    @Resource
-    MemoryLock memoryLock;
-
-    @Resource
-    HistoryService historyService;
-
     @ApiOperation(value = "创建流程接口")
     @RequestMapping(value = "/createDeployment", method = RequestMethod.POST)
     @Transactional
     @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = Object.class)})
     public Result createDeployment() throws IOException {
-        DeploymentBuilder builder = repositoryService.createDeployment();
-        ClassPathResource resource = new ClassPathResource("testform1.zip");
-        ZipInputStream zip = new ZipInputStream(resource.getInputStream());
-        builder.addZipInputStream(zip);
-        return formPropertiesGet(builder.deploy().getId(), null);
+        return ResultUtil.ok(activitiService.createDeployment(Arrays.asList(TFCustomTypeEnum.OFFICE_SOP_FLOW)));
     }
 
     @ApiOperation(value = "获取流程部署信息")
@@ -108,42 +52,9 @@ public class ActivitiFromHtmlController {
     @Transactional
     @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = Object.class)})
     public Result formPropertiesGet(@ApiParam(value = "流程部署id") @RequestParam(required = false) String flowDeploymentId,
+                                    @ApiParam(value = "流程id") @RequestParam(required = false) Long flowId,
                                     @ApiParam(value = "流程任务id") @RequestParam(required = false) Long taskId) {
-        Map<String, Object> map = new HashMap<>();
-        FlowResult flowResult = null;
-        TFCustomFlow tfCustomFlow = null;
-        if (Objects.nonNull(flowDeploymentId)) {
-            tfCustomFlow = tfCustomFlowService.getOne(new QueryWrapper<TFCustomFlow>().lambda().eq(TFCustomFlow::getFlowDeploymentId, flowDeploymentId));
-            Optional.ofNullable(tfCustomFlow).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程没有部署数据!"));
-            if (Objects.isNull(tfCustomFlow.getFlowDefinitionId())) {
-                String processDefinitionId = activitiConsumerService.findProcessDefinitionIdByDeploymentId(flowDeploymentId);
-                tfCustomFlow.setFlowDefinitionId(processDefinitionId);
-                tfCustomFlowService.updateById(tfCustomFlow);
-            }
-            flowResult = JSONObject.parseObject(tfCustomFlow.getFlowProcessVar(), FlowResult.class);
-            map = this.getFlowFormPropertie(flowResult, map, 1);
-        } else {
-            List<Task> taskList = taskService.createTaskQuery().taskId(String.valueOf(taskId)).list();
-            if (CollectionUtils.isEmpty(taskList)) {
-                throw ExceptionResultEnum.ERROR.exception("流程任务数据为空!");
-            }
-            Long flowId = Long.parseLong(taskList.get(0).getProcessInstanceId());
-            TFCustomFlowEntity tfCustomFlowEntity = tfCustomFlowEntityService.getOne(new QueryWrapper<TFCustomFlowEntity>().lambda().eq(TFCustomFlowEntity::getFlowId, flowId));
-            Optional.ofNullable(tfCustomFlowEntity).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程没有实例数据!"));
-            tfCustomFlow = tfCustomFlowService.getById(tfCustomFlowEntity.gettFCustomFlowId());
-            Optional.ofNullable(tfCustomFlow).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程没有部署数据!"));
-
-            flowResult = JSONObject.parseObject(tfCustomFlowEntity.getFlowProcessVar(), FlowResult.class);
-            LinkedHashMap<String, FlowTaskResult> setupMap = flowResult.getSetupMap();
-            for (Task task : taskList) {
-                FlowTaskResult currFlowTaskResult = GsonUtil.fromJson(GsonUtil.toJson(setupMap.get(task.getTaskDefinitionKey())), FlowTaskResult.class);
-                map = this.getFlowFormPropertie(flowResult, map, currFlowTaskResult.getSetup());
-                break;
-            }
-        }
-        map.put(SystemConstant.FLOW_DEPLOYMENT_ID, tfCustomFlow.getFlowDeploymentId());
-        map.put(SystemConstant.ID, tfCustomFlow.getId());
-        return ResultUtil.ok(map);
+        return ResultUtil.ok(activitiService.formPropertiesGet(flowDeploymentId, flowId, taskId));
     }
 
     @ApiOperation(value = "流程审批接口")
@@ -168,175 +79,7 @@ public class ActivitiFromHtmlController {
             formDataMap.put(key, value[0]);
         }
         map.putAll(formDataMap);
-
-        List<String> approveIdList = new ArrayList<>();
-        if (!CollectionUtils.isEmpty(approveUserIds)) {
-            approveIdList = approveUserIds.stream().map(s -> String.valueOf(s)).collect(Collectors.toList());
-        } else {
-            if (approve == FlowApprovePassEnum.START || approve == FlowApprovePassEnum.DRAFT || approve == FlowApprovePassEnum.PASS) {
-                approveIdList.add("123");//否则是当前登录用户
-            }
-        }
-        String processFlowId = null;
-        TFCustomFlowEntity tfCustomFlowEntity = null;
-        TFFlowApprove tfFlowApprove = null;
-        Task taskTemp = null;
-        FlowResult flowResult = null;
-        if (Objects.nonNull(flowDeploymentId) && Objects.isNull(taskId)) {
-            TFCustomFlow tfCustomFlow = tfCustomFlowService.getOne(new QueryWrapper<TFCustomFlow>().lambda().eq(TFCustomFlow::getFlowDeploymentId, flowDeploymentId));
-            Optional.ofNullable(tfCustomFlow.getFlowProcessVar()).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程没有部署数据!"));
-
-            map.put(SystemConstant.DEFAULT_ASSIGNEE_LIST + 1, approveIdList);
-            ProcessInstance processInstance = runtimeService.startProcessInstanceById(tfCustomFlow.getFlowDefinitionId(), map);
-            processFlowId = processInstance.getId();
-            tfCustomFlowEntity = new TFCustomFlowEntity(tfCustomFlow.getId(), null);
-            tfFlowApprove = new TFFlowApprove(null, Long.parseLong(approveIdList.get(approveIdList.size() - 1)), FlowStatusEnum.valueOf(approve.name()), null);
-            flowResult = JSONObject.parseObject(tfCustomFlow.getFlowProcessVar(), FlowResult.class);
-        } else if (Objects.nonNull(taskId)) {
-            taskTemp = taskService.createTaskQuery().taskId(String.valueOf(taskId)).singleResult();
-            Optional.ofNullable(taskTemp).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程任务数据为空!"));
-            processFlowId = taskTemp.getProcessInstanceId();
-        }
-
-        boolean lock = memoryLock.lock(SystemConstant.LOCK_FLOW_TASK_PREFIX + processFlowId, processFlowId, SystemConstant.LOCK_FLOW_TASK_TIME_OUT);
-        if (!lock) {
-            throw ExceptionResultEnum.ERROR.exception("正在审批中,请稍候再试!");
-        }
-        try {
-            List<Task> taskList = new ArrayList<>();
-            if (Objects.isNull(taskTemp)) {
-                taskList = taskService.createTaskQuery().processInstanceId(processFlowId).list();
-            } else {
-                tfCustomFlowEntity = tfCustomFlowEntityService.getOne(new QueryWrapper<TFCustomFlowEntity>().lambda().eq(TFCustomFlowEntity::getFlowId, Long.parseLong(processFlowId)));
-                Optional.ofNullable(tfCustomFlowEntity).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程没有实例数据!"));
-                flowResult = JSONObject.parseObject(tfCustomFlowEntity.getFlowProcessVar(), FlowResult.class);
-
-                tfFlowApprove = tfFlowApproveService.getOne(new QueryWrapper<TFFlowApprove>().lambda().eq(TFFlowApprove::getFlowId, Long.parseLong(processFlowId)));
-                Optional.ofNullable(tfFlowApprove).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程没有审批数据!"));
-                taskList.add(taskTemp);
-            }
-            List<TFFlowLog> tfFlowLogList = new ArrayList<>();
-            LinkedHashMap<String, FlowTaskResult> setupMap = flowResult.getSetupMap();
-
-            tfCustomFlowEntity.setFlowId(Long.parseLong(processFlowId));
-            tfFlowApprove.setFlowId(Long.parseLong(processFlowId));
-            tfFlowApprove.setApproveMaxSetup(setupMap.size());
-            for (Task task : taskList) {
-                BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
-                FlowNode currFlow = (FlowNode) bpmnModel.getMainProcess().getFlowElement(task.getTaskDefinitionKey());
-                FlowTaskResult currFlowTaskResult = null, nextFlowTaskResult = null, formDataFlowTaskResult = null;
-                Integer nrOfCompletedInstances = null, nrOfInstances = null;
-                boolean multiInstance = false;
-                if (currFlow instanceof UserTask) {
-                    if (currFlow.getBehavior() instanceof MultiInstanceActivityBehavior) {
-                        nrOfCompletedInstances = (Integer) taskService.getVariable(task.getId(), SystemConstant.NR_OF_COMPLETED_INSTANCES);
-                        nrOfCompletedInstances++;
-                        nrOfInstances = (Integer) taskService.getVariable(task.getId(), SystemConstant.NR_OF_INSTANCES);
-                        multiInstance = true;
-                    }
-                    currFlowTaskResult = GsonUtil.fromJson(GsonUtil.toJson(setupMap.get(task.getTaskDefinitionKey())), FlowTaskResult.class);
-                    if (Objects.nonNull(formProperties)) {
-                        formDataFlowTaskResult = JSONObject.parseObject(formProperties, FlowTaskResult.class);
-                    }
-                    int currSetup = currFlowTaskResult.getSetup().intValue();
-                    if (currSetup != 1 && approve == FlowApprovePassEnum.START) {
-                        throw ExceptionResultEnum.ERROR.exception("只有流程第一步才需要提交!");
-                    }
-                    //流程流水日志
-                    TFFlowLog tfFlowLog = new TFFlowLog(null, Long.parseLong(task.getAssignee()), null,
-                            currFlowTaskResult.getSetup(), Long.parseLong(processFlowId),
-                            Long.parseLong(task.getId()), tfCustomFlowEntity.getId(), approveIdList.toString().replaceAll("\\[", "").replaceAll("\\]", ""));
-                    if (approve == FlowApprovePassEnum.PASS || approve == FlowApprovePassEnum.DRAFT || approve == FlowApprovePassEnum.START) {
-                        currSetup = currSetup == setupMap.size() - 1 ? 0 : currSetup + 1;
-                        nextFlowTaskResult = this.getNextFlowTaskResult(nrOfCompletedInstances,
-                                nrOfInstances,
-                                currFlowTaskResult,
-                                nextFlowTaskResult,
-                                currSetup,
-                                setupMap,
-                                approve);
-
-                        this.approvePass(currFlowTaskResult,
-                                setupMap,
-                                multiInstance,
-                                nrOfCompletedInstances,
-                                nrOfInstances,
-                                tfFlowApprove,
-                                tfFlowLog,
-                                nextFlowTaskResult,
-                                map,
-                                approve,
-                                approveRemark);
-                        map.put(SystemConstant.DEFAULT_ASSIGNEE_LIST + nextFlowTaskResult.getSetup(), approveIdList);
-                    } else if (approve == FlowApprovePassEnum.REJECT || approve == FlowApprovePassEnum.CANCEL) {
-                        currSetup = currSetup - 1;
-                        nextFlowTaskResult = this.getNextFlowTaskResult(nrOfCompletedInstances,
-                                nrOfInstances,
-                                currFlowTaskResult,
-                                nextFlowTaskResult,
-                                currSetup,
-                                setupMap,
-                                approve);
-
-                        this.approveReject(multiInstance,
-                                map,
-                                currFlowTaskResult,
-                                nextFlowTaskResult,
-                                tfFlowApprove,
-                                tfFlowLog,
-                                approve,
-                                approveRemark);
-                    }
-                    map.put(SystemConstant.APPROVE, nextFlowTaskResult.getTaskKey());
-                    map.put(SystemConstant.DEFAULT_ASSIGNEE_LIST + nextFlowTaskResult.getSetup(), approveIdList);
-                    if (Objects.nonNull(formDataFlowTaskResult) && Objects.equals(task.getTaskDefinitionKey(), formDataFlowTaskResult.getTaskKey())) {
-                        setupMap.put(task.getTaskDefinitionKey(), formDataFlowTaskResult);
-                    }
-                    flowResult.setSetupMap(setupMap);
-                    tfCustomFlowEntity.setFlowProcessVar(JacksonUtil.parseJson(flowResult));
-                    if (approve == FlowApprovePassEnum.START || approve == FlowApprovePassEnum.PASS
-                            || approve == FlowApprovePassEnum.CANCEL || approve == FlowApprovePassEnum.REJECT) {
-                        if (approve == FlowApprovePassEnum.CANCEL || approve == FlowApprovePassEnum.REJECT) {
-                            List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery()
-                                    .processInstanceId(task.getProcessInstanceId()).orderByHistoricTaskInstanceEndTime().desc().list();
-                            if (!CollectionUtils.isEmpty(historicTaskInstanceList)) {
-                                Set<String> approveIdSet = new LinkedHashSet<>();
-                                for (int i = historicTaskInstanceList.size() - 1; i >= 0; i--) {
-                                    HistoricTaskInstance historicTaskInstance = historicTaskInstanceList.get(i);
-                                    if (Objects.equals(historicTaskInstance.getTaskDefinitionKey(), nextFlowTaskResult.getTaskKey())) {
-                                        approveIdSet.add(historicTaskInstance.getAssignee());
-                                    }
-                                }
-                                map.put(SystemConstant.DEFAULT_ASSIGNEE_LIST + nextFlowTaskResult.getSetup(), new ArrayList<>(approveIdSet));
-                            }
-                        }
-                        taskService.complete(task.getId(), map);
-                    }
-//                    if (approve != FlowApprovePassEnum.DRAFT && approve != FlowApprovePassEnum.REJECT) {
-//                        taskService.complete(task.getId(), map);
-//                    } else if (approve == FlowApprovePassEnum.REJECT) {
-//                        ((TaskServiceImpl) taskService).getCommandExecutor().execute(new ProcessEventRejectCmd(task.getId(), nextFlowTaskResult.getTaskKey(), map));
-//                        if (Objects.nonNull(map.get(SystemConstant.DEFAULT_ASSIGNEE_LIST + nextFlowTaskResult.getSetup()))) {
-//                            List<String> rejectApproveIdList = (List<String>) map.get(SystemConstant.DEFAULT_ASSIGNEE_LIST + nextFlowTaskResult.getSetup());
-//                            tfFlowLog.setPendApproveId(rejectApproveIdList.toString().replaceAll("\\[", "").replaceAll("\\]", ""));
-//                        }
-//                    }
-                    tfFlowLogList.add(tfFlowLog);
-                }
-            }
-            tfCustomFlowEntityService.saveOrUpdate(tfCustomFlowEntity);
-            tfFlowApproveService.saveOrUpdate(tfFlowApprove);
-            tfFlowLogService.saveBatch(tfFlowLogList);
-        } catch (Exception e) {
-            log.error(SystemConstant.LOG_ERROR, e);
-            if (e instanceof ApiException) {
-                ResultUtil.error((ApiException) e, e.getMessage());
-            } else {
-                ResultUtil.error(e.getMessage());
-            }
-        } finally {
-            memoryLock.unlock(SystemConstant.LOCK_FLOW_TASK_PREFIX + processFlowId);
-        }
+        map = activitiService.taskApprove(flowDeploymentId, approve, taskId, formProperties, approveUserIds, approveRemark, map);
         return ResultUtil.ok(true);
     }
 
@@ -344,246 +87,23 @@ public class ActivitiFromHtmlController {
     @RequestMapping(value = "/getTaskList", method = RequestMethod.POST)
     @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = Object.class)})
     public Result getTaskList(@ApiParam(value = "用户id", required = true) @RequestParam Long userId) {
-        Map<String, Object> map = new HashMap<>();
-        List<FormPropertyBean> formPropertyList = new LinkedList<>();
-        List<Task> taskList = taskService.createTaskQuery().taskAssignee(String.valueOf(userId)).list();
-        if (!CollectionUtils.isEmpty(taskList)) {
-            for (Task t : taskList) {
-                TFCustomFlowEntity tfCustomFlowEntity = tfCustomFlowEntityService.getOne(new QueryWrapper<TFCustomFlowEntity>().lambda().eq(TFCustomFlowEntity::getFlowId, Long.parseLong(t.getProcessInstanceId())));
-                Optional.ofNullable(tfCustomFlowEntity).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程没有实例数据!"));
-                TFCustomFlow tfCustomFlow = tfCustomFlowService.getById(tfCustomFlowEntity.gettFCustomFlowId());
-                Optional.ofNullable(tfCustomFlow).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程没有部署数据!"));
-
-                FlowResult flowResult = JSONObject.parseObject(tfCustomFlowEntity.getFlowProcessVar(), FlowResult.class);
-                LinkedHashMap<String, FlowTaskResult> setupMap = flowResult.getSetupMap();
-                for (Task task : taskList) {
-                    FlowTaskResult currFlowTaskResult = GsonUtil.fromJson(GsonUtil.toJson(setupMap.get(task.getTaskDefinitionKey())), FlowTaskResult.class);
-                    map = this.getFlowFormPropertie(flowResult, map, currFlowTaskResult.getSetup());
-                    break;
-                }
-                formPropertyList.add(new FormPropertyBean(Long.parseLong(t.getProcessInstanceId()), Long.parseLong(t.getId()), userId, (FlowTaskResult) map.get(SystemConstant.FORM_PROPERTIES)));
-            }
-        }
-        return ResultUtil.ok(formPropertyList);
+        return ResultUtil.ok(activitiService.getTaskList(userId));
     }
 
-//    @ApiOperation(value = "流程提交接口")
-//    @RequestMapping(value = "/complete", method = RequestMethod.POST)
-//    @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = Object.class)})
-//    public Map<String, Object> complete(@ApiParam(value = "流程taskId", required = true) @RequestParam String taskId,
-//                                        @ApiParam(value = "上传文件") @RequestParam(required = false) MultipartFile[] files, HttpServletRequest
-//                                                request) {
-//        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
-//        Map<String, Object> varMap = new HashMap<>();
-//        Map<String, String> formDataMap = new HashMap<>();
-//        Map<String, String[]> parameterMap = request.getParameterMap();
-//        Set<Map.Entry<String, String[]>> entrySet = parameterMap.entrySet();
-//        for (Map.Entry<String, String[]> entry : entrySet) {
-//            String key = entry.getKey();
-//            String[] value = entry.getValue();
-//            formDataMap.put(key, value[0]);
-//        }
-//        varMap.putAll(formDataMap);
-//        String flowTaskId = task.getId();
-//        String processInstanceId = task.getProcessInstanceId();
-//        String processDefinitionId = task.getProcessDefinitionId();
-//        formService.submitTaskFormData(flowTaskId, formDataMap);
-//        List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
-//        if (!CollectionUtils.isEmpty(taskList)) {
-//            List<FormPropertyBean> formPropertyList = new LinkedList<>();
-//            for (Task t : taskList) {
-//                String nextFlowTaskId = t.getId();
-//                Object o = formService.getRenderedTaskForm(nextFlowTaskId);
-//                log.info("userId:{},taskId:{},flowId:{},processDefinitionId:{}", t.getAssignee(), nextFlowTaskId, processInstanceId, processDefinitionId);
-//                if (Objects.nonNull(o)) {
-//                    log.info("task formProperties:{}", JacksonUtil.parseJson(o));
-//                    List<FlowFormWidgetResult> list = JSONArray.parseArray(o.toString(), FlowFormWidgetResult.class);
-//                    formPropertyList.add(new FormPropertyBean(processInstanceId, flowTaskId, t.getAssignee(), null));
-//                }
-//                varMap.put("formProperties", formPropertyList);
-//            }
-//        }
-//        return varMap;
-//    }
-
     @ApiOperation(value = "结束流程接口")
     @RequestMapping(value = "/delete", method = RequestMethod.POST)
     @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = Object.class)})
-    public Result delete(String runId) {
-        return ResultUtil.ok(activitiConsumerService.deleteProcessInstance(runId));
-    }
-
-    /**
-     * 获取表单属性
-     *
-     * @param flowResult
-     * @param map
-     * @param setup
-     * @return
-     */
-    public Map<String, Object> getFlowFormPropertie(FlowResult flowResult, Map<String, Object> map, int setup) {
-        Map<String, FlowTaskResult> setupMap = flowResult.getSetupMap();
-        for (Map.Entry<String, FlowTaskResult> entry : setupMap.entrySet()) {
-            FlowTaskResult flowTaskResultTemp = GsonUtil.fromJson(GsonUtil.toJson(entry.getValue()), FlowTaskResult.class);
-            if (flowTaskResultTemp.getSetup().intValue() == setup) {
-                map.put(SystemConstant.FORM_PROPERTIES, flowTaskResultTemp);
-                break;
-            }
-        }
-        return map;
-    }
-
-    /**
-     * 审批通过
-     *
-     * @param currFlowTaskResult
-     * @param setupMap
-     * @param multiInstance
-     * @param nrOfCompletedInstances
-     * @param nrOfInstances
-     * @param tfFlowApprove
-     * @param tfFlowLog
-     * @param nextFlowTaskResult
-     * @param map
-     * @param approvePass
-     * @param approveRemark
-     */
-    public void approvePass(FlowTaskResult currFlowTaskResult,
-                            Map<String, FlowTaskResult> setupMap,
-                            boolean multiInstance,
-                            Integer nrOfCompletedInstances,
-                            Integer nrOfInstances,
-                            TFFlowApprove tfFlowApprove,
-                            TFFlowLog tfFlowLog,
-                            FlowTaskResult nextFlowTaskResult,
-                            Map<String, Object> map,
-                            FlowApprovePassEnum approvePass,
-                            String approveRemark) {
-        if (multiInstance) {
-            map.computeIfAbsent(FlowApproveOperationEnum.REJECT.getId() + currFlowTaskResult.getSetup(), v -> 0);
-        }
-        if (currFlowTaskResult.getSetup().intValue() == setupMap.size() - 1) {
-            if (multiInstance && Objects.nonNull(nrOfCompletedInstances)
-                    && Objects.nonNull(nrOfInstances)
-                    && nrOfCompletedInstances.intValue() == nrOfInstances.intValue()) {
-                tfFlowApprove.setStatus(FlowStatusEnum.FINISH);
-                tfFlowApprove.setSetup(FlowApproveSetupEnum.FINISH.getSetup());
-            } else if (!multiInstance) {
-                tfFlowApprove.setStatus(FlowStatusEnum.FINISH);
-                tfFlowApprove.setSetup(FlowApproveSetupEnum.FINISH.getSetup());
-            } else {
-                tfFlowApprove.setStatus(FlowStatusEnum.AUDITING);
-                tfFlowApprove.setSetup(nextFlowTaskResult.getSetup());
-            }
-        } else {
-            if (approvePass == FlowApprovePassEnum.DRAFT || approvePass == FlowApprovePassEnum.START) {
-                tfFlowApprove.setStatus(FlowStatusEnum.valueOf(approvePass.name()));
-            } else {
-                tfFlowApprove.setStatus(FlowStatusEnum.AUDITING);
-            }
-            tfFlowApprove.setSetup(nextFlowTaskResult.getSetup());
-        }
-        if (tfFlowApprove.getStatus() == FlowStatusEnum.START) {
-            tfFlowLog.setApproveOperation(FlowApproveOperationEnum.START);
-        } else if (tfFlowApprove.getStatus() == FlowStatusEnum.DRAFT) {
-            tfFlowLog.setApproveOperation(FlowApproveOperationEnum.DRAFT);
-        } else {
-            tfFlowLog.setApproveOperation(FlowApproveOperationEnum.APPROVE);
-        }
-        if (Objects.nonNull(approveRemark)) {
-            tfFlowLog.setApproveRemark(approveRemark);
-        } else {
-            tfFlowLog.setApproveRemark(tfFlowLog.getApproveOperation().getTitle());
-        }
-//        map.put(SystemConstant.APPROVE, nextFlowTaskResult.getTaskKey());
-    }
-
-    /**
-     * 审批驳回
-     *
-     * @param multiInstance
-     * @param map
-     * @param currFlowTaskResult
-     * @param nextFlowTaskResult
-     * @param tfFlowApprove
-     * @param tfFlowLog
-     * @param approvePass
-     * @param approveRemark
-     */
-    protected void approveReject(boolean multiInstance,
-                                 Map<String, Object> map,
-                                 FlowTaskResult currFlowTaskResult,
-                                 FlowTaskResult nextFlowTaskResult,
-                                 TFFlowApprove tfFlowApprove,
-                                 TFFlowLog tfFlowLog,
-                                 FlowApprovePassEnum approvePass,
-                                 String approveRemark) {
-        if (multiInstance) {
-            map.computeIfAbsent(FlowApproveOperationEnum.REJECT.getId() + currFlowTaskResult.getSetup(), v -> 1);
-        }
-//        map.put(SystemConstant.APPROVE, nextFlowTaskResult.getTaskKey());
-        tfFlowApprove.setSetup(nextFlowTaskResult.getSetup());
-        tfFlowApprove.setStatus(FlowStatusEnum.convertToEnum(approvePass.name()));
-        tfFlowLog.setApproveOperation(FlowApproveOperationEnum.convertToEnum(approvePass.name()));
-        if (Objects.nonNull(approveRemark)) {
-            tfFlowLog.setApproveRemark(approveRemark);
-        } else {
-            tfFlowLog.setApproveRemark(tfFlowLog.getApproveOperation().getTitle());
-        }
-    }
-
-    /**
-     * 获取流程下一节点
-     *
-     * @param nrOfCompletedInstances
-     * @param nrOfInstances
-     * @param currFlowTaskResult
-     * @param nextFlowTaskResult
-     * @param currSetup
-     * @param setupMap
-     * @param approvePass
-     * @return
-     */
-    public FlowTaskResult getNextFlowTaskResult(Integer nrOfCompletedInstances,
-                                                Integer nrOfInstances,
-                                                FlowTaskResult currFlowTaskResult,
-                                                FlowTaskResult nextFlowTaskResult,
-                                                int currSetup,
-                                                Map<String, FlowTaskResult> setupMap,
-                                                FlowApprovePassEnum approvePass) {
-        if (approvePass == FlowApprovePassEnum.PASS || approvePass == FlowApprovePassEnum.START || approvePass == FlowApprovePassEnum.DRAFT) {
-            if (Objects.nonNull(nrOfCompletedInstances)
-                    && Objects.nonNull(nrOfInstances)
-                    && nrOfCompletedInstances.intValue() != nrOfInstances.intValue() || approvePass == FlowApprovePassEnum.DRAFT) {
-                nextFlowTaskResult = currFlowTaskResult;
-            } else {
-                nextFlowTaskResult = this.getNextFlowTaskResult(setupMap, currSetup, nextFlowTaskResult);
-            }
-        } else if (approvePass == FlowApprovePassEnum.REJECT || approvePass == FlowApprovePassEnum.CANCEL) {
-            nextFlowTaskResult = this.getNextFlowTaskResult(setupMap, currSetup, nextFlowTaskResult);
-        }
-        Optional.ofNullable(nextFlowTaskResult).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("该节点不能审批通过"));
-        return nextFlowTaskResult;
+    public Result delete(@ApiParam(value = "流程id", required = true) Long flowId) {
+        activitiService.flowEnd(flowId);
+        return ResultUtil.ok(true);
     }
 
-    /**
-     * 获取下级审核节点
-     *
-     * @param setupMap
-     * @param currSetup
-     * @param nextFlowTaskResult
-     * @return
-     */
-    public FlowTaskResult getNextFlowTaskResult(Map<String, FlowTaskResult> setupMap,
-                                                int currSetup,
-                                                FlowTaskResult nextFlowTaskResult) {
-        for (Map.Entry<String, FlowTaskResult> entry : setupMap.entrySet()) {
-            FlowTaskResult flowTaskResultTemp = GsonUtil.fromJson(GsonUtil.toJson(entry.getValue()), FlowTaskResult.class);
-            if (flowTaskResultTemp.getSetup().intValue() == currSetup) {
-                nextFlowTaskResult = flowTaskResultTemp;
-                break;
-            }
-        }
-        return nextFlowTaskResult;
+    @ApiOperation(value = "流程转办接口")
+    @RequestMapping(value = "/task/approver/exchange", method = RequestMethod.POST)
+    @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = Object.class)})
+    public Result taskApproverExchange(@ApiParam(value = "用户id", required = true) Long userId,
+                                       @ApiParam(value = "用户id", required = true) Long taskId) {
+        activitiService.taskApproverExchange(userId, taskId);
+        return ResultUtil.ok(true);
     }
 }