Browse Source

审核流

gongdecai 4 years ago
parent
commit
6622ba732e

+ 247 - 0
winsea-haixin-plugin-yiliangyiyun/src/main/java/com/yh/saas/plugin/yiliangyiyun/controller/NewWorkflowController.java

@@ -0,0 +1,247 @@
+package com.yh.saas.plugin.yiliangyiyun.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.plugins.Page;
+import com.winsea.svc.base.security.util.AuthSecurityUtils;
+import com.winsea.svc.base.workflow.entity.Workflow;
+import com.yh.saas.common.support.util.StringUtils;
+import com.yh.saas.plugin.yiliangyiyun.service.INewWorkflowService;
+import com.yh.saas.toolkit.workflow.command.WorkflowCommand;
+import com.yh.saas.toolkit.workflow.service.IWorkflowService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.StreamUtils;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 工作流API
+ *
+ * @author gdc
+ */
+@RequestMapping("/newWorkflow")
+@RestController
+public class NewWorkflowController {
+
+    @Autowired
+    private HttpServletResponse response;
+
+    @Autowired
+    private INewWorkflowService workflowService;
+
+    /**
+     * 创建工作流
+     *
+     * @param workflow 工作流对象
+     * @return 工作流ID
+     */
+    @PostMapping("/api/create")
+    public String create(@RequestBody Workflow workflow) {
+        if (StringUtils.isEmpty(workflow.getCompId())) {
+            workflow.setCompId(AuthSecurityUtils.getCurrentUserInfo().getCompId());
+        }
+        return workflowService.create(workflow);
+    }
+
+    /**
+     * 修改工作流信息
+     *
+     * @param workflow 工作流对象
+     * @return 工作流ID
+     */
+    @PostMapping("/api/changeInfo")
+    public String changeInfo(@RequestBody Workflow workflow) {
+        if (StringUtils.isEmpty(workflow.getCompId())) {
+            workflow.setCompId(AuthSecurityUtils.getCurrentUserInfo().getCompId());
+        }
+        return workflowService.changeInfo(workflow);
+    }
+
+    /**
+     * 开始工作流
+     *
+     * @param command 开始命令
+     */
+    @PostMapping("/api/startInstance")
+    public void startInstance(@RequestBody WorkflowCommand.StartInstance command) {
+        workflowService.startInstance(command.getWorkflowId(), command.getBusinessKey());
+    }
+
+    /**
+     * 激活工作流
+     *
+     * @param command 激活命令
+     */
+    @PostMapping("/api/activateInstance")
+    public void activateInstance(@RequestBody WorkflowCommand.ActivateInstance command) {
+        workflowService.activateInstance(command.getWorkflowId(), command.getBusinessKey());
+    }
+
+    /**
+     * 挂起工作流
+     *
+     * @param command 挂起命令
+     */
+    @PostMapping("/api/suspendInstance")
+    public void suspendInstance(@RequestBody WorkflowCommand.SuspendInstance command) {
+        workflowService.suspendInstance(command.getWorkflowId(), command.getBusinessKey());
+    }
+
+    /**
+     * 签收
+     *
+     * @param command 签收命令
+     */
+    @PostMapping("/api/claim")
+    public void claim(@RequestBody WorkflowCommand.ClaimTask command) {
+        if (StringUtils.isEmpty(command.getUserId())) {
+            workflowService.claim(command.getTaskId());
+        } else {
+            workflowService.claim(command.getTaskId(), command.getUserId());
+        }
+    }
+
+    /**
+     * 处理任务
+     *
+     * @param command 处理任务命令
+     */
+    @PostMapping("/api/handle")
+    public void handle(@RequestBody WorkflowCommand.HandleTask command) {
+        workflowService.handle(command.getTaskId(), command.getApproved(), command.getAuditMind(),
+                command.getNeedReapply());
+    }
+
+    /**
+     * 获取流程图
+     *
+     * @param workflowId 工作流ID
+     * @throws IOException
+     */
+    @GetMapping("/query/processDiagram")
+    public void getInstancePicture(@RequestParam String workflowId) throws IOException {
+        InputStream processDiagram = workflowService.getProcessDiagram(workflowId);
+        if (null != processDiagram) {
+            response.setContentType("application/force-download");
+            response.setHeader("Content-Disposition", "attachment;fileName=" + workflowId + ".png");
+
+            StreamUtils.copy(processDiagram, response.getOutputStream());
+            response.getOutputStream().close();
+        }
+    }
+
+    /**
+     * 获取工作流定义列表
+     *
+     * @param businessCode 业务编码
+     * @param tmpCompId    公司ID
+     * @return 工作流定义列表
+     */
+    @GetMapping("/query/workflowDefinitions")
+    public List<Workflow> getWorkflowDefinitions(@RequestParam String businessCode,
+                                                 @RequestParam(name = "compId", required = false) String tmpCompId) {
+        String compId = tmpCompId;
+        if (StringUtils.isEmpty(tmpCompId)) {
+            compId = AuthSecurityUtils.getCurrentUserInfo().getCompId();
+        }
+        return workflowService.getWorkflowDefinitions(businessCode, compId);
+    }
+
+    /**
+     * 通过业务编码查询工作流列表
+     *
+     * @param businessCode 业务编号
+     * @return 工作流列表
+     */
+    @GetMapping("/query/workflowsByBusinessCode")
+    public List<Workflow> findWorkflowsByBusinessCode(@RequestParam String businessCode) {
+        return workflowService.findWorkflowsByBusinessCode(businessCode);
+    }
+
+    /**
+     * 获取工作流详情
+     *
+     * @param workflowId 工作流ID
+     * @return 工作流详情
+     */
+    @GetMapping("/query/workflowInfo")
+    public Workflow getWorkflowInfo(@RequestParam String workflowId) {
+        return workflowService.getWorkflowDetail(workflowId);
+    }
+
+    /**
+     * 获取任务列表
+     *
+     * @param workflowIds 工作流ID列表
+     * @param currentPage 页码
+     * @param pageSize    分页大小
+     * @return 任务列表
+     */
+    @GetMapping("/query/tasks")
+    public Page<Object> getTaskList(@RequestParam String workflowIds, @RequestParam Integer currentPage,
+                                    @RequestParam Integer pageSize) {
+        return workflowService.getTaskList(Arrays.asList(workflowIds.split(",")), currentPage, pageSize);
+    }
+
+    /**
+     * 获取活动的任务
+     *
+     * @param workflowIds 工作流ID列表
+     * @param businessKey 业务编码
+     * @return 活动的任务
+     */
+    @GetMapping("/query/activeTask")
+    public JSONObject getActiveTask(@RequestParam String workflowIds, @RequestParam String businessKey) {
+        return workflowService.getActiveTask(Arrays.asList(workflowIds.split(",")), businessKey);
+    }
+
+    /**
+     * 获取活动的任务
+     *
+     * @param workflowIds 工作流ID列表
+     * @param businessKey 业务编码
+     * @return 活动的任务
+     */
+    @GetMapping("/query/preActiveTask")
+    public JSONObject getActiveTask(@RequestParam String staffId,@RequestParam String workflowIds, @RequestParam String businessKey) {
+        return workflowService.getActiveTask(staffId,Arrays.asList(workflowIds.split(",")), businessKey);
+    }
+
+    /**
+     * 查询 - 当前审核流业务实例处于第几步骤
+     *
+     * @param workflowId  审核流id
+     * @param businessKey 主键业务
+     * @return 第几步
+     */
+    @GetMapping("/query/findWorkflowStepNumber")
+    public Integer findWorkflowStepNumber(@RequestParam String workflowId, @RequestParam String businessKey) {
+        return workflowService.findWorkflowStepNumber(workflowId, businessKey);
+    }
+
+    /**
+     * 判断当前任务是否处于最后一级节点
+     * <p>
+     * `     * @param taskId 任务id
+     *
+     * @return 是||否
+     */
+    @GetMapping("/query/judgeBusinessLastStep")
+    public boolean judgeBusinessLastStep(@RequestParam String taskId) {
+        return workflowService.judgeBusinessLastStep(taskId);
+    }
+
+    /**
+     * 删除  - 删除最新审核流(改为旧审核流)
+     *
+     * @param workflow 审核流配置对象
+     */
+    @PostMapping("/api/removeLatestWorkflow")
+    public void removeLatestWorkflow(@RequestBody Workflow workflow) {
+        workflowService.removeLatestWorkflow(workflow.getId());
+    }
+}

+ 255 - 0
winsea-haixin-plugin-yiliangyiyun/src/main/java/com/yh/saas/plugin/yiliangyiyun/service/INewWorkflowService.java

@@ -0,0 +1,255 @@
+package com.yh.saas.plugin.yiliangyiyun.service;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.plugins.Page;
+import com.winsea.svc.base.workflow.entity.Workflow;
+
+import java.io.InputStream;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 工作流服务
+ *
+ * @author gdc
+ */
+public interface INewWorkflowService {
+
+    /**
+     * 创建工作流
+     *
+     * @param workflow 工作流对象
+     * @return 工作流ID
+     */
+    String create(Workflow workflow);
+
+    /**
+     * 修改工作流信息
+     *
+     * @param workflow 工作流对象
+     * @return 工作流ID
+     */
+    String changeInfo(Workflow workflow);
+
+    /**
+     * 获取工作流详情
+     *
+     * @param workflowId 工作流ID
+     * @return 工作流详情
+     */
+    Workflow getWorkflowDetail(String workflowId);
+
+    /**
+     * 通过业务编码获取最新工作流定义列表<br/>
+     * 查询公司下所有
+     *
+     * @param businessCode 业务编码
+     * @param compId       公司ID
+     * @return 最新工作流定义列表
+     */
+    List<Workflow> getWorkflowDefinitions(String businessCode, String compId);
+
+    /**
+     * 通过业务编码查询最新工作流<br/>
+     * 根据用户和角色查询
+     *
+     * @param businessCode 业务编码
+     * @return 最新关联工作流
+     */
+    Workflow findLatestWorkflowByBusinessCode(String businessCode);
+
+    /**
+     * 通过业务编码和公司ID获取最新工作流
+     *
+     * @param businessCode 业务编码
+     * @param compId       公司ID
+     * @return 最新关联工作流
+     */
+    Workflow getLatestWorkflowByBusinessCodeAndCompId(String businessCode, String compId);
+
+    /**
+     * 通过业务编码查询工作流列表<br/>
+     * 根据用户和角色查询
+     *
+     * @param businessCode 业务编码
+     * @return 关联工作流列表
+     */
+    List<Workflow> findWorkflowsByBusinessCode(String businessCode);
+
+    /**
+     * 通过业务编码查询工作流ID列表
+     *
+     * @param businessCode 业务编码
+     * @return 关联工作流ID列表
+     */
+    List<String> findWorkflowIdsByBusinessCode(String businessCode);
+
+    /**
+     * 获取流程图
+     *
+     * @param workflowId 工作流ID
+     * @return InputStream
+     */
+    InputStream getProcessDiagram(String workflowId);
+
+    /**
+     * 开始一个工作流
+     *
+     * @param processId   工作流ID
+     * @param businessKey 业务码
+     */
+    void startInstance(String workflowId, String businessKey);
+
+    /**
+     * 开始一个工作流
+     *
+     * @param processId   工作流ID
+     * @param businessKey 业务码
+     * @param startUserId 申请用户ID
+     */
+    void startInstance(String workflowId, String businessKey, String startUserId);
+
+    /**
+     * 激活工作流
+     *
+     * @param processId   工作流ID
+     * @param businessKey 业务码
+     * 
+     * @return 工作流ID
+     */
+    String activateInstance(String workflowId, String businessKey);
+
+    /**
+     * 挂起工作流
+     *
+     * @param processId   工作流ID
+     * @param businessKey 业务码
+     */
+    void suspendInstance(String workflowId, String businessKey);
+
+    /**
+     * 结束工作流
+     *
+     * @param workflowId  工作流ID
+     * @param businessKey 业务码
+     * @param reason      结束原因
+     */
+    void stopInstance(String workflowId, String businessKey, String reason);
+
+    /**
+     * 当前登录人签收
+     *
+     * @param taskId 任务ID
+     */
+    void claim(String taskId);
+
+    /**
+     * 签收
+     *
+     * @param taskId 任务ID
+     * @param userId 用户ID
+     */
+    void claim(String taskId, String userId);
+
+    /**
+     * 任务ID
+     *
+     * @param taskId      任务ID
+     * @param approved    是否同意
+     * @param auditMind   审核意见
+     * @param needReapply 是否需要重新申请
+     */
+    void handle(String taskId, boolean approved, String auditMind, boolean needReapply);
+
+    /**
+     * 获取任务分页列表
+     *
+     * @param workflowIds 工作流ID列表
+     * @param current     页码
+     * @param size        分页大小
+     * @return 任务分页列表<br />
+     * records->任务列表<br/>
+     * taskId->任务ID,taskName->任务名称,workflowId->工作流ID,businessKey->业务编码
+     */
+    Page<Object> getTaskList(List<String> workflowIds, int current, int size);
+
+    /**
+     * 获得审批人代办的所有任务相关businessKey
+     *
+     * @param businessCode 业务编码
+     * @return businessKeys
+     */
+    List<String> getTaskBusinessKeysByCode(String businessCode);
+
+    /**
+     * 获得审批人代办的所有任务相关businessKey
+     *
+     * @param workflowId 工作流ID
+     * @return businessKeys
+     */
+    List<String> getTaskBusinessKeysByFlowId(String workflowId);
+
+    /**
+     * 获得审批人已办的所有任务相关businessKey
+     *
+     * @param businessCode 业务编码
+     * @return businessKeys
+     */
+    List<String> getDoneTaskBusinessKeysByCode(String businessCode);
+
+    /**
+     * 获得审批人已办的所有任务相关businessKey
+     *
+     * @param workflowId 工作流ID
+     * @return businessKeys
+     */
+    List<String> getDoneTaskBusinessKeysByFlowId(String workflowId);
+
+    /**
+     * 获取活动的任务
+     *
+     * @param workflowIds 工作流ID列表
+     * @param businessKey 业务编码
+     * @return 活动的任务<br />
+     * taskId->任务ID,taskName->任务名称,workflowId->工作流ID
+     */
+    JSONObject getActiveTask(List<String> workflowIds, String businessKey);
+
+    /**
+     * 获取活动的任务
+     *
+     * @param workflowIds 工作流ID列表
+     * @param businessKey 业务编码
+     * @return 活动的任务<br />
+     * taskId->任务ID,taskName->任务名称,workflowId->工作流ID
+     */
+    JSONObject getActiveTask(String staffId, List<String> workflowIds, String businessKey);
+
+    /**
+     * Mybatis plus
+     */
+    Workflow selectById(Serializable id);
+
+    /**
+     * 查询 - 当前审核流业务实例处于第几步骤
+     *
+     * @param workflowId  审核流id
+     * @param businessKey 主键业务
+     * @return 第几步
+     */
+    Integer findWorkflowStepNumber(String workflowId, String businessKey);
+
+    /**
+     * 判断当前任务是否处于最后一级节点
+     *
+     * @param businessKey 业务主键id
+     * @return 是||否
+     */
+    boolean judgeBusinessLastStep(String businessKey);
+
+    /**
+     * 删除最新审核流(改为旧审核流)
+     * @param workflowId 审核流id
+     */
+    void removeLatestWorkflow(String workflowId);
+}

+ 46 - 37
winsea-haixin-plugin-yiliangyiyun/src/main/java/com/yh/saas/plugin/yiliangyiyun/service/impl/InOutWarehouseTaskServiceImpl.java

@@ -26,6 +26,7 @@ import org.apache.commons.collections.CollectionUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.StringUtils;
+
 import java.util.*;
 import java.util.*;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 
 
@@ -40,13 +41,15 @@ import java.util.stream.Collectors;
 @Service
 @Service
 public class InOutWarehouseTaskServiceImpl extends ServiceImpl<InOutWarehouseTaskMapper, InOutWarehouseTask> implements IInOutWarehouseTaskService {
 public class InOutWarehouseTaskServiceImpl extends ServiceImpl<InOutWarehouseTaskMapper, InOutWarehouseTask> implements IInOutWarehouseTaskService {
     @Autowired
     @Autowired
-     private IInOutWarehouseTaskService inOutWarehouseTaskService;
+    private IInOutWarehouseTaskService inOutWarehouseTaskService;
     @Autowired
     @Autowired
     private ICommonBillOperateHisService billOperateHisService;
     private ICommonBillOperateHisService billOperateHisService;
     @Autowired
     @Autowired
     private IWorkflowService workflowService;
     private IWorkflowService workflowService;
+
     /**
     /**
      * 出入库任务新增 编辑
      * 出入库任务新增 编辑
+     *
      * @param inOutWarehouseTask
      * @param inOutWarehouseTask
      * @return
      * @return
      */
      */
@@ -61,16 +64,16 @@ public class InOutWarehouseTaskServiceImpl extends ServiceImpl<InOutWarehouseTas
             inOutWarehouseTask.setTaskStatus(StatusEnum.TASK_REVIEWED.getName());
             inOutWarehouseTask.setTaskStatus(StatusEnum.TASK_REVIEWED.getName());
             inOutWarehouseTask.setEstablishDate(new Date());
             inOutWarehouseTask.setEstablishDate(new Date());
             //出库任务,入库任务,赋值关联id
             //出库任务,入库任务,赋值关联id
-            if ("1".equals(inOutWarehouseTask.getTaskTypeKey()) || "2".equals(inOutWarehouseTask.getTaskTypeKey())){
+            if ("1".equals(inOutWarehouseTask.getTaskTypeKey()) || "2".equals(inOutWarehouseTask.getTaskTypeKey())) {
                 inOutWarehouseTask.setRelevanceId(inOutWarehouseTask.getId());
                 inOutWarehouseTask.setRelevanceId(inOutWarehouseTask.getId());
             }
             }
             //新增移库出库任务时,获取发货库和出库量
             //新增移库出库任务时,获取发货库和出库量
-            else if("3".equals(inOutWarehouseTask.getTaskTypeKey()) && "1".equals(inOutWarehouseTask.getInOutFlag())){
+            else if ("3".equals(inOutWarehouseTask.getTaskTypeKey()) && "1".equals(inOutWarehouseTask.getInOutFlag())) {
                 inOutWarehouseTask.setSendWarehouse(inOutWarehouseTask.getWarehouseName());
                 inOutWarehouseTask.setSendWarehouse(inOutWarehouseTask.getWarehouseName());
                 inOutWarehouseTask.setDeliveryVolume(inOutWarehouseTask.getWeight());
                 inOutWarehouseTask.setDeliveryVolume(inOutWarehouseTask.getWeight());
             }
             }
             //新增移库入库任务时,获取收货库和入库量
             //新增移库入库任务时,获取收货库和入库量
-            else if("3".equals(inOutWarehouseTask.getTaskTypeKey()) && "2".equals(inOutWarehouseTask.getInOutFlag())){
+            else if ("3".equals(inOutWarehouseTask.getTaskTypeKey()) && "2".equals(inOutWarehouseTask.getInOutFlag())) {
                 inOutWarehouseTask.setReceiveWarehouse(inOutWarehouseTask.getWarehouseNameIn());
                 inOutWarehouseTask.setReceiveWarehouse(inOutWarehouseTask.getWarehouseNameIn());
                 inOutWarehouseTask.setStorageVolume(inOutWarehouseTask.getWeightIn());
                 inOutWarehouseTask.setStorageVolume(inOutWarehouseTask.getWeightIn());
             }
             }
@@ -144,7 +147,7 @@ public class InOutWarehouseTaskServiceImpl extends ServiceImpl<InOutWarehouseTas
     @Override
     @Override
     public boolean selectTaskNo(String moveTaskNo) {
     public boolean selectTaskNo(String moveTaskNo) {
         // 根据出入出入库编号查询数据
         // 根据出入出入库编号查询数据
-        InOutWarehouseTask inOutWarehouseTask= this.selectOne(new EntityWrapper<InOutWarehouseTask>().eq(InOutWarehouseTask.QueryFiles.MOVE_TASK_NO, moveTaskNo)
+        InOutWarehouseTask inOutWarehouseTask = this.selectOne(new EntityWrapper<InOutWarehouseTask>().eq(InOutWarehouseTask.QueryFiles.MOVE_TASK_NO, moveTaskNo)
                 .eq(InOutWarehouseTask.QueryFiles.DELETE_FLAG, NumberConstant.CONSTANT0));
                 .eq(InOutWarehouseTask.QueryFiles.DELETE_FLAG, NumberConstant.CONSTANT0));
         //如果没有可以使用
         //如果没有可以使用
         if (inOutWarehouseTask == null) {
         if (inOutWarehouseTask == null) {
@@ -156,26 +159,27 @@ public class InOutWarehouseTaskServiceImpl extends ServiceImpl<InOutWarehouseTas
 
 
     /**
     /**
      * 出入库任务列表
      * 出入库任务列表
+     *
      * @param inOutWarehouseTask
      * @param inOutWarehouseTask
      * @return
      * @return
      */
      */
     @Override
     @Override
-    public Page<InOutWarehouseTask> selectInOutWarehouseTask(InOutWarehouseTask inOutWarehouseTask){
+    public Page<InOutWarehouseTask> selectInOutWarehouseTask(InOutWarehouseTask inOutWarehouseTask) {
         Map<String, Object> pageView = new HashMap<>();
         Map<String, Object> pageView = new HashMap<>();
         pageView.put("startRecord", (inOutWarehouseTask.getCurrentPage() - 1)
         pageView.put("startRecord", (inOutWarehouseTask.getCurrentPage() - 1)
                 * inOutWarehouseTask.getPageSize());
                 * inOutWarehouseTask.getPageSize());
         //公司id
         //公司id
-        pageView.put("compId",inOutWarehouseTask.getCompId());
-        pageView.put("searchKeyWord",inOutWarehouseTask.getSearchKeyWord());
+        pageView.put("compId", inOutWarehouseTask.getCompId());
+        pageView.put("searchKeyWord", inOutWarehouseTask.getSearchKeyWord());
         pageView.put("searchType", inOutWarehouseTask.getSearchType());
         pageView.put("searchType", inOutWarehouseTask.getSearchType());
-        pageView.put("pageSize",inOutWarehouseTask.getPageSize());
-        pageView.put("currentPage",inOutWarehouseTask.getCurrentPage());
+        pageView.put("pageSize", inOutWarehouseTask.getPageSize());
+        pageView.put("currentPage", inOutWarehouseTask.getCurrentPage());
         // 查询出入库任务总数
         // 查询出入库任务总数
         Integer dataCount = baseMapper.getCountByCondition(pageView);
         Integer dataCount = baseMapper.getCountByCondition(pageView);
         List<InOutWarehouseTask> dataList = baseMapper.getListByCondition(pageView);
         List<InOutWarehouseTask> dataList = baseMapper.getListByCondition(pageView);
-        if(CollectionUtils.isNotEmpty(dataList)){
-            dataList.forEach(inOutWarehouseTask1 -> {
-
+        if (CollectionUtils.isNotEmpty(dataList)) {
+//            dataList.forEach(inOutWarehouseTask1 -> {
+            for (InOutWarehouseTask inOutWarehouseTask1 : dataList) {
                 String taskId = "";
                 String taskId = "";
                 // 只有待审核状态才有taskId
                 // 只有待审核状态才有taskId
                 if (StringUtils.isNotBlank(inOutWarehouseTask1.getWorkflowId())) {
                 if (StringUtils.isNotBlank(inOutWarehouseTask1.getWorkflowId())) {
@@ -183,7 +187,7 @@ public class InOutWarehouseTaskServiceImpl extends ServiceImpl<InOutWarehouseTas
                     taskId = jsonObject.getString("taskId");
                     taskId = jsonObject.getString("taskId");
                     inOutWarehouseTask1.setTaskId(taskId);
                     inOutWarehouseTask1.setTaskId(taskId);
                 }
                 }
-            });
+            }
         }
         }
         Page<InOutWarehouseTask> page = new Page<>();
         Page<InOutWarehouseTask> page = new Page<>();
         page.setRecords(dataList == null ? Lists.newArrayList() : dataList);
         page.setRecords(dataList == null ? Lists.newArrayList() : dataList);
@@ -195,28 +199,30 @@ public class InOutWarehouseTaskServiceImpl extends ServiceImpl<InOutWarehouseTas
 
 
     /**
     /**
      * 查看出入库任务
      * 查看出入库任务
+     *
      * @param relevanceId
      * @param relevanceId
      * @return
      * @return
      */
      */
     @Override
     @Override
-    public List<InOutWarehouseTask> getInOutWarehouseTask(String relevanceId){
+    public List<InOutWarehouseTask> getInOutWarehouseTask(String relevanceId) {
         List<InOutWarehouseTask> inOutWarehouseTaskList = inOutWarehouseTaskService.selectList(new EntityWrapper<InOutWarehouseTask>()
         List<InOutWarehouseTask> inOutWarehouseTaskList = inOutWarehouseTaskService.selectList(new EntityWrapper<InOutWarehouseTask>()
-            .eq(InOutWarehouseTask.QueryFiles.relevanceId,relevanceId).eq(InOutWarehouseTask.QueryFiles.DELETE_FLAG,NumberConstant.CONSTANT0));
+                .eq(InOutWarehouseTask.QueryFiles.relevanceId, relevanceId).eq(InOutWarehouseTask.QueryFiles.DELETE_FLAG, NumberConstant.CONSTANT0));
         return inOutWarehouseTaskList;
         return inOutWarehouseTaskList;
     }
     }
 
 
     /**
     /**
      * 删除出入库任务
      * 删除出入库任务
+     *
      * @param id
      * @param id
      */
      */
     @Override
     @Override
-    public void deleteInOutWarehouseTask(String id ,String relevanceId){
+    public void deleteInOutWarehouseTask(String id, String relevanceId) {
         //查询出入库任务
         //查询出入库任务
         InOutWarehouseTask inOutWarehouseTask = this.selectById(id);
         InOutWarehouseTask inOutWarehouseTask = this.selectById(id);
         if (inOutWarehouseTask != null) {
         if (inOutWarehouseTask != null) {
             //出库任务,入库任务,移库先删入库
             //出库任务,入库任务,移库先删入库
             if ("1".equals(inOutWarehouseTask.getTaskTypeKey()) || "2".equals(inOutWarehouseTask.getTaskTypeKey()) ||
             if ("1".equals(inOutWarehouseTask.getTaskTypeKey()) || "2".equals(inOutWarehouseTask.getTaskTypeKey()) ||
-                    ("3".equals(inOutWarehouseTask.getTaskTypeKey()) && "2".equals(inOutWarehouseTask.getInOutFlag())) ) {
+                    ("3".equals(inOutWarehouseTask.getTaskTypeKey()) && "2".equals(inOutWarehouseTask.getInOutFlag()))) {
                 inOutWarehouseTaskService.deleteById(inOutWarehouseTask.getId());
                 inOutWarehouseTaskService.deleteById(inOutWarehouseTask.getId());
             }
             }
             //移库先删出库,退库并出库
             //移库先删出库,退库并出库
@@ -234,15 +240,16 @@ public class InOutWarehouseTaskServiceImpl extends ServiceImpl<InOutWarehouseTas
 
 
     /**
     /**
      * 更改状态
      * 更改状态
+     *
      * @param id
      * @param id
      * @return
      * @return
      */
      */
     @Override
     @Override
-    public String editStatus(String id){
+    public String editStatus(String id) {
         //查询出入库任务
         //查询出入库任务
         InOutWarehouseTask inOutWarehouseTask = this.selectById(id);
         InOutWarehouseTask inOutWarehouseTask = this.selectById(id);
         //更改状态
         //更改状态
-        if (inOutWarehouseTask != null ){
+        if (inOutWarehouseTask != null) {
             if (StatusEnum.TASK_DO.getFlag().equals(inOutWarehouseTask.getTaskStatusKey())) {
             if (StatusEnum.TASK_DO.getFlag().equals(inOutWarehouseTask.getTaskStatusKey())) {
                 inOutWarehouseTask.setTaskStatusKey(StatusEnum.TASK_COMPLETED.getFlag());
                 inOutWarehouseTask.setTaskStatusKey(StatusEnum.TASK_COMPLETED.getFlag());
                 inOutWarehouseTask.setTaskStatus(StatusEnum.TASK_COMPLETED.getName());
                 inOutWarehouseTask.setTaskStatus(StatusEnum.TASK_COMPLETED.getName());
@@ -276,7 +283,7 @@ public class InOutWarehouseTaskServiceImpl extends ServiceImpl<InOutWarehouseTas
         //公司id
         //公司id
         pageView.put("compId", inOutWarehouseTask.getCompId());
         pageView.put("compId", inOutWarehouseTask.getCompId());
         pageView.put("searchKeyWord", inOutWarehouseTask.getSearchKeyWord());
         pageView.put("searchKeyWord", inOutWarehouseTask.getSearchKeyWord());
-        pageView.put("searchType",inOutWarehouseTask.getSearchType());
+        pageView.put("searchType", inOutWarehouseTask.getSearchType());
         pageView.put("pageSize", inOutWarehouseTask.getPageSize());
         pageView.put("pageSize", inOutWarehouseTask.getPageSize());
         pageView.put("currentPage", inOutWarehouseTask.getCurrentPage());
         pageView.put("currentPage", inOutWarehouseTask.getCurrentPage());
 
 
@@ -285,18 +292,18 @@ public class InOutWarehouseTaskServiceImpl extends ServiceImpl<InOutWarehouseTas
         Integer dataCount = this.baseMapper.getMoveCountByCondition(pageView);
         Integer dataCount = this.baseMapper.getMoveCountByCondition(pageView);
 
 
 
 
-        if(!CollectionUtils.isEmpty(dataList)){
-            for(InOutWarehouseTask inOutWarehouseTaska : dataList){
+        if (!CollectionUtils.isEmpty(dataList)) {
+            for (InOutWarehouseTask inOutWarehouseTaska : dataList) {
 
 
                 //定义累计退库量
                 //定义累计退库量
                 String stockReturnCount = "";
                 String stockReturnCount = "";
 
 
                 //查询退库量
                 //查询退库量
                 List<InOutWarehouseTask> inOutWarehouseTaskList = inOutWarehouseTaskService.selectList(new EntityWrapper<InOutWarehouseTask>()
                 List<InOutWarehouseTask> inOutWarehouseTaskList = inOutWarehouseTaskService.selectList(new EntityWrapper<InOutWarehouseTask>()
-                        .eq("move_task_no",inOutWarehouseTaska.getMoveTaskNo())
-                        .eq("in_out_type_key","6")
-                        .eq("delete_flag","0"));
-                if(!CollectionUtils.isEmpty(inOutWarehouseTaskList)) {
+                        .eq("move_task_no", inOutWarehouseTaska.getMoveTaskNo())
+                        .eq("in_out_type_key", "6")
+                        .eq("delete_flag", "0"));
+                if (!CollectionUtils.isEmpty(inOutWarehouseTaskList)) {
                     for (InOutWarehouseTask inoutwarehouse : inOutWarehouseTaskList) {
                     for (InOutWarehouseTask inoutwarehouse : inOutWarehouseTaskList) {
                         if (StringUtils.isEmpty(stockReturnCount)) {
                         if (StringUtils.isEmpty(stockReturnCount)) {
                             stockReturnCount = "0";
                             stockReturnCount = "0";
@@ -318,20 +325,21 @@ public class InOutWarehouseTaskServiceImpl extends ServiceImpl<InOutWarehouseTas
 
 
     /**
     /**
      * 查看移库任务
      * 查看移库任务
+     *
      * @param moveTaskNo
      * @param moveTaskNo
      * @return
      * @return
      */
      */
     @Override
     @Override
-    public List<InOutWarehouseTask> getInOutWarehouseTaskRelocation(String moveTaskNo){
+    public List<InOutWarehouseTask> getInOutWarehouseTaskRelocation(String moveTaskNo) {
         List<InOutWarehouseTask> inOutWarehouseTaskList = inOutWarehouseTaskService.selectList(new EntityWrapper<InOutWarehouseTask>()
         List<InOutWarehouseTask> inOutWarehouseTaskList = inOutWarehouseTaskService.selectList(new EntityWrapper<InOutWarehouseTask>()
-                .eq("move_task_no",moveTaskNo));
-        if(!CollectionUtils.isEmpty(inOutWarehouseTaskList)){
+                .eq("move_task_no", moveTaskNo));
+        if (!CollectionUtils.isEmpty(inOutWarehouseTaskList)) {
             inOutWarehouseTaskList.forEach(inOutWarehouseTask -> {
             inOutWarehouseTaskList.forEach(inOutWarehouseTask -> {
-                 List<InOutWarehouseTask> inOutWarehouseTaskList1 = inOutWarehouseTaskService.selectList(new EntityWrapper<InOutWarehouseTask>()
-                         .eq("in_out_type_key","6")
-                         .eq("contract_no",inOutWarehouseTask.getMoveTaskNo()));
-            //累计退库量
-            String stockReturnCount = "";
+                List<InOutWarehouseTask> inOutWarehouseTaskList1 = inOutWarehouseTaskService.selectList(new EntityWrapper<InOutWarehouseTask>()
+                        .eq("in_out_type_key", "6")
+                        .eq("contract_no", inOutWarehouseTask.getMoveTaskNo()));
+                //累计退库量
+                String stockReturnCount = "";
                 for (InOutWarehouseTask inoutwarehouse : inOutWarehouseTaskList1) {
                 for (InOutWarehouseTask inoutwarehouse : inOutWarehouseTaskList1) {
                     if (StringUtils.isEmpty(stockReturnCount)) {
                     if (StringUtils.isEmpty(stockReturnCount)) {
                         stockReturnCount = "0";
                         stockReturnCount = "0";
@@ -341,15 +349,16 @@ public class InOutWarehouseTaskServiceImpl extends ServiceImpl<InOutWarehouseTas
             });
             });
         }
         }
         return inOutWarehouseTaskList;
         return inOutWarehouseTaskList;
-    }   
+    }
 
 
     /**
     /**
      * 出入库任务审核 编辑
      * 出入库任务审核 编辑
+     *
      * @param inOutWarehouseTask
      * @param inOutWarehouseTask
      * @return
      * @return
      */
      */
     @Override
     @Override
-    public String checkOrUpdateInOutTask(InOutWarehouseTask inOutWarehouseTask){
+    public String checkOrUpdateInOutTask(InOutWarehouseTask inOutWarehouseTask) {
         this.updateById(inOutWarehouseTask);
         this.updateById(inOutWarehouseTask);
         return inOutWarehouseTask.getId();
         return inOutWarehouseTask.getId();
     }
     }

+ 1229 - 0
winsea-haixin-plugin-yiliangyiyun/src/main/java/com/yh/saas/plugin/yiliangyiyun/service/impl/NewWorkflowServiceImpl.java

@@ -0,0 +1,1229 @@
+package com.yh.saas.plugin.yiliangyiyun.service.impl;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.alipay.sofa.runtime.api.annotation.SofaReference;
+import com.baomidou.mybatisplus.mapper.BaseMapper;
+import com.baomidou.mybatisplus.plugins.Page;
+import com.google.common.collect.Lists;
+import com.winsea.svc.base.base.entity.*;
+import com.winsea.svc.base.base.service.*;
+import com.winsea.svc.base.base.util.ObjectUtils;
+import com.winsea.svc.base.base.util.provider.BeanWorkFlowProvider;
+import com.winsea.svc.base.security.entity.User;
+import com.winsea.svc.base.security.util.AuthSecurityUtils;
+import com.winsea.svc.base.workflow.configservice.IWorkflowConfigService;
+import com.winsea.svc.base.workflow.entity.Workflow;
+import com.winsea.svc.base.workflow.entity.WorkflowListener;
+import com.winsea.svc.base.workflow.entity.WorkflowStep;
+import com.yh.saas.common.support.util.ContextWrapper;
+import com.yh.saas.common.support.util.IdGenerator;
+import com.yh.saas.common.support.util.StringUtils;
+import com.yh.saas.common.support.workflow.AbstractWorkflowTaskListener;
+import com.yh.saas.common.support.workflow.IWorkflowTaskChecklist;
+import com.yh.saas.plugin.yiliangyiyun.service.INewWorkflowService;
+import com.yh.saas.toolkit.workflow.activiti.ActivitiWorkflowBuilder;
+import com.yh.saas.toolkit.workflow.activiti.cmd.DeleteTaskCmd;
+import com.yh.saas.toolkit.workflow.activiti.util.ActivitiCountersignUtils;
+import com.yh.saas.toolkit.workflow.activiti.util.ActivitiHistoryUtils;
+import com.yh.saas.toolkit.workflow.activiti.util.ActivitiProcessUtils;
+import com.yh.saas.toolkit.workflow.activiti.util.ActivitiTaskUtils;
+import com.yh.saas.toolkit.workflow.config.WorkflowProperties;
+import com.yh.saas.toolkit.workflow.constants.ActivitiVariableNameConstants;
+import com.yh.saas.toolkit.workflow.exception.WorkflowErrorCodeEnums;
+import com.yh.saas.toolkit.workflow.exception.WorkflowException;
+import com.yh.saas.toolkit.workflow.service.IWorkflowHistoryService;
+import com.yh.saas.toolkit.workflow.service.IWorkflowListenerService;
+import com.yh.saas.toolkit.workflow.service.IWorkflowService;
+import com.yh.saas.toolkit.workflow.service.IWorkflowStepService;
+import lombok.extern.slf4j.Slf4j;
+import org.activiti.bpmn.model.FlowElement;
+import org.activiti.bpmn.model.Process;
+import org.activiti.bpmn.model.UserTask;
+import org.activiti.engine.*;
+import org.activiti.engine.history.HistoricProcessInstance;
+import org.activiti.engine.runtime.ProcessInstance;
+import org.activiti.engine.task.Task;
+import org.activiti.engine.task.TaskInfo;
+import org.activiti.engine.task.TaskQuery;
+import org.apache.commons.collections.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.InputStream;
+import java.io.Serializable;
+import java.lang.reflect.ParameterizedType;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+/**
+ * 工作流服务实现
+ *
+ * @author gdc
+ */
+@Transactional
+@Service
+@Slf4j
+public class NewWorkflowServiceImpl implements INewWorkflowService {
+
+    private static final String TASK_QUERY_TASK_ID = "taskId";
+
+    private static final String TASK_QUERY_TASK_NAME = "taskName";
+
+    private static final String TASK_QUERY_WORKFLOW_ID = "workflowId";
+
+    private static final String TASK_QUERY_BUSINESS_KEY = "businessKey";
+
+    private static final String WORKFLOW_ID_FIELD = "workflowId";
+
+    private static final String WORK_FLOW_ID_FIELD = "workFlowId";
+
+    public static final String SERVICE_NAME_SPAREPART = "sparepart";
+    public static final String SERVICE_NAME_MATERIEL = "materiel";
+    public static final String SERVICE_NAME_NAVIGATION = "navigation";
+    public static final String SERVICE_NAME_PURCHASE = "purchase";
+
+    private Map<String, BaseMapper<?>> entityClassBaseMapperMap = new ConcurrentHashMap<>();
+
+    @Autowired
+    private WorkflowProperties workflowProperties;
+
+    @Autowired
+    private RedisTemplate<String, String> redisTemplate;
+
+    @Autowired
+    private ProcessEngine processEngine;
+
+    @Autowired
+    private ManagementService managementService;
+
+    @Autowired
+    private RuntimeService runtimeService;
+
+    @Autowired
+    private TaskService taskService;
+
+    @Autowired
+    private IdentityService identityService;
+
+    @Autowired
+    private IWorkflowStepService workflowStepService;
+
+    @Autowired
+    private IWorkflowListenerService workflowListenerService;
+
+    @Autowired
+    private IWorkflowHistoryService workflowHistoryService;
+
+    @SofaReference
+    private IWorkflowConfigService workflowConfigService;
+
+    @SofaReference
+    private ICommonStaffService staffService;
+
+    @SofaReference
+    private ICommonCompanyService companyService;
+
+    @SofaReference
+    private ILanguageChangeService languageChangeService;
+
+    @SofaReference
+    private IAuditHistoryService auditHistoryService;
+
+    @SofaReference
+    private ICommonFlowBusinessTableService flowBusinessTableService;
+
+    @SofaReference
+    private ICommonStaffVesselService staffVesselService;
+
+    private ThreadLocal<String> localUserId = new ThreadLocal<>();
+
+    @Override
+    public String create(Workflow workflow) {
+        workflow.setId(generateFlowId()); // 工作流ID将作为Activiti流程定义ID,必须以字母或下划线开头
+        workflow.setLatest(1); // 最新版
+        insert(workflow);
+
+        // 创建步骤和全局监听器
+        createStepsAndListeners(workflow.getId(), workflow.getSteps(), workflow.getListeners());
+
+        // 将全局监听器绑定到所有步骤
+        workflow.getSteps().stream().forEach(step -> {
+            if (CollectionUtils.isEmpty(step.getListeners())) {
+                step.setListeners(workflow.getListeners());
+            } else {
+                step.getListeners().addAll(workflow.getListeners());
+            }
+        });
+
+        // 如果是租户创建的工作流则部署工作流
+        if (!StringUtils.isEmpty(workflow.getCompId())) {
+            // 设置租户ID
+            workflow.setTenantId(companyService.selectById(workflow.getCompId()).getTenantId());
+
+            buildActivitiWorkflow(workflow);
+        }
+        return workflow.getId();
+    }
+
+    @Override
+    public String changeInfo(Workflow workflow) {
+        Workflow originalWorkflow = this.selectById(workflow.getId());
+
+        // 模板修改
+        if (null == originalWorkflow.getCompId()) {
+            // 删除步骤和全局监听器
+            workflowStepService.removeByWorkflowId(workflow.getId());
+            workflowListenerService.removeByFlowId(workflow.getId());
+
+            // 创建步骤和全局监听器
+            createStepsAndListeners(workflow.getId(), workflow.getSteps(), workflow.getListeners());
+
+            updateById(workflow);
+            return workflow.getId();
+        }
+        // 工作流修改
+        else {
+            // 设置原始工作流为旧版
+            originalWorkflow.setLatest(0);
+            updateById(originalWorkflow);
+
+            // 创建新版工作流
+            return create(workflow);
+        }
+    }
+
+    @Override
+    public Workflow getWorkflowDetail(String workflowId) {
+        return workflowConfigService.getWorkflowDetail(workflowId);
+    }
+
+    @Override
+    public List<Workflow> getWorkflowDefinitions(String businessCode, String compId) {
+        return workflowConfigService.getWorkflowDefinitions(businessCode, compId);
+    }
+
+    @Override
+    public Workflow findLatestWorkflowByBusinessCode(String businessCode) {
+        return workflowConfigService.findLatestWorkflowByBusinessCode(businessCode, getCurrentCompId(), getCurrentUserRoles());
+    }
+
+    @Override
+    public Workflow getLatestWorkflowByBusinessCodeAndCompId(String businessCode, String compId) {
+        return workflowConfigService.getLatestWorkflowByBusinessCodeAndCompId(businessCode, compId);
+    }
+
+    @Override
+    public List<Workflow> findWorkflowsByBusinessCode(String businessCode) {
+        return workflowConfigService.findWorkflowsByBusinessCode(businessCode, getCurrentCompId(),
+                getCurrentUserRoles());
+    }
+
+    @Override
+    public List<String> findWorkflowIdsByBusinessCode(String businessCode) {
+        return findWorkflowsByBusinessCode(businessCode).stream().map(Workflow::getId).collect(Collectors.toList());
+    }
+
+    @Override
+    public InputStream getProcessDiagram(String workflowId) {
+        return ActivitiProcessUtils.getProcessDiagram(workflowId);
+    }
+
+    @Override
+    public void startInstance(String workflowId, String businessKey) {
+        startInstance(workflowId, businessKey, getCurrentUserId());
+    }
+
+    @Override
+    public void startInstance(String workflowId, String businessKey, String startUserId) {
+        // 设置发起人ID
+        identityService.setAuthenticatedUserId(startUserId);
+
+        // 开始流程
+        Map<String, Object> vars = new HashMap<>();
+        vars.put(ActivitiVariableNameConstants.START_USER_ID, startUserId);
+        vars.put(ActivitiVariableNameConstants.STEP_NUMBER, 1);
+        runtimeService.startProcessInstanceByKey(workflowId, businessKey, vars);
+
+        ProcessInstance processInstance = ActivitiProcessUtils.findInstanceByWorkflowIdAndBusinessKey(workflowId,
+                businessKey);
+
+        if (null == processInstance) {
+            notify(workflowId,
+                    taskListener -> taskListener.handleStatusChanged(businessKey, "已完成", "Completed", true));
+        } else {
+            // 跳过占位步骤
+            skipPlaceholder(processInstance.getProcessInstanceId());
+
+            // 设置审批状态
+            setApprovedOnStart(processInstance);
+
+            if ("1".equals(getWorkflowDetail(workflowId).getCreatorQuickAuditFlag())) {
+                // 跳过相邻步骤是同一人
+                skipAdjacentSameApprover(processInstance);
+            }
+        }
+    }
+
+    @Override
+    public String activateInstance(String workflowId, String businessKey) {
+        ProcessInstance instance = ActivitiProcessUtils.findInstanceByWorkflowIdAndBusinessKey(workflowId, businessKey);
+        String currentWorkflowId = reaunchAudit(instance.getId());
+        if (!workflowId.equals(currentWorkflowId)) {
+            return currentWorkflowId;
+        }
+
+        String processExecutionId = instance.getId();
+
+        // 首先激活流程实例,否则跳转不了
+        runtimeService.activateProcessInstanceById(instance.getId());
+
+        // 设置审核历史用变量
+        String startInfos = ActivitiProcessUtils.getProcessVariable(processExecutionId,
+                ActivitiVariableNameConstants.START_INFOS, String.class);
+        String staffId = null == getCurrentUserId() ? instance.getStartUserId() : getCurrentUserId();
+
+        String startInfo = getStartInfo(staffId, System.currentTimeMillis());
+        if (StringUtils.isEmpty(startInfos)) {
+            startInfos = getStartInfo(staffId, instance.getStartTime().getTime()) + "," + startInfo;
+        } else {
+            startInfos = startInfos + "," + startInfo;
+        }
+        ActivitiProcessUtils.setProcessVariable(processExecutionId, ActivitiVariableNameConstants.START_INFOS,
+                startInfos);
+
+        // 获取跳转用变量
+        String jumpPreTaskId = ActivitiProcessUtils.getProcessVariable(processExecutionId,
+                ActivitiVariableNameConstants.JUMP_PRE_TASK_ID, String.class);
+        String jumpToUserTaskId = ActivitiProcessUtils.getProcessVariable(processExecutionId,
+                ActivitiVariableNameConstants.JUMP_TO_USER_TASK_ID, String.class);
+
+        // 如果有跳转标识则进行流程跳转
+        if (null != jumpPreTaskId && null != jumpToUserTaskId) {
+            ActivitiTaskUtils.jump(jumpPreTaskId, jumpToUserTaskId);
+        }
+
+        // 清理跳转用变量
+        ActivitiProcessUtils.removeProcessVariable(processExecutionId, ActivitiVariableNameConstants.JUMP_PRE_TASK_ID);
+        ActivitiProcessUtils.removeProcessVariable(processExecutionId,
+                ActivitiVariableNameConstants.JUMP_TO_USER_TASK_ID);
+
+        // 设置当前步骤
+        ActivitiProcessUtils.setProcessVariable(processExecutionId, ActivitiVariableNameConstants.STEP_NUMBER, 1);
+
+        // 跳过占位步骤
+        skipPlaceholder(instance.getProcessInstanceId());
+
+        // 设置审批状态
+        setApprovedOnStart(instance);
+
+        return workflowId;
+    }
+
+    @Override
+    public void suspendInstance(String workflowId, String businessKey) {
+        ProcessInstance instance = ActivitiProcessUtils.findInstanceByWorkflowIdAndBusinessKey(workflowId, businessKey);
+        if (null != instance) {
+            runtimeService.suspendProcessInstanceById(instance.getProcessInstanceId());
+        }
+    }
+
+    @Override
+    public void stopInstance(String workflowId, String businessKey, String reason) {
+        ProcessInstance instance = ActivitiProcessUtils.findInstanceByWorkflowIdAndBusinessKey(workflowId, businessKey);
+        if (null != instance) {
+            notifyStatusChanged(workflowId, businessKey, reason);
+
+            deleteProcessInstanceWrapper(instance.getProcessInstanceId(), reason);
+        }
+    }
+
+    @Override
+    public void claim(String taskId) {
+        claim(taskId, getCurrentUserId());
+    }
+
+    @Override
+    public void claim(String taskId, String userId) {
+        try {
+            taskService.claim(taskId, userId);
+        } catch (ActivitiTaskAlreadyClaimedException ex) {
+            throw new WorkflowException(WorkflowErrorCodeEnums.TASK_REPEATED_CLAIMED);
+        }
+    }
+
+    @Override
+    public void handle(String taskId, boolean approved, String auditMind, boolean needReapply) {
+        // 先签收,保证审核历史有数据
+        claim(taskId);
+
+        Task task = ActivitiTaskUtils.getTaskById(taskId);
+        if (null != task) {
+            ProcessInstance instance = ActivitiProcessUtils.getInstanceById(task.getProcessInstanceId());
+            String processExecutionId = instance.getId();
+
+            // 设置任务自己的变量信息
+            ActivitiTaskUtils.setTaskVariableLocal(taskId, ActivitiVariableNameConstants.APPROVAL_FLAG, approved);
+            ActivitiTaskUtils.setTaskVariableLocal(taskId, ActivitiVariableNameConstants.AUDIT_MIND, auditMind);
+            ActivitiTaskUtils.setTaskVariableLocal(taskId, ActivitiVariableNameConstants.OPERATOR_USER_ID,
+                    getCurrentUserId());
+
+            // 设置流程id
+            ActivitiProcessUtils.setProcessVariable(processExecutionId,
+                    ActivitiVariableNameConstants.TASK_DEFINITION_KEY, task.getTaskDefinitionKey());
+
+            // 如果是会签则增加访问计数
+            if (ActivitiCountersignUtils.isCountersignTask(task)) {
+                ActivitiCountersignUtils.increaseLoopCounter(task.getId());
+            }
+
+            // 通过
+            if (approved) {
+                // 当前状态,如果节点没有走下去(会签),会用作状态恢复
+                String currentStatus = ActivitiProcessUtils.getProcessVariable(instance.getId(),
+                        ActivitiVariableNameConstants.APPROVAL_STATUS, String.class);
+
+                // 更新最后审批状态
+                ActivitiProcessUtils.setProcessVariable(processExecutionId, ActivitiVariableNameConstants.APPROVAL_FLAG,
+                        approved);
+
+                // 将状态先至诚“已完成”,解决流程结束状态改变不了问题
+                ActivitiProcessUtils.setProcessVariable(instance.getId(), ActivitiVariableNameConstants.APPROVAL_STATUS,
+                        "已完成");
+
+                // 设置流程
+                ActivitiProcessUtils.setProcessVariable(processExecutionId,
+                        ActivitiVariableNameConstants.TASK_DEFINITION_KEY, task.getTaskDefinitionKey());
+
+                taskService.complete(taskId, getConditionMap(instance.getProcessInstanceId()));
+
+                // 记录当前是哪个步骤
+                Task activeTask = ActivitiTaskUtils.getActiveTask(instance.getProcessInstanceId());
+                if (null != activeTask) {
+                    String definitionKey = ActivitiProcessUtils.getProcessVariable(processExecutionId,
+                            ActivitiVariableNameConstants.TASK_DEFINITION_KEY, String.class);
+                    if (!StringUtils.isEmpty(definitionKey)
+                            && !definitionKey.equals(activeTask.getTaskDefinitionKey())) {
+                        Integer stepNumber = ActivitiProcessUtils.getProcessVariable(processExecutionId,
+                                ActivitiVariableNameConstants.STEP_NUMBER, Integer.class);
+                        if (null != stepNumber) {
+                            ActivitiProcessUtils.setProcessVariable(processExecutionId,
+                                    ActivitiVariableNameConstants.STEP_NUMBER, ++stepNumber);
+                        }
+                    }
+                }
+
+                // 跳过占位步骤
+                skipPlaceholder(instance.getProcessInstanceId());
+
+                // 设置审批状态
+                setApprovedStatusOnApproved(instance, task, currentStatus);
+
+                if ("1".equals(getWorkflowDetail(instance.getProcessDefinitionKey()).getSkipAdjacentFlag())) {
+                    // 跳过相邻步骤是同一人
+                    skipAdjacentSameApprover(instance);
+                }
+
+            }
+            // 拒绝
+            else {
+                if (ActivitiCountersignUtils.isCountersignTask(task)
+                        && !ActivitiCountersignUtils.canCompleteCountersign(task)
+                        || !ActivitiCountersignUtils.isCountersignTask(task)) {
+
+                    // 更新最后审批状态
+                    // 必须先执行,否则流程挂起执行不了
+                    ActivitiProcessUtils.setProcessVariable(processExecutionId,
+                            ActivitiVariableNameConstants.APPROVAL_FLAG, approved);
+
+                    // 驳回
+                    reject(task, needReapply);
+
+                    // 发送申请被拒绝通知,申请被驳回
+                    notifyApplicationRejected(instance.getProcessDefinitionKey(), instance.getBusinessKey(), true,
+                            needReapply);
+                } else {
+                    // 发送申请被拒绝通知,申请还在进行中
+                    notifyApplicationRejected(instance.getProcessDefinitionKey(), instance.getBusinessKey(), false,
+                            needReapply);
+
+                    // 删除任务
+                    managementService.executeCommand(new DeleteTaskCmd(taskId));
+                }
+            }
+
+            String businessId = instance.getBusinessKey();
+            String taskName = task.getName();
+            String staffId = getCurrentUserId();
+            saveHistory(businessId, taskName, staffId, auditMind, approved);
+        }
+    }
+
+    @Override
+    public Page<Object> getTaskList(List<String> workflowIds, int current, int size) {
+        TaskQuery taskQuery = ActivitiTaskUtils.getTaskQueryByUserAndRoles(getCurrentUserId(), getCurrentUserRoles(),
+                workflowIds);
+        List<TaskInfo> tasks = taskQuery.listPage((current - 1) * size, size).stream().map(task -> (TaskInfo) task)
+                .collect(Collectors.toList());
+        return generateIPage(current, size, taskQuery.count(), getTaskDetailInfos(workflowIds.get(0), tasks));
+    }
+
+    @Override
+    public List<String> getTaskBusinessKeysByCode(String businessCode) {
+        List<String> workflowIds = findWorkflowIdsByBusinessCode(businessCode);
+        if (CollectionUtils.isEmpty(workflowIds)) {
+            return new ArrayList<>();
+        }
+        return getTaskBusinessKeys(workflowIds);
+    }
+
+    @Override
+    public List<String> getTaskBusinessKeysByFlowId(String workflowId) {
+        return getTaskBusinessKeys(Lists.newArrayList(workflowId));
+    }
+
+    @Override
+    public List<String> getDoneTaskBusinessKeysByCode(String businessCode) {
+        List<String> doneTaskBusinessKeys = workflowHistoryService
+                .getCheckerHisInstBusinessKeysByCode(getCurrentUserId(), businessCode);
+
+        // 删除待办任务
+        List<String> currentTaskBusinessKeys = getTaskBusinessKeysByCode(businessCode);
+        doneTaskBusinessKeys.removeAll(currentTaskBusinessKeys);
+
+        return doneTaskBusinessKeys;
+    }
+
+    @Override
+    public List<String> getDoneTaskBusinessKeysByFlowId(String workflowId) {
+        List<String> doneTaskBusinessKeys = workflowHistoryService
+                .getCheckerHisInstBusinessKeysByFlowId(getCurrentUserId(), workflowId);
+
+        // 删除待办任务
+        List<String> currentTaskBusinessKeys = getTaskBusinessKeysByFlowId(workflowId);
+        doneTaskBusinessKeys.removeAll(currentTaskBusinessKeys);
+
+        return doneTaskBusinessKeys;
+    }
+
+    @Override
+    public JSONObject getActiveTask(List<String> workflowIds, String businessKey) {
+        Task activeTask = ActivitiTaskUtils.getActiveTask(getCurrentUserId(), getCurrentUserRoles(), workflowIds,
+                businessKey);
+        JSONObject activeTaskJsonObj = new JSONObject();
+        if (activeTask != null) {
+            activeTaskJsonObj.put(TASK_QUERY_TASK_ID, activeTask.getId());
+            activeTaskJsonObj.put(TASK_QUERY_TASK_NAME, activeTask.getName());
+            activeTaskJsonObj.put(TASK_QUERY_WORKFLOW_ID, getTaskWorkflowId(activeTask));
+        }
+        return activeTaskJsonObj;
+    }
+
+    @Override
+    public JSONObject getActiveTask(String staffId, List<String> workflowIds, String businessKey) {
+        List<String> roleIds = AuthSecurityUtils.getUserRoles(staffId).stream().map(CommonRole::getRoleId).collect(Collectors.toList());
+        Task activeTask = ActivitiTaskUtils.getActiveTask(staffId, roleIds, workflowIds,
+                businessKey);
+        JSONObject activeTaskJsonObj = new JSONObject();
+        if (activeTask != null) {
+            activeTaskJsonObj.put(TASK_QUERY_TASK_ID, activeTask.getId());
+            activeTaskJsonObj.put(TASK_QUERY_TASK_NAME, activeTask.getName());
+            activeTaskJsonObj.put(TASK_QUERY_WORKFLOW_ID, getTaskWorkflowId(activeTask));
+        }
+        return activeTaskJsonObj;
+    }
+
+    @Override
+    public Workflow selectById(Serializable id) {
+        return workflowConfigService.selectById(id);
+    }
+
+    @Override
+    public Integer findWorkflowStepNumber(String workflowId, String businessKey) {
+        HistoricProcessInstance historicProcessInstance = ActivitiHistoryUtils.findHistoricProcessInstance(workflowId, businessKey);
+        Map<String, Object> map = historicProcessInstance.getProcessVariables();
+        if (null == map.get(ActivitiVariableNameConstants.STEP_NUMBER)) {
+            return 0;
+        }
+        return Integer.parseInt(map.get(ActivitiVariableNameConstants.STEP_NUMBER).toString());
+    }
+
+    @Override
+    public boolean judgeBusinessLastStep(String taskId) {
+        // 当前任务
+        Task currentTask = taskService.createTaskQuery().taskId(taskId).singleResult();
+        String sequenceFlowId = currentTask.getTaskDefinitionKey() + "-" + "endEvent";
+        // 获取流程定义
+        Process process = ActivitiProcessUtils.getMainProcess(currentTask.getProcessDefinitionId());
+        Map<String, FlowElement> map = process.getFlowElementMap();
+        return map.containsKey(sequenceFlowId);
+    }
+
+    @Override
+    public void removeLatestWorkflow(String workflowId) {
+        Workflow workflow = this.selectById(workflowId);
+        if (workflow == null) {
+            return;
+        }
+        workflow.setLatest(0);
+        this.updateById(workflow);
+    }
+
+
+    /**
+     * 审核被驳回
+     *
+     * @param task        task
+     * @param needReapply 是否需要重新申请
+     */
+    private void reject(Task task, boolean needReapply) {
+        ProcessInstance instance = ActivitiProcessUtils.getInstanceById(task.getProcessInstanceId());
+        String processExecutionId = instance.getId();
+        String firstUserTaskId = ActivitiTaskUtils.getFirstUserTask(task.getProcessDefinitionId()).getId();
+
+        // 清除会签变量,防止回退不能完整走会签节点
+        ActivitiCountersignUtils.clearCountersignVars(task);
+
+        // 删除未审批的任务
+        deleteUnapprovedTask(instance.getProcessInstanceId());
+
+        if (needReapply) {
+            // 设置用户重新申请要跳转的节点
+            ActivitiProcessUtils.setProcessVariable(processExecutionId, ActivitiVariableNameConstants.JUMP_PRE_TASK_ID,
+                    task.getId());
+            ActivitiProcessUtils.setProcessVariable(processExecutionId,
+                    ActivitiVariableNameConstants.JUMP_TO_USER_TASK_ID, firstUserTaskId);
+
+            // 设置审批状态
+            setApprovedStatusOnRejected(instance, task, needReapply);
+
+            // 挂起流程
+            runtimeService.suspendProcessInstanceById(instance.getProcessInstanceId());
+        } else {
+            ActivitiTaskUtils.jump(task.getId(), firstUserTaskId);
+
+            // 跳过占位步骤
+            skipPlaceholder(instance.getProcessInstanceId());
+
+            // 设置审批状态
+            setApprovedStatusOnRejected(instance, task, needReapply);
+        }
+    }
+
+    /**
+     * 重新发起审核流
+     *
+     * @param instanceId 流程实例ID
+     * @return 新流程ID
+     */
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    private String reaunchAudit(String instanceId) {
+        ProcessInstance instance = ActivitiProcessUtils.getInstanceById(instanceId);
+        String businessCode = selectById(instance.getProcessDefinitionKey()).getBusinessCode();
+
+        String staffId = null == getCurrentUserId() ? instance.getStartUserId() : getCurrentUserId();
+        CommonStaff staff = staffService.selectById(staffId);
+
+        Workflow workflow = getLatestWorkflowByBusinessCodeAndCompId(businessCode, staff.getCompId());
+
+        // 如果审核流被修改,则废弃旧的审核流并开启新的审核流
+        if (null != workflow && !workflow.getId().equals(instance.getProcessDefinitionKey())) {
+            deleteProcessInstanceWrapper(instance.getId(), "");
+            startInstance(workflow.getId(), instance.getBusinessKey(), instance.getStartUserId());
+
+            CommonFlowBusinessTable flowBusinessTable = flowBusinessTableService.selectById(businessCode);
+            if (null != flowBusinessTable) {
+                BaseMapper baseMapper = getEntityClassBaseMapperMap()
+                        .get(flowBusinessTable.getBusinessTableEntityClass());
+                if (null != baseMapper) {
+                    Object entity = baseMapper.selectById(instance.getBusinessKey());
+                    if (setEntityWorkflowId(entity, instance.getProcessDefinitionKey(), workflow.getId())) {
+                        baseMapper.updateById(entity);
+                    }
+                }
+            }
+            return workflow.getId();
+        }
+        return instance.getProcessDefinitionKey();
+    }
+
+    /**
+     * 获取实体中的流程ID
+     *
+     * @param entity 实体
+     * @return 流程ID
+     */
+    private String getEntityWorkflowId(Object entity) {
+        Object workflowId = null;
+
+        try {
+            workflowId = ObjectUtils.getFieldValue(entity, WORKFLOW_ID_FIELD);
+        } catch (Exception e) {
+            // ignore
+        }
+
+        if (null == workflowId) {
+            try {
+                workflowId = ObjectUtils.getFieldValue(entity, WORK_FLOW_ID_FIELD);
+            } catch (Exception e) {
+                // ignore
+            }
+        }
+        return null != workflowId ? workflowId.toString() : null;
+    }
+
+    /**
+     * 设置实体流程ID
+     *
+     * @param entity            实体
+     * @param originalWrkflowId 原流程ID
+     * @param currentWorkflowId 新流程ID
+     * @return 是否设置成功
+     */
+    private boolean setEntityWorkflowId(Object entity, String originalWrkflowId, String currentWorkflowId) {
+        if (null == entity) {
+            return false;
+        }
+
+        String originalWrkflowIds = getEntityWorkflowId(entity);
+        if (null == originalWrkflowIds || originalWrkflowIds.isEmpty()) {
+            return false;
+        }
+
+        String workflowIds = originalWrkflowIds.replace(originalWrkflowId, currentWorkflowId);
+
+        try {
+            ObjectUtils.setFieldValue(entity, WORKFLOW_ID_FIELD, workflowIds);
+        } catch (Exception e) {
+            // ignore
+        }
+
+        try {
+            ObjectUtils.setFieldValue(entity, WORK_FLOW_ID_FIELD, workflowIds);
+        } catch (Exception e) {
+            // ignore
+        }
+        return true;
+    }
+
+    /**
+     * 跳过占位步骤
+     *
+     * @param processInstanceId 流程实例ID
+     */
+    private void skipPlaceholder(String processInstanceId) {
+        Task task = ActivitiTaskUtils.getActiveTask(processInstanceId);
+        if (null != task && "_PLACEHOLDER_".equals(task.getName())) {
+            // 完成占位步骤
+            taskService.complete(task.getId(), getConditionMap(processInstanceId));
+
+            // 跳过占位步骤
+            skipPlaceholder(processInstanceId);
+        }
+    }
+
+    /**
+     * 删除未审批的任务
+     *
+     * @param processInstanceId 流程ID
+     */
+    private void deleteUnapprovedTask(String processInstanceId) {
+        ActivitiTaskUtils.getActiveTasks(processInstanceId).stream().filter(activeTask -> !activeTask.isSuspended())
+                .filter(activeTask -> null == ActivitiTaskUtils.getTaskVariableLocal(activeTask.getId(),
+                        ActivitiVariableNameConstants.APPROVAL_FLAG))
+                .forEach(activeTask -> managementService.executeCommand(new DeleteTaskCmd(activeTask.getId())));
+    }
+
+    /**
+     * 设置审批状态,流程启动场景
+     *
+     * @param instance 流程实例
+     */
+    private void setApprovedOnStart(ProcessInstance instance) {
+        Task nextTask = ActivitiTaskUtils.getActiveTask(instance.getProcessInstanceId());
+        String workflowId = instance.getProcessDefinitionKey();
+        String businessKey = instance.getBusinessKey();
+
+        String status = null;
+        if (null == nextTask) {
+            status = "已完成";
+        } else {
+            status = "待" + nextTask.getName();
+            ActivitiProcessUtils.setProcessVariable(instance.getId(), ActivitiVariableNameConstants.APPROVAL_STATUS,
+                    status);
+        }
+        notifyStatusChanged(workflowId, businessKey, status);
+    }
+
+    /**
+     * 设置审批状态,审核通过场景
+     *
+     * @param instance      流程实例
+     * @param preTask       上一步
+     * @param currentStatus 当前状态
+     */
+    private void setApprovedStatusOnApproved(ProcessInstance instance, Task preTask, String currentStatus) {
+        Task nextTask = ActivitiTaskUtils.getActiveTask(instance.getProcessInstanceId());
+        String workflowId = instance.getProcessDefinitionKey();
+        String businessKey = instance.getBusinessKey();
+
+        String status = null;
+        if (null != nextTask) {
+            if (!nextTask.getTaskDefinitionKey().equals(preTask.getTaskDefinitionKey())) {
+                status = "待" + nextTask.getName();
+            } else {
+                status = currentStatus;
+            }
+        } else {
+            notifyStatusChanged(workflowId, businessKey, "已完成");
+        }
+
+        if (null != status) {
+            ActivitiProcessUtils.setProcessVariable(instance.getId(), ActivitiVariableNameConstants.APPROVAL_STATUS,
+                    status);
+
+            notifyStatusChanged(workflowId, businessKey, status);
+        }
+    }
+
+    /**
+     * 结束流程
+     *
+     * @param processInstanceId 流程实例ID
+     * @param deleteReason      结束原因
+     */
+    private void deleteProcessInstanceWrapper(String processInstanceId, String deleteReason) {
+        try {
+            ContextWrapper.getApplicationContext().getBean(this.getClass()).deleteProcessInstance(processInstanceId,
+                    deleteReason);
+        } catch (ActivitiObjectNotFoundException ex) {
+            // 流程已结束
+        }
+    }
+
+    /**
+     * 结束流程
+     *
+     * @param processInstanceId 流程实例ID
+     * @param deleteReason      结束原因
+     */
+    @Transactional(propagation = Propagation.NESTED)
+    public void deleteProcessInstance(String processInstanceId, String deleteReason) {
+        runtimeService.deleteProcessInstance(processInstanceId, deleteReason);
+    }
+
+    /**
+     * 设置审批状态,审核不通过场景
+     *
+     * @param instance    流程实例
+     * @param preTask     上一步
+     * @param needReapply 是否需要重新申请
+     */
+    private void setApprovedStatusOnRejected(ProcessInstance instance, Task preTask, Boolean needReapply) {
+        Task nextTask = ActivitiTaskUtils.getActiveTask(instance.getProcessInstanceId());
+        String workflowId = instance.getProcessDefinitionKey();
+        String businessKey = instance.getBusinessKey();
+
+        String status = null;
+        if (needReapply) {
+            status = preTask.getName() + "失败";
+        } else {
+            status = "待" + nextTask.getName();
+        }
+
+        ActivitiProcessUtils.setProcessVariable(instance.getId(), ActivitiVariableNameConstants.APPROVAL_STATUS,
+                status);
+
+        notifyStatusChanged(workflowId, businessKey, status);
+    }
+
+    /**
+     * 通知状态变更
+     *
+     * @param workflowId  工作流ID
+     * @param businessKey 业务ID
+     * @param status      状态
+     */
+    private void notifyStatusChanged(String workflowId, String businessKey, String status) {
+        boolean processIsEnd = "已完成".equals(status);
+        String compId = null;
+        User user = AuthSecurityUtils.getCurrentUserInfo();
+        if (null != user) {
+            compId = user.getCompId();
+        } else {
+            ProcessInstance processInstance = ActivitiProcessUtils.findInstanceByWorkflowIdAndBusinessKey(workflowId,
+                    businessKey);
+            compId = staffService.selectById(processInstance.getStartUserId()).getCompId();
+        }
+
+        String statusEn = languageChangeService.findLanguageBySourceType(compId, LanguageChange.LanguageStataus.CHINESE,
+                processIsEnd ? status : status.substring(1), LanguageChange.LanguageStataus.ENGLISH);
+        notify(workflowId, taskListener -> taskListener.handleStatusChanged(businessKey, status,
+                !StringUtils.isEmpty(statusEn) ? "Waiting for the " + statusEn : null, processIsEnd));
+    }
+
+    /**
+     * 通知申请被拒绝
+     *
+     * @param workflowId          工作流ID
+     * @param businessKey         业务ID
+     * @param applicationRepulsed 申请被打回
+     * @param needReapply         是否需要重新填写
+     */
+    private void notifyApplicationRejected(String workflowId, String businessKey, boolean applicationRepulsed,
+                                           boolean needReapply) {
+        notify(workflowId, taskListener -> {
+            if (applicationRepulsed) {
+                taskListener.handleRejectApplicationRepulsed(workflowId, businessKey, needReapply);
+            } else {
+                taskListener.handleRejectApplicationProcessing(workflowId, businessKey);
+            }
+        });
+    }
+
+    /**
+     * 通知
+     *
+     * @param workflowId 工作流ID
+     * @param consumer   通知业务
+     */
+    private void notify(String workflowId, Consumer<AbstractWorkflowTaskListener> consumer) {
+        List<WorkflowListener> workflowListeners = workflowListenerService.findByFlowId(workflowId);
+
+        // 调用默认任务监听器
+        final String defaultTaskListenerId = "defaultWorkflowTaskListener";
+        WorkflowListener defaultWorkflowTaskListener = workflowListeners.stream()
+                .filter(workflowListener -> defaultTaskListenerId.equals(workflowListener.getListenerId())).findAny()
+                .orElse(null);
+        if (null == defaultWorkflowTaskListener) {
+            AbstractWorkflowTaskListener defaultTaskListener = ContextWrapper.getApplicationContext()
+                    .getBean(defaultTaskListenerId, AbstractWorkflowTaskListener.class);
+            consumer.accept(defaultTaskListener);
+        }
+
+        // 通知
+        workflowListeners.stream().forEach(workflowListener -> {
+            AbstractWorkflowTaskListener taskListener = ContextWrapper.getApplicationContext()
+                    .getBean(workflowListener.getListenerId(), AbstractWorkflowTaskListener.class);
+            consumer.accept(taskListener);
+        });
+    }
+
+    /**
+     * 获取流程分支条件
+     *
+     * @param processInstanceId 流程ID
+     * @return 分支条件
+     */
+    private Map<String, Object> getConditionMap(String processInstanceId) {
+        ProcessInstance processInstance = ActivitiProcessUtils.getInstanceById(processInstanceId);
+        Workflow workflow = selectById(processInstance.getProcessDefinitionKey());
+
+        Map<String, Object> conditionValueMap = null;
+        if (null != workflow) {
+            IWorkflowTaskChecklist<?> checklistImpl = getChecklistImpl(workflow.getChecklistId());
+            if (null != checklistImpl) {
+                conditionValueMap = checklistImpl.getCondtionValueMap(processInstance.getBusinessKey());
+            }
+        }
+        return null != conditionValueMap ? conditionValueMap : new HashMap<>();
+    }
+
+    /**
+     * 获取任务详情
+     *
+     * @param workflowId 工作流ID
+     * @param tasks      任务列表
+     * @return 任务详情列表
+     */
+    private JSONArray getTaskDetailInfos(String workflowId, List<TaskInfo> tasks) {
+        Workflow workflow = selectById(workflowId);
+        IWorkflowTaskChecklist<?> checklistImpl = getChecklistImpl(workflow.getChecklistId());
+        if (null == workflow.getChecklistId() || null == checklistImpl) {
+            JSONArray jsonArray = new JSONArray();
+            tasks.forEach(task -> jsonArray.add(getTaskJsonInfo(task)));
+            return jsonArray;
+        }
+
+        // 通过checklist服务获取具体record对象
+        List<?> results = checklistImpl.getRecords(tasks.stream()
+                .map(task -> ActivitiProcessUtils.getInstanceById(task.getProcessInstanceId()).getBusinessKey())
+                .collect(Collectors.toList()));
+
+        // 为checklist添加任务Id和任务名称
+        JSONArray jsonArray = JSONObject.parseArray(JSONObject.toJSONString(results));
+        for (int i = 0; i < jsonArray.size(); i++) {
+            JSONObject taskJsonObj = jsonArray.getJSONObject(i);
+            taskJsonObj.putAll(getTaskJsonInfo(tasks.get(i)));
+
+            // 设置审核状态
+            String approvalStatus = ActivitiProcessUtils.getProcessVariable(tasks.get(i).getProcessInstanceId(),
+                    ActivitiVariableNameConstants.APPROVAL_STATUS, String.class);
+            taskJsonObj.put(ActivitiVariableNameConstants.APPROVAL_STATUS, approvalStatus);
+        }
+        return jsonArray;
+    }
+
+    /**
+     * 获取任务JSON信息
+     *
+     * @param task 任务信息
+     * @return 任务JSON信息
+     */
+    private JSONObject getTaskJsonInfo(TaskInfo task) {
+        JSONObject taskJsonObj = new JSONObject();
+        taskJsonObj.put(TASK_QUERY_TASK_ID, task.getId());
+        taskJsonObj.put(TASK_QUERY_TASK_NAME, task.getName());
+        taskJsonObj.put(TASK_QUERY_WORKFLOW_ID, getTaskWorkflowId(task));
+        taskJsonObj.put(TASK_QUERY_BUSINESS_KEY,
+                ActivitiProcessUtils.getInstanceById(task.getProcessInstanceId()).getBusinessKey());
+        return taskJsonObj;
+    }
+
+    /**
+     * 获取checklist实现类
+     *
+     * @param checklistId checklist id
+     * @return checklist实现类
+     */
+    private IWorkflowTaskChecklist<?> getChecklistImpl(String checklistId) {
+        if (StringUtils.isEmpty(checklistId)) {
+            return null;
+        }
+
+        return (IWorkflowTaskChecklist<?>) ContextWrapper.getApplicationContext().getBean(checklistId);
+    }
+
+    /**
+     * 生成工作流ID
+     *
+     * @return 工作流ID
+     */
+    private String generateFlowId() {
+        return "_" + IdGenerator.generateLongIncrId(); // 工作流ID规则与Activiti流程ID命名规则保持一致
+    }
+
+    /**
+     * 获取当前用户角色列表
+     *
+     * @return 角色列表
+     */
+    private List<String> getCurrentUserRoles() {
+        return getUserRoles(getCurrentUserId());
+    }
+
+    /**
+     * 获取用户角色列表
+     *
+     * @param userId 用户ID
+     * @return 角色列表
+     */
+    private List<String> getUserRoles(String userId) {
+        return AuthSecurityUtils.getUserRoles(userId).stream().map(role -> role.getRoleId())
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * 获取当前用户ID
+     *
+     * @return 当前用户ID
+     */
+    private String getCurrentUserId() {
+        if (!StringUtils.isEmpty(localUserId.get())) {
+            return localUserId.get();
+        }
+        return null == AuthSecurityUtils.getCurrentUserInfo() ? null
+                : AuthSecurityUtils.getCurrentUserInfo().getUserId();
+    }
+
+    /**
+     * 获取当前用户所属公司ID
+     *
+     * @return 当前用户所属公司ID
+     */
+    private String getCurrentCompId() {
+        return AuthSecurityUtils.getCurrentUserInfo().getCompId();
+    }
+
+    /**
+     * 生成page对象
+     *
+     * @param current 页码
+     * @param size    分页大小
+     * @param total   总数
+     * @param records 数据
+     * @return page
+     */
+    private Page<Object> generateIPage(int current, int size, long total, List<Object> records) {
+        Page<Object> page = new Page<>(current, size);
+        page.setTotal(total);
+        page.setRecords(records);
+        return page;
+    }
+
+    /**
+     * 创建工作流步骤和全局监听
+     *
+     * @param workflowId 工作流ID
+     * @param steps      工作流步骤
+     * @param listeners  工作流全局监听器
+     */
+    private void createStepsAndListeners(String workflowId, List<WorkflowStep> steps,
+                                         List<WorkflowListener> listeners) {
+        // 创建工作流步骤
+        if (!CollectionUtils.isEmpty(steps)) {
+            steps.stream().forEach(step -> step.setWorkflowId(workflowId));
+            workflowStepService.createBatch(steps);
+        }
+
+        // 创建工作流全局监听器
+        if (!CollectionUtils.isEmpty(listeners)) {
+            listeners.stream().forEach(listener -> listener.setWorkflowId(workflowId));
+            workflowListenerService.createBatch(listeners);
+        }
+    }
+
+    /**
+     * 获取任务工作流ID
+     *
+     * @param task 任务
+     * @return 任务所属工作流ID
+     */
+    private String getTaskWorkflowId(TaskInfo task) {
+        return null != task ? task.getProcessDefinitionId().substring(0, task.getProcessDefinitionId().indexOf(':'))
+                : null;
+    }
+
+    /**
+     * 获取工作流任务业务编码
+     *
+     * @param workflowIds 工作流ID列表
+     * @return 工作流任务业务编码列表
+     */
+    private List<String> getTaskBusinessKeys(List<String> workflowIds) {
+        return ActivitiTaskUtils.getTaskQueryByUserAndRoles(getCurrentUserId(), getCurrentUserRoles(), workflowIds)
+                .list().stream()
+                .map(task -> ActivitiProcessUtils.getInstanceById(task.getProcessInstanceId()).getBusinessKey())
+                .collect(Collectors.toList());
+    }
+
+    private void saveHistory(String businessId, String taskName, String staffId, String auditMind, boolean approved) {
+        AuditHistory auditHistory = new AuditHistory();
+        auditHistory.setBusinessId(businessId);
+        auditHistory.setStaffId(staffId);
+        auditHistory.setTaskName(taskName);
+        auditHistory.setAuditOpinion(auditMind);
+        auditHistory.setAdoptFlag(approved ? "1" : "0");
+        auditHistoryService.create(auditHistory);
+    }
+
+    /**
+     * 跳过相邻审核人
+     */
+    private void skipAdjacentSameApprover(ProcessInstance instance) {
+        if (null == getCurrentUserId()) {
+            return;
+        }
+        // 获取服务code
+        String businessCode = selectById(instance.getProcessDefinitionKey()).getBusinessCode();
+
+        String vesselId = null;
+        Map<String, BeanWorkFlowProvider> beanMap = ContextWrapper.getApplicationContext()
+                .getBeansOfType(BeanWorkFlowProvider.class);
+        if (null != beanMap) {
+            BeanWorkFlowProvider service = beanMap
+                    .get(StringUtils.underlineToCamel(businessCode.toLowerCase().replace("-", "_")));
+            if (null != service) {
+                vesselId = service.getVesselId(instance.getBusinessKey());
+            }
+        }
+        Task task = ActivitiTaskUtils.getActiveTask(getCurrentUserId(), getCurrentUserRoles(),
+                Lists.newArrayList(instance.getProcessDefinitionKey()), instance.getBusinessKey());
+        // 如果业务关联要求过滤船舶
+        if (!StringUtils.isEmpty(vesselId)) {
+            // 1.先获取船舶关联人员
+            List<String> staffIds = staffVesselService.findStaffIdsWithVesselAndRoles(vesselId, getCurrentUserRoles());
+            if (!staffIds.contains(getCurrentUserId())) {
+                return;
+            } else {
+                // 2.查看是否是会签
+                if (task != null && ActivitiCountersignUtils.isCountersignTask(task)) {
+                    UserTask userTask = ActivitiTaskUtils.getFirstUserTask(task.getProcessDefinitionId());
+                    if (null != userTask) {
+                        if (ActivitiCountersignUtils.isCountersignatureTask(userTask)) {
+                            handle(task.getId(), true, "_PLACEHOLDER_", false);
+                            return;
+                        } else {
+                            handle(task.getId(), false, "_PLACEHOLDER_", false);
+                            return;
+                        }
+                    }
+                }
+            }
+        }
+        if (null != task) {
+            handle(task.getId(), true, "_PLACEHOLDER_", false);
+        }
+    }
+
+    /**
+     * 创建工作流<br>
+     * 自动判断创建远程的还是本地的
+     */
+    private void buildActivitiWorkflow(Workflow workflow) {
+        String businessCode = workflow.getBusinessCode();
+        String moduleName = businessCode.substring(0, businessCode.indexOf('-')).toLowerCase();
+        String serviceName = moduleName;
+        if (null != workflowProperties.getConsumerModules()) {
+            Entry<String, List<String>> targetEntry = workflowProperties.getConsumerModules().entrySet().stream()
+                    .filter(entry -> entry.getValue().contains(moduleName)).findAny().orElse(null);
+            if (null != targetEntry) {
+                serviceName = targetEntry.getKey();
+            }
+        }
+
+        if ((null != workflowProperties.getConsumers() && workflowProperties.getConsumers().contains(serviceName))) {
+            redisTemplate.opsForList().leftPush("/topic/" + serviceName + "/workflow/build",
+                    JSONObject.toJSONString(workflow));
+        } else {
+            new ActivitiWorkflowBuilder(workflow).addFlowElement().addFlowLine().build(processEngine);
+        }
+    }
+
+
+    private boolean insert(Workflow entity) {
+        return workflowConfigService.insert(entity);
+    }
+
+    private boolean updateById(Workflow entity) {
+        return workflowConfigService.updateById(entity);
+    }
+
+    private String getStartInfo(String startUserId, Object startTime) {
+        return (null != startUserId ? startUserId : "") + "|" + (null != startTime ? String.valueOf(startTime) : "");
+    }
+
+    private Map<String, BaseMapper<?>> getEntityClassBaseMapperMap() {
+        if (entityClassBaseMapperMap.isEmpty()) {
+            ContextWrapper.getApplicationContext().getBeansOfType(BaseMapper.class).values().forEach(baseMapper -> {
+                try {
+                    Class<?> entityClass = (Class<?>) ((ParameterizedType) (((Class<?>) baseMapper.getClass()
+                            .getGenericInterfaces()[0]).getGenericInterfaces()[0])).getActualTypeArguments()[0];
+                    entityClassBaseMapperMap.put(entityClass.getName(), baseMapper);
+                } catch (ClassCastException ex) {
+                    // ignore
+                }
+            });
+        }
+        return entityClassBaseMapperMap;
+    }
+}

+ 1 - 0
winsea-haixin-plugin-yiliangyiyun/src/main/resources/mapper/InOutWarehouseTaskMapper.xml

@@ -47,6 +47,7 @@
         relevance_id as relevanceId,
         relevance_id as relevanceId,
         task_type_key as taskTypeKey,
         task_type_key as taskTypeKey,
         task_status_key as taskStatusKey,
         task_status_key as taskStatusKey,
+        workflow_id as workflowId,
         in_out_flag as inOutFlag
         in_out_flag as inOutFlag
         FROM in_out_warehouse_task
         FROM in_out_warehouse_task
         WHERE
         WHERE