From ab17b1339f4d9917cd40bb0bbdbc8cb949bf9a80 Mon Sep 17 00:00:00 2001 From: yxt_djz Date: Thu, 9 Feb 2023 11:46:38 +0800 Subject: [PATCH] =?UTF-8?q?flowable=E5=90=8E=E7=AB=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yxt/anrui/flowable/CodeMsgEnum.java | 44 + .../anrui/flowable/FlowableApplication.java | 27 + .../flowable/biz/flow/FlowableMapper.java | 18 + .../flowable/biz/flow/FlowableMapper.xml | 63 + .../anrui/flowable/biz/flow/FlowableRest.java | 447 ++++ .../flowable/biz/flow/FlowableService.java | 276 +++ .../flowdefinition/FlowDefinitionRest.java | 143 ++ .../flowdefinition/FlowDefinitionService.java | 273 +++ .../biz/flowinstance/FlowInstanceRest.java | 71 + .../biz/flowinstance/FlowInstanceService.java | 106 + .../biz/flowtask/FlowTaskController.java | 331 +++ .../flowable/biz/flowtask/FlowTaskMapper.java | 46 + .../flowable/biz/flowtask/FlowTaskMapper.xml | 236 ++ .../biz/flowtask/FlowTaskService.java | 2079 +++++++++++++++++ .../flowable/biz/process/ExpressionCmd.java | 47 + .../flowable/biz/process/ProcessService.java | 162 ++ .../processcomment/ProcessCommentMapper.java | 72 + .../processcomment/ProcessCommentMapper.xml | 20 + .../processcomment/ProcessCommentRest.java | 105 + .../processcomment/ProcessCommentService.java | 135 ++ .../biz/service/impl/FlowTaskServiceImpl.java | 364 +++ .../sysdeployform/SysDeployFormMapper.java | 74 + .../biz/sysdeployform/SysDeployFormMapper.xml | 66 + .../sysdeployform/SysDeployFormService.java | 94 + .../biz/sysform/SysFormController.java | 108 + .../flowable/biz/sysform/SysFormMapper.java | 77 + .../flowable/biz/sysform/SysFormMapper.xml | 34 + .../flowable/biz/sysform/SysFormService.java | 130 ++ .../biz/sysformlink/SysFormLinkMapper.java | 37 + .../biz/sysformlink/SysFormLinkMapper.xml | 16 + .../biz/sysformlink/SysFormLinkRest.java | 59 + .../biz/sysformlink/SysFormLinkService.java | 80 + .../biz/sysprourl/SysProUrlController.java | 128 + .../biz/sysprourl/SysProUrlMapper.java | 93 + .../biz/sysprourl/SysProUrlMapper.xml | 135 ++ .../biz/sysprourl/SysProUrlService.java | 206 ++ .../biz/systaskform/SysTaskFormMapper.java | 65 + .../biz/systaskform/SysTaskFormMapper.xml | 61 + .../anrui/flowable/common/EnumResultBean.java | 62 + .../flowable/common/ProcessConstants.java | 73 + .../DefaultProcessDiagramCanvasExt.java | 342 +++ .../DefaultProcessDiagramGeneratorExt.java | 397 ++++ .../config/DiRemoteAccountResource.java | 47 + .../anrui/flowable/config/FlowableConfig.java | 22 + .../flowable/config/P6spySqlFormatConfig.java | 25 + .../flowable/config/ProcessEngineConfig.java | 212 ++ .../anrui/flowable/config/Swagger2Config.java | 36 + .../flowable/factory/FlowServiceFactory.java | 41 + .../BaseVehicleExecutionListener.java | 23 + .../listener/ManagerEndExecutionListener.java | 21 + .../listener/ManagerTaskListener.java | 101 + .../controller/HolidayTestController.java | 53 + .../test/controller/TestController.java | 41 + .../test/service/IHolidayTestService.java | 39 + .../test/service/impl/HolidayTestService.java | 149 ++ .../anrui/flowable/utils/FlowableUtils.java | 620 +++++ 56 files changed, 8832 insertions(+) create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/CodeMsgEnum.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/FlowableApplication.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow/FlowableMapper.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow/FlowableMapper.xml create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow/FlowableRest.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow/FlowableService.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowdefinition/FlowDefinitionRest.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowdefinition/FlowDefinitionService.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowinstance/FlowInstanceRest.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowinstance/FlowInstanceService.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowtask/FlowTaskController.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowtask/FlowTaskMapper.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowtask/FlowTaskMapper.xml create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowtask/FlowTaskService.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/process/ExpressionCmd.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/process/ProcessService.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentMapper.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentMapper.xml create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentRest.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentService.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/service/impl/FlowTaskServiceImpl.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysdeployform/SysDeployFormMapper.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysdeployform/SysDeployFormMapper.xml create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysdeployform/SysDeployFormService.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysform/SysFormController.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysform/SysFormMapper.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysform/SysFormMapper.xml create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysform/SysFormService.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysformlink/SysFormLinkMapper.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysformlink/SysFormLinkMapper.xml create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysformlink/SysFormLinkRest.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysformlink/SysFormLinkService.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysprourl/SysProUrlController.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysprourl/SysProUrlMapper.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysprourl/SysProUrlMapper.xml create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysprourl/SysProUrlService.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/systaskform/SysTaskFormMapper.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/systaskform/SysTaskFormMapper.xml create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/common/EnumResultBean.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/common/ProcessConstants.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/DefaultProcessDiagramCanvasExt.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/DefaultProcessDiagramGeneratorExt.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/DiRemoteAccountResource.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/FlowableConfig.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/P6spySqlFormatConfig.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/ProcessEngineConfig.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/Swagger2Config.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/factory/FlowServiceFactory.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/listener/BaseVehicleExecutionListener.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/listener/ManagerEndExecutionListener.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/listener/ManagerTaskListener.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/test/controller/HolidayTestController.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/test/controller/TestController.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/test/service/IHolidayTestService.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/test/service/impl/HolidayTestService.java create mode 100644 yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/utils/FlowableUtils.java diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/CodeMsgEnum.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/CodeMsgEnum.java new file mode 100644 index 00000000..4d88e137 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/CodeMsgEnum.java @@ -0,0 +1,44 @@ +package com.yxt.anrui.flowable; + +import com.yxt.common.core.result.IResultCodeMsg; + +/** + * 统一返回信息的code和msg,需要更新并安装yxt-common-core项目 + */ +public enum CodeMsgEnum implements IResultCodeMsg { + + /** + * 返回正常 + */ + HTML200("200", "返回正常"), + /** + * 页面不存在 + */ + HTML404("404", "页面不存在"), + /** + * 服务器错误 + */ + HTML500("500", "服务器错误"), + /** + * 用户名不存在 + */ + AF_U_5001("af_u_5001", "用户名不存在"); + + private String code; + private String msg; + + private CodeMsgEnum(String code, String msg) { + this.code = code; + this.msg = msg; + } + + @Override + public String getMsg() { + return msg; + } + + @Override + public String getCode() { + return code; + } +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/FlowableApplication.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/FlowableApplication.java new file mode 100644 index 00000000..50c704cc --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/FlowableApplication.java @@ -0,0 +1,27 @@ +package com.yxt.anrui.flowable; + + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.openfeign.EnableFeignClients; + +/** + * @author dimengzhe + */ +@SpringBootApplication(exclude = { + org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class, + //如果自定义了安全配置,请检查是否需要排除下面ManagementWebSecurityAutoConfiguration配置 + //org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration.class +}, scanBasePackages = { + "com.yxt.common.base.config", + "org.flowable.ui.modeler", "org.flowable.ui.common","com.yxt.anrui.flowable.*" +}) +@EnableDiscoveryClient +@EnableFeignClients(basePackages = {"com.yxt.anrui.*","com.yxt.supervise.*"}) +public class FlowableApplication { + + public static void main(String[] args) { + SpringApplication.run(FlowableApplication.class, args); + } +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow/FlowableMapper.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow/FlowableMapper.java new file mode 100644 index 00000000..b5955863 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow/FlowableMapper.java @@ -0,0 +1,18 @@ +package com.yxt.anrui.flowable.biz.flow; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yxt.anrui.flowable.api.flow.FlowProcinst; +import com.yxt.anrui.flowable.api.flow.Flowable; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.Map; + +@Mapper +public interface FlowableMapper extends BaseMapper { + void insetFlowableTask(Map params); + FlowProcinst getFlowProcinstById(@Param("id") String id); + @Select("select * from act_hi_procinst where proc_inst_id_=#{id}") + Map getProcessInstanceById(@Param("id") String procInsId); +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow/FlowableMapper.xml b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow/FlowableMapper.xml new file mode 100644 index 00000000..ed11d894 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow/FlowableMapper.xml @@ -0,0 +1,63 @@ + + + + + insert into `act_ru_task` ( `days`, `zd`,initiator,outcome) + VALUES + ( + #{days,jdbcType=VARCHAR}, + #{zd,jdbcType=VARCHAR} + #{initiator,jdbcType=VARCHAR} + #{outcome,jdbcType=VARCHAR} + ) + + + + + \ No newline at end of file diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow/FlowableRest.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow/FlowableRest.java new file mode 100644 index 00000000..7d6a7c5c --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow/FlowableRest.java @@ -0,0 +1,447 @@ +/********************************************************* + ********************************************************* + ******************** ******************* + ************* ************ + ******* _oo0oo_ ******* + *** o8888888o *** + * 88" . "88 * + * (| -_- |) * + * 0\ = /0 * + * ___/`---'\___ * + * .' \\| |// '. * + * / \\||| : |||// \ * + * / _||||| -:- |||||- \ * + * | | \\\ - /// | | * + * | \_| ''\---/'' |_/ | * + * \ .-\__ '-' ___/-. / * + * ___'. .' /--.--\ `. .'___ * + * ."" '< `.___\_<|>_/___.' >' "". * + * | | : `- \`.;`\ _ /`;.`/ - ` : | | * + * \ \ `_. \_ __\ /__ _/ .-` / / * + * =====`-.____`.___ \_____/___.-`___.-'===== * + * `=---=' * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * + *********__佛祖保佑__永无BUG__验收通过__钞票多多__********* + *********************************************************/ +package com.yxt.anrui.flowable.biz.flow; + + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.yxt.anrui.flowable.api.flow.*; +import com.yxt.anrui.flowable.api.flowcomment.FlowComment; +import com.yxt.anrui.flowable.api.flowtask.LatestTaskVo; +import com.yxt.anrui.flowable.biz.flowtask.FlowTaskService; +import com.yxt.anrui.flowable.biz.process.ProcessService; +import com.yxt.anrui.flowable.sqloperationsymbol.BusinessVariables; +import com.yxt.common.base.utils.StringUtils; +import com.yxt.common.core.query.PagerQuery; +import com.yxt.common.core.result.ResultBean; +import com.yxt.supervise.system.sysuser.SysUserFeign; +import com.yxt.supervise.system.sysuser.SysUserVo; +import com.yxt.supervise.system.sysuser.UserQuery; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiParam; +import org.flowable.bpmn.model.FlowElement; +import org.flowable.bpmn.model.UserTask; +import org.flowable.engine.TaskService; +import org.flowable.task.api.DelegationState; +import org.flowable.task.api.Task; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.*; + +/** + * Project: anrui-parent
+ * File: FlowableRest.java
+ * Class: com.yxt.anrui.portal.biz.flow.FlowableRest
+ * Description: <描述类的功能>.
+ * Copyright: Copyright (c) 2011
+ * Company: https://gitee.com/liuzp315
+ * Makedate: 2021/10/23 上午11:13
+ * + * @author popo + * @version 1.0 + * @since 1.0 + */ +@RestController +@RequestMapping("v1/flow") +@Api(tags = "业务系统中业务和工作流相关操作") +public class FlowableRest implements FlowableFeign { + + @Autowired + private FlowableService flowableService; + @Autowired + private FlowTaskService flowtaskService; + @Autowired + private SysUserFeign sysUserFeign; + @Resource + protected TaskService taskService; + @Resource + private ProcessService processService; + @Override + public ResultBean businessStart(BusinessVariables bv) { + return flowableService.businessStart( bv); + } + + @Override + public ResultBean processPagerList(@ApiParam(value = "当前页码", required = true) @RequestParam("pageNum") Integer pageNum, + @ApiParam(value = "每页条数", required = true) @RequestParam("pageSize") Integer pageSize) { + return flowableService.processPagerList(pageNum, pageSize); + } + + @Override + public ResultBean myprocess(@ApiParam(value = "用户sid") @PathVariable(value = "userSid") String userSid, + @ApiParam(value = "变量集合,json对象") @RequestBody PagerQuery taskQueryPagerQuery) { + return flowableService.myprocess(userSid, taskQueryPagerQuery); + } + + @Override + public ResultBean stopProcess(FlowTaskVo flowTaskVo) { + flowableService.stopProcess(flowTaskVo); + return ResultBean.fireSuccess(); + } + + @Override + public ResultBean deleteProcess(String procInsId) { + flowableService.deleteProcess(procInsId); + return ResultBean.fireSuccess(); + } + + @Override + public ResultBean getNextNodeUserSidsOfCreate(BusinessVariables bv) { + //根据业务参数取流程流转的环节 信息 + return flowtaskService.getNextNodeUserSidsOfCreate(bv) ; + } + + @Override + public ResultBean getNextNodeUserSidsOfSubmit(BusinessVariables bv) { + ResultBean rb = ResultBean.fireSuccess(); + String orgSidPath=bv.getOrgSidPath(); + String taskDefKey=bv.getTaskDefKey(); + //根据业务参数取流程流转的环节 信息 + List> list = (List>) + flowtaskService.getProcessCirculationNodesByMap(bv).getData(); + Map task_map=new HashMap<>(); + //取第二个环节的配置角色 + boolean endTask=true; + for (int i=0;i< list.size();i++){ + String id=list.get(i).get("id").toString(); + if(id.equals(taskDefKey)&&i+1 startProcess(BusinessVariables dto) { + log.info("startProcess.dto:{}",dto); + ResultBean rb = ResultBean.fireFail(); + + if (StringUtils.isBlank(dto.getBusinessSid())) { + return rb.setMsg("businessSid 不能为空!"); + } + + if(dto.getFormVariables()==null) + dto.setFormVariables(new HashMap()); + Map formVariables = dto.getFormVariables(); + if(StringUtils.isNotBlank(dto.getOrgSidPath())){ + String orgPath=dto.getOrgSidPath(); + formVariables.put("createrOrgPath",orgPath);//发起人的组织结构sid + //dto.setFormVariables(formVariables); + } + + dto.getFormVariables().put("businessSid",dto.getBusinessSid()); + String nextNodeUserSids_ = dto.getNextNodeUserSids(); + if(StringUtils.isBlank(nextNodeUserSids_)){ + ResultBean nextNodeUserSidsOfCreate = getNextNodeUserSidsOfCreate(dto); + boolean success = nextNodeUserSidsOfCreate.getSuccess(); + if(!success){ + return rb.setMsg(nextNodeUserSidsOfCreate.getMsg()); + } + nextNodeUserSids_=nextNodeUserSidsOfCreate.getData().getUserSid(); + dto.getFormVariables().put(BusinessVariables.ORGPATH,nextNodeUserSidsOfCreate.getData().getOrgPath()); + } + dto.setNextNodeUserSids(nextNodeUserSids_); + ResultBean resultBean1 = flowableService.businessStart(dto); + UpdateFlowFieldVo vo = new UpdateFlowFieldVo(); + if (resultBean1.getSuccess() && resultBean1.getData() != null) { + vo.setSid("" + dto.getBusinessSid()); + Map map = (Map) resultBean1.getData(); + vo.setProcDefId(dto.getModelId()); + vo.setNodeState(map.get("nodeState")); + vo.setProcInsId(map.get("procInsId")); + vo.setTaskDefKey(map.get("taskDefKey")); + vo.setTaskId(map.get("taskId")); + vo.setNextNodeUserSids(nextNodeUserSids_); + } + return rb.success().setData(vo); + } + + Logger log= LoggerFactory.getLogger(FlowableRest.class); + @Override + public ResultBean handleProsess(BusinessVariables dto) { + return handleProsess(dto,true); + } + + /** + * + * @param dto + * @param b 是否连续跳转环节 + * @return + */ + public ResultBean handleProsess(BusinessVariables dto,boolean b) { + log.info("BusinessVariables:{}", JSONObject.toJSONString(dto)); + log.info("b:{}", b); + UpdateFlowFieldVo vo = new UpdateFlowFieldVo(); + ResultBean rb = ResultBean.fireFail(); + // Map formVariables = dto.getFormVariables(); + + String taskId = dto.getTaskId(); + if (StringUtils.isBlank(taskId)) { + return rb.setMsg("taskId 不能为空!"); + } + if (StringUtils.isBlank(dto.getBusinessSid())) { + return rb.setMsg("businessSid 不能为空!"); + } + /*if(formVariables==null){ + return rb.setMsg("业务参数集合 不能为空!"); + }*/ + if(dto.getFormVariables()==null) + dto.setFormVariables(new HashMap()); + Map formVariables = dto.getFormVariables(); + formVariables.put("businessSid",dto.getBusinessSid()); + + String nextUserSid = dto.getNextNodeUserSids(); + if(StringUtils.isBlank(nextUserSid)){ + ResultBean nextNodeUserSidsOfSubmit = getNextNodeUserSidsOfSubmit(dto); + if (!nextNodeUserSidsOfSubmit.getSuccess()) { + return rb.setMsg("nextUserSid 不能为空!"); + } + nextUserSid=nextNodeUserSidsOfSubmit.getData().getUserSid(); + formVariables.put(BusinessVariables.ORGPATH,nextNodeUserSidsOfSubmit.getData().getOrgPath()); + } + String comment = dto.getComment(); + if (StringUtils.isBlank(comment)) { + comment=""; + //return rb.setMsg("comment 不能为空!"); + } + String instanceId = dto.getInstanceId(); + if (StringUtils.isBlank(instanceId)) { + return rb.setMsg("instanceId 不能为空!"); + } + String userSid = dto.getUserSid(); + if (StringUtils.isBlank(userSid)) { + return rb.setMsg("userSid 不能为空!"); + + } + String businessSid =dto.getBusinessSid(); + if (StringUtils.isBlank(businessSid)) { + return rb.setMsg("业务sid 不能为空!"); + } + Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); + if (Objects.isNull(task)) { + return rb.setMsg("任务不存在"); + } + String assignee = task.getAssignee(); + if(b&&(StringUtils.isNotBlank(assignee)&& assignee.indexOf(userSid)<0)){ + return rb.setMsg("当前用户不是环节的待办人,不能进行办理操作!"); + } + String nodeState = ""; + String taskDefKey = ""; + vo.setSid(businessSid); + + if (DelegationState.PENDING.equals(task.getDelegationState())) { + taskService.addComment(taskId, instanceId, + FlowComment.DELEGATE.getType(), comment); + // Map values =(Map) formVariables.get("values"); + taskService.resolveTask(taskId, formVariables); + } else { + taskService.addComment(taskId, instanceId, FlowComment.NORMAL.getType(), comment); + log.error("taskid:{},userSid:{}",taskId, userSid); + log.error("formVariables:{}",JSON.toJSONString(formVariables)); + taskService.setAssignee(taskId, userSid); + //formVariables.remove("userSid"); + /*for(Map.Entry entry:formVariables.entrySet()){ + taskService.setVariable(taskId,entry.getKey(),entry.getValue()); + System.out.println(entry.getKey()+"--->"+entry.getValue()); + }*/ + taskService.complete(taskId, formVariables); + //根据流程实例的id取最新的待办环节,给环节设置上用户sid + ResultBean> ll = flowtaskService.getLatestTasksNew(instanceId); + if (ll.getData().size() > 0) { + LatestTaskVo latestTaskVo = ll.getData().get(0); + String id_ = latestTaskVo.getId_(); + taskService.setAssignee(id_, nextUserSid); + vo.setTaskId(id_); + /* for(Map.Entry entry:formVariables.entrySet()){ + taskService.setVariable(id_,entry.getKey(),entry.getValue()); + taskService.setVariableLocal(id_,entry.getKey(),entry.getValue()); + + System.out.println(entry.getKey()+"--->"+entry.getValue()); + }*/ + // taskService.setVariables(id_,formVariables); + //在act_ru_variable表中增加环节上的业务参数的变量 + taskService.setVariablesLocal(id_,formVariables); + nodeState = latestTaskVo.getName_(); + taskDefKey = latestTaskVo.getTask_def_key_(); + } else { + nodeState = FlowComment.SETTLE.getRemark(); + taskDefKey = "Event_end"; + vo.setNodeState(FlowComment.SETTLE.getRemark()); + } + } + //ResultBean flowRecordVoResultBean = flowableService.flowRecord(dto.getInstanceId(), dto.getModelId()); + List flowElements = processService.calApprovePath(dto.getModelId(), dto.getModelId(), + dto.getFormVariables()); + boolean contains=false; + for(int i=0;i candidateGroups = userTask.getCandidateGroups(); + List sysUserVoLists=new ArrayList<>(); + //根据角色查询用户 + for(String roleSid:candidateGroups){ + UserQuery userQuery = new UserQuery(); + userQuery.setRoleSid(roleSid); + userQuery.setOrgSidPath(dto.getOrgSidPath()); + ResultBean> userByRole = sysUserFeign.getUserByRole(userQuery); + boolean success = userByRole.getSuccess(); + if(!success){ + continue; + } + sysUserVoLists.addAll(userByRole.getData()); + } + //当前环节运营部总经理 刘丽艳 点击同意 下一环节 事业部副总经理 (nextUserSid) 和事业部总经理(sysUserVoLists.get(0).getSid()) + //判断查询回来的用户的集合size是1 并且用户的sid和下一环节的用户的sid相同。 + if(sysUserVoLists.size()==1&&sysUserVoLists.get(0).getSid().equals(nextUserSid)){ + contains=true; + break; + } + } + } + if(contains){ + break; + } + } + if(contains){ + dto.setUserSid(nextUserSid); + dto.setTaskId(vo.getTaskId()); + dto.setTaskDefKey(taskDefKey); + return handleProsess(dto,false); + } + vo.setProcInsId(instanceId); + vo.setProcDefId(task.getProcessDefinitionId()); + vo.setNodeState(nodeState); + vo.setTaskDefKey(taskDefKey); + vo.setNextNodeUserSids(nextUserSid); + return rb.success().setData(vo); + } + @Override + public ResultBean revokeProcess(com.yxt.anrui.flowable.api.flowtask.FlowTaskVo fl) { + ResultBean rb = ResultBean.fireFail(); + if (StringUtils.isBlank(fl.getBusinessSid())) { + return rb.setMsg("businessSid 不能为空!"); + } + if( fl.getValues()==null){ + fl.setValues(new HashMap()); + } + fl.getValues().put("businessSid",fl.getBusinessSid()); + UpdateFlowFieldVo vo = new UpdateFlowFieldVo(); + ResultBean flowProcinstById = flowableService.getFlowProcinstById(fl.getInstanceId()); + if(!StringUtils.isBlank(flowProcinstById.getData().getEND_TIME_())){ + return rb.setMsg("撤回失败,流程已办结或终止"); + } + ResultBean> resultBean = flowtaskService.revokeProcess(fl); + if (!resultBean.getSuccess()) { + return rb.setMsg(resultBean.getMsg()); + } + String nodeState = resultBean.getData().get(0).getName_(); + String taskDefKey = resultBean.getData().get(0).getTask_def_key_(); + String incomingSourceRef = resultBean.getData().get(0).getIncomingSourceRef(); + vo.setSid(fl.getBusinessSid()); + vo.setTaskId(resultBean.getData().get(0).getId_()); + if (incomingSourceRef.contains("start")) { + vo.setNodeState(nodeState); + vo.setTaskDefKey(taskDefKey); + } else { + vo.setNodeState( nodeState); + vo.setTaskDefKey( taskDefKey); + } + return rb.success().setData(vo); + } + + @Override + public ResultBean taskReject(com.yxt.anrui.flowable.api.flowtask.FlowTaskVo fl) { + ResultBean rb = ResultBean.fireFail(); + UpdateFlowFieldVo vo = new UpdateFlowFieldVo(); + + if (StringUtils.isBlank(fl.getBusinessSid())) { + return rb.setMsg("businessSid 不能为空!"); + } + if( fl.getValues()==null){ + fl.setValues(new HashMap()); + } + fl.getValues().put("businessSid",fl.getBusinessSid()); + + ResultBean> resultBean = flowtaskService.taskReject(fl); + if (!resultBean.getSuccess()) { + return rb.setMsg(resultBean.getMsg()); + } + String orgPath = resultBean.getData().get(0).getOrgPath(); + String nodeState = resultBean.getData().get(0).getName_(); + String taskDefKey = resultBean.getData().get(0).getTask_def_key_(); + String incomingSourceRef = resultBean.getData().get(0).getIncomingSourceRef(); + String taskId = resultBean.getData().get(0).getId_(); + vo.setSid(fl.getBusinessSid()); + vo.setNodeState( nodeState); + vo.setTaskDefKey( taskDefKey); + vo.setTaskId(taskId); + /* if (incomingSourceRef.contains("start")) { + vo.setNodeState( SysFormLinkFlowStateEnum.REJECT.getCode()); + }*/ + Map formVariables=new HashMap<>(); + formVariables.put(BusinessVariables.ORGPATH,orgPath); + //在act_ru_variable表中增加环节上的业务参数的变量 + taskService.setVariablesLocal(taskId,formVariables); + ResultBean resultBean1 = ResultBean.fireSuccess(); + return resultBean1.success().setData(vo); + } + + @Override + public ResultBean breakProcess(com.yxt.anrui.flowable.api.flowtask.FlowTaskVo fl) { + ResultBean rb = ResultBean.fireFail(); + if (StringUtils.isBlank(fl.getBusinessSid())) { + return rb.setMsg("businessSid 不能为空!"); + } + if( fl.getValues()==null){ + fl.setValues(new HashMap()); + } + fl.getValues().put("businessSid",fl.getBusinessSid()); + UpdateFlowFieldVo vo = new UpdateFlowFieldVo(); + ResultBean resultBean = flowableService.breakProcess(fl); + if (!resultBean.getSuccess()) { + return resultBean; + } + vo.setSid(fl.getBusinessSid()); + vo.setNodeState(resultBean.getData().getNodeState()); + vo.setTaskDefKey( "Event_end"); + return rb.success().setData(vo); + } +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow/FlowableService.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow/FlowableService.java new file mode 100644 index 00000000..5850fa83 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow/FlowableService.java @@ -0,0 +1,276 @@ +package com.yxt.anrui.flowable.biz.flow; + + +import cn.hutool.core.bean.BeanUtil; +import com.yxt.anrui.flowable.api.flow.*; +import com.yxt.anrui.flowable.api.flowtask.FlowTask; +import com.yxt.anrui.flowable.api.flowtask.FlowTaskVo; +import com.yxt.anrui.flowable.api.flowtask.LatestTaskVo; +import com.yxt.anrui.flowable.api.utils.ProcessStateEnum; +import com.yxt.anrui.flowable.biz.flowdefinition.FlowDefinitionService; +import com.yxt.anrui.flowable.biz.flowtask.FlowTaskService; +import com.yxt.anrui.flowable.sqloperationsymbol.BusinessTaskParam; +import com.yxt.anrui.flowable.sqloperationsymbol.BusinessTaskQuery; +import com.yxt.anrui.flowable.sqloperationsymbol.BusinessVariables; +import com.yxt.anrui.flowable.sqloperationsymbol.SQLOperationSymbol; +import com.yxt.common.base.service.MybatisBaseService; +import com.yxt.common.base.utils.StringUtils; +import com.yxt.common.core.query.PagerQuery; +import com.yxt.common.core.result.ResultBean; +import org.flowable.engine.TaskService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +public class FlowableService extends MybatisBaseService { + @Autowired + private FlowDefinitionService flowDefinitionService; + @Autowired + private FlowTaskService flowTaskService; + @Autowired + private TaskService taskService; + + public ResultBean getFlowProcinstById(String id) { + ResultBean rb = ResultBean.fireFail(); + FlowProcinst fp=baseMapper.getFlowProcinstById(id); + if(fp==null){ + return rb; + } + return rb.success().setData(fp); + } + public ResultBean businessStart(BusinessVariables bv) { + if (StringUtils.isBlank(bv.getBusinessSid())) { + return ResultBean.fireFail().setMsg("businessSid 不能为空!"); + } + /*if(bv.getFormVariables()==null){ + return ResultBean.fireFail().setMsg("业务参数集合 不能为空!"); + }*/ + if(bv.getFormVariables()==null) + bv.setFormVariables(new HashMap()); + bv.getFormVariables().put("businessSid",bv.getBusinessSid()); + ResultBean rb = flowDefinitionService.businessStart(bv); + if (!rb.getSuccess()) { + return rb; + } + String procId = rb.getData().getProcInsId(); + List list = flowTaskService.getLatestTasks(procId); + String nodeState = list.get(0).getName_(); + String task_def_key_ = list.get(0).getTask_def_key_(); + Map map = new HashMap<>(); + map.put("sid", bv.getBusinessSid()); + map.put("nodeState", nodeState); + map.put("procInsId", rb.getData().getProcInsId()); + map.put("taskDefKey", task_def_key_); + map.put("taskId",list.get(0).getId_()); + taskService.setVariablesLocal(list.get(0).getId_(),bv.getFormVariables()); + return new ResultBean().success().setData(map); + } + + public ResultBean myprocess(String userSid, PagerQuery taskQueryPagerQuery) { + PagerQuery pq = new PagerQuery<>(); + String days = taskQueryPagerQuery.getParams().getDays(); + String zd = taskQueryPagerQuery.getParams().getZd(); + pq.setCurrent(taskQueryPagerQuery.getCurrent()); + pq.setSize(taskQueryPagerQuery.getSize()); + BusinessTaskQuery businessTaskQuery = BusinessTaskQuery.create(); + if (StringUtils.isNotBlank(zd)) { + BusinessTaskParam businessTaskParam = new BusinessTaskParam(); + businessTaskParam.setField("zd"); + businessTaskParam.setSqlOperationSymbol(SQLOperationSymbol.LIKE); + businessTaskParam.setValue(zd); + businessTaskQuery.add(businessTaskParam); + } + if (StringUtils.isNotBlank(days)) { + BusinessTaskParam businessTaskParam = new BusinessTaskParam(); + businessTaskParam.setField("days"); + businessTaskParam.setSqlOperationSymbol(SQLOperationSymbol.EQUAL); + businessTaskParam.setValue(days); + businessTaskQuery.add(businessTaskParam); + } + pq.setParams(businessTaskQuery); + return flowTaskService.businessMyprocessNew(userSid, pq); + } + + public ResultBean processPagerList(Integer pageNum, Integer pageSize) { + return flowDefinitionService.pagerListNew(pageNum, pageSize); + } + + public ResultBean todoTaskList(String userSid, PagerQuery pQuery) { + TaskQuery params = pQuery.getParams(); + if (StringUtils.isBlank(userSid)) { + return ResultBean.fireFail().setMsg("用户SID为空"); + } + PagerQuery taskQueryPagerQuery = new PagerQuery<>(); + taskQueryPagerQuery.setCurrent(pQuery.getCurrent()).setSize(pQuery.getSize()); + + String days = params.getDays(); + String processDefinitionId = params.getProcessDefinitionId(); + String startTime = params.getStartTime(); + BusinessTaskQuery taskQuery = new BusinessTaskQuery(); + List taskParamList = new ArrayList<>(); + if (StringUtils.isNotBlank(days)) { + BusinessTaskParam taskParam = new BusinessTaskParam(); + taskParam.setField("zd1"); + taskParam.setValue(days); + taskParam.setSqlOperationSymbol(SQLOperationSymbol.EQUAL); + taskParamList.add(taskParam); + } + if (StringUtils.isNotBlank(startTime)) { + BusinessTaskParam taskParam = new BusinessTaskParam(); + taskParam.setField("startTime"); + taskParam.setValue(startTime); + taskParam.setSqlOperationSymbol(SQLOperationSymbol.EQUAL); + taskParamList.add(taskParam); + } + if (StringUtils.isNotBlank(processDefinitionId)) { + BusinessTaskParam taskParam = new BusinessTaskParam(); + taskParam.setField("processDefinitionId"); + taskParam.setSqlOperationSymbol(SQLOperationSymbol.NONE); + taskParam.setValue(processDefinitionId); + taskParamList.add(taskParam); + } + taskQuery.setFields(taskParamList); + taskQueryPagerQuery.setParams(taskQuery); + return flowTaskService.businessTodoListNew(userSid, taskQueryPagerQuery); + } + + public ResultBean doneTaskList(String userSid, PagerQuery pQuery) { + TaskQuery params = pQuery.getParams(); + if (StringUtils.isBlank(userSid)) { + return ResultBean.fireFail().setMsg("用户SID为空"); + } + PagerQuery taskQueryPagerQuery = new PagerQuery<>(); + taskQueryPagerQuery.setCurrent(pQuery.getCurrent()).setSize(pQuery.getSize()); + String zd1 = params.getZd1(); + String processDefinitionId = params.getProcessDefinitionId(); + String startTime = params.getStartTime(); + BusinessTaskQuery taskQuery = new BusinessTaskQuery(); + List taskParamList = new ArrayList<>(); + if (StringUtils.isNotBlank(zd1)) { + BusinessTaskParam taskParam = new BusinessTaskParam(); + taskParam.setField("zd1"); + taskParam.setValue(zd1); + taskParam.setSqlOperationSymbol(SQLOperationSymbol.EQUAL); + taskParamList.add(taskParam); + } + if (StringUtils.isNotBlank(startTime)) { + BusinessTaskParam taskParam = new BusinessTaskParam(); + taskParam.setField("startTime"); + taskParam.setValue(startTime); + taskParam.setSqlOperationSymbol(SQLOperationSymbol.EQUAL); + taskParamList.add(taskParam); + } + if (StringUtils.isNotBlank(processDefinitionId)) { + BusinessTaskParam taskParam = new BusinessTaskParam(); + taskParam.setField("processDefinitionId"); + taskParam.setSqlOperationSymbol(SQLOperationSymbol.NONE); + taskParam.setValue(processDefinitionId); + taskParamList.add(taskParam); + } + taskQuery.setFields(taskParamList); + taskQueryPagerQuery.setParams(taskQuery); + return flowTaskService.businessDoneListNew(userSid, taskQueryPagerQuery); + } + + /** + * 取消 + * + * @param variables + * @return + */ + public ResultBean complete(Map variables) { + BusinessVariables bv = BusinessVariables.builder().build(); + bv.setFormVariables(variables); + ResultBean resultBean = flowTaskService.businessComplete(bv); + if (!resultBean.getSuccess()) { + return resultBean; + } + String nodeState = ""; + if (resultBean.getData() != null) { + ResultBean> listResultBean = flowTaskService.getLatestTasksNew(resultBean.getData().getProcInsId()); + if (listResultBean.getSuccess() && listResultBean.getData() != null && listResultBean.getData().size() != 0) { + nodeState = listResultBean.getData().get(0).getName_(); + } else { + nodeState = ProcessStateEnum.FINISHED.getStateName(); + } + } + Map map = new HashMap<>(); + map.put("nodeState", nodeState); + return new ResultBean().success().setData(map); + } + + /** + * 撤回 + * + * @param userSid + * @param flowTaskVo + * @return + */ + public ResultBean revokeProcess(String userSid, FlowTaskVo flowTaskVo) { + com.yxt.anrui.flowable.api.flowtask.FlowTaskVo fl = new com.yxt.anrui.flowable.api.flowtask.FlowTaskVo(); + BeanUtil.copyProperties(flowTaskVo, fl); + fl.setUserSid(userSid); + ResultBean> resultBean = flowTaskService.revokeProcess(fl); + if (!resultBean.getSuccess()) { + return resultBean; + } + String nodeState = resultBean.getData().get(0).getName_(); + Map map = new HashMap<>(); + map.put("nodeState", nodeState); + return new ResultBean().success().setData(map); + } + + public ResultBean flowRecord(String procInsId, String deployId) { + return flowTaskService.businessFlowRecord(procInsId); + } + + public ResultBean taskReject(FlowTaskVo flowTaskVo) { + com.yxt.anrui.flowable.api.flowtask.FlowTaskVo fl = new com.yxt.anrui.flowable.api.flowtask.FlowTaskVo(); + BeanUtil.copyProperties(flowTaskVo, fl); + ResultBean> resultBean = flowTaskService.taskReject(fl); + if (!resultBean.getSuccess()) { + return resultBean; + } + String nodeState = resultBean.getData().get(0).getName_(); + Map map = new HashMap<>(); + map.put("nodeState", nodeState); + return new ResultBean().success().setData(map); + } + + /** + * 终止流程 + * + * @param flowTaskVo + * @return + */ + public ResultBean breakProcess(com.yxt.anrui.flowable.api.flowtask.FlowTaskVo flowTaskVo) { + /* com.yxt.anrui.flowable.api.flowtask.FlowTaskVo fl = new com.yxt.anrui.flowable.api.flowtask.FlowTaskVo(); + BeanUtil.copyProperties(flowTaskVo, fl);*/ + ResultBean resultBean = flowTaskService.breakProcess(flowTaskVo); + if (!resultBean.getSuccess()) { + return resultBean; + } + UpdateFlowFieldVo vo=new UpdateFlowFieldVo(); + vo.setNodeState(String.valueOf(resultBean.getData())); + return resultBean.success().setData(vo); + } + + public void stopProcess(com.yxt.anrui.flowable.api.flow.FlowTaskVo flowTaskVo) { + com.yxt.anrui.flowable.api.flowtask.FlowTaskVo fl = new com.yxt.anrui.flowable.api.flowtask.FlowTaskVo(); + BeanUtil.copyProperties(flowTaskVo, fl); + flowTaskService.stopProcess(flowTaskVo.getUserSid(), fl); + } + + public void deleteProcess(String procInsId) { + flowTaskService.deleteProcessNew(procInsId); + } + + public Map getProcessInstanceById(String procInsId) { + return baseMapper.getProcessInstanceById(procInsId); + } +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowdefinition/FlowDefinitionRest.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowdefinition/FlowDefinitionRest.java new file mode 100644 index 00000000..245f3134 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowdefinition/FlowDefinitionRest.java @@ -0,0 +1,143 @@ +package com.yxt.anrui.flowable.biz.flowdefinition; + +import com.yxt.anrui.flowable.api.flowdefinition.FlowDefinitionFeign; +import com.yxt.anrui.flowable.api.flowdefinition.FlowSaveXmlQuery; +import com.yxt.anrui.flowable.api.flowdefinition.SysUser; +import com.yxt.common.core.result.ResultBean; +import com.yxt.supervise.system.sysrole.SysRoleFeign; +import com.yxt.supervise.system.sysrole.SysRoleVo; +import com.yxt.supervise.system.sysuser.SysUserFeign; +import com.yxt.supervise.system.sysuser.SysUserVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiParam; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.multipart.MultipartFile; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Map; + +/** + * @author dimengzhe + * @date 2021/6/16 17:14 + * @description 流程定义 + */ +@Api(tags = "流程定义") +@Controller +@RequestMapping("/v1/flowable/definition") +public class FlowDefinitionRest implements FlowDefinitionFeign { + + private static final Logger log = LoggerFactory.getLogger(FlowDefinitionRest.class); + + @Autowired + private FlowDefinitionService flowDefinitionService; + + @Autowired + private SysUserFeign sysUserFeign; + + @Autowired + private SysRoleFeign sysRoleFeign; + + @Override + public ResultBean importFile(String name, String category, MultipartFile file) { + InputStream in = null; + try { + in = file.getInputStream(); + flowDefinitionService.importFile(name, category, in); + } catch (Exception e) { + log.error("导入失败:", e); + return ResultBean.fireFail().setMsg(e.getMessage()); + } finally { + try { + if (in != null) { + in.close(); + } + } catch (IOException e) { + log.error("关闭输入流出错", e); + } + } + + return ResultBean.fireSuccess().setMsg("导入成功"); + } + + @Override + public ResultBean pagerList(Integer pageNum, Integer pageSize) { + return flowDefinitionService.pagerListNew(pageNum, pageSize); + } + + @Override + public ResultBean updateState(Integer state, String deployId) { + flowDefinitionService.updateState(state, deployId); + return ResultBean.fireSuccess(); + } + + @Override + public ResultBean delete(String deployId) { + flowDefinitionService.delete(deployId); + return ResultBean.fireSuccess(); + } + + @Override + public ResultBean save(FlowSaveXmlQuery flowSaveXmlQuery) { + InputStream in = null; + try { + in = new ByteArrayInputStream(flowSaveXmlQuery.getXml().getBytes(StandardCharsets.UTF_8)); + flowDefinitionService.importFile(flowSaveXmlQuery.getName(), flowSaveXmlQuery.getCategory(), in); + } catch (Exception e) { + log.error("导入失败:", e); + return ResultBean.fireFail().setMsg(e.getMessage()); + } finally { + try { + if (in != null) { + in.close(); + } + } catch (IOException e) { + log.error("关闭输入流出错", e); + } + } + + return ResultBean.fireSuccess().setMsg("导入成功"); + } + + @Override + public ResultBean readXml(String deployId) { + try { + return flowDefinitionService.readXml(deployId); + } catch (Exception e) { + e.printStackTrace(); + return ResultBean.fireFail().setMsg("加载xml文件异常"); + } + } + + @Override + public ResultBean userList(SysUser user) { + ResultBean> list = sysUserFeign.list(); + return list; + } + + @Override + public ResultBean roleList() { + ResultBean> list = sysRoleFeign.list(); + return list; + } + + @Override + public ResultBean start(@ApiParam(value = "流程定义id") @PathVariable(value = "procDefId") String procDefId, + @ApiParam(value = "变量集合,json对象") @RequestBody Map variables) { + return flowDefinitionService.startProcessInstanceById(procDefId, variables); + } + + /* @Override + public ResultBean businessStart(@ApiParam(value = "变量集合") @RequestBody BusinessVariables dto) { + return flowDefinitionService.businessStart(dto); + }*/ +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowdefinition/FlowDefinitionService.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowdefinition/FlowDefinitionService.java new file mode 100644 index 00000000..aefaa4f9 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowdefinition/FlowDefinitionService.java @@ -0,0 +1,273 @@ +package com.yxt.anrui.flowable.biz.flowdefinition; + +/** + * @author dimengzhe + * @date 2021/6/16 17:19 + * @description 流程定义 + */ + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yxt.anrui.flowable.api.flowdefinition.FlowDefinitionVo; +import com.yxt.anrui.flowable.api.flowtask.FlowTask; +import com.yxt.anrui.flowable.api.flowtask.LatestTaskVo; +import com.yxt.anrui.flowable.api.sysform.SysForm; +import com.yxt.anrui.flowable.biz.flow.FlowableService; +import com.yxt.anrui.flowable.biz.flowtask.FlowTaskService; +import com.yxt.anrui.flowable.biz.sysdeployform.SysDeployFormService; +import com.yxt.anrui.flowable.api.flowcomment.FlowComment; +import com.yxt.anrui.flowable.common.ProcessConstants; +import com.yxt.anrui.flowable.factory.FlowServiceFactory; +import com.yxt.anrui.flowable.sqloperationsymbol.BusinessVariables; +import com.yxt.common.base.utils.JPushServer; +import com.yxt.common.base.utils.StringUtils; +import com.yxt.common.core.result.ResultBean; +import com.yxt.supervise.system.sysuser.SysUser; +import com.yxt.supervise.system.sysuser.SysUserFeign; +import com.yxt.supervise.system.sysuser.SysUserVo; +import org.apache.commons.io.IOUtils; +import org.flowable.engine.repository.Deployment; +import org.flowable.engine.repository.ProcessDefinition; +import org.flowable.engine.repository.ProcessDefinitionQuery; +import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.*; + +@Service +public class FlowDefinitionService extends FlowServiceFactory { + + private static final String BPMN_FILE_SUFFIX = ".bpmn"; + @Autowired + private SysDeployFormService sysDeployFormService; + @Autowired + private SysUserFeign sysUserFeign; + @Autowired + private FlowableService flowableService; + /** + * 导入流程文件 + * + * @param name + * @param category + * @param in + */ + public void importFile(String name, String category, InputStream in) { + Deployment deploy = repositoryService.createDeployment().addInputStream(name + BPMN_FILE_SUFFIX, in).name(name).category(category).deploy(); + ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deploy.getId()).singleResult(); + repositoryService.setProcessDefinitionCategory(definition.getId(), category); + } + + public Page list(Integer pageNum, Integer pageSize) { + Page page = new Page<>(); + // 流程定义列表数据查询 + ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery() + .orderByProcessDefinitionKey().asc(); + page.setTotal(processDefinitionQuery.count()); + List processDefinitionList = processDefinitionQuery.listPage((pageNum - 1) * pageSize, pageSize); + + List dataList = new ArrayList<>(); + for (ProcessDefinition processDefinition : processDefinitionList) { + String deploymentId = processDefinition.getDeploymentId(); + Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult(); + FlowDefinitionVo reProcDef = new FlowDefinitionVo(); + BeanUtils.copyProperties(processDefinition, reProcDef); + SysForm sysForm = sysDeployFormService.selectSysDeployFormByDeployId(deploymentId); + if (Objects.nonNull(sysForm)) { + reProcDef.setFormName(sysForm.getFormName()); + reProcDef.setFormId(Long.valueOf(sysForm.getId())); + } + // 流程定义时间 + reProcDef.setDeploymentTime(deployment.getDeploymentTime()); + dataList.add(reProcDef); + } + page.setRecords(dataList); + return page; + } + + /** + * 激活或挂起流程定义 + * + * @param state 状态 + * @param deployId 流程部署ID + */ + public void updateState(Integer state, String deployId) { + ProcessDefinition procDef = repositoryService.createProcessDefinitionQuery().deploymentId(deployId).singleResult(); + // 激活 + if (state == 1) { + repositoryService.activateProcessDefinitionById(procDef.getId(), true, null); + } + // 挂起 + if (state == 2) { + repositoryService.suspendProcessDefinitionById(procDef.getId(), true, null); + } + } + + /** + * 删除流程定义 + * + * @param deployId 流程部署ID act_ge_bytearray 表中 deployment_id值 + */ + public void delete(String deployId) { + // true 允许级联删除 ,不设置会导致数据库外键关联异常 + repositoryService.deleteDeployment(deployId, true); + } + + public ResultBean readXml(String deployId) throws IOException { + ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deployId).singleResult(); + InputStream inputStream = repositoryService.getResourceAsStream(definition.getDeploymentId(), definition.getResourceName()); + String result = IOUtils.toString(inputStream, StandardCharsets.UTF_8.name()); + return ResultBean.fireSuccess().setData(result); + } + + /** + * 根据流程定义ID启动流程实例 + * + * @param procDefId 流程定义Id + * @param variables 流程变量 + * @return + */ + public ResultBean startProcessInstanceById(String procDefId, Map variables) { + try { + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(procDefId) + .latestVersion().singleResult(); + if (Objects.nonNull(processDefinition) && processDefinition.isSuspended()) { + return ResultBean.fireFail().setMsg("流程已被挂起,请先激活流程"); + } +// variables.put("skip", true); +// variables.put(ProcessConstants.FLOWABLE_SKIP_EXPRESSION_ENABLED, true); + // 设置流程发起人Id到流程中 + SysUser sysUser = new SysUser();//SecurityUtils.getLoginUser().getUser(); + sysUser.setSid("0d8d8119-d476-47ce-89c2-075cd809dda6"); + identityService.setAuthenticatedUserId(sysUser.getSid().toString()); + variables.put(ProcessConstants.PROCESS_INITIATOR, ""); + ProcessInstance processInstance = runtimeService.startProcessInstanceById(procDefId, variables); + // 给第一步申请人节点设置任务执行人和意见 todo:第一个节点不设置为申请人节点有点问题? + Task task = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).singleResult(); + if (Objects.nonNull(task)) { + taskService.addComment(task.getId(), processInstance.getProcessInstanceId(), FlowComment.START.getType(), sysUser.getUserName() + "发起流程申请"); +// taskService.setAssignee(task.getId(), sysUser.getUserId().toString()); + taskService.complete(task.getId(), variables); + } + return ResultBean.fireSuccess().setMsg("流程启动成功"); + } catch (Exception e) { + e.printStackTrace(); + return ResultBean.fireFail().setMsg("流程启动错误"); + } + } + + @Autowired + private FlowTaskService flowTaskService; + + /** + * 根据流程定义ID启动流程实例 + * + * @param procDefId 流程定义Id + * @param userSid 发起人sid + * @param variables 流程变量 + * @return + */ + public ResultBean businessStartProcessInstanceById(String procDefId, String userSid, String nextNodeUserSids, Map variables) { + try { + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(procDefId) + .latestVersion().singleResult(); + if (Objects.nonNull(processDefinition) && processDefinition.isSuspended()) { + ResultBean rb = ResultBean.fireFail(); + return rb.setData(new FlowTask()).setMsg("流程已被挂起,请先激活流程"); + } + // 设置流程发起人Id到流程中 + ResultBean sysUserVoResultBean = sysUserFeign.fetchBySid(userSid); + SysUserVo sysUser = sysUserVoResultBean.getData(); + identityService.setAuthenticatedUserId(sysUser.getSid()); + variables.put(ProcessConstants.PROCESS_INITIATOR, userSid); + variables.put(ProcessConstants.USER_TYPE_ASSIGNEE, userSid); + ProcessInstance processInstance = runtimeService.startProcessInstanceById(procDefId, variables); + // 给第一步申请人节点设置任务执行人和意见 todo:第一个节点不设置为申请人节点有点问题? + Task task = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).singleResult(); + /* for(Map.Entry entry:variables.entrySet()){ + taskService.setVariable(task.getId(),entry.getKey(),entry.getValue()); + System.out.println(entry.getKey()+"--->"+entry.getValue()); + }*/ + if (Objects.nonNull(task)) { + taskService.addComment(task.getId(), processInstance.getProcessInstanceId(), FlowComment.START.getType(), + sysUser.getName() + "发起流程申请"); + taskService.setAssignee(task.getId(), userSid); + taskService.setVariablesLocal(task.getId(),variables); + taskService.complete(task.getId(), variables); + + } + ResultBean> latestTasksNew = flowTaskService.getLatestTasksNew(processInstance.getId()); + List data = latestTasksNew.getData(); + LatestTaskVo latestTaskVo = data.get(0); + String id_ = latestTaskVo.getId_(); + taskService.setAssignee(id_,nextNodeUserSids); + ResultBean rb = new ResultBean<>(); + FlowTask flowTask = new FlowTask(); + flowTask.setTaskId(task.getId()); + flowTask.setTaskName(task.getName()); + flowTask.setProcInsId(task.getProcessInstanceId()); + return rb.success().setData(flowTask).setMsg("流程启动成功"); + } catch (Exception e) { + e.printStackTrace(); + ResultBean rb = ResultBean.fireFail(); + return rb.setData(new FlowTask()).setMsg("流程启动错误"); + } + } + + /** + * 向下一环节待办人发出推送 + * + * @param taskId + */ + private void sendPush(String taskId) { + ResultBean nextTasks = flowTaskService.getNextTasks(taskId); + System.out.println(nextTasks.getData()); + String assignee = ((HashMap) ((ArrayList) nextTasks.getData()).get(0)).get("assignee").toString(); + String name = ((HashMap) ((ArrayList) nextTasks.getData()).get(0)).get("name").toString(); + System.out.println("assignee:" + assignee); + Integer id = sysUserFeign.fetchBySid(assignee).getData().getId(); + System.out.println("id:" + id); + JPushServer.sendPushAlias(name, name, "msg_type", "系统消息", id.toString()); + } + + public ResultBean businessStart(BusinessVariables dto) { + ResultBean resultBean = new ResultBean<>(); + Map variables = dto.getFormVariables(); + variables.put(BusinessVariables.ORGPATH,dto.getOrgSidPath()); + Object procDefId_obj = dto.getModelId(); + Object userSid_obj = dto.getUserSid(); + String procDefId = null; + String userSid = null; + if (procDefId_obj == null) { + return resultBean.fail().setData(new FlowTask()).setMsg("procDefId 不能为空"); + } else { + procDefId = (String) procDefId_obj; + if (StringUtils.isBlank(procDefId)) { + resultBean.fail().setData(new FlowTask()).setMsg("procDefId 不能为空"); + return resultBean; + } + } + if (userSid_obj == null) { + resultBean.fail().setData(new FlowTask()).setMsg("userSid 不能为空"); + return resultBean; + } else { + userSid = (String) userSid_obj; + if (StringUtils.isBlank(userSid)) { + resultBean.fail().setData(new FlowTask()).setMsg("userSid 不能为空"); + return resultBean; + } + } + resultBean = businessStartProcessInstanceById(procDefId, userSid,dto.getNextNodeUserSids(), variables); + return resultBean; + } + + public ResultBean pagerListNew(Integer pageNum, Integer pageSize) { + Page pageList = list(pageNum, pageSize); + return ResultBean.fireSuccess().setData(pageList); + } + +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowinstance/FlowInstanceRest.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowinstance/FlowInstanceRest.java new file mode 100644 index 00000000..cd89fcb3 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowinstance/FlowInstanceRest.java @@ -0,0 +1,71 @@ +package com.yxt.anrui.flowable.biz.flowinstance; + +/** + * @author dimengzhe + * @date 2021/6/16 9:10 + * @description + */ + +import com.yxt.anrui.flowable.api.flowdefinition.FlowInstanceDto; +import com.yxt.anrui.flowable.api.flowinstance.FlowInstanceFeign; +import com.yxt.anrui.flowable.api.flowinstance.FlowInstanceVo; +import com.yxt.common.core.result.ResultBean; +import io.swagger.annotations.Api; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +@Api(tags = "工作流流程实例管理") +@RequestMapping("v1/flowable/instance") +@Controller +public class FlowInstanceRest implements FlowInstanceFeign { + + @Autowired + private FlowInstanceService flowInstanceService; + + @Override + public ResultBean startProcess(FlowInstanceDto flowTaskDto) { + FlowInstanceVo flowTaskVo = new FlowInstanceVo(); + ResultBean resultBean = ResultBean.fireFail(); + if (flowTaskDto == null) { + return resultBean.setData(flowTaskVo); + } + flowTaskVo = flowInstanceService.startProcess(flowTaskDto); + if (null == flowTaskVo) { + return resultBean.setData(flowTaskVo); + } + return resultBean.success().setData(flowTaskVo); + } + + /** + * 根据流程定义id启动流程实例 + * + * @param procDefId 流程定义id + * @return + */ + @Override + public ResultBean startById(String procDefId) { + return flowInstanceService.startProcessInstanceById(procDefId); + } + + /** + * 删除流程实例 + * + * @param instanceId 流程实例ID + * @param deleteReason 删除原因 + * @return + */ + @Override + public ResultBean delete(String instanceId, String deleteReason) { + flowInstanceService.delete(instanceId, deleteReason); + return ResultBean.fireSuccess(); + } + + @Override + public ResultBean updateState(Integer state, String instanceId) { + flowInstanceService.updateState(state, instanceId); + return ResultBean.fireSuccess(); + } + + +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowinstance/FlowInstanceService.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowinstance/FlowInstanceService.java new file mode 100644 index 00000000..ee666ff8 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowinstance/FlowInstanceService.java @@ -0,0 +1,106 @@ +package com.yxt.anrui.flowable.biz.flowinstance; + +import com.yxt.anrui.flowable.api.flowdefinition.FlowInstanceDto; +import com.yxt.anrui.flowable.api.flowinstance.FlowInstanceVo; +import com.yxt.anrui.flowable.factory.FlowServiceFactory; +import com.yxt.common.core.result.ResultBean; +import org.flowable.common.engine.api.FlowableObjectNotFoundException; +import org.flowable.engine.history.HistoricProcessInstance; +import org.flowable.engine.runtime.ProcessInstance; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Objects; + +/** + * @author dimengzhe + * @date 2021/6/16 10:18 + * @description 工作流流程实例管理 + */ +@Service +public class FlowInstanceService extends FlowServiceFactory { + + /** + * 根据流程定义ID启动流程实例 + * + * @param procDefId 流程定义Id + * @return + */ + + public ResultBean startProcessInstanceById(String procDefId) { + try { + runtimeService.startProcessInstanceById(procDefId); + } catch (Exception e) { + e.printStackTrace(); + return ResultBean.fireFail().setMsg("流程启动错误"); + } + return ResultBean.fireSuccess().setMsg("流程启动成功"); + } + + /** + * 删除流程实例ID + * + * @param instanceId 流程实例ID + * @param deleteReason 删除原因 + */ + + @Transactional(rollbackFor = Exception.class) + public void delete(String instanceId, String deleteReason) { + + // 查询历史数据 + HistoricProcessInstance historicProcessInstance = getHistoricProcessInstanceById(instanceId); + if (historicProcessInstance.getEndTime() != null) { + historyService.deleteHistoricProcessInstance(historicProcessInstance.getId()); + return; + } + // 删除流程实例 + runtimeService.deleteProcessInstance(instanceId, deleteReason); + // 删除历史流程实例 + historyService.deleteHistoricProcessInstance(instanceId); + } + + /** + * 激活或挂起流程实例 + * + * @param state 状态 + * @param instanceId 流程实例ID + */ + + public void updateState(Integer state, String instanceId) { + // 激活 + if (state == 1) { + runtimeService.activateProcessInstanceById(instanceId); + } + // 挂起 + if (state == 2) { + runtimeService.suspendProcessInstanceById(instanceId); + } + } + + /** + * 根据实例ID查询历史实例数据 + * + * @param processInstanceId + * @return + */ + + public HistoricProcessInstance getHistoricProcessInstanceById(String processInstanceId) { + HistoricProcessInstance historicProcessInstance = + historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); + if (Objects.isNull(historicProcessInstance)) { + throw new FlowableObjectNotFoundException("流程实例不存在: " + processInstanceId); + } + return historicProcessInstance; + } + + + public FlowInstanceVo startProcess(FlowInstanceDto flowTaskDto) { + //流程定义id + String processDefinitionId = flowTaskDto.getProcessId(); + ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinitionId); + FlowInstanceVo flowTaskVo = new FlowInstanceVo(); + //流程实例id + flowTaskVo.setInstanceId(processInstance.getId()); + return flowTaskVo; + } +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowtask/FlowTaskController.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowtask/FlowTaskController.java new file mode 100644 index 00000000..e96854dd --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowtask/FlowTaskController.java @@ -0,0 +1,331 @@ +package com.yxt.anrui.flowable.biz.flowtask; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yxt.anrui.flowable.api.flow.UserAndOrgPath; +import com.yxt.anrui.flowable.api.flowtask.*; +import com.yxt.anrui.flowable.api.utils.RecordQuery; +import com.yxt.anrui.flowable.biz.process.ProcessService; +import com.yxt.anrui.flowable.sqloperationsymbol.BusinessTaskParam; +import com.yxt.anrui.flowable.sqloperationsymbol.BusinessTaskQuery; +import com.yxt.anrui.flowable.sqloperationsymbol.BusinessVariables; +import com.yxt.anrui.flowable.test.StartProcessInstanceQuery; +import com.yxt.anrui.flowable.utils.FlowableUtils; +import com.yxt.common.core.query.PagerQuery; +import com.yxt.common.core.result.ResultBean; +import io.swagger.annotations.Api; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.flowable.bpmn.model.FlowElement; +import org.flowable.engine.HistoryService; +import org.flowable.engine.RepositoryService; +import org.flowable.engine.TaskService; +import org.flowable.engine.history.HistoricProcessInstance; +import org.flowable.engine.history.HistoricProcessInstanceQuery; +import org.flowable.engine.repository.ProcessDefinition; +import org.flowable.task.api.Task; +import org.flowable.task.api.history.HistoricTaskInstance; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.*; +import java.util.stream.Collectors; + + +/** + *

工作流任务管理

+ * + * @author XuanXuan + * @date 2021-04-03 + */ +@Api(tags = "工作流流程任务管理") +@RestController +@RequestMapping("/v1/flowable/task") +public class FlowTaskController implements FlowTaskFeign { + @Autowired + private FlowTaskService flowTaskService; + @Resource + protected HistoryService historyService; + @Resource + protected RepositoryService repositoryService; + @Resource + protected TaskService taskService; + @Resource + private ProcessService processService; + + @Override + public ResultBean startProcessInstanceByKey(StartProcessInstanceQuery startProcessInstanceQuery) { + return null; + } + + @Override + public ResultBean businessComplete(@RequestBody BusinessVariables dto) { + return flowTaskService.businessComplete(dto); + } + + @Override + public ResultBean complete(@RequestBody FlowTaskVo flowTaskVo) { + return flowTaskService.complete(flowTaskVo); + } + + @Override + public ResultBean todoList(PagerQuery taskQueryPagerQuery) { + int size = Integer.valueOf(taskQueryPagerQuery.getSize() + ""); + int current = Integer.valueOf(taskQueryPagerQuery.getCurrent() + ""); + ResultBean> resultBean = flowTaskService.todoList(current, size); + return resultBean; + } + + @Override + public ResultBean> businessTodoList(String userSid, PagerQuery businessTaskQuery) { + int size = Integer.valueOf(businessTaskQuery.getSize() + ""); + int current = Integer.valueOf(businessTaskQuery.getCurrent() + ""); + List fields = businessTaskQuery.getParams().getFields(); + /* AtomicReference orgPath= new AtomicReference<>(""); + fields.forEach(f->{ + if(f.getField().equals(BusinessVariables.ORGPATH)) + orgPath.set(f.getValue()); + });*/ + String orgPath=null; + for(BusinessTaskParam b: fields){ + if(b.getField().equals(BusinessVariables.ORGPATH)) { + orgPath=b.getValue(); + } + } + ResultBean> resultBean = flowTaskService.businessTodoList(userSid, orgPath, fields, current, size); + return resultBean; + } + + @Override + public ResultBean> businessTodoListForApp(String userSid, PagerQuery businessTaskQuery) { + int size = Integer.valueOf(businessTaskQuery.getSize() + ""); + int current = Integer.valueOf(businessTaskQuery.getCurrent() + ""); + List fields = businessTaskQuery.getParams().getFields(); + String companySid=""; + if(fields.size()>0){ + for(BusinessTaskParam b:fields){ + if(b.getField().equals(BusinessVariables.ORGPATH)){ + companySid=b.getValue(); + } + } + } + ResultBean> resultBean = flowTaskService.businessTodoListForApp(userSid,companySid, fields, current, size); + return resultBean; + } + + @Override + public ResultBean getTodoNum(String userSid) { + return flowTaskService.getTodoNum(userSid,null); + } + + @Override + public ResultBean getTodoNum(UserAndOrgPath uaop) { + String userSid=uaop.getUserSid(); + String orgPath=uaop.getOrgPath(); + return flowTaskService.getTodoNum(userSid,orgPath); + } + + @Override + public ResultBean doneList(PagerQuery taskQueryPagerQuery) { + int size = Integer.valueOf(taskQueryPagerQuery.getSize() + ""); + int current = Integer.valueOf(taskQueryPagerQuery.getCurrent() + ""); + return flowTaskService.finishedList(current, size); + } + + @Override + public ResultBean businessDoneList(String userSid, PagerQuery taskQueryPagerQuery) { + return flowTaskService.businessDoneListNew(userSid, taskQueryPagerQuery); + } + @Override + public ResultBean> businessDoneListForApp(String userSid, PagerQuery taskQueryPagerQuery) { + return flowTaskService.businessDoneListNewForApp(userSid, taskQueryPagerQuery); + } + + @Override + public ResultBean flowRecord(RecordQuery recordQuery) { + String deployId = recordQuery.getDeployId(); + String procInsId = recordQuery.getProcInsId(); + return flowTaskService.flowRecord(procInsId, deployId); + } + + @Override + public ResultBean stopProcess(String userSid, FlowTaskVo flowTaskVo) { + return flowTaskService.stopProcessNew(userSid, flowTaskVo); + } + + @Override + public ResultBean myprocess(PagerQuery taskQueryPagerQuery) { + FlowTaskQuery params = taskQueryPagerQuery.getParams(); + String userSid = params.getUserSid(); + if (StringUtils.isBlank(userSid)) + return ResultBean.fireFail().setMsg("用户SID不可为空~"); + int currentPage = (int) (taskQueryPagerQuery.getCurrent() - 1); + Page page = new Page<>(); + // Long userId =5001L;// SecurityUtils.getLoginUser().getUser().getUserId(); + HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery() + .startedBy(userSid) + .orderByProcessInstanceStartTime() + .desc(); + List historicProcessInstances = query + .listPage(currentPage, 10); + page.setTotal(query.count()); + List flowList = new ArrayList<>(); + for (HistoricProcessInstance hisIns : historicProcessInstances) { + FlowTaskDto flowTask = new FlowTaskDto(); + flowTask.setCreateTime(hisIns.getStartTime()); + flowTask.setFinishTime(hisIns.getEndTime()); + flowTask.setProcInsId(hisIns.getId()); + + // 计算耗时 + if (Objects.nonNull(hisIns.getEndTime())) { + long time = hisIns.getEndTime().getTime() - hisIns.getStartTime().getTime(); + flowTask.setDuration(FlowableUtils.getDate(time)); + } else { + long time = System.currentTimeMillis() - hisIns.getStartTime().getTime(); + flowTask.setDuration(FlowableUtils.getDate(time)); + } + // 流程定义信息 + ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() + .processDefinitionId(hisIns.getProcessDefinitionId()) + .singleResult(); + flowTask.setDeployId(pd.getDeploymentId()); + flowTask.setProcDefName(pd.getName()); + flowTask.setProcDefVersion(pd.getVersion()); + flowTask.setCategory(pd.getCategory()); + flowTask.setProcDefVersion(pd.getVersion()); + + // 当前所处流程 + List taskList = taskService.createTaskQuery().processInstanceId(hisIns.getId()).list(); + if (CollectionUtils.isNotEmpty(taskList)) { + flowTask.setTaskId(taskList.get(0).getId()); + } else { + List historicTaskInstance = historyService.createHistoricTaskInstanceQuery().processInstanceId(hisIns.getId()).orderByHistoricTaskInstanceEndTime().desc().list(); + flowTask.setTaskId(historicTaskInstance.get(0).getId()); + } + flowList.add(flowTask); + } + page.setRecords(flowList); + return ResultBean.fireSuccess().setData(page); + } + + @Override + public ResultBean businessMyprocess(String userSid, PagerQuery businessTaskQuery) { + return flowTaskService.businessMyprocessNew(userSid, businessTaskQuery); + } + + @Override + public ResultBean processVariables(String taskId) { + return flowTaskService.processVariables(taskId); + } + + @Override + public ResultBean getFlowViewer(String procInsId) { + return flowTaskService.getFlowViewer(procInsId); + } + + @Override + public ResultBean findReturnTaskList(FlowTaskVo flowTaskVo) { + return flowTaskService.findReturnTaskList(flowTaskVo); + } + + @Override + public ResultBean taskReturn(@RequestBody FlowTaskVo flowTaskVo) { + flowTaskService.taskReturn(flowTaskVo); + return ResultBean.fireSuccess(); + } + + @Override + public ResultBean> taskReject(FlowTaskVo flowTaskVo) { + return flowTaskService.taskReject(flowTaskVo); + } + + @Override + public ResultBean> revokeProcess(@RequestBody FlowTaskVo flowTaskVo) { + return flowTaskService.revokeProcess(flowTaskVo); + } + + @Override + public ResultBean breakProcess(FlowTaskVo flowTaskVo) { + return flowTaskService.breakProcess(flowTaskVo); + } + + @Override + public ResultBean flowRecord(String procInsId, String deployId) { + return flowTaskService.flowRecord(procInsId, deployId); + } + + @Override + public ResultBean businessFlowRecord(String procInsId) { + return flowTaskService.businessFlowRecord(procInsId); + } + + @Override + public ResultBean deleteProcess(String procInsId) { + return flowTaskService.deleteProcessNew(procInsId); + } + + @Override + public ResultBean getNextTasks(String taskId) { + return flowTaskService.getNextTasks(taskId); + } + + @Override + public ResultBean> getLatestTasks(String procId) { + return flowTaskService.getLatestTasksNew(procId); + } + + @Override + public ResultBean> getProcessCirculationNodes(String procId, + String modelId, + String k, + String v, String outcome) { + Map map = new HashMap<>(); + map.put(k, v); + map.put("outcome", outcome); + List flowElements = processService.calApprovePath(procId, modelId, map); + List collect = flowElements.stream().filter(item -> item.getId().length() > 0).collect(Collectors.toList()); + for (int i = 0; i < collect.size(); i++) { + if (collect.get(i).getId().equals(modelId)) { + FlowElement item = collect.get(i + 1); + String s = JSON.toJSONString(item); + JSONObject jsonObject = JSONObject.parseObject(s); + Object candidateGroups = jsonObject.get("candidateGroups"); + JSONArray candidateGroups_arr = new JSONArray(); + if (candidateGroups != null) { + candidateGroups_arr = JSONArray.parseArray(candidateGroups.toString()); + } + if (candidateGroups_arr.size() > 0) { + } + } + } + ResultBean> rb = new ResultBean>(); + return rb.setData(flowElements); + } + + @Override + public ResultBean getProcessCirculationNodesByMap(BusinessVariables bv) { + return flowTaskService.getProcessCirculationNodesByMap(bv); + } + + @Override + public ResultBean readXml(String deployId) { + return flowTaskService.readXml(deployId); + } + + @Override + public ResultBean getNextNodesForSubmit(BusinessVariables bv) { + return flowTaskService.getNextNodesForSubmit(bv); + } + + @Override + public ResultBean getPreviousNodesForReject(BusinessVariables bv) { + return flowTaskService.getPreviousNodesForReject(bv); + } +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowtask/FlowTaskMapper.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowtask/FlowTaskMapper.java new file mode 100644 index 00000000..b3686657 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowtask/FlowTaskMapper.java @@ -0,0 +1,46 @@ +package com.yxt.anrui.flowable.biz.flowtask; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.yxt.anrui.flowable.api.flowtask.FlowTask; +import com.yxt.anrui.flowable.api.flowtask.LatestTaskVo; +import com.yxt.anrui.flowable.api.flowtask.TaskQueryParamsVo; +import com.yxt.anrui.flowable.api.flowtask.TaskVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.flowable.task.api.history.HistoricTaskInstance; + +import java.util.List; +import java.util.Map; + +/** + * 流程任务关联单Mapper接口 + * + * @author XuanXuan Xuan + * @date 2021-04-03 + */ +@Mapper +public interface FlowTaskMapper extends BaseMapper { + + IPage getApplyedTasksPagerModel(IPage page, @Param("params") TaskQueryParamsVo params); + + /*取消*/ + List> finishedList(@Param("userSid")String userSid, + @Param("list")List> list, @Param("page")int page, @Param("size")int size); + + List> finishedList1(Map map); + + int finishedListCount(Map map); + + /** + * 根据流程实例的id查询最新的待办环节 + * @param procId + * @return + */ + List getLatestTasks(@Param("procId")String procId); + + Map getHistTaskByID(@Param("procId")String procId,@Param("taskId")String id); + + Map getTaskByDefKey(@Param("procId")String processInstanceId, @Param("taskId")String id); + Map getActHiVarinstForOrgPath(@Param("taskId")String taskId); +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowtask/FlowTaskMapper.xml b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowtask/FlowTaskMapper.xml new file mode 100644 index 00000000..e048fde1 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowtask/FlowTaskMapper.xml @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowtask/FlowTaskService.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowtask/FlowTaskService.java new file mode 100644 index 00000000..541c3228 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flowtask/FlowTaskService.java @@ -0,0 +1,2079 @@ +package com.yxt.anrui.flowable.biz.flowtask; + +import cn.hutool.core.map.MapUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.google.common.collect.Lists; +import com.yxt.anrui.flowable.api.flow.UserAndOrgPath; +import com.yxt.anrui.flowable.api.flowcomment.FlowComment; +import com.yxt.anrui.flowable.api.flowcomment.FlowCommentDto; +import com.yxt.anrui.flowable.api.flowtask.*; +import com.yxt.anrui.flowable.api.sysform.SysForm; +import com.yxt.anrui.flowable.api.sysprourl.SysProUrlVo; +import com.yxt.anrui.flowable.biz.flow.FlowableService; +import com.yxt.anrui.flowable.biz.process.ProcessService; +import com.yxt.anrui.flowable.biz.sysdeployform.SysDeployFormService; +import com.yxt.anrui.flowable.biz.sysprourl.SysProUrlService; +import com.yxt.anrui.flowable.exception.CustomException; +import com.yxt.anrui.flowable.sqloperationsymbol.BusinessTaskParam; +import com.yxt.anrui.flowable.sqloperationsymbol.BusinessTaskQuery; +import com.yxt.anrui.flowable.sqloperationsymbol.BusinessVariables; +import com.yxt.anrui.flowable.sqloperationsymbol.SQLOperationSymbol; +import com.yxt.anrui.flowable.utils.FlowableUtils; +import com.yxt.common.base.config.component.FileUploadComponent; +import com.yxt.common.base.service.MybatisBaseService; +import com.yxt.common.base.utils.ConstantUtils; +import com.yxt.common.base.utils.DateUtils; +import com.yxt.common.base.utils.StringUtils; +import com.yxt.common.core.query.PagerQuery; +import com.yxt.common.core.result.ResultBean; +import com.yxt.supervise.system.sysorganization.SysOrganizationFeign; +import com.yxt.supervise.system.sysorganization.SysOrganizationVo; +import com.yxt.supervise.system.sysstafforg.SysStaffOrgFeign; +import com.yxt.supervise.system.sysuser.SysUser; +import com.yxt.supervise.system.sysuser.SysUserFeign; +import com.yxt.supervise.system.sysuser.SysUserVo; +import com.yxt.supervise.system.sysuser.UserQuery; +import com.yxt.supervise.system.sysuserrole.SysUserRoleFeign; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.io.IOUtils; +import org.flowable.bpmn.model.Process; +import org.flowable.bpmn.model.*; +import org.flowable.common.engine.api.FlowableException; +import org.flowable.common.engine.api.FlowableObjectNotFoundException; +import org.flowable.common.engine.impl.identity.Authentication; +import org.flowable.engine.HistoryService; +import org.flowable.engine.RepositoryService; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.history.HistoricActivityInstance; +import org.flowable.engine.history.HistoricProcessInstance; +import org.flowable.engine.history.HistoricProcessInstanceQuery; +import org.flowable.engine.impl.persistence.entity.ExecutionEntity; +import org.flowable.engine.repository.ProcessDefinition; +import org.flowable.engine.runtime.Execution; +import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.engine.task.Comment; +import org.flowable.identitylink.api.history.HistoricIdentityLink; +import org.flowable.task.api.DelegationState; +import org.flowable.task.api.Task; +import org.flowable.task.api.TaskQuery; +import org.flowable.task.api.history.HistoricTaskInstance; +import org.flowable.task.api.history.HistoricTaskInstanceQuery; +import org.flowable.ui.modeler.service.FlowableFormService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.sql.Timestamp; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author XuanXuan + * @date 2021-04-03 + **/ +@Service +public class FlowTaskService extends MybatisBaseService { + @Resource + private ProcessService processService; + @Autowired + FlowTaskMapper flowTaskMapper; + @Resource + protected HistoryService historyService; + @Resource + protected TaskService taskService; + @Resource + private SysDeployFormService sysInstanceFormService; + @Resource + protected RepositoryService repositoryService; + @Resource + protected FlowableFormService flowableFormService; + @Resource + private SysUserFeign sysUserFeign; + @Resource + private SysUserRoleFeign sysUserRoleFeign; + @Resource + private FileUploadComponent fileUploadComponent; + @Resource + protected RuntimeService runtimeService; + @Resource + private SysProUrlService sysProUrlService; + @Resource + private SysStaffOrgFeign sysStaffOrgFeign; + @Resource + private SysOrganizationFeign sysOrganizationFeign; + @Resource + private FlowableService flowableService; + public ResultBean getNextNodeUserSidsOfCreate(BusinessVariables bv){ + ResultBean rb = ResultBean.fireFail(); + String orgSidPath=bv.getOrgSidPath(); + //根据业务参数取流程流转的环节 信息 + List> list = (List>) getProcessCirculationNodesByMap(bv).getData(); + if(list==null||list.size()<2){ + return rb.setMsg("流程设计问题"); + } + //取第二个环节的配置角色 + Object o = list.get(1).get("candidateGroups"); + if(o==null){ + return rb.setMsg("流程设计问题"); + } + return getNextUserSids(rb, orgSidPath, o); + } + public ResultBean getNextUserSids(ResultBean rb, String orgSidPath, Object o) { + UserAndOrgPath mapParam=new UserAndOrgPath(); + JSONArray jsonArray = JSONArray.parseArray(JSON.toJSONString(o)); + String roleSid = jsonArray.get(0).toString(); + //根据组织架构、角色两个参数取相关符合条件的用户信息 + UserQuery userQuery = new UserQuery(); + userQuery.setRoleSid(roleSid); + userQuery.setOrgSidPath(orgSidPath); + List sysUserVos = sysUserFeign.getUserByRole(userQuery).getData(); + if(sysUserVos==null||sysUserVos.size()<1){ + return rb.fail().setMsg("环节没有用户"); + } + StringBuilder nextNodeUserSids = new StringBuilder(); + StringBuilder nextNodeOrgPathSids = new StringBuilder(); + for (SysUserVo su : sysUserVos) { + nextNodeUserSids.append(su.getSid()).append(","); + nextNodeOrgPathSids.append(su.getOrgSidPath()).append(","); + } + //符合条件的用户的sid,拼接的字符串 + String nextNodeUserSids_ = nextNodeUserSids.toString(); + String nextNodeOrgPathSids_ = nextNodeOrgPathSids.toString(); + if(StringUtils.isBlank(nextNodeUserSids_)) + return rb.fail().setMsg("环节没有用户"); + nextNodeUserSids_ = nextNodeUserSids_.substring(0, nextNodeUserSids_.length() - 1); + nextNodeOrgPathSids_ = nextNodeOrgPathSids_.substring(0, nextNodeOrgPathSids_.length() - 1); + mapParam.setUserSid(nextNodeUserSids_); + mapParam.setOrgPath(nextNodeOrgPathSids_); + return rb.success().setData(mapParam); + } + public ResultBean getProcessCirculationNodesByMap(BusinessVariables bv) { + String modelId = null; + if (bv.getModelId()!= null) { + modelId = bv.getModelId(); + } + String procId = null; + if (bv.getModelId() != null) { + procId = bv.getModelId(); + } + /* if(bv.getFormVariables()==null){ + return ResultBean.fireFail().setMsg("业务参数集合 不能为空!"); + }*/ + if(bv.getFormVariables()==null) + bv.setFormVariables(new HashMap()); + List flowElements = processService.calApprovePath(procId, modelId, bv.getFormVariables()); + List collect = flowElements.stream().filter(item -> item.getId().length() > 0).collect(Collectors.toList()); + for (int i = 0; i < collect.size(); i++) { + if (collect.get(i).getId().equals(modelId)) { + FlowElement item = collect.get(i + 1); + String s = JSON.toJSONString(item); + JSONObject jsonObject = JSONObject.parseObject(s); + Object candidateGroups = jsonObject.get("candidateGroups"); + JSONArray candidateGroups_arr = new JSONArray(); + if (candidateGroups != null) { + candidateGroups_arr = JSONArray.parseArray(candidateGroups.toString()); + } + if (candidateGroups_arr.size() > 0) { + } + } + } + ResultBean>> rb = new ResultBean>>(); + List> list = new ArrayList<>(); + for (FlowElement f : flowElements) { + Map map = new HashMap<>(); + map.put("name", f.getName()); + map.put("id", f.getId()); + String s = JSON.toJSONString(f); + JSONObject jsonObject = JSONObject.parseObject(s); + Object candidateGroups = jsonObject.get("candidateGroups"); + map.put("candidateGroups", candidateGroups); + list.add(map); + } + return rb.setData(list); + } + + /** + * 流程历史流转记录 + * + * @param procInsId 流程实例Id + * @return + */ + public ResultBean flowRecord(String procInsId, String deployId) { + Map map = new HashMap(); + if (StringUtils.isNotBlank(procInsId)) { + List list = historyService + .createHistoricActivityInstanceQuery() + .processInstanceId(procInsId) + .orderByHistoricActivityInstanceStartTime() + .desc().list(); + List hisFlowList = new ArrayList<>(); + for (HistoricActivityInstance histIns : list) { + if (StringUtils.isNotBlank(histIns.getTaskId())) { + FlowTask flowTask = new FlowTask(); + flowTask.setTaskId(histIns.getTaskId()); + flowTask.setTaskName(histIns.getActivityName()); + flowTask.setCreateTime(histIns.getStartTime()); + flowTask.setFinishTime(histIns.getEndTime().toString()); + if (StringUtils.isNotBlank(histIns.getAssignee())) { + /* SysUser sysUser = sysUserService.selectUserById(Long.parseLong(histIns.getAssignee())); + flowTask.setAssigneeId(sysUser.getUserId()); + flowTask.setAssigneeName(sysUser.getNickName()); + flowTask.setDeptName(sysUser.getDept().getDeptName());*/ + } + // 展示审批人员 + List linksForTask = historyService.getHistoricIdentityLinksForTask(histIns.getTaskId()); + StringBuilder stringBuilder = new StringBuilder(); + for (HistoricIdentityLink identityLink : linksForTask) { + if ("candidate".equals(identityLink.getType())) { + if (StringUtils.isNotBlank(identityLink.getUserId())) { + /*SysUser sysUser = sysUserService.selectUserById(Long.parseLong(identityLink.getUserId())); + stringBuilder.append(sysUser.getNickName()).append(",");*/ + } + if (StringUtils.isNotBlank(identityLink.getGroupId())) { + /* SysRole sysRole = sysRoleService.selectRoleById(Long.parseLong(identityLink.getGroupId())); + stringBuilder.append(sysRole.getRoleName()).append(",");*/ + } + } + } + if (StringUtils.isNotBlank(stringBuilder)) { + flowTask.setCandidate(stringBuilder.substring(0, stringBuilder.length() - 1)); + } + + flowTask.setDuration(histIns.getDurationInMillis() == null || histIns.getDurationInMillis() == 0 ? null : FlowableUtils.getDate(histIns.getDurationInMillis())); + // 获取意见评论内容 + List commentList = taskService.getProcessInstanceComments(histIns.getProcessInstanceId()); + /* commentList.forEach(comment -> { + if (histIns.getTaskId().equals(comment.getTaskId())) { + String type = comment.getType(); + FlowCommentDto build = FlowCommentDto.builder().type(type).comment(comment.getFullMessage()).build(); + flowTask.setComment(build); + } + });*/ + hisFlowList.add(flowTask); + } + } + map.put("flowList", hisFlowList); + } + // 第一次申请获取初始化表单 + if (StringUtils.isNotBlank(deployId)) { + SysForm sysForm = sysInstanceFormService.selectSysDeployFormByDeployId(deployId); + if (Objects.isNull(sysForm)) { + return ResultBean.fireFail().setMsg("请先配置流程表单"); + } + map.put("formData", JSONObject.parseObject(sysForm.getFormContent())); + } + return ResultBean.fireSuccess().setData(map); + } + + /** + * 流程历史流转记录 + * + * @param procInsId 流程实例Id + * @return + */ + public ResultBean businessFlowRecord(String procInsId) { + ResultBean rb=ResultBean.fireFail(); + FlowRecordVo flowRecordVo = new FlowRecordVo(); + if (StringUtils.isNotBlank(procInsId)) { + List list = historyService + .createHistoricActivityInstanceQuery() + .processInstanceId(procInsId) + .orderByHistoricActivityInstanceStartTime() + .desc().list(); + Map processInstance=processService.getProcessInstanceById(procInsId); + List hisFlowList = new ArrayList<>(); + for (HistoricActivityInstance histIns : list) { + if (StringUtils.isNotBlank(histIns.getTaskId())) { + FlowTask flowTask = new FlowTask(); + flowTask.setTaskId(histIns.getTaskId()); + flowTask.setTaskName(histIns.getActivityName()); + flowTask.setTaskDefKey(histIns.getActivityId()); + Date startTime = histIns.getStartTime(); + flowTask.setCreateTime(startTime); + Date endTime = histIns.getEndTime(); + flowTask.setFinishTime(endTime.toString()); + //processInstance.get("END_TIME_") timestap类型不能转string + String end_time_ = processInstance.get("END_TIME_") == null ? "" : "end"; + flowTask.setProcessEndTime(end_time_); +/* + flowTask.setCreateTime(histIns.getStartTime()); + flowTask.setFinishTime(histIns.getEndTime());*/ + if (StringUtils.isNotBlank(histIns.getAssignee())) { + ResultBean> sysUserVoResultBean = sysUserFeign.fetchBySids(histIns.getAssignee());// sysUserService.selectUserById(Long.parseLong(histIns.getAssignee())); + List data1 = sysUserVoResultBean.getData(); + List taskUserInfos=new ArrayList<>(); + for( SysUserVo data:data1){ + TaskUserInfo taskUserInfo=new TaskUserInfo(); + taskUserInfo.setAssigneeName(data.getName()); + taskUserInfo.setAssigneeSid(data.getSid()); + if(!StringUtils.isBlank(data.getHeadImage())){ + taskUserInfo.setAssigneeHeadImage(fileUploadComponent.getUrlPrefix() +data.getHeadImage()); + } + taskUserInfos.add(taskUserInfo); + } + flowTask.setTaskUserInfos(taskUserInfos); + } + // 展示审批人员 + List linksForTask = historyService.getHistoricIdentityLinksForTask(histIns.getTaskId()); + StringBuilder stringBuilder = new StringBuilder(); + for (HistoricIdentityLink identityLink : linksForTask) { + if ("candidate".equals(identityLink.getType())) { + if (StringUtils.isNotBlank(identityLink.getUserId())) { + /*SysUser sysUser = sysUserService.selectUserById(Long.parseLong(identityLink.getUserId())); + stringBuilder.append(sysUser.getNickName()).append(",");*/ + } + if (StringUtils.isNotBlank(identityLink.getGroupId())) { + /* SysRole sysRole = sysRoleService.selectRoleById(Long.parseLong(identityLink.getGroupId())); + stringBuilder.append(sysRole.getRoleName()).append(",");*/ + } + } + } + if (StringUtils.isNotBlank(stringBuilder)) { + flowTask.setCandidate(stringBuilder.substring(0, stringBuilder.length() - 1)); + } + + flowTask.setDuration(histIns.getDurationInMillis() == null || histIns.getDurationInMillis() == 0 ? null : FlowableUtils.getDate(histIns.getDurationInMillis())); + // 获取意见评论内容 + List commentList = taskService.getProcessInstanceComments(histIns.getProcessInstanceId()); + commentList.forEach(comment -> { + if (histIns.getTaskId().equals(comment.getTaskId())) { + String type = comment.getType(); + FlowCommentDto build = FlowCommentDto.builder().type(type).comment(comment.getFullMessage()).build(); + flowTask.setComment(build); + } + }); + hisFlowList.add(flowTask); + } + } + flowRecordVo.setFlowList(hisFlowList); + } + return rb.success().setData(flowRecordVo); + } + + /** + * 获取流程执行过程 + * + * @param procInsId + * @return + */ + public ResultBean getFlowViewer(String procInsId) { + List flowViewerList = new ArrayList<>(); + FlowViewerDto flowViewerDto; + // 获得活动的节点 + List hisActIns = historyService.createHistoricActivityInstanceQuery() + .processInstanceId(procInsId) + .orderByHistoricActivityInstanceStartTime() + .asc().list(); + for (HistoricActivityInstance activityInstance : hisActIns) { + if (!"sequenceFlow".equals(activityInstance.getActivityType())) { + flowViewerDto = new FlowViewerDto(); + flowViewerDto.setKey(activityInstance.getActivityId()); + flowViewerDto.setCompleted(!Objects.isNull(activityInstance.getEndTime())); + flowViewerList.add(flowViewerDto); + } + } + return ResultBean.fireSuccess().setData(flowViewerList); + } + + /** + * 代办任务列表 + * + * @param pageNum 当前页码 + * @param pageSize 每页条数 + * @return + */ + public ResultBean> todoList(Integer pageNum, Integer pageSize) { + Page page = new Page<>(); + // Long userId = SecurityUtils.getLoginUser().getUser().getUserId(); + TaskQuery taskQuery = taskService.createTaskQuery() + .active() + .includeProcessVariables() + .taskAssignee("0d8d8119-d476-47ce-89c2-075cd809dda6") + .orderByTaskCreateTime().desc(); + page.setTotal(taskQuery.count()); + List taskList = taskQuery.listPage(pageNum - 1, pageSize); + List flowList = new ArrayList<>(); + for (Task task : taskList) { + FlowTaskDto flowTask = new FlowTaskDto(); + // 当前流程信息 + flowTask.setTaskId(task.getId()); + flowTask.setTaskDefKey(task.getTaskDefinitionKey()); + flowTask.setCreateTime(task.getCreateTime()); + flowTask.setProcDefId(task.getProcessDefinitionId()); + flowTask.setTaskName(task.getName()); + // 流程定义信息 + ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() + .processDefinitionId(task.getProcessDefinitionId()) + .singleResult(); + flowTask.setDeployId(pd.getDeploymentId()); + flowTask.setProcDefName(pd.getName()); + flowTask.setProcDefVersion(pd.getVersion()); + flowTask.setProcInsId(task.getProcessInstanceId()); + + // 流程发起人信息 + HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() + .processInstanceId(task.getProcessInstanceId()) + .singleResult(); + SysUser startUser = new SysUser();//sysUserService.selectUserById(Long.parseLong(historicProcessInstance.getStartUserId())); +// SysUser startUser = sysUserService.selectUserById(Long.parseLong(task.getAssignee())); + flowTask.setStartUserSid(startUser.getSid()); + flowTask.setStartUserName(startUser.getUserName()); + flowTask.setStartDeptName(""); + flowList.add(flowTask); + } + page.setRecords(flowList); + ResultBean> rb = new ResultBean>().fireFail(); + return rb.setData(page); + } + + /** + * 代办任务列表 + * + * @param userSid 参数 + * @param params 参数 + * @param pageNum 当前页码 + * @param pageSize 每页条数 + * @return + */ + public ResultBean> businessTodoList(String userSid,String orgPath, List params, Integer pageNum, + Integer pageSize) { + + Page page = new Page<>(); + TaskQuery taskQuery = taskService.createTaskQuery(); + + // 流程参数 + Map paramMap = new HashMap<>(); + // 挂载表单参数 + for (BusinessTaskParam btq : params) { + paramMap.put(btq.getField(), btq.getValue()); +// if(btq.getSqlOperationSymbol().equals(SQLOperationSymbol.EQUAL)){ +// taskQuery.processVariableValueEquals(btq.getField(),btq.getValue()); +// } +// if(btq.getSqlOperationSymbol().equals(SQLOperationSymbol.LIKE)){ +// taskQuery.processVariableValueLike(btq.getField(),"%"+btq.getValue()+"%"); +// } +// if(btq.getSqlOperationSymbol().equals(SQLOperationSymbol.NONE)){ +// if("processDefinitionId".equals(btq.getField())){ +// taskQuery.processDefinitionId(btq.getValue()); +// } +// } + if (btq.getSqlOperationSymbol().equals(SQLOperationSymbol.NONE)) { + if ("orgSid".equals(btq.getField())) { + String value = btq.getValue(); + String[] split = value.split(","); + for (int i = 0; i < split.length; i++) { + if (i != 0) { + taskQuery.or().processVariableValueLike("orgSid", split[i] + "%"); + } else { + taskQuery.processVariableValueLike("orgSid", split[0] + "%"); + } + } + } + } + } + // 用户角色sid + // List roleSidList = sysUserRoleFeign.getUserRoleSidByUserSid(userSid).getData(); + /* if (CollectionUtils.isEmpty(roleSidList)) { + return new ResultBean().fail().setMsg("请先设置用户角色"); + }*/ + TaskQuery or = taskQuery.active() + .includeProcessVariables() + .includeTaskLocalVariables(); + if(StringUtils.isNotBlank(orgPath)){ + // or.taskVariableValueLike("orgPath", "%" + orgPath + "%"); + } + //.taskCandidateGroupIn(roleSidList) + or.taskAssigneeLike("%" + userSid + "%") + .orderByTaskCreateTime().desc(); + // 查询筛选条件 + if (paramMap.get("startDate") != null && StringUtils.isNotBlank(paramMap.get("startDate").toString())) { + taskQuery.taskCreatedAfter(DateUtils.dateStrConvertDate(paramMap.get("startDate").toString(), "yyyy-MM-dd")); + } + if (paramMap.get("endDate") != null && StringUtils.isNotBlank(paramMap.get("endDate").toString())) { + taskQuery.taskCreatedBefore(DateUtils.dateStrConvertDate(paramMap.get("endDate").toString(), "yyyy-MM-dd")); + } + if (paramMap.get("proDefName") != null && StringUtils.isNotBlank(paramMap.get("proDefName").toString())) { + taskQuery.processDefinitionNameLike("%" + paramMap.get("proDefName") + "%"); + } + page.setTotal(taskQuery.count()); + int p = (pageNum - 1) * pageSize; + List taskList = taskQuery.listPage(p, pageSize); + List flowList = new ArrayList<>(); + for (Task task : taskList) { + + FlowTaskDto flowTask = new FlowTaskDto(); + Map processVariables = task.getProcessVariables(); + flowTask.setProcessVariables(processVariables); + Map taskLocalVariables= task.getTaskLocalVariables(); + System.out.println(JSON.toJSONString(taskLocalVariables)); + // 当前流程信息 + flowTask.setTaskId(task.getId()); + flowTask.setTaskDefKey(task.getTaskDefinitionKey()); + flowTask.setCreateTime(task.getCreateTime()); + + flowTask.setProcDefId(task.getProcessDefinitionId()); + flowTask.setTaskName(task.getName()); + // 流程定义信息 + ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() + .processDefinitionId(task.getProcessDefinitionId()) + .singleResult(); + flowTask.setDeployId(pd.getDeploymentId()); + flowTask.setProcDefName(pd.getName()); + flowTask.setProcDefVersion(pd.getVersion()); + flowTask.setProcInsId(task.getProcessInstanceId()); + // 流程发起人信息 + HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() + .processInstanceId(task.getProcessInstanceId()) + .singleResult(); + flowTask.setProcessCreateTime(historicProcessInstance.getStartTime()); + ResultBean sysUserVoResultBean = sysUserFeign.fetchBySid(historicProcessInstance.getStartUserId()); + if(sysUserVoResultBean.getData()!=null){ + flowTask.setStartUserSid(sysUserVoResultBean.getData().getSid()); + flowTask.setStartUserName(sysUserVoResultBean.getData().getName()); + String createOrgPath = ConstantUtils.getString(flowTask.getProcessVariables(),"createrOrgPath",""); + String ogrName=""; + if(StringUtils.isNotBlank(createOrgPath)){ + List stringList = Arrays.asList(createOrgPath.split("/")); + ResultBean sysOrganizationVoResultBean = sysOrganizationFeign.fetchBySid(stringList.get(stringList.size()-1)); + if(sysOrganizationVoResultBean.getData() != null){ + if(StringUtils.isNotBlank(sysOrganizationVoResultBean.getData().getPsid())){ + ResultBean sysOrganizationVoResultBeanP = sysOrganizationFeign.fetchBySid(sysOrganizationVoResultBean.getData().getPsid()); + if(sysOrganizationVoResultBeanP.getData() != null){ + ogrName=sysOrganizationVoResultBeanP.getData().getName(); + flowTask.setStartDeptName(ogrName+"-"+sysOrganizationVoResultBean.getData().getName()); + } + }else{ + flowTask.setStartDeptName(sysOrganizationVoResultBean.getData().getName()); + } + } + }else{ + flowTask.setStartDeptName(sysUserVoResultBean.getData().getOrganizationName()); + } + } + ResultBean sysUserVoResultBean2 = sysUserFeign.fetchBySid(userSid); + flowTask.setAssigneeName(sysUserVoResultBean2.getData().getName()); + flowTask.setAssigneeSid(sysUserVoResultBean2.getData().getSid()); + flowTask.setDeptName(sysUserVoResultBean2.getData().getOrganizationName()); + + // 设置手机端参数 +// Map> variablesMap = getAppOrPcVariables(flowTask); +// flowTask.setAppVariables(variablesMap.get("appVariables")); +// // 设置pc端参数 +// flowTask.setPcVariables(variablesMap.get("pcVariables")); + + flowList.add(flowTask); + } + page.setRecords(flowList); + ResultBean> rb = new ResultBean>(); + return rb.success().setData(page); + } + + /** + * 业务系统查询待办任务列表数量 + * + * @param userSid + * @return + */ + public ResultBean getTodoNum(String userSid,String orgPath) { + TaskQuery taskQuery = taskService.createTaskQuery() + .taskAssigneeLike("%" + userSid + "%"); + + if(StringUtils.isNotBlank(orgPath)){ + /*taskQuery + .taskVariableValueLike("orgPath", "%"+orgPath+"%");*/ + } + long num = taskQuery.count(); + return new ResultBean().success().setData(Integer.parseInt(String.valueOf(num))); + } + + /** + * 获取流程变量 + * + * @param taskId + * @return + */ + public ResultBean processVariables(String taskId) { + // 流程变量 + HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().includeProcessVariables().finished().taskId(taskId).singleResult(); + if (Objects.nonNull(historicTaskInstance)) { + return ResultBean.fireSuccess().setData(historicTaskInstance.getProcessVariables()); + } else { + Map variables = taskService.getVariables(taskId); + return ResultBean.fireSuccess().setData(variables); + } + } + + /** + * 已办任务列表 + * + * @param pageNum 当前页码 + * @param pageSize 每页条数 + * @return + */ + public ResultBean> finishedList(Integer pageNum, Integer pageSize) { + + Page page = new Page<>(); + HistoricTaskInstanceQuery taskInstanceQuery = historyService.createHistoricTaskInstanceQuery() + .includeProcessVariables() + .finished() + .taskAssignee("0d8d8119-d476-47ce-89c2-075cd809dda6") + .orderByHistoricTaskInstanceEndTime() + .desc(); + List historicTaskInstanceList = taskInstanceQuery.listPage(pageNum - 1, pageSize); + List hisTaskList = Lists.newArrayList(); + for (HistoricTaskInstance histTask : historicTaskInstanceList) { + FlowTaskDto flowTask = new FlowTaskDto(); + // 当前流程信息 + flowTask.setTaskId(histTask.getId()); + // 审批人员信息 + flowTask.setCreateTime(histTask.getCreateTime()); + flowTask.setFinishTime(histTask.getEndTime()); + flowTask.setDuration(FlowableUtils.getDate(histTask.getDurationInMillis())); + flowTask.setProcDefId(histTask.getProcessDefinitionId()); + flowTask.setTaskDefKey(histTask.getTaskDefinitionKey()); + flowTask.setTaskName(histTask.getName()); + + // 流程定义信息 + ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() + .processDefinitionId(histTask.getProcessDefinitionId()) + .singleResult(); + flowTask.setDeployId(pd.getDeploymentId()); + flowTask.setProcDefName(pd.getName()); + flowTask.setProcDefVersion(pd.getVersion()); + flowTask.setProcInsId(histTask.getProcessInstanceId()); + flowTask.setHisProcInsId(histTask.getProcessInstanceId()); + + // 流程发起人信息 + HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() + .processInstanceId(histTask.getProcessInstanceId()) + .singleResult(); + //SysUser startUser = sysUserService.selectUserById(Long.parseLong(historicProcessInstance.getStartUserId())); + flowTask.setStartUserSid("usersid"); + flowTask.setStartUserName("username"); + flowTask.setStartDeptName("deptName"); + hisTaskList.add(flowTask); + } + page.setTotal(hisTaskList.size()); + page.setRecords(hisTaskList); +// Map result = new HashMap<>(); +// result.put("result",page); +// result.put("finished",true); + ResultBean> rb = new ResultBean>().fireFail(); + return rb.setData(page); + } + + /** + * 已办任务列表 + * + * @param pageNum 当前页码 + * @param pageSize 每页条数 + * @return + */ + public ResultBean> businessFinishedList(String userSid, List params, Integer pageNum, Integer pageSize) { + + Page page = new Page<>(); + Map paraMap = new HashMap<>(); + List> ll = new ArrayList<>(); + for (BusinessTaskParam btq : params) { + paraMap.put(btq.getField(), btq.getValue()); + + Map mapss = new HashMap<>(); + if (btq.getSqlOperationSymbol().equals(SQLOperationSymbol.EQUAL)) { + mapss.put("symbol", "="); + mapss.put("value", btq.getValue()); + mapss.put("filed", btq.getField()); + } + if (btq.getSqlOperationSymbol().equals(SQLOperationSymbol.LIKE)) { + mapss.put("symbol", "like"); + mapss.put("value", "%" + btq.getValue() + "%"); + mapss.put("filed", btq.getField()); + } + /* if(btq.getSqlOperationSymbol().equals(SQLOperationSymbol.NONE)){ + if("processDefinitionId".equals(btq.getField())){ + taskInstanceQuery.processDefinitionId(btq.getValue()); + } + }*/ + ll.add(mapss); + } + + paraMap.put("userSid", userSid); + paraMap.put("list", ll); + paraMap.put("page", (pageNum - 1) * pageSize); + paraMap.put("size", pageSize); + // List> maps = baseMapper.finishedList(userSid, ll ,(pageNum-1)*pageSize,pageSize); + List> maps = baseMapper.finishedList1(paraMap); + int count = baseMapper.finishedListCount(paraMap); + + List hisTaskList = new ArrayList(); + for (Map histTask : maps) { + FlowTaskDto flowTask = new FlowTaskDto(); + // 当前流程信息 + flowTask.setTaskId(histTask.get("ID_").toString()); + // 审批人员信息 + Timestamp start_time_ = (Timestamp) histTask.get("START_TIME_"); + long time = start_time_.getTime(); + Date date = new Date(time); + flowTask.setCreateTime(date); + flowTask.setAssigneeSid(histTask.get("ASSIGNEE_") == null ? "" : histTask.get("ASSIGNEE_").toString()); + if (histTask.get("ASSIGNEE_") != null && StringUtils.isNotBlank(histTask.get("ASSIGNEE_").toString())) { + ResultBean> assignee_ = sysUserFeign.fetchBySids(histTask.get("ASSIGNEE_").toString()); + StringBuilder userName=new StringBuilder(); + List data1 = assignee_.getData(); + for( SysUserVo data:data1){ + userName.append(data.getName()).append(","); + } + String userName_str=""; + userName_str=userName.substring(0,userName.length()-1); + flowTask.setAssigneeName(userName_str); + } + + flowTask.setHasRevokeButton(userSid.equals(flowTask.getAssigneeSid()) ? true : false); + flowTask.setProcDefId(histTask.get("PROC_DEF_ID_") == null ? "" : histTask.get("PROC_DEF_ID_").toString()); + flowTask.setTaskDefKey(histTask.get("taskDefKey") == null ? "" : histTask.get("taskDefKey").toString()); + flowTask.setTaskName(histTask.get("NAME_") == null ? "" : histTask.get("NAME_").toString()); + // 判断是否办结 + /*Object end_act_id_ = histTask.get("END_ACT_ID_"); + if (end_act_id_ != null) { + flowTask.setTaskName(ProcessStateEnum.FINISHED.getStateName()); + }*/ + + // 流程定义信息 +// ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() +// .processDefinitionId(histTask.get("PROC_DEF_ID_").toString()) +// .singleResult(); + flowTask.setDeployId(histTask.get("DEPLOYMENT_ID_") == null ? "" : histTask.get("DEPLOYMENT_ID_").toString()); + flowTask.setProcDefName(histTask.get("PROC_DEF_NAME_") == null ? "" : histTask.get("PROC_DEF_NAME_").toString()); + flowTask.setProcDefVersion(histTask.get("PROC_DEF_VERSION_") == null ? 0 : Integer.parseInt(histTask.get("PROC_DEF_VERSION_").toString())); + flowTask.setProcInsId(histTask.get("PROC_INST_ID_").toString()); + flowTask.setHisProcInsId(histTask.get("PROC_INST_ID_").toString()); + + // 流程发起人信息 +// HistoricProcessInstance hi = historyService.createHistoricProcessInstanceQuery() +// .processInstanceId(histTask.get("PROC_INST_ID_").toString()) +// .singleResult(); + ResultBean sysUserVoResultBean = sysUserFeign.fetchBySid(histTask.get("START_USER_ID_").toString()); + flowTask.setStartUserSid(sysUserVoResultBean.getData().getSid()); + flowTask.setStartUserName(sysUserVoResultBean.getData().getName()); + // ResultBean sysUserVoResultBean = sysUserFeign.fetchBySid(historicProcessInstance.getStartUserId()); + if(sysUserVoResultBean.getData()!=null){ + flowTask.setStartUserSid(sysUserVoResultBean.getData().getSid()); + flowTask.setStartUserName(sysUserVoResultBean.getData().getName()); + /*ResultBean pathSidByUserSid = sysStaffOrgFeign.getPathSidByUserSid(sysUserVoResultBean.getData().getSid()); + String ogrName=""; + if(pathSidByUserSid.getData()!=null){ + ResultBean sysOrganizationVoResultBean = sysOrganizationFeign.fetchBySid(pathSidByUserSid.getData()); + ogrName=sysOrganizationVoResultBean.getData().getName(); + } + flowTask.setStartDeptName(ogrName+"-"+sysUserVoResultBean.getData().getOrganizationName());*/ + } + // flowTask.setStartDeptName(sysUserVoResultBean.getData().getOrganizationName()); + HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().includeProcessVariables().taskId(flowTask.getTaskId()).singleResult(); + flowTask.setProcessVariables(historicTaskInstance.getProcessVariables()); + Object end_act_id = histTask.get("end_act_id_"); + if (end_act_id != null) { + flowTask.setEndActId((String) end_act_id); + } + Object end_time = histTask.get("END_TIME_"); + if (end_time != null) { + Timestamp end_time_t = (Timestamp) end_time; + long end_time_t_l = end_time_t.getTime(); + flowTask.setEndTime(new Date(end_time_t_l)); + } + flowTask.setProcessVariables(historicTaskInstance.getProcessVariables()); + String createOrgPath = ConstantUtils.getString(flowTask.getProcessVariables(),"createrOrgPath",""); + String ogrName=""; + if(StringUtils.isNotBlank(createOrgPath)){ + List stringList = Arrays.asList(createOrgPath.split("/")); + ResultBean sysOrganizationVoResultBean = sysOrganizationFeign.fetchBySid(stringList.get(stringList.size()-1)); + if(sysOrganizationVoResultBean.getData() != null){ + if(StringUtils.isNotBlank(sysOrganizationVoResultBean.getData().getPsid())){ + ResultBean sysOrganizationVoResultBeanP = sysOrganizationFeign.fetchBySid(sysOrganizationVoResultBean.getData().getPsid()); + if(sysOrganizationVoResultBeanP.getData() != null){ + ogrName=sysOrganizationVoResultBeanP.getData().getName(); + flowTask.setStartDeptName(ogrName+"-"+sysOrganizationVoResultBean.getData().getName()); + } + }else{ + flowTask.setStartDeptName(sysOrganizationVoResultBean.getData().getName()); + } + } + }else{ + ResultBean pathSidByUserSid = sysStaffOrgFeign.getPathSidByUserSid(sysUserVoResultBean.getData().getSid()); + if(pathSidByUserSid.getData()!=null){ + ResultBean sysOrganizationVoResultBean = sysOrganizationFeign.fetchBySid(pathSidByUserSid.getData()); + if(sysOrganizationVoResultBean.getData() != null){ + ogrName=sysOrganizationVoResultBean.getData().getName(); + flowTask.setStartDeptName(ogrName+"-"+sysUserVoResultBean.getData().getOrganizationName()); + }else{ + flowTask.setStartDeptName(sysUserVoResultBean.getData().getOrganizationName()); + } + } + + } + hisTaskList.add(flowTask); + } + page.setTotal(count); + page.setRecords(hisTaskList); + ResultBean> rb = new ResultBean>(); + return rb.success().setData(page); + } + /** + * 已办任务列表 + * + * @param pageNum 当前页码 + * @param pageSize 每页条数 + * @return + */ + public ResultBean> businessFinishedListForApp(String userSid, List params, Integer pageNum, Integer pageSize) { + + Page page = new Page<>(); + Map paraMap = new HashMap<>(); + List> ll = new ArrayList<>(); + for (BusinessTaskParam btq : params) { + paraMap.put(btq.getField(), btq.getValue()); + + Map mapss = new HashMap<>(); + if (btq.getSqlOperationSymbol().equals(SQLOperationSymbol.EQUAL)) { + mapss.put("symbol", "="); + mapss.put("value", btq.getValue()); + mapss.put("filed", btq.getField()); + } + if (btq.getSqlOperationSymbol().equals(SQLOperationSymbol.LIKE)) { + mapss.put("symbol", "like"); + mapss.put("value", "%" + btq.getValue() + "%"); + mapss.put("filed", btq.getField()); + } + /* if(btq.getSqlOperationSymbol().equals(SQLOperationSymbol.NONE)){ + if("processDefinitionId".equals(btq.getField())){ + taskInstanceQuery.processDefinitionId(btq.getValue()); + } + }*/ + ll.add(mapss); + } + + paraMap.put("userSid", userSid); + paraMap.put("list", ll); + paraMap.put("page", (pageNum - 1) * pageSize); + paraMap.put("size", pageSize); + // List> maps = baseMapper.finishedList(userSid, ll ,(pageNum-1)*pageSize,pageSize); + List> maps = baseMapper.finishedList1(paraMap); + int count = baseMapper.finishedListCount(paraMap); + + List hisTaskList = new ArrayList(); + for (Map histTask : maps) { + FlowTaskDto flowTask = new FlowTaskDto(); + // 当前流程信息 + flowTask.setTaskId(histTask.get("ID_").toString()); + // 审批人员信息 + Timestamp start_time_ = (Timestamp) histTask.get("START_TIME_"); + Timestamp processCreateTime = (Timestamp) histTask.get("processCreateTime"); + + long time = start_time_.getTime(); + long processCreateTime1 = processCreateTime.getTime(); + Date date = new Date(time); + flowTask.setCreateTime(date); + flowTask.setProcessCreateTime(new Date(processCreateTime1)); + flowTask.setAssigneeSid(histTask.get("ASSIGNEE_") == null ? "" : histTask.get("ASSIGNEE_").toString()); + if (histTask.get("ASSIGNEE_") != null && StringUtils.isNotBlank(histTask.get("ASSIGNEE_").toString())) { + ResultBean> assignee_ = sysUserFeign.fetchBySids(histTask.get("ASSIGNEE_").toString()); + StringBuilder userName=new StringBuilder(); + List data1 = assignee_.getData(); + for( SysUserVo data:data1){ + userName.append(data.getName()).append(","); + } + String userName_str=""; + userName_str=userName.substring(0,userName.length()-1); + flowTask.setAssigneeName(userName_str); + } + + flowTask.setHasRevokeButton(userSid.equals(flowTask.getAssigneeSid()) ? true : false); + flowTask.setProcDefId(histTask.get("PROC_DEF_ID_") == null ? "" : histTask.get("PROC_DEF_ID_").toString()); + flowTask.setTaskDefKey(histTask.get("taskDefKey") == null ? "" : histTask.get("taskDefKey").toString()); + flowTask.setTaskName(histTask.get("NAME_") == null ? "" : histTask.get("NAME_").toString()); + // 判断是否办结 + /*Object end_act_id_ = histTask.get("END_ACT_ID_"); + if (end_act_id_ != null) { + flowTask.setTaskName(ProcessStateEnum.FINISHED.getStateName()); + }*/ + + // 流程定义信息 +// ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() +// .processDefinitionId(histTask.get("PROC_DEF_ID_").toString()) +// .singleResult(); + flowTask.setDeployId(histTask.get("DEPLOYMENT_ID_") == null ? "" : histTask.get("DEPLOYMENT_ID_").toString()); + flowTask.setProcDefName(histTask.get("PROC_DEF_NAME_") == null ? "" : histTask.get("PROC_DEF_NAME_").toString()); + flowTask.setProcDefVersion(histTask.get("PROC_DEF_VERSION_") == null ? 0 : Integer.parseInt(histTask.get("PROC_DEF_VERSION_").toString())); + flowTask.setProcInsId(histTask.get("PROC_INST_ID_").toString()); + flowTask.setHisProcInsId(histTask.get("PROC_INST_ID_").toString()); + + // 流程发起人信息 +// HistoricProcessInstance hi = historyService.createHistoricProcessInstanceQuery() +// .processInstanceId(histTask.get("PROC_INST_ID_").toString()) +// .singleResult(); + ResultBean sysUserVoResultBean = sysUserFeign.fetchBySid(histTask.get("START_USER_ID_").toString()); + flowTask.setStartUserSid(sysUserVoResultBean.getData().getSid()); + flowTask.setStartUserName(sysUserVoResultBean.getData().getName()); +// flowTask.setStartDeptName(sysUserVoResultBean.getData().getOrganizationName()); + HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().includeProcessVariables().taskId(flowTask.getTaskId()).singleResult(); + flowTask.setProcessVariables(historicTaskInstance.getProcessVariables()); + Object end_act_id = histTask.get("end_act_id_"); + if (end_act_id != null) { + flowTask.setEndActId((String) end_act_id); + } + Object end_time = histTask.get("END_TIME_"); + if (end_time != null) { + Timestamp end_time_t = (Timestamp) end_time; + long end_time_t_l = end_time_t.getTime(); + flowTask.setEndTime(new Date(end_time_t_l)); + } + flowTask.setProcessVariables(historicTaskInstance.getProcessVariables()); + + ResultBean> listResultBean = sysProUrlService.selectUrlByKey(flowTask.getProcDefId(), flowTask.getTaskDefKey(), "2", "2"); + if(listResultBean.getData()!=null&&listResultBean.getData().size()>0){ + flowTask.setSysProUrlVo(listResultBean.getData().get(0)); + } + //发起人部门 + String createOrgPath = ConstantUtils.getString(flowTask.getProcessVariables(),"createOrgPath",""); + String ogrName=""; + if(StringUtils.isNotBlank(createOrgPath)){ + List stringList = Arrays.asList(createOrgPath.split("/")); + ResultBean sysOrganizationVoResultBean = sysOrganizationFeign.fetchBySid(stringList.get(stringList.size()-1)); + if(sysOrganizationVoResultBean.getData() != null){ + if(StringUtils.isNotBlank(sysOrganizationVoResultBean.getData().getPsid())){ + ResultBean sysOrganizationVoResultBeanP = sysOrganizationFeign.fetchBySid(sysOrganizationVoResultBean.getData().getPsid()); + if(sysOrganizationVoResultBeanP.getData() != null){ + ogrName=sysOrganizationVoResultBeanP.getData().getName(); + flowTask.setStartDeptName(ogrName+"-"+sysOrganizationVoResultBean.getData().getName()); + } + }else{ + flowTask.setStartDeptName(sysOrganizationVoResultBean.getData().getName()); + } + } + }else{ + ResultBean pathSidByUserSid = sysStaffOrgFeign.getPathSidByUserSid(sysUserVoResultBean.getData().getSid()); + if(pathSidByUserSid.getData()!=null){ + ResultBean sysOrganizationVoResultBean = sysOrganizationFeign.fetchBySid(pathSidByUserSid.getData()); + if(sysOrganizationVoResultBean.getData() != null){ + ogrName=sysOrganizationVoResultBean.getData().getName(); + flowTask.setStartDeptName(ogrName+"-"+sysUserVoResultBean.getData().getOrganizationName()); + }else{ + flowTask.setStartDeptName(sysUserVoResultBean.getData().getOrganizationName()); + } + + } + + } + + + hisTaskList.add(flowTask); + } + page.setTotal(count); + page.setRecords(hisTaskList); + ResultBean> rb = new ResultBean>(); + return rb.success().setData(page); + } + + /** + * 完成任务 + * + * @param taskVo 请求实体参数 + */ + @Transactional(rollbackFor = Exception.class) + public ResultBean complete(FlowTaskVo taskVo) { + Task task = taskService.createTaskQuery().taskId(taskVo.getTaskId()).singleResult(); + if (Objects.isNull(task)) { + return ResultBean.fireFail().setMsg("任务不存在"); + } + if (DelegationState.PENDING.equals(task.getDelegationState())) { + taskService.addComment(taskVo.getTaskId(), taskVo.getInstanceId(), FlowComment.DELEGATE.getType(), taskVo.getComment()); + taskService.resolveTask(taskVo.getTaskId(), taskVo.getValues()); + } else { + taskService.addComment(taskVo.getTaskId(), taskVo.getInstanceId(), FlowComment.NORMAL.getType(), taskVo.getComment()); + String userSid = taskVo.getUserSid(); + taskService.setAssignee(taskVo.getTaskId(), userSid); + taskService.complete(taskVo.getTaskId(), taskVo.getValues()); + } + return ResultBean.fireSuccess(); + } + + /** + * 完成任务 + * + * @param dto 请求实体参数 + */ + // @Transactional(rollbackFor = Exception.class) + public ResultBean businessComplete(BusinessVariables dto) { + + ResultBean rb = ResultBean.fireFail(); + + + if(dto.getFormVariables()==null) + dto.setFormVariables(new HashMap()); + Map formVariables = dto.getFormVariables(); + String taskId = (String) formVariables.get("taskId"); + String procInsId = (String) formVariables.get("instanceId"); + String nextUserSid = (String) formVariables.get("nextUserSid"); + if (StringUtils.isBlank(taskId)) { + return rb.setMsg("taskId 不能为空!").setData(new FlowTask()); + } + Object comment_obj = formVariables.get("comment"); + String comment = null; + if (comment_obj == null) { + return rb.fail().setMsg("comment 不能为空!").setData(new FlowTask()); + } else { + comment = (String) comment_obj; + if (StringUtils.isBlank(comment)) { + return rb.fail().setMsg("comment 不能为空!").setData(new FlowTask()); + } + } + Object instanceId_obj = formVariables.get("instanceId"); + String instanceId = null; + if (instanceId_obj == null) { + return rb.fail().setMsg("instanceId 不能为空!").setData(new FlowTask()); + } else { + instanceId = (String) instanceId_obj; + if (StringUtils.isBlank(instanceId)) { + return rb.fail().setMsg("instanceId 不能为空!").setData(new FlowTask()); + } + } + Object userSid_obj = formVariables.get("userSid"); + String userSid = null; + if (userSid_obj == null) { + return rb.fail().setMsg("userSid 不能为空!").setData(new FlowTask()); + } else { + userSid = (String) userSid_obj; + if (StringUtils.isBlank(userSid)) { + return rb.fail().setMsg("userSid 不能为空!").setData(new FlowTask()); + } + } + Object businessSid_obj = formVariables.get("businessSid"); + String businessSid = null; + if (businessSid_obj == null) { + return rb.setMsg("业务sid 不能为空!").setData(new FlowTask()); + } else { + businessSid = (String) businessSid_obj; + if (StringUtils.isBlank(businessSid)) { + return rb.fail().setMsg("业务sid 不能为空!").setData(new FlowTask()); + } + } + Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); + if (Objects.isNull(task)) { + return rb.setMsg("任务不存在").setData(new FlowTask()); + } + if (DelegationState.PENDING.equals(task.getDelegationState())) { + taskService.addComment(taskId, instanceId, + FlowComment.DELEGATE.getType(), comment); + // Map values =(Map) formVariables.get("values"); + taskService.resolveTask(taskId, formVariables); + } else { + taskService.addComment(taskId, instanceId, + FlowComment.NORMAL.getType(), comment); + taskService.setAssignee(taskId, userSid); + taskService.complete(taskId, formVariables); + + //根据流程实例的id取最新的待办环节,给环节设置上用户sid + ResultBean> ll = getLatestTasksNew(procInsId); + if (ll.getData().size() > 0) { + LatestTaskVo latestTaskVo = ll.getData().get(0); + String id_ = latestTaskVo.getId_(); + taskService.setAssignee(id_, nextUserSid); + } + } + FlowTask flowTask = new FlowTask(); + flowTask.setTaskId(task.getId()); + flowTask.setTaskName(task.getName()); + flowTask.setProcInsId(task.getProcessInstanceId()); + rb.success().setData(flowTask); + return rb; + } + + public ResultBean findReturnTaskList(FlowTaskVo flowTaskVo) { + // 当前任务 task + Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult(); + // 获取流程定义信息 + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() + .processDefinitionId(task.getProcessDefinitionId()).singleResult(); + // 获取所有节点信息,暂不考虑子流程情况 + Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0); + Collection flowElements = process.getFlowElements(); + // 获取当前任务节点元素 + UserTask source = null; + if (flowElements != null) { + for (FlowElement flowElement : flowElements) { + // 类型为用户节点 + if (flowElement.getId().equals(task.getTaskDefinitionKey())) { + source = (UserTask) flowElement; + } + } + } + // 获取节点的所有路线 + List> roads = FlowableUtils.findRoad(source, null, null, null); + // 可回退的节点列表 + List userTaskList = new ArrayList<>(); + for (List road : roads) { + if (userTaskList.size() == 0) { + // 还没有可回退节点直接添加 + userTaskList = road; + } else { + // 如果已有回退节点,则比对取交集部分 + userTaskList.retainAll(road); + } + } + return ResultBean.fireSuccess().setData(userTaskList); + } + + /** + * 退回任务 + * + * @param flowTaskVo 请求实体参数 + */ + // @Transactional(rollbackFor = Exception.class) + public void taskReturn(FlowTaskVo flowTaskVo) { + if (taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult().isSuspended()) { + throw new CustomException("任务处于挂起状态"); + } + String comment = flowTaskVo.getComment(); + if (StringUtils.isBlank(comment)) { + // comment=""; + throw new CustomException("comment 不能为空!"); + // return rb.setMsg("comment 不能为空!"); + } + // 当前任务 task + Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult(); + // 获取流程定义信息 + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult(); + // 获取所有节点信息 + Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0); + // 获取全部节点列表,包含子节点 + Collection allElements = FlowableUtils.getAllElements(process.getFlowElements(), null); + // 获取当前任务节点元素 + FlowElement source = null; + // 获取跳转的节点元素 + FlowElement target = null; + if (allElements != null) { + for (FlowElement flowElement : allElements) { + // 当前任务节点元素 + if (flowElement.getId().equals(task.getTaskDefinitionKey())) { + source = flowElement; + } + // 跳转的节点元素 + if (flowElement.getId().equals(flowTaskVo.getTargetKey())) { + target = flowElement; + } + } + } + + // 从当前节点向前扫描 + // 如果存在路线上不存在目标节点,说明目标节点是在网关上或非同一路线上,不可跳转 + // 否则目标节点相对于当前节点,属于串行 + Boolean isSequential = FlowableUtils.iteratorCheckSequentialReferTarget(source, flowTaskVo.getTargetKey(), null, null); + if (!isSequential) { + throw new CustomException("当前节点相对于目标节点,不属于串行关系,无法回退"); + } + // 获取所有正常进行的任务节点 Key,这些任务不能直接使用,需要找出其中需要撤回的任务 + List runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list(); + List runTaskKeyList = new ArrayList<>(); + runTaskList.forEach(item -> runTaskKeyList.add(item.getTaskDefinitionKey())); + // 需退回任务列表 + List currentIds = new ArrayList<>(); + // 通过父级网关的出口连线,结合 runTaskList 比对,获取需要撤回的任务 + List currentUserTaskList = FlowableUtils.iteratorFindChildUserTasks(target, runTaskKeyList, null, null); + currentUserTaskList.forEach(item -> currentIds.add(item.getId())); + + // 循环获取那些需要被撤回的节点的ID,用来设置驳回原因 + List currentTaskIds = new ArrayList<>(); + currentIds.forEach(currentId -> runTaskList.forEach(runTask -> { + if (currentId.equals(runTask.getTaskDefinitionKey())) { + currentTaskIds.add(runTask.getId()); + } + })); + // 设置回退意见 + for (String currentTaskId : currentTaskIds) { + taskService.addComment(currentTaskId, task.getProcessInstanceId(), FlowComment.REBACK.getType(), comment); + } + try { + // 1 对 1 或 多 对 1 情况,currentIds 当前要跳转的节点列表(1或多),targetKey 跳转到的节点(1) + runtimeService.createChangeActivityStateBuilder() + .processInstanceId(task.getProcessInstanceId()) + .moveActivityIdsToSingleActivityId(currentIds, flowTaskVo.getTargetKey()).changeState(); + } catch (FlowableObjectNotFoundException e) { + throw new CustomException("未找到流程实例,流程可能已发生变化"); + } catch (FlowableException e) { + throw new CustomException("无法取消或开始活动"); + } + } + + + /** + * 驳回任务 + * + * @param flowTaskVo + */ + public ResultBean> taskReject(FlowTaskVo flowTaskVo) { + return taskReject_(flowTaskVo,false); + } + /** + * 驳回任务 + * + * @param flowTaskVo + */ + public ResultBean> taskReject_(FlowTaskVo flowTaskVo,boolean b) { + // 当前任务 task + Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult(); + if (task.isSuspended()) { + return new ResultBean>().fail().setMsg("任务处于挂起状态").setData(new ArrayList<>()); + } + // 获取流程定义信息 + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult(); + // 获取所有节点信息 + Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0); + // 获取全部节点列表,包含子节点 + Collection allElements = FlowableUtils.getAllElements(process.getFlowElements(), null); + // 获取当前任务节点元素 + FlowElement source = null; + if (allElements != null) { + for (FlowElement flowElement : allElements) { + // 类型为用户节点 + if (flowElement.getId().equals(task.getTaskDefinitionKey())) { + // 获取节点信息 + source = flowElement; + } + } + } + + // 目的获取所有跳转到的节点 targetIds + // 获取当前节点的所有父级用户任务节点 + // 深度优先算法思想:延边迭代深入 + List parentUserTaskList = FlowableUtils.iteratorFindParentUserTasks(source, null, null); + if (parentUserTaskList == null || parentUserTaskList.size() == 0) { + return new ResultBean>().fail().setMsg("当前节点为初始任务节点,不能驳回").setData(new ArrayList<>()); + } + // 获取活动 ID 即节点 Key + List parentUserTaskKeyList = new ArrayList<>(); + parentUserTaskList.forEach(item -> parentUserTaskKeyList.add(item.getId())); + // 获取全部历史节点活动实例,即已经走过的节点历史,数据采用开始时间升序 + List historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery().processInstanceId(task.getProcessInstanceId()).orderByHistoricTaskInstanceStartTime().asc().list(); + HistoricTaskInstance historicTaskInstance = historicTaskInstanceList.get(historicTaskInstanceList.size() - 2); + Map actHiVarinstForOrgPath = flowTaskMapper.getActHiVarinstForOrgPath(historicTaskInstance.getId()); + //Object o = actHiVarinstForOrgPath.get(BusinessVariables.ORGPATH); + String orgPath = MapUtil.getStr(actHiVarinstForOrgPath,"TEXT_"); + // 数据清洗,将回滚导致的脏数据清洗掉 + List lastHistoricTaskInstanceList = FlowableUtils.historicTaskInstanceClean(allElements, historicTaskInstanceList); + // 此时历史任务实例为倒序,获取最后走的节点 + List targetIds = new ArrayList<>(); + // 循环结束标识,遇到当前目标节点的次数 + int number = 0; + StringBuilder parentHistoricTaskKey = new StringBuilder(); + for (String historicTaskInstanceKey : lastHistoricTaskInstanceList) { + // 当会签时候会出现特殊的,连续都是同一个节点历史数据的情况,这种时候跳过 + if (parentHistoricTaskKey.toString().equals(historicTaskInstanceKey)) { + continue; + } + parentHistoricTaskKey = new StringBuilder(historicTaskInstanceKey); + if (historicTaskInstanceKey.equals(task.getTaskDefinitionKey())) { + number++; + } + // 在数据清洗后,历史节点就是唯一一条从起始到当前节点的历史记录,理论上每个点只会出现一次 + // 在流程中如果出现循环,那么每次循环中间的点也只会出现一次,再出现就是下次循环 + // number == 1,第一次遇到当前节点 + // number == 2,第二次遇到,代表最后一次的循环范围 + if (number == 2) { + break; + } + // 如果当前历史节点,属于父级的节点,说明最后一次经过了这个点,需要退回这个点 + if (parentUserTaskKeyList.contains(historicTaskInstanceKey)) { + targetIds.add(historicTaskInstanceKey); + } + } + + // 目的获取所有需要被跳转的节点 currentIds + // 取其中一个父级任务,因为后续要么存在公共网关,要么就是串行公共线路 + UserTask oneUserTask = parentUserTaskList.get(0); + // 判断是否驳回到发起环节,设置发起人 + if (oneUserTask.getIncomingFlows().get(0).getSourceRef().contains("start")) { + oneUserTask.setAssignee(historicTaskInstanceList.get(0).getAssignee()); + } + // 获取所有正常进行的任务节点 Key,这些任务不能直接使用,需要找出其中需要撤回的任务 + List runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list(); + List runTaskKeyList = new ArrayList<>(); + runTaskList.forEach(item -> runTaskKeyList.add(item.getTaskDefinitionKey())); + // 需驳回任务列表 + List currentIds = new ArrayList<>(); + // 通过父级网关的出口连线,结合 runTaskList 比对,获取需要撤回的任务 + List currentUserTaskList = FlowableUtils.iteratorFindChildUserTasks(oneUserTask, runTaskKeyList, null, null); + currentUserTaskList.forEach(item -> currentIds.add(item.getId())); + // 规定:并行网关之前节点必须需存在唯一用户任务节点,如果出现多个任务节点,则并行网关节点默认为结束节点,原因为不考虑多对多情况 + if (targetIds.size() > 1 && currentIds.size() > 1) { + return new ResultBean>().fail().setMsg("任务出现多对多情况,无法撤回").setData(new ArrayList<>()); + } + + // 循环获取那些需要被撤回的节点的ID,用来设置驳回原因 + List currentTaskIds = new ArrayList<>(); + currentIds.forEach(currentId -> runTaskList.forEach(runTask -> { + if (currentId.equals(runTask.getTaskDefinitionKey())) { + currentTaskIds.add(runTask.getId()); + } + })); + // 设置驳回意见 + currentTaskIds.forEach(item -> { + taskService.addComment(item, task.getProcessInstanceId(), FlowComment.REJECT.getType(), flowTaskVo.getComment()); + taskService.setAssignee(item, flowTaskVo.getUserSid()); + }); + + // 最近环节 + List latestTaskList = new ArrayList<>(); + try { + // 如果父级任务多于 1 个,说明当前节点不是并行节点,原因为不考虑多对多情况 + if (targetIds.size() > 1) { + // 1 对 多任务跳转,currentIds 当前节点(1),targetIds 跳转到的节点(多) + runtimeService.createChangeActivityStateBuilder() + .processInstanceId(task.getProcessInstanceId()). + moveSingleActivityIdToActivityIds(currentIds.get(0), targetIds).changeState(); + } + // 如果父级任务只有一个,因此当前任务可能为网关中的任务 + if (targetIds.size() == 1) { + // 1 对 1 或 多 对 1 情况,currentIds 当前要跳转的节点列表(1或多),targetIds.get(0) 跳转到的节点(1) + runtimeService.createChangeActivityStateBuilder() + .processInstanceId(task.getProcessInstanceId()) + .moveActivityIdsToSingleActivityId(currentIds, targetIds.get(0)).changeState(); + } + // 最近环节 + for(UserTask item:parentUserTaskList){ + Map map2 = flowTaskMapper.getTaskByDefKey(task.getProcessInstanceId(), targetIds.get(0)); + Map map = flowTaskMapper.getHistTaskByID(task.getProcessInstanceId(), targetIds.get(0)); + String assignee_ =item.getAssignee(); + if(map.get("ASSIGNEE_")!=null){ + assignee_ = map.get("ASSIGNEE_").toString(); + } + if(map2==null){ + continue; + } + String id_ = map2.get("id_").toString(); + ResultBean> listResultBean_2=null; + if(flowTaskVo.getUserSid().equals(assignee_)){ + flowTaskVo.setTaskId(id_); + flowTaskVo.setUserSid(assignee_); + flowTaskVo.setTargetKey(item.getId()); + listResultBean_2= taskReject_(flowTaskVo, true); + }else{ + taskService.setAssignee(id_, assignee_); + } + LatestTaskVo latestTaskVo = new LatestTaskVo(); + latestTaskVo.setASSIGNEE_(item.getAssignee()); + latestTaskVo.setId_(listResultBean_2!=null&&listResultBean_2.getData().size()!=0?listResultBean_2.getData().get(0).getId_():id_); + latestTaskVo.setName_(listResultBean_2!=null&&listResultBean_2.getData().size()!=0?listResultBean_2.getData().get(0).getName_():item.getName()); + latestTaskVo.setTask_def_key_(listResultBean_2!=null&&listResultBean_2.getData().size()!=0?listResultBean_2.getData().get(0).getTask_def_key_():item.getId()); + latestTaskVo.setIncomingSourceRef(listResultBean_2!=null&&listResultBean_2.getData().size()!=0?listResultBean_2.getData().get(0).getIncomingSourceRef():item.getIncomingFlows().get(0).getSourceRef()); + latestTaskVo.setOrgPath(listResultBean_2!=null&&listResultBean_2.getData().size()!=0?listResultBean_2.getData().get(0).getOrgPath():orgPath); + latestTaskList.add(latestTaskVo); + } + + } catch (FlowableObjectNotFoundException e) { + throw new CustomException("未找到流程实例,流程可能已发生变化"); + } catch (FlowableException e) { + throw new CustomException("无法取消或开始活动"); + } + return new ResultBean>().success().setData(latestTaskList); + } + + public ResultBean businessMyprocessNew(String userSid, PagerQuery businessTaskQuery) { + int size = Integer.valueOf(businessTaskQuery.getSize() + ""); + int current = Integer.valueOf(businessTaskQuery.getCurrent() + ""); + List fields = businessTaskQuery.getParams().getFields(); + return businessMyprocess(userSid, fields, current, size); + } + + public ResultBean businessMyprocess(String userSid, List params, int current, int size) { + Page page = new Page<>(); + HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery(); + for (BusinessTaskParam btq : params) { + if (btq.getSqlOperationSymbol().equals(SQLOperationSymbol.EQUAL)) { + historicProcessInstanceQuery.variableValueEquals(btq.getField(), btq.getValue()); + } + if (btq.getSqlOperationSymbol().equals(SQLOperationSymbol.LIKE)) { + historicProcessInstanceQuery.variableValueLike(btq.getField(), "%" + btq.getValue() + "%"); + } + } + historicProcessInstanceQuery.startedBy(userSid).notDeleted() + .orderByProcessInstanceStartTime() + .desc(); + List historicProcessInstances = historicProcessInstanceQuery.listPage((current - 1) * size, size); + long count = historicProcessInstanceQuery.count(); + page.setTotal(count); + List flowList = new ArrayList<>(); + for (HistoricProcessInstance hisIns : historicProcessInstances) { + FlowTaskDto flowTask = new FlowTaskDto(); + flowTask.setCreateTime(hisIns.getStartTime()); + flowTask.setFinishTime(hisIns.getEndTime()); + flowTask.setProcInsId(hisIns.getId()); + + // 计算耗时 + if (Objects.nonNull(hisIns.getEndTime())) { + long time = hisIns.getEndTime().getTime() - hisIns.getStartTime().getTime(); + flowTask.setDuration(FlowableUtils.getDate(time)); + } else { + long time = System.currentTimeMillis() - hisIns.getStartTime().getTime(); + flowTask.setDuration(FlowableUtils.getDate(time)); + } + // 流程定义信息 + ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() + .processDefinitionId(hisIns.getProcessDefinitionId()) + .singleResult(); + flowTask.setDeployId(pd.getDeploymentId()); + flowTask.setProcDefName(pd.getName()); + flowTask.setProcDefVersion(pd.getVersion()); + flowTask.setCategory(pd.getCategory()); + flowTask.setProcDefVersion(pd.getVersion()); + + // 当前所处流程 + List taskList = taskService.createTaskQuery().processInstanceId(hisIns.getId()).list(); + if (CollectionUtils.isNotEmpty(taskList)) { + flowTask.setTaskId(taskList.get(0).getId()); + } else { + List historicTaskInstance = historyService.createHistoricTaskInstanceQuery().processInstanceId(hisIns.getId()).orderByHistoricTaskInstanceEndTime().desc().list(); + flowTask.setTaskId(historicTaskInstance.get(0).getId()); + } + flowList.add(flowTask); + } + page.setRecords(flowList); + return ResultBean.fireSuccess().setData(page); + } + + private String getTaskId(String currentActivityId, String processInstanceId, String processDefinitionId) { + BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId); + FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(currentActivityId); + List list=flowNode.getIncomingFlows(); + if(list.size()==0){ + return ""; + } + + List list1=new ArrayList<>(); + for( SequenceFlow sequenceFlow:list){ + String sourceRef = sequenceFlow.getSourceRef(); + list1= historyService.createHistoricActivityInstanceQuery().activityId(sourceRef) + .processInstanceId(processInstanceId).orderByHistoricActivityInstanceStartTime().desc().list(); + if(list1.size()>0){ + break; + } + } + // 获取上一个节点的activityId + HistoricActivityInstance historicActivityInstance = list1.get(0);//singleResult() + String activityType = historicActivityInstance.getActivityType(); + String historicActivityInstanceActivityId = historicActivityInstance.getActivityId(); + if (!"userTask".equals(activityType)) { + return getTaskId(historicActivityInstanceActivityId, processInstanceId, processDefinitionId); + } + return historicActivityInstance.getTaskId(); + } + public ResultBean> revokeProcess(FlowTaskVo flowTaskVo,int j) { + HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().taskId(flowTaskVo.getTaskId()).singleResult(); + Execution execution = runtimeService.createExecutionQuery().executionId(historicTaskInstance.getExecutionId()).singleResult(); + DelegateExecution delegateExecution = (DelegateExecution) execution; + if (delegateExecution == null) { + return new ResultBean>().fail().setMsg("流程已办结,不能撤回!").setData(new ArrayList<>()); + } + // 获取当前节点的activityId,即xml中每个标签的ID + String currentActivityId = delegateExecution.getCurrentActivityId(); + String taskId = getTaskId(currentActivityId, historicTaskInstance.getProcessInstanceId(), historicTaskInstance.getProcessDefinitionId()); + if (StringUtils.isBlank(taskId)) { + return new ResultBean>().fail().setMsg("流程找不到上一环节,撤回操作失败!").setData(new ArrayList<>()); + } + HistoricTaskInstance historicTaskInstance1 = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult(); + String assignee = historicTaskInstance1.getAssignee(); + String userSid = flowTaskVo.getUserSid(); + ResultBean flowRecordVoResultBean = flowableService.flowRecord(flowTaskVo.getInstanceId(), flowTaskVo.getInstanceId()); + List flowList = flowRecordVoResultBean.getData().getFlowList(); + String ybrsid=""; + int ii=0; + + FlowTask flowTask_1 = flowList.get(j+1); + List taskUserInfos_1 = flowTask_1.getTaskUserInfos(); + TaskUserInfo taskUserInfo_1 = taskUserInfos_1.get(0); + + FlowTask flowTask_0 = flowList.get(j); + List taskUserInfos_0 = flowTask_0.getTaskUserInfos(); + TaskUserInfo taskUserInfo_0 = taskUserInfos_0.get(0); + String assigneeSid1 = taskUserInfo_1.getAssigneeSid(); + String assigneeSid0 = taskUserInfo_0.getAssigneeSid(); + + if(!assigneeSid1.equals(assigneeSid0)){ + ybrsid=assignee; + }else{ + FlowTask flowTask1 = flowList.get(1); + for(int i=1;i taskUserInfos = flowTask.getTaskUserInfos(); + TaskUserInfo taskUserInfo = taskUserInfos.get(0); + if(assigneeSid0.equals(taskUserInfo.getAssigneeSid())){ + if(!FlowComment.RECALL.getType().equals( flowTask1.getComment().getType())){ + ii++; + } + continue; + }else{ + ybrsid=flowList.get(i).getTaskUserInfos().get(0).getAssigneeSid(); + break; + } + } + } + + if (!ybrsid.equals(userSid)) { + return new ResultBean>().fail().setMsg("您不是上一环节处理人,不能进行撤回操作!").setData(new ArrayList<>()); + } else { + ResultBean> listResultBean = null; + for(int i=0;i<=ii;i++){ //ii==2的问题 + listResultBean = revokeProcess_(historicTaskInstance.getProcessInstanceId(),userSid); + } + return listResultBean; + } + } + public ResultBean> revokeProcess(FlowTaskVo flowTaskVo) { + return revokeProcess(flowTaskVo,0); + } + + // @Transactional(rollbackFor = Exception.class) + private ResultBean> revokeProcess_( String processInstanceId, + String assignee ) { + // 流程回退到上一个节点,审批人继续审批 + // 获取流程定义信息 + Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult(); + ProcessDefinition processDefinition = repositoryService + .createProcessDefinitionQuery() + .processDefinitionId(task.getProcessDefinitionId()).singleResult(); + // 获取所有节点信息 + Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0); + // 获取全部节点列表,包含子节点 + Collection allElements = + FlowableUtils.getAllElements(process.getFlowElements(), null); + // 获取当前任务节点元素 + FlowElement source = null; + if (allElements != null) { + for (FlowElement flowElement : allElements) { + //类型为用户节点 + if (flowElement.getId().equals(task.getTaskDefinitionKey())) { + //获取节点信息 + source = flowElement; + } + } + } + // 目的获取所有跳转到的节点 targetIds + // 获取当前节点的所有父级用户任务节点 + // 深度优先算法思想:延边迭代深入 + //申请人申请后,销售经理审批同意,随后销售经理再撤回,申请人再撤回。 申请人->网关->销售经理->销售支持部经理 + List parentUserTaskList = FlowableUtils.iteratorFindParentUserTasks(source, null, null); + if (parentUserTaskList == null || parentUserTaskList.size() == 0) { + // throw new CustomException("当前节点为"); + return new ResultBean>().fail().setMsg("当前节点为").setData(new ArrayList<>()); + } + // 如果流程已经结束,则得到结束节点 + if (historyService.createHistoricProcessInstanceQuery().finished() + .processInstanceId(processInstanceId).count() > 0) { + return new ResultBean>().fail().setMsg("当前已经结束不能撤回").setData(new ArrayList<>()); + } + // 获取活动 ID 即节点 Key + List parentUserTaskKeyList = new ArrayList<>(); + parentUserTaskList.forEach(item -> parentUserTaskKeyList.add(item.getId())); + // 获取全部历史节点活动实例,即已经走过的节点历史,数据采用开始时间升序 + List historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery() + .processInstanceId(processInstanceId) + .orderByHistoricTaskInstanceStartTime().asc().list(); + HistoricTaskInstance historicTaskInstance = historicTaskInstanceList.get(historicTaskInstanceList.size() - 1); + Map actHiVarinstForOrgPath = flowTaskMapper.getActHiVarinstForOrgPath(historicTaskInstance.getId()); + String orgPath = MapUtil.getStr(actHiVarinstForOrgPath,"TEXT_"); + // 数据清洗,将回滚导致的脏数据清洗掉 + List lastHistoricTaskInstanceList = FlowableUtils.historicTaskInstanceClean(allElements, historicTaskInstanceList); + + // 此时历史任务实例为倒序,获取最后走的节点 + List targetIds = new ArrayList<>(); + int number = 0; + StringBuilder parentHistoricTaskKey = new StringBuilder(); + for (String historicTaskInstanceKey : lastHistoricTaskInstanceList) { + // 当会签时候会出现特殊的,连续都是同一个节点历史数据的情况,这种时候跳过 + if (parentHistoricTaskKey.toString().equals(historicTaskInstanceKey)) { + continue; + } + parentHistoricTaskKey = new StringBuilder(historicTaskInstanceKey); + if (historicTaskInstanceKey.equals(task.getTaskDefinitionKey())) { + number++; + } + // 在数据清洗后,历史节点就是唯一一条从起始到当前节点的历史记录,理论上每个点只会出现一次 + // 在流程中如果出现循环,那么每次循环中间的点也只会出现一次,再出现就是下次循环 + // number == 1,第一次遇到当前节点 + // number == 2,第二次遇到,代表最后一次的循环范围 + if (number == 2) { + break; + } + // 如果当前历史节点,属于父级的节点,说明最后一次经过了这个点,需要退回这个点 + if (parentUserTaskKeyList.contains(historicTaskInstanceKey)) { + targetIds.add(historicTaskInstanceKey); + } + } + // 目的获取所有需要被跳转的节点 currentIds + // 取其中一个父级任务,因为后续要么存在公共网关,要么就是串行公共线路 + UserTask oneUserTask = parentUserTaskList.get(0); + // 获取所有正常进行的任务节点 Key,这些任务不能直接使用,需要找出其中需要撤回的任务 + List runTaskList = taskService.createTaskQuery() + .processInstanceId(processInstanceId).list(); + List runTaskKeyList = new ArrayList<>(); + runTaskList.forEach(item -> runTaskKeyList.add(item.getTaskDefinitionKey())); + // 需驳回任务列表 + List currentIds = new ArrayList<>(); + // 通过父级网关的出口连线,结合 runTaskList 比对,获取需要撤回的任务 + List currentUserTaskList = FlowableUtils.iteratorFindChildUserTasks(oneUserTask, runTaskKeyList, null, null); + currentUserTaskList.forEach(item -> currentIds.add(item.getId())); + // 规定:并行网关之前节点必须需存在唯一用户任务节点, + // 如果出现多个任务节点,则并行网关节点默认为结束节点,原因为不考虑多对多情况 + if (targetIds.size() > 1 && currentIds.size() > 1) { + return new ResultBean>().fail().setMsg("任务出现多对多情况,无法撤回").setData(new ArrayList<>()); + } + // 循环获取那些需要被撤回的节点的ID,用来设置驳回原因 + List currentTaskIds = new ArrayList<>(); + currentIds.forEach(currentId -> runTaskList.forEach(runTask -> { + if (currentId.equals(runTask.getTaskDefinitionKey())) { + currentTaskIds.add(runTask.getId()); + } + })); + // 设置撤回意见 + currentTaskIds.forEach(item -> { + taskService.addComment(item, processInstanceId,FlowComment.RECALL.getType(), "撤回办理"); + // 设置实际办理人 + taskService.setAssignee(item, assignee); + }); + + // 最近环节 + List latestTaskList = new ArrayList<>(); + try { + // 如果父级任务多于 1 个,说明当前节点不是并行节点,原因为不考虑多对多情况 + if (targetIds.size() > 1) { + // 1 对 多任务跳转,currentIds 当前节点(1),targetIds 跳转到的节点(多) + runtimeService.createChangeActivityStateBuilder() + .processInstanceId(processInstanceId). + moveSingleActivityIdToActivityIds(currentIds.get(0), targetIds).changeState(); + } + // 如果父级任务只有一个,因此当前任务可能为网关中的任务 + if (targetIds.size() == 1) { + // 1 对 1 或 多 对 1 情况,currentIds 当前要跳转的节点列表(1或多),targetIds.get(0) 跳转到的节点(1) + runtimeService.createChangeActivityStateBuilder() + .processInstanceId(processInstanceId) + .moveActivityIdsToSingleActivityId(currentIds, targetIds.get(0)).changeState(); + } + // 最近环节 + parentUserTaskList.forEach(item -> { + LatestTaskVo latestTaskVo = new LatestTaskVo(); + latestTaskVo.setASSIGNEE_(item.getAssignee()); + latestTaskVo.setName_(item.getName()); + latestTaskVo.setTask_def_key_(item.getId()); + latestTaskVo.setIncomingSourceRef(item.getIncomingFlows().get(0).getSourceRef()); + latestTaskVo.setOrgPath(orgPath); + + Map task_map = flowTaskMapper.getTaskByDefKey(processInstanceId, item.getId()); + if(task_map!=null){ + taskService.setAssignee(task_map.get("id_").toString(), assignee); + latestTaskVo.setId_(task_map.get("id_").toString()); + latestTaskList.add(latestTaskVo); + } + }); + } catch (FlowableObjectNotFoundException e) { + throw new CustomException("未找到流程实例,流程可能已发生变化"); + } catch (FlowableException e) { + throw new CustomException("无法取消或开始活动"); + } + return new ResultBean>().success().setData(latestTaskList); + } + + /** + * 终止流程 + * + * @param flowTaskVo + * @return + */ + public ResultBean breakProcess(FlowTaskVo flowTaskVo) { + // 当前任务 task + Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult(); + if (task.isSuspended()) { + return new ResultBean().fail().setMsg("任务处于挂起状态"); + } + String comment = flowTaskVo.getComment(); + if (StringUtils.isBlank(comment)) { + throw new CustomException("comment 不能为空!"); + } + String processInstanceId = flowTaskVo.getInstanceId(); + ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); + if (processInstance != null) { + //1、获取终止节点 + List endNodes = findEndFlowElement(processInstance.getProcessDefinitionId()); + String endId = endNodes.get(0).getId(); + // 2、执行终止 + List executions = runtimeService.createExecutionQuery().parentId(processInstanceId).list(); + List executionIds = new ArrayList<>(); + executions.forEach(execution -> executionIds.add(execution.getId())); + taskService.setAssignee(flowTaskVo.getTaskId(), flowTaskVo.getUserSid()); + taskService.addComment(flowTaskVo.getTaskId(), processInstanceId, FlowComment.STOP.getType(), comment); + runtimeService.createChangeActivityStateBuilder().moveExecutionsToSingleActivityId(executionIds, endId).changeState(); + return new ResultBean().success().setMsg("终止成功").setData(FlowComment.STOP.getRemark()); + } else { + return new ResultBean().fail().setMsg("终止失败不存在运行的流程实例"); + } + } + + private List findEndFlowElement(String processDefId) { + Process mainProcess = repositoryService.getBpmnModel(processDefId).getMainProcess(); + Collection list = mainProcess.getFlowElements(); + if (CollectionUtils.isEmpty(list)) { + return Collections.EMPTY_LIST; + } + return list.stream().filter(f -> f instanceof EndEvent).collect(Collectors.toList()); + } + + public void stopProcess(String userSid, FlowTaskVo flowTaskVo) { + List task = taskService.createTaskQuery().processInstanceId(flowTaskVo.getInstanceId()).list(); + if (CollectionUtils.isEmpty(task)) { + throw new CustomException("流程未启动或已执行完成,取消申请失败"); + } + ResultBean sysUserVoResultBean = sysUserFeign.fetchBySid(userSid); + SysUserVo sysUser = sysUserVoResultBean.getData(); + ProcessInstance processInstance = + runtimeService.createProcessInstanceQuery().processInstanceId(flowTaskVo.getInstanceId()).singleResult(); + BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId()); + if (Objects.nonNull(bpmnModel)) { + Process process = bpmnModel.getMainProcess(); + List endNodes = process.findFlowElementsOfType(EndEvent.class, false); + if (CollectionUtils.isNotEmpty(endNodes)) { + Authentication.setAuthenticatedUserId(sysUser.getSid().toString()); + String endId = endNodes.get(0).getId(); + List executions = + runtimeService.createExecutionQuery().parentId(processInstance.getProcessInstanceId()).list(); + List executionIds = new ArrayList<>(); + executions.forEach(execution -> executionIds.add(execution.getId())); + runtimeService.createChangeActivityStateBuilder().moveExecutionsToSingleActivityId(executionIds, + endId).changeState(); + } + } + + } + + /** + * instId 流程实例ID + * delReason 删除原因 + */ + public void deleteProcess(String procInsId, String delReason) { + runtimeService.deleteProcessInstance(procInsId, delReason); + } + + public ResultBean getNextTasks(String taskId) { + Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); + String node = "next"; + String processDefinitionId = task.getProcessDefinitionId(); + return getNextUserTasks(processDefinitionId, task.getExecutionId(), node); + } + + private ResultBean getNextUserTasks(String processDefinitionId, String executionId, String node) { + ExecutionEntity ee = (ExecutionEntity) runtimeService.createExecutionQuery() + .executionId(executionId).singleResult(); + // 当前审批节点 + String crruentActivityId = ee.getActivityId(); + BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId); + FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(crruentActivityId); + // 输出连线 + List outFlows = flowNode.getOutgoingFlows(); + List> lists = new ArrayList<>(); + getNodes(outFlows, node, lists); + System.out.println(JSON.toJSONString(lists)); + return ResultBean.fireSuccess().setData(lists); + } + + /** + * 根据流程实例的id查询最新的待办环节 + * + * @param procId + * @return + */ + public List getLatestTasks(String procId) { + return baseMapper.getLatestTasks(procId); + } + + public void getNodes(List outFlows, String node, List> lists) { + for (SequenceFlow sequenceFlow : outFlows) { + //当前审批节点 + if ("now".equals(node)) { + FlowElement sourceFlowElement = sequenceFlow.getSourceFlowElement(); + System.out.println("当前节点: id=" + sourceFlowElement.getId() + ",name=" + sourceFlowElement.getName()); + } else if ("next".equals(node)) { + // 下一个审批节点 + FlowElement targetFlow = sequenceFlow.getTargetFlowElement(); + if (targetFlow instanceof UserTask) { + System.out.println("下一节点: id=" + targetFlow.getId() + ",name=" + targetFlow.getName()); + Map map = new HashMap<>(); + map.put("id", targetFlow.getId()); + map.put("candidateGroups", ((UserTask) targetFlow).getCandidateGroups()); + map.put("name", targetFlow.getName()); + map.put("assignee", ((UserTask) targetFlow).getAssignee()); + lists.add(map); + } + if (targetFlow instanceof EndEvent) {// 如果下个审批节点为结束节点 + System.out.println("下一节点为结束节点:id=" + targetFlow.getId() + ",name=" + targetFlow.getName()); + Map map = new HashMap<>(); + map.put("id", targetFlow.getId()); + map.put("name", targetFlow.getName()); + // map.put("assignee", ((UserTask) targetFlow).getAssignee()); + lists.add(map); + } + if (targetFlow instanceof Gateway) {// 如果下个审批节点为结束节点 + List outgoingFlows = ((Gateway) targetFlow).getOutgoingFlows(); + getNodes(outgoingFlows, node, lists); + System.out.println("下一节点为结束节点:id=" + targetFlow.getId() + ",name=" + targetFlow.getName()); + } + } + } + } + + public ResultBean> getLatestTasksNew(String procId) { + List latestTasks = getLatestTasks(procId); + return new ResultBean>().success().setData(latestTasks); + } + + public ResultBean businessTodoListNew(String userSid, PagerQuery businessTaskQuery) { + int size = Integer.valueOf(businessTaskQuery.getSize() + ""); + int current = Integer.valueOf(businessTaskQuery.getCurrent() + ""); + List fields = businessTaskQuery.getParams().getFields(); + String companySid=""; + ResultBean> resultBean = businessTodoList(userSid,companySid, fields, current, size); + return resultBean; + } + + public ResultBean businessDoneListNew(String userSid, PagerQuery taskQueryPagerQuery) { + int size = Integer.valueOf(taskQueryPagerQuery.getSize() + ""); + int current = Integer.valueOf(taskQueryPagerQuery.getCurrent() + ""); + List fields = taskQueryPagerQuery.getParams().getFields(); + return businessFinishedList(userSid, fields, current, size); + } + public ResultBean> businessDoneListNewForApp(String userSid, PagerQuery taskQueryPagerQuery) { + int size = Integer.valueOf(taskQueryPagerQuery.getSize() + ""); + int current = Integer.valueOf(taskQueryPagerQuery.getCurrent() + ""); + List fields = taskQueryPagerQuery.getParams().getFields(); + return businessFinishedListForApp(userSid, fields, current, size); + } + + public ResultBean stopProcessNew(String userSid, FlowTaskVo flowTaskVo) { + stopProcess(userSid, flowTaskVo); + return ResultBean.fireSuccess(); + } + + public ResultBean deleteProcessNew(String procInsId) { + deleteProcess(procInsId, "删除"); + return ResultBean.fireSuccess(); + } + + public ResultBean readXml(String deployId) { + ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deployId).singleResult(); + if(definition==null){ + definition = repositoryService.createProcessDefinitionQuery().processDefinitionId(deployId).singleResult(); + } + InputStream inputStream = repositoryService.getResourceAsStream(definition.getDeploymentId(), definition.getResourceName()); + String result = null; + try { + result = IOUtils.toString(inputStream, StandardCharsets.UTF_8.name()); + } catch (IOException e) { + e.printStackTrace(); + } + ResultBean r = ResultBean.fireSuccess().setData(result); + return r; + } + + public ResultBean getNextNodesForSubmit(BusinessVariables bv) { + String modelId = null; + if (bv.getModelId()!= null) { + modelId = bv.getModelId(); + } + String procId = null; + if (bv.getModelId() != null) { + procId = bv.getModelId(); + } + if(bv.getFormVariables()==null) + bv.setFormVariables(new HashMap()); + List flowElements = processService.calApprovePath(procId, modelId, bv.getFormVariables()); + ResultBean>> rb = new ResultBean>>(); + List> list = new ArrayList<>(); + boolean endTask=true; + Map map = new HashMap<>(); + for (int i=0;i()); + List flowElements = processService.calApprovePath(procId, modelId, bv.getFormVariables()); + ResultBean>> rb = new ResultBean>>(); + List> list = new ArrayList<>(); + boolean startTask=true; + Map map = new HashMap<>(); + for (int i=0;i0&&bv.getTaskDefKey().equals(f.getId())){ + f =flowElements.get(i-1); + map.put("name", f.getName()); + map.put("id", f.getId()); + String s = JSON.toJSONString(f); + JSONObject jsonObject = JSONObject.parseObject(s); + Object candidateGroups = jsonObject.get("candidateGroups"); + map.put("candidateGroups", candidateGroups); + startTask=false; + map.put("startTask",startTask); + } + } + if(startTask){ + map.put("name", ""); + map.put("id",""); + map.put("candidateGroups", ""); + map.put("startTask",true); + } + list.add(map); + return rb.setData(list); + } + + public ResultBean> businessTodoListForApp(String userSid,String orgPath, List params, int pageNum, int pageSize) { + Page page = new Page<>(); + TaskQuery taskQuery = taskService.createTaskQuery(); + // 流程参数 + Map paramMap = new HashMap<>(); + // 挂载表单参数 + for (BusinessTaskParam btq : params) { + paramMap.put(btq.getField(), btq.getValue()); + if (btq.getSqlOperationSymbol().equals(SQLOperationSymbol.NONE)) { + if ("orgSid".equals(btq.getField())) { + String value = btq.getValue(); + String[] split = value.split(","); + for (int i = 0; i < split.length; i++) { + if (i != 0) { + taskQuery.or().processVariableValueLike("orgSid", split[i] + "%"); + } else { + taskQuery.processVariableValueLike("orgSid", split[0] + "%"); + } + } + } + } + } + TaskQuery or = taskQuery.active() + .includeProcessVariables() + ; + if(StringUtils.isNotBlank(orgPath)){ + /* or.taskVariableValueLike("orgPath", "%" + orgPath + "%");*/ + } + or.taskAssigneeLike("%" + userSid + "%") + .orderByTaskCreateTime().desc(); + // 查询筛选条件 + if (paramMap.get("startDate") != null && StringUtils.isNotBlank(paramMap.get("startDate").toString())) { + taskQuery.taskCreatedAfter(DateUtils.dateStrConvertDate(paramMap.get("startDate").toString(), "yyyy-MM-dd")); + } + if (paramMap.get("endDate") != null && StringUtils.isNotBlank(paramMap.get("endDate").toString())) { + taskQuery.taskCreatedBefore(DateUtils.dateStrConvertDate(paramMap.get("endDate").toString(), "yyyy-MM-dd")); + } + if (paramMap.get("proDefName") != null && StringUtils.isNotBlank(paramMap.get("proDefName").toString())) { + taskQuery.processDefinitionNameLike("%" + paramMap.get("proDefName") + "%"); + } + page.setTotal(taskQuery.count()); + int p = (pageNum - 1) * pageSize; + List taskList = taskQuery.listPage(p, pageSize); + List flowList = new ArrayList<>(); + for (Task task : taskList) { + FlowTaskDto flowTask = new FlowTaskDto(); + Map processVariables = task.getProcessVariables(); + flowTask.setProcessVariables(processVariables); + // 当前流程信息 + flowTask.setTaskId(task.getId()); + flowTask.setTaskDefKey(task.getTaskDefinitionKey()); + flowTask.setCreateTime(task.getCreateTime()); + flowTask.setProcDefId(task.getProcessDefinitionId()); + flowTask.setTaskName(task.getName()); + // 流程定义信息 + ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() + .processDefinitionId(task.getProcessDefinitionId()) + .singleResult(); + flowTask.setDeployId(pd.getDeploymentId()); + flowTask.setProcDefName(pd.getName()); + flowTask.setProcDefVersion(pd.getVersion()); + flowTask.setProcInsId(task.getProcessInstanceId()); + // 流程发起人信息 + HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() + .processInstanceId(task.getProcessInstanceId()) + .singleResult(); + flowTask.setProcessCreateTime(historicProcessInstance.getStartTime()); + ResultBean sysUserVoResultBean = sysUserFeign.fetchBySid(historicProcessInstance.getStartUserId()); + if(sysUserVoResultBean.getData() != null) { + flowTask.setStartUserSid(sysUserVoResultBean.getData().getSid()); + flowTask.setStartUserName(sysUserVoResultBean.getData().getName()); +// flowTask.setStartDeptName(sysUserVoResultBean.getData().getOrganizationName()); + String createOrgPath = ConstantUtils.getString(flowTask.getProcessVariables(),"createOrgPath",""); + String ogrName=""; + if(StringUtils.isNotBlank(createOrgPath)){ + List stringList = Arrays.asList(createOrgPath.split("/")); + ResultBean sysOrganizationVoResultBean = sysOrganizationFeign.fetchBySid(stringList.get(stringList.size()-1)); + if(sysOrganizationVoResultBean.getData() != null){ + if(StringUtils.isNotBlank(sysOrganizationVoResultBean.getData().getPsid())){ + ResultBean sysOrganizationVoResultBeanP = sysOrganizationFeign.fetchBySid(sysOrganizationVoResultBean.getData().getPsid()); + if(sysOrganizationVoResultBeanP.getData() != null){ + ogrName=sysOrganizationVoResultBeanP.getData().getName(); + flowTask.setStartDeptName(ogrName+"-"+sysOrganizationVoResultBean.getData().getName()); + } + }else{ + flowTask.setStartDeptName(sysOrganizationVoResultBean.getData().getName()); + } + } + }else{ + flowTask.setStartDeptName(sysUserVoResultBean.getData().getOrganizationName()); + } + } + ResultBean sysUserVoResultBean2 = sysUserFeign.fetchBySid(userSid); + if(sysUserVoResultBean2.getData() != null) { + flowTask.setAssigneeName(sysUserVoResultBean2.getData().getName()); + flowTask.setAssigneeSid(sysUserVoResultBean2.getData().getSid()); + flowTask.setDeptName(sysUserVoResultBean2.getData().getOrganizationName()); + } + String procDefId = flowTask.getProcDefId(); + String taskDefKey = flowTask.getTaskDefKey(); + ResultBean> listResultBean = sysProUrlService.selectUrlByKey(procDefId, taskDefKey, "1", "2"); + if(listResultBean.getData()!=null&&listResultBean.getData().size()>0){ + flowTask.setSysProUrlVo(listResultBean.getData().get(0)); + } + flowList.add(flowTask); + } + page.setRecords(flowList); + ResultBean> rb = new ResultBean>(); + return rb.success().setData(page); + } +} \ No newline at end of file diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/process/ExpressionCmd.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/process/ExpressionCmd.java new file mode 100644 index 00000000..38cd903e --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/process/ExpressionCmd.java @@ -0,0 +1,47 @@ +package com.yxt.anrui.flowable.biz.process; + +import org.apache.commons.lang3.StringUtils; +import org.flowable.common.engine.api.delegate.Expression; +import org.flowable.common.engine.impl.interceptor.Command; +import org.flowable.common.engine.impl.interceptor.CommandContext; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.flowable.engine.impl.persistence.entity.ExecutionEntity; +import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl; + +import java.io.Serializable; +import java.util.Map; + +public class ExpressionCmd implements Command, Serializable { + protected RuntimeService runtimeService; + + protected ProcessEngineConfigurationImpl processEngineConfiguration; + + protected String processInstanceId; + + protected String exp; + + protected Map variableMap; + + public ExpressionCmd(RuntimeService runtimeService, ProcessEngineConfigurationImpl processEngineConfiguration, String processInstanceId, String exp, Map variableMap) { + this.runtimeService = runtimeService; + this.processEngineConfiguration = processEngineConfiguration; + this.processInstanceId = processInstanceId; + this.exp = exp; + this.variableMap = variableMap; + } + + @Override + public Boolean execute(CommandContext commandContext) { + Expression expression = processEngineConfiguration.getExpressionManager().createExpression(this.exp); + ExecutionEntity executionEntity; + if(StringUtils.isNotBlank(this.processInstanceId)){ + executionEntity = (ExecutionEntity) runtimeService.createProcessInstanceQuery().processInstanceId(this.processInstanceId).includeProcessVariables().singleResult(); + }else { + executionEntity = new ExecutionEntityImpl(); + executionEntity.setVariables(variableMap); + } + Object value = expression.getValue(executionEntity); + return value != null && "true".equals(value.toString()); + } +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/process/ProcessService.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/process/ProcessService.java new file mode 100644 index 00000000..06b1d91a --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/process/ProcessService.java @@ -0,0 +1,162 @@ +package com.yxt.anrui.flowable.biz.process; +import com.yxt.anrui.flowable.biz.flow.FlowableService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.flowable.bpmn.model.*; +import org.flowable.engine.ManagementService; +import org.flowable.engine.RepositoryService; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.ui.modeler.domain.Model; +import org.flowable.ui.modeler.serviceapi.ModelService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.*; + +@Slf4j +@Service +public class ProcessService { + @Autowired + RuntimeService runtimeService; + + @Autowired + RepositoryService repositoryService; + + @Autowired + ModelService modelService; + + @Autowired + ManagementService managementService; + + @Autowired + ProcessEngineConfigurationImpl processEngineConfiguration; + + @Autowired + FlowableService flowableService; + + /** + * 1. 首先拿到BpmnModel,所有流程定义信息都可以通过BpmnModel获取;若流程尚未发起,则用modelId查询最新部署的流程定义数据; + * 若流程已经发起,可以通过流程实例的processDefinitionId查询流程定义的历史数据。 + * @param variableMap 流程变量,用于计算条件分支 + */ + public List calApprovePath(String processInstanceId, String modelId, Map variableMap){ + BpmnModel bpmnModel=repositoryService.getBpmnModel(modelId); + // BpmnModel bpmnModel2 =repositoryService.getBpmnModel(processInstanceId); + /*if(StringUtils.isNotBlank(processInstanceId)){ + ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); + bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId()); + }else { + Model model = modelService.getModel(modelId); + bpmnModel = modelService.getBpmnModel(model); + }*/ + Collection flowElements =new ArrayList<>(); + Collection flowElements2 = bpmnModel.getMainProcess().getFlowElements(); + flowElements.addAll(flowElements2); + List passElements = new ArrayList<>(); + dueStartElement(passElements, flowElements, variableMap); + return passElements; + } + + /** + * 2. 找到开始节点,通过它的目标节点,然后再不断往下找。 + */ + private void dueStartElement(List passElements, Collection flowElements, Map variableMap){ + Optional startElementOpt = flowElements.stream().filter(flowElement -> flowElement instanceof StartEvent).findFirst(); + startElementOpt.ifPresent(startElement -> { + flowElements.remove(startElement); + List outgoingFlows = ((StartEvent) startElement).getOutgoingFlows(); + String targetRef = outgoingFlows.get(0).getTargetRef(); + // 根据ID找到FlowElement + FlowElement targetElementOfStartElement = getFlowElement(flowElements, targetRef); + if (targetElementOfStartElement instanceof UserTask) { + this.getPassElementList(passElements, flowElements, targetElementOfStartElement, variableMap); + } + }); + } + + /** + * 3. 我只用到了UserTask、ExclusiveGateway、ParallelGateway,所以代码里只列举了这三种,如果用到了其他的,可以再自己补充 + */ + private void getPassElementList(List passElements, Collection flowElements, FlowElement curFlowElement, Map variableMap){ + // 任务节点 + if (curFlowElement instanceof UserTask) { + this.dueUserTaskElement(passElements, flowElements, curFlowElement, variableMap); + return; + } + // 排他网关 + if (curFlowElement instanceof ExclusiveGateway) { + this.dueExclusiveGateway(passElements, flowElements, curFlowElement, variableMap); + return; + } + // 并行网关 + if(curFlowElement instanceof ParallelGateway){ + this.dueParallelGateway(passElements, flowElements, curFlowElement, variableMap); + } + } + + private void dueUserTaskElement(List passElements, Collection flowElements, + FlowElement curFlowElement, Map variableMap){ + passElements.add(curFlowElement); + List outgoingFlows = ((UserTask) curFlowElement).getOutgoingFlows(); + String targetRef = outgoingFlows.get(0).getTargetRef(); + if (outgoingFlows.size() > 1) { + // 找到表达式成立的sequenceFlow + SequenceFlow sequenceFlow = getSequenceFlow(variableMap, outgoingFlows); + targetRef = sequenceFlow.getTargetRef(); + } + // 根据ID找到FlowElement + FlowElement targetElement = getFlowElement(flowElements, targetRef); + this.getPassElementList(passElements, flowElements, targetElement, variableMap); + } + + private void dueExclusiveGateway(List passElements, Collection flowElements, FlowElement curFlowElement, Map variableMap){ + // 获取符合条件的sequenceFlow的目标FlowElement + List exclusiveGatewayOutgoingFlows = ((ExclusiveGateway) curFlowElement).getOutgoingFlows(); + flowElements.remove(curFlowElement); + // 找到表达式成立的sequenceFlow + SequenceFlow sequenceFlow = getSequenceFlow(variableMap, exclusiveGatewayOutgoingFlows); + // 根据ID找到FlowElement + FlowElement targetElement = getFlowElement(flowElements, sequenceFlow.getTargetRef()); + this.getPassElementList(passElements, flowElements, targetElement, variableMap); + } + + private void dueParallelGateway(List passElements, Collection flowElements, FlowElement curFlowElement, Map variableMap){ + FlowElement targetElement; + List parallelGatewayOutgoingFlows = ((ParallelGateway) curFlowElement).getOutgoingFlows(); + for(SequenceFlow sequenceFlow : parallelGatewayOutgoingFlows){ + targetElement = getFlowElement(flowElements, sequenceFlow.getTargetRef()); + this.getPassElementList(passElements, flowElements, targetElement, variableMap); + } + } + + private FlowElement getFlowElement(Collection flowElements, String targetRef) { + return flowElements.stream().filter(flowElement -> targetRef.equals(flowElement.getId())).findFirst().orElse(null); + } + + /** + * 4. 根据传入的变量,计算出表达式成立的那一条SequenceFlow + * @param variableMap + * @param outgoingFlows + * @return + */ + private SequenceFlow getSequenceFlow(Map variableMap, List outgoingFlows) { + Optional sequenceFlowOpt = outgoingFlows.stream().filter(item -> { + try { + return this.getElValue(item.getConditionExpression(), variableMap); + } catch (Exception e) { + return false; + } + }).findFirst(); + return sequenceFlowOpt.orElse(outgoingFlows.get(0)); + } + + private boolean getElValue(String exp, Map variableMap){ + return managementService.executeCommand(new ExpressionCmd(runtimeService, processEngineConfiguration, null, exp, variableMap)); + } + + public Map getProcessInstanceById(String procInsId) { + return flowableService.getProcessInstanceById(procInsId); + } +} \ No newline at end of file diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentMapper.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentMapper.java new file mode 100644 index 00000000..2974556e --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentMapper.java @@ -0,0 +1,72 @@ +/********************************************************* + ********************************************************* + ******************** ******************* + ************* ************ + ******* _oo0oo_ ******* + *** o8888888o *** + * 88" . "88 * + * (| -_- |) * + * 0\ = /0 * + * ___/`---'\___ * + * .' \\| |// '. * + * / \\||| : |||// \ * + * / _||||| -:- |||||- \ * + * | | \\\ - /// | | * + * | \_| ''\---/'' |_/ | * + * \ .-\__ '-' ___/-. / * + * ___'. .' /--.--\ `. .'___ * + * ."" '< `.___\_<|>_/___.' >' "". * + * | | : `- \`.;`\ _ /`;.`/ - ` : | | * + * \ \ `_. \_ __\ /__ _/ .-` / / * + * =====`-.____`.___ \_____/___.-`___.-'===== * + * `=---=' * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * + *********__佛祖保佑__永无BUG__验收通过__钞票多多__********* + *********************************************************/ +package com.yxt.anrui.flowable.biz.processcomment; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.yxt.anrui.flowable.api.processcomment.ProcessComment; +import com.yxt.anrui.flowable.api.processcomment.ProcessCommentDto; +import com.yxt.anrui.flowable.api.processcomment.ProcessCommentVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + * Project: processcomment(流程评论)
+ * File: ProcessCommentMapper.java
+ * Class: com.yxt.anrui.flowable.api.processcomment.biz.processcomment.ProcessCommentMapper
+ * Description: process_comment.
+ * Copyright: Copyright (c) 2011
+ * Company: https://gitee.com/liuzp315
+ * Makedate: 2023-01-30 14:40:37
+ * + * @author liupopo + * @version 1.0 + * @since 1.0 + */ +@Mapper +public interface ProcessCommentMapper extends BaseMapper { + + //@Update("update process_comment set name=#{msg} where id=#{id}") + //IPage voPage(IPage page, @Param(Constants.WRAPPER) QueryWrapper qw); + + IPage selectPageVo(IPage page, @Param(Constants.WRAPPER) Wrapper qw); + + List selectListAllVo(@Param(Constants.WRAPPER) Wrapper qw); + + @Select("select * from process_comment") + List selectListVo(); + + List getCommentList(@Param("processId")String processId); + @Select("select * from process_comment where sid=#{sid}") + ProcessComment fetchBySid(@Param("sid")String sid); + + void insertByDto(ProcessCommentDto dto); +} \ No newline at end of file diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentMapper.xml b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentMapper.xml new file mode 100644 index 00000000..4b3c0d8d --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentMapper.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + insert into `process_comment` ( `sid`, `reviewer`, `reviewerSid`, `time`, `content`, `processId`, `processInstSid`) + values(#{sid},#{reviewer},#{reviewerSid},#{time},#{content},#{processId},#{processInstSid}); + + \ No newline at end of file diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentRest.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentRest.java new file mode 100644 index 00000000..cb660f5d --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentRest.java @@ -0,0 +1,105 @@ +/********************************************************* + ********************************************************* + ******************** ******************* + ************* ************ + ******* _oo0oo_ ******* + *** o8888888o *** + * 88" . "88 * + * (| -_- |) * + * 0\ = /0 * + * ___/`---'\___ * + * .' \\| |// '. * + * / \\||| : |||// \ * + * / _||||| -:- |||||- \ * + * | | \\\ - /// | | * + * | \_| ''\---/'' |_/ | * + * \ .-\__ '-' ___/-. / * + * ___'. .' /--.--\ `. .'___ * + * ."" '< `.___\_<|>_/___.' >' "". * + * | | : `- \`.;`\ _ /`;.`/ - ` : | | * + * \ \ `_. \_ __\ /__ _/ .-` / / * + * =====`-.____`.___ \_____/___.-`___.-'===== * + * `=---=' * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * + *********__佛祖保佑__永无BUG__验收通过__钞票多多__********* + *********************************************************/ +package com.yxt.anrui.flowable.biz.processcomment; + +import com.yxt.anrui.flowable.api.processcomment.*; +import com.yxt.common.core.query.PagerQuery; +import com.yxt.common.core.result.ResultBean; +import com.yxt.common.core.vo.PagerVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.Date; +import java.util.List; +import java.util.UUID; + +/** + * Project: processcomment(流程评论)
+ * File: ProcessCommentFeignFallback.java
+ * Class: com.yxt.anrui.flowable.api.processcomment.biz.processcomment.ProcessCommentRest
+ * Description: process_comment.
+ * Copyright: Copyright (c) 2011
+ * Company: https://gitee.com/liuzp315
+ * Makedate: 2023-01-30 14:40:37
+ * + * @author liupopo + * @version 1.0 + * @since 1.0 + */ +@Api(tags = "process_comment") +@RestController +@RequestMapping("v1/processcomment") +public class ProcessCommentRest implements ProcessCommentFeign { + + @Autowired + private ProcessCommentService processCommentService; + + @Override + @ApiOperation("根据条件分页查询数据的列表") + @PostMapping("/listPage") + public ResultBean> listPage(@RequestBody PagerQuery pq){ + ResultBean rb = ResultBean.fireFail(); + PagerVo pv = processCommentService.listPageVo(pq); + return rb.success().setData(pv); + } + + @Override + @ApiOperation("新增或修改") + @PostMapping("/save") + public ResultBean save(@RequestBody ProcessCommentDto dto){ + ResultBean rb = ResultBean.fireFail(); + dto.setTime(new Date()); + processCommentService.saveOrUpdateDto(dto); + return rb.success(); + } + + @Override + @ApiOperation("根据sid批量删除") + @PostMapping("/delBySids") + public ResultBean delBySids(@RequestBody String[] sids){ + ResultBean rb = ResultBean.fireFail(); + processCommentService.delBySids(sids); + return rb.success(); + } + + @Override + @ApiOperation("根据SID获取一条记录") + @GetMapping("/fetchDetailsBySid/{sid}") + public ResultBean fetchDetailsBySid(@PathVariable("sid") String sid){ + ResultBean rb = ResultBean.fireFail(); + ProcessCommentDetailsVo vo = processCommentService.fetchDetailsVoBySid(sid); + return rb.success().setData(vo); + } + + @Override + public ResultBean> getCommentList(String processId) { + ResultBean rb = ResultBean.fireFail(); + List vo = processCommentService.getCommentList(processId); + return rb.success().setData(vo); + } +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentService.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentService.java new file mode 100644 index 00000000..7527bdc5 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentService.java @@ -0,0 +1,135 @@ +/********************************************************* + ********************************************************* + ******************** ******************* + ************* ************ + ******* _oo0oo_ ******* + *** o8888888o *** + * 88" . "88 * + * (| -_- |) * + * 0\ = /0 * + * ___/`---'\___ * + * .' \\| |// '. * + * / \\||| : |||// \ * + * / _||||| -:- |||||- \ * + * | | \\\ - /// | | * + * | \_| ''\---/'' |_/ | * + * \ .-\__ '-' ___/-. / * + * ___'. .' /--.--\ `. .'___ * + * ."" '< `.___\_<|>_/___.' >' "". * + * | | : `- \`.;`\ _ /`;.`/ - ` : | | * + * \ \ `_. \_ __\ /__ _/ .-` / / * + * =====`-.____`.___ \_____/___.-`___.-'===== * + * `=---=' * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * + *********__佛祖保佑__永无BUG__验收通过__钞票多多__********* + *********************************************************/ +package com.yxt.anrui.flowable.biz.processcomment; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.yxt.anrui.flowable.api.flowtask.AppUserVo; +import com.yxt.anrui.flowable.api.flowtask.TaskUserInfo; +import com.yxt.anrui.flowable.api.processcomment.*; +import com.yxt.common.base.config.component.FileUploadComponent; +import com.yxt.supervise.system.sysuser.SysUserFeign; +import com.yxt.supervise.system.sysuser.SysUserVo; +import org.apache.commons.lang3.StringUtils; +import com.yxt.common.base.service.MybatisBaseService; +import com.yxt.common.base.utils.PagerUtil; +import com.yxt.common.core.query.PagerQuery; +import com.yxt.common.core.result.ResultBean; +import com.yxt.common.core.vo.PagerVo; + +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * Project: processcomment(流程评论)
+ * File: ProcessCommentService.java
+ * Class: com.yxt.anrui.flowable.api.processcomment.biz.processcomment.ProcessCommentService
+ * Description: process_comment 业务逻辑.
+ * Copyright: Copyright (c) 2011
+ * Company: https://gitee.com/liuzp315
+ * Makedate: 2023-01-30 14:40:37
+ * + * @author liupopo + * @version 1.0 + * @since 1.0 + */ +@Service +public class ProcessCommentService extends MybatisBaseService { + @Resource + private SysUserFeign sysUserFeign; + @Resource + private FileUploadComponent fileUploadComponent; + private QueryWrapper createQueryWrapper(ProcessCommentQuery query) { + // todo: 这里根据具体业务调整查询条件 + // 多字段Like示例:qw.and(wrapper -> wrapper.like("name", query.getName()).or().like("remark", query.getName())); + QueryWrapper qw = new QueryWrapper<>(); + return qw; + } + + public PagerVo listPageVo(PagerQuery pq) { + ProcessCommentQuery query = pq.getParams(); + QueryWrapper qw = createQueryWrapper(query); + IPage page = PagerUtil.queryToPage(pq); + IPage pagging = baseMapper.selectPageVo(page, qw); + PagerVo p = PagerUtil.pageToVo(pagging, null); + return p; + } + + public void saveOrUpdateDto(ProcessCommentDto dto){ + String dtoSid = dto.getSid(); + if (StringUtils.isBlank(dtoSid)) { + dto.setSid(UUID.randomUUID().toString()); + baseMapper.insertByDto(dto); + return; + } + this.updateByDto(dto); + } + + public void insertByDto(ProcessCommentDto dto){ + ProcessComment entity = new ProcessComment(); + BeanUtil.copyProperties(dto, entity, "id", "sid"); + baseMapper.insert(entity); + } + + public void updateByDto(ProcessCommentDto dto){ + String dtoSid = dto.getSid(); + if (StringUtils.isBlank(dtoSid)) { + return; + } + ProcessComment entity = fetchBySid(dtoSid); + BeanUtil.copyProperties(dto, entity, "id", "sid"); + baseMapper.updateById(entity); + } + + public ProcessCommentDetailsVo fetchDetailsVoBySid(String sid){ + ProcessComment entity = fetchBySid(sid); + ProcessCommentDetailsVo vo = new ProcessCommentDetailsVo(); + BeanUtil.copyProperties(entity, vo); + return vo; + } + + public List getCommentList(String processId) { + List commentList = baseMapper.getCommentList(processId); + for(ProcessCommentVo histIns:commentList){ + ResultBean> sysUserVoResultBean = sysUserFeign.fetchBySids(histIns.getReviewerSid());// sysUserService.selectUserById(Long.parseLong(histIns.getAssignee())); + List data1 = sysUserVoResultBean.getData(); + for( SysUserVo data:data1){ + AppUserVo taskUserInfo=new AppUserVo(); + taskUserInfo.setAssigneeName(data.getName()); + if(!com.yxt.common.base.utils.StringUtils.isBlank(data.getHeadImage())){ + taskUserInfo.setAssigneeHeadImage(fileUploadComponent.getUrlPrefix() +data.getHeadImage()); + } + histIns.setTaskUserInfo(taskUserInfo); + } + } + return commentList; + } +} \ No newline at end of file diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/service/impl/FlowTaskServiceImpl.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/service/impl/FlowTaskServiceImpl.java new file mode 100644 index 00000000..acec5b60 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/service/impl/FlowTaskServiceImpl.java @@ -0,0 +1,364 @@ +package com.yxt.anrui.flowable.biz.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.google.common.collect.Lists; +import com.yxt.anrui.flowable.api.flowcomment.FlowCommentDto; +import com.yxt.anrui.flowable.api.flowtask.FlowTaskDto; +import com.yxt.anrui.flowable.api.flowtask.CompleteTaskQuery; +import com.yxt.anrui.flowable.api.flowtask.FlowTaskQuery; +import com.yxt.anrui.flowable.api.flowtask.FlowTaskQueryOne; +import com.yxt.anrui.flowable.api.flowcomment.FlowComment; +import com.yxt.anrui.flowable.factory.FlowServiceFactory; +import com.yxt.anrui.flowable.test.StartProcessInstanceQuery; +import com.yxt.anrui.flowable.utils.FlowableUtils; +import com.yxt.common.core.query.PagerQuery; +import com.yxt.common.core.result.ResultBean; +import com.yxt.supervise.system.sysuser.SysUserFeign; +import com.yxt.supervise.system.sysuser.SysUserVo; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.flowable.bpmn.model.BpmnModel; +import org.flowable.bpmn.model.EndEvent; +import org.flowable.bpmn.model.Process; +import org.flowable.common.engine.impl.identity.Authentication; +import org.flowable.engine.history.HistoricActivityInstance; +import org.flowable.engine.history.HistoricProcessInstance; +import org.flowable.engine.repository.ProcessDefinition; +import org.flowable.engine.runtime.Execution; +import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.engine.task.Comment; +import org.flowable.identitylink.api.history.HistoricIdentityLink; +import org.flowable.task.api.DelegationState; +import org.flowable.task.api.Task; +import org.flowable.task.api.TaskQuery; +import org.flowable.task.api.history.HistoricTaskInstance; +import org.flowable.task.api.history.HistoricTaskInstanceQuery; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.*; + +/** + * @author dimengzhe + * @date 2021/7/29 15:33 + * @description + */ +@Service +public class FlowTaskServiceImpl extends FlowServiceFactory { + + @Autowired + private SysUserFeign sysUserFeign; + + + public ResultBean startProcessInstanceByKey(StartProcessInstanceQuery params) { + ResultBean returnVo = ResultBean.fireSuccess(); + if (StringUtils.isNotBlank(params.getProcessDefinitionId())) { + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(params.getProcessDefinitionId()) + .latestVersion().singleResult(); + if (processDefinition != null && processDefinition.isSuspended()) { + returnVo = new ResultBean().fail().setMsg("此流程已经挂起,请联系系统管理员!"); + return returnVo; + } + ResultBean user = sysUserFeign.fetchBySid(params.getUserSid()); + if (!user.getSuccess()) { + returnVo = new ResultBean().fail().setMsg("当前发起人不存在,请确认"); + return returnVo; + } + identityService.setAuthenticatedUserId(params.getUserSid()); + ProcessInstance processInstance = runtimeService.startProcessInstanceById(params.getProcessDefinitionId(), params.getVariables()); + Task task = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).singleResult(); + if (Objects.nonNull(task)) { + taskService.addComment(task.getId(), processInstance.getProcessInstanceId(), FlowComment.START.getType(), params.getUserSid() + "发起流程申请"); + taskService.complete(task.getId(), params.getVariables()); + } + returnVo.setData(processInstance); + } else { + returnVo = new ResultBean().fail().setMsg("Parameters should not be null"); + } + return returnVo; + } + + + public ResultBean todoList(PagerQuery taskQueryPagerQuery) { + int pageNum = (int) taskQueryPagerQuery.getCurrent();//当前页 + int pageSize = (int) taskQueryPagerQuery.getSize();//每页条数 + String userSid = taskQueryPagerQuery.getParams().getUserSid(); + Page page = new Page<>(); + TaskQuery taskQuery = taskService.createTaskQuery() + .processVariableValueEquals("zd","12") + // .taskVariableValueEquals("zd","12") + .active() + .includeProcessVariables() + .taskAssignee(userSid) + .orderByTaskCreateTime().desc(); + page.setTotal(taskQuery.count()); + List taskList = taskQuery.listPage(pageNum - 1, pageSize); + List flowList = new ArrayList<>(); + for (Task task : taskList) { + FlowTaskDto flowTask = new FlowTaskDto(); + // 当前流程信息 + flowTask.setTaskId(task.getId());//任务编号 + flowTask.setTaskDefKey(task.getTaskDefinitionKey());//任务定义key + flowTask.setCreateTime(task.getCreateTime());//任务创建时间 + flowTask.setProcDefId(task.getProcessDefinitionId());//流程id + flowTask.setTaskName(task.getName());//任务名称 + // 流程定义信息 + ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() + .processDefinitionId(task.getProcessDefinitionId()) + .singleResult(); + flowTask.setDeployId(pd.getDeploymentId());//流程部署编号 + flowTask.setProcDefName(pd.getName());//流程定义名称 + flowTask.setProcDefVersion(pd.getVersion());//流程定义内置使用版本 + flowTask.setProcInsId(task.getProcessInstanceId());//流程实例ID + // 流程发起人信息 + HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() + .processInstanceId(task.getProcessInstanceId()) + .singleResult(); + ResultBean startUser = sysUserFeign.fetchBySid(historicProcessInstance.getStartUserId()); + if (!startUser.getSuccess()) { + return ResultBean.fireFail().setMsg("当前流程发起人不存在"); + } + flowTask.setStartUserSid(startUser.getData().getSid()); + flowTask.setStartUserName(startUser.getData().getName()); + flowList.add(flowTask); + } + page.setRecords(flowList); + return ResultBean.fireSuccess().setData(page); + } + + + public ResultBean doneList(PagerQuery taskQueryPagerQuery) { + int pageNum = (int) taskQueryPagerQuery.getCurrent();//当前页 + int pageSize = (int) taskQueryPagerQuery.getSize();//每页条数 + String userSid = taskQueryPagerQuery.getParams().getUserSid(); + Page page = new Page<>(); + HistoricTaskInstanceQuery taskInstanceQuery = historyService.createHistoricTaskInstanceQuery() + .includeProcessVariables() + .finished() + .taskAssignee(userSid) + .orderByHistoricTaskInstanceEndTime() + .desc(); + List historicTaskInstanceList = taskInstanceQuery.listPage(pageNum - 1, pageSize); + List hisTaskList = Lists.newArrayList(); + for (HistoricTaskInstance histTask : historicTaskInstanceList) { + FlowTaskDto flowTask = new FlowTaskDto(); + // 当前流程信息 + flowTask.setTaskId(histTask.getId()); + // 审批人员信息 + flowTask.setCreateTime(histTask.getCreateTime()); + flowTask.setFinishTime(histTask.getEndTime()); + flowTask.setDuration(FlowableUtils.getDate(histTask.getDurationInMillis())); + flowTask.setProcDefId(histTask.getProcessDefinitionId()); + flowTask.setTaskDefKey(histTask.getTaskDefinitionKey()); + flowTask.setTaskName(histTask.getName()); + + // 流程定义信息 + ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() + .processDefinitionId(histTask.getProcessDefinitionId()) + .singleResult(); + flowTask.setDeployId(pd.getDeploymentId()); + flowTask.setProcDefName(pd.getName()); + flowTask.setProcDefVersion(pd.getVersion()); + flowTask.setProcInsId(histTask.getProcessInstanceId()); + flowTask.setHisProcInsId(histTask.getProcessInstanceId()); + + // 流程发起人信息 + HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() + .processInstanceId(histTask.getProcessInstanceId()) + .singleResult(); + ResultBean startUser = sysUserFeign.fetchBySid(historicProcessInstance.getStartUserId()); + if (!startUser.getSuccess()) { + return ResultBean.fireFail().setMsg("当前流程发起人不存在"); + } + flowTask.setStartUserSid(startUser.getData().getSid()); + flowTask.setStartUserName(startUser.getData().getName()); + hisTaskList.add(flowTask); + } + page.setTotal(hisTaskList.size()); + page.setRecords(hisTaskList); + return ResultBean.fireSuccess().setData(page); + } + + + public ResultBean complete(CompleteTaskQuery completeTaskQuery) { + Task task = taskService.createTaskQuery().taskId(completeTaskQuery.getTaskId()).singleResult(); + if (Objects.isNull(task)) { + return ResultBean.fireFail().setMsg("任务不存在"); + } + if (DelegationState.PENDING.equals(task.getDelegationState())) { + taskService.addComment(completeTaskQuery.getTaskId(), completeTaskQuery.getInstanceId(), FlowComment.DELEGATE.getType(), completeTaskQuery.getComment()); + taskService.resolveTask(completeTaskQuery.getTaskId(), completeTaskQuery.getVariables()); + } else { + taskService.addComment(completeTaskQuery.getTaskId(), completeTaskQuery.getInstanceId(), FlowComment.NORMAL.getType(), completeTaskQuery.getComment()); + ResultBean startUser = sysUserFeign.fetchBySid(completeTaskQuery.getUserSid()); + if (!startUser.getSuccess()) { + return ResultBean.fireFail().setMsg("当前流程发起人不存在"); + } + taskService.setAssignee(completeTaskQuery.getTaskId(), startUser.getData().getSid()); + taskService.complete(completeTaskQuery.getTaskId(), completeTaskQuery.getVariables()); + } + return ResultBean.fireSuccess(); + } + + + public ResultBean flowRecord(String procInsId, String deployId) { + Map map = new HashMap(); + if (org.apache.commons.lang3.StringUtils.isNotBlank(procInsId)) { + List list = historyService + .createHistoricActivityInstanceQuery() + .processInstanceId(procInsId) + .orderByHistoricActivityInstanceStartTime() + .desc().list(); + List hisFlowList = new ArrayList<>(); + for (HistoricActivityInstance histIns : list) { + if (StringUtils.isNotBlank(histIns.getTaskId())) { + FlowTaskDto flowTask = new FlowTaskDto(); + flowTask.setTaskId(histIns.getTaskId()); + flowTask.setTaskName(histIns.getActivityName()); + flowTask.setCreateTime(histIns.getStartTime()); + flowTask.setFinishTime(histIns.getEndTime()); + if (StringUtils.isNotBlank(histIns.getAssignee())) { + ResultBean sysUser = sysUserFeign.fetchBySid(histIns.getAssignee()); + if (!sysUser.getSuccess()) { + return ResultBean.fireFail().setMsg("当前流程发起人不存在"); + } + flowTask.setAssigneeSid(sysUser.getData().getSid()); + flowTask.setAssigneeName(sysUser.getData().getName()); + flowTask.setDeptName(sysUser.getData().getDepartmentName()); + } + // 展示审批人员 + List linksForTask = historyService.getHistoricIdentityLinksForTask(histIns.getTaskId()); + StringBuilder stringBuilder = new StringBuilder(); + for (HistoricIdentityLink identityLink : linksForTask) { + if ("candidate".equals(identityLink.getType())) { + if (StringUtils.isNotBlank(identityLink.getUserId())) { + ResultBean sysUser = sysUserFeign.fetchBySid(identityLink.getUserId()); + stringBuilder.append(sysUser.getData().getName()).append(","); + } + } + } + if (org.apache.commons.lang3.StringUtils.isNotBlank(stringBuilder)) { + flowTask.setCandidate(stringBuilder.substring(0, stringBuilder.length() - 1)); + } + + flowTask.setDuration(histIns.getDurationInMillis() == null || histIns.getDurationInMillis() == 0 ? null :FlowableUtils.getDate(histIns.getDurationInMillis())); + // 获取意见评论内容 + List commentList = taskService.getProcessInstanceComments(histIns.getProcessInstanceId()); + commentList.forEach(comment -> { + if (histIns.getTaskId().equals(comment.getTaskId())) { + flowTask.setComment(FlowCommentDto.builder().type(comment.getType()).comment(comment.getFullMessage()).build()); + } + }); + hisFlowList.add(flowTask); + } + } + map.put("flowList", hisFlowList); + } + // 第一次申请获取初始化表单 + /* if (StringUtils.isNotBlank(deployId)) { + SysForm sysForm = sysInstanceFormService.selectSysDeployFormByDeployId(deployId); + if (Objects.isNull(sysForm)) { + return AjaxResult.error("请先配置流程表单"); + } + map.put("formData", JSONObject.parseObject(sysForm.getFormContent())); + }*/ + return ResultBean.fireSuccess().setData(map); + } + + + public ResultBean stopProcess(FlowTaskQueryOne flowTaskQueryOne) { + List task = taskService.createTaskQuery().processInstanceId(flowTaskQueryOne.getInstanceId()).list(); + if (CollectionUtils.isEmpty(task)) { + return ResultBean.fireFail().setMsg("流程未启动或已执行完成,取消申请失败"); + } + ResultBean sysUserVoResultBean = sysUserFeign.fetchBySid(flowTaskQueryOne.getUserSid()); + if (!sysUserVoResultBean.getSuccess()) { + return ResultBean.fireFail().setMsg("该申请的申请人不存在"); + } + ProcessInstance processInstance = + runtimeService.createProcessInstanceQuery().processInstanceId(flowTaskQueryOne.getInstanceId()).singleResult(); + BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId()); + if (Objects.nonNull(bpmnModel)) { + Process process = bpmnModel.getMainProcess(); + List endNodes = process.findFlowElementsOfType(EndEvent.class, false); + if (CollectionUtils.isNotEmpty(endNodes)) { + Authentication.setAuthenticatedUserId(sysUserVoResultBean.getData().getSid()); + String endId = endNodes.get(0).getId(); + List executions = + runtimeService.createExecutionQuery().parentId(processInstance.getProcessInstanceId()).list(); + List executionIds = new ArrayList<>(); + executions.forEach(execution -> executionIds.add(execution.getId())); + runtimeService.createChangeActivityStateBuilder().moveExecutionsToSingleActivityId(executionIds, + endId).changeState(); + } + } + + return ResultBean.fireSuccess(); + } + + + public ResultBean myprocess(PagerQuery taskQueryPagerQuery) { + int pageNum = (int) taskQueryPagerQuery.getCurrent();//当前页 + int pageSize = (int) taskQueryPagerQuery.getSize();//每页条数 + String userSid = taskQueryPagerQuery.getParams().getUserSid(); + Page page = new Page<>(); + List historicProcessInstances = historyService.createHistoricProcessInstanceQuery() + .startedBy(userSid) + .orderByProcessInstanceStartTime() + .desc() + .listPage(pageNum - 1, pageSize); + page.setTotal(historicProcessInstances.size()); + List flowList = new ArrayList<>(); + for (HistoricProcessInstance hisIns : historicProcessInstances) { + FlowTaskDto flowTask = new FlowTaskDto(); + flowTask.setCreateTime(hisIns.getStartTime()); + flowTask.setFinishTime(hisIns.getEndTime()); + flowTask.setProcInsId(hisIns.getId()); + // 计算耗时 + if (Objects.nonNull(hisIns.getEndTime())) { + long time = hisIns.getEndTime().getTime() - hisIns.getStartTime().getTime(); + flowTask.setDuration(FlowableUtils.getDate(time)); + } else { + long time = System.currentTimeMillis() - hisIns.getStartTime().getTime(); + flowTask.setDuration(FlowableUtils.getDate(time)); + } + // 流程定义信息 + ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() + .processDefinitionId(hisIns.getProcessDefinitionId()) + .singleResult(); + flowTask.setDeployId(pd.getDeploymentId()); + flowTask.setProcDefName(pd.getName()); + flowTask.setProcDefVersion(pd.getVersion()); + flowTask.setCategory(pd.getCategory()); + flowTask.setProcDefVersion(pd.getVersion()); + + // 当前所处流程 + List taskList = taskService.createTaskQuery().processInstanceId(hisIns.getId()).list(); + if (CollectionUtils.isNotEmpty(taskList)) { + flowTask.setTaskId(taskList.get(0).getId()); + } else { + List historicTaskInstance = historyService.createHistoricTaskInstanceQuery().processInstanceId(hisIns.getId()).orderByHistoricTaskInstanceEndTime().desc().list(); + flowTask.setTaskId(historicTaskInstance.get(0).getId()); + } + flowList.add(flowTask); + } + page.setRecords(flowList); + return ResultBean.fireSuccess().setData(page); + } + + + public ResultBean processVariables(String taskId) { + HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().includeProcessVariables().finished().taskId(taskId).singleResult(); + if (Objects.nonNull(historicTaskInstance)) { + return ResultBean.fireSuccess().setData(historicTaskInstance.getProcessVariables()); + } else { + Map variables = taskService.getVariables(taskId); + return ResultBean.fireSuccess().setData(variables); + } + } + + + public ResultBean getNextFlowNode(FlowTaskQueryOne flowTaskQueryOne) { + return null; + } +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysdeployform/SysDeployFormMapper.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysdeployform/SysDeployFormMapper.java new file mode 100644 index 00000000..4a4a0db9 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysdeployform/SysDeployFormMapper.java @@ -0,0 +1,74 @@ +package com.yxt.anrui.flowable.biz.sysdeployform; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yxt.anrui.flowable.api.sysform.SysForm; +import com.yxt.anrui.flowable.api.sysdeployform.SysDeployForm; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 流程实例关联表单Mapper接口 + * + * @author XuanXuan Xuan + * @date 2021-03-30 + */ +@Mapper +public interface SysDeployFormMapper extends BaseMapper { + /** + * 查询流程实例关联表单 + * + * @param id 流程实例关联表单ID + * @return 流程实例关联表单 + */ + public SysDeployForm selectSysDeployFormById(Long id); + + /** + * 查询流程实例关联表单列表 + * + * @param SysDeployForm 流程实例关联表单 + * @return 流程实例关联表单集合 + */ + public List selectSysDeployFormList(SysDeployForm SysDeployForm); + + /** + * 新增流程实例关联表单 + * + * @param SysDeployForm 流程实例关联表单 + * @return 结果 + */ + public int insertSysDeployForm(SysDeployForm SysDeployForm); + + /** + * 修改流程实例关联表单 + * + * @param SysDeployForm 流程实例关联表单 + * @return 结果 + */ + public int updateSysDeployForm(SysDeployForm SysDeployForm); + + /** + * 删除流程实例关联表单 + * + * @param id 流程实例关联表单ID + * @return 结果 + */ + public int deleteSysDeployFormById(Long id); + + /** + * 批量删除流程实例关联表单 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteSysDeployFormByIds(Long[] ids); + + + + /** + * 查询流程挂着的表单 + * @param deployId + * @return + */ + SysForm selectSysDeployFormByDeployId(String deployId); +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysdeployform/SysDeployFormMapper.xml b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysdeployform/SysDeployFormMapper.xml new file mode 100644 index 00000000..b4748b5c --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysdeployform/SysDeployFormMapper.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + select id, form_id, deploy_id from sys_deploy_form + + + + + + + + + + insert into sys_deploy_form + + form_id, + deploy_id, + + + #{formId}, + #{deployId}, + + + + + update sys_deploy_form + + form_id = #{formId}, + deploy_id = #{deployId}, + + where id = #{id} + + + + delete from sys_deploy_form where id = #{id} + + + + delete from sys_deploy_form where id in + + #{id} + + + \ No newline at end of file diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysdeployform/SysDeployFormService.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysdeployform/SysDeployFormService.java new file mode 100644 index 00000000..ce7b85fb --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysdeployform/SysDeployFormService.java @@ -0,0 +1,94 @@ +package com.yxt.anrui.flowable.biz.sysdeployform; + +import com.yxt.anrui.flowable.api.sysform.SysForm; +import com.yxt.anrui.flowable.api.sysdeployform.SysDeployForm; +import com.yxt.common.base.service.MybatisBaseService; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 流程实例关联表单Service业务层处理 + * + * @author XuanXuan Xuan + * @date 2021-04-03 + */ +@Service +public class SysDeployFormService extends MybatisBaseService { + + /** + * 查询流程实例关联表单 + * + * @param id 流程实例关联表单ID + * @return 流程实例关联表单 + */ + public SysDeployForm selectSysDeployFormById(Long id) + { + return baseMapper.selectSysDeployFormById(id); + } + + /** + * 查询流程实例关联表单列表 + * + * @param sysDeployForm 流程实例关联表单 + * @return 流程实例关联表单 + */ + public List selectSysDeployFormList(SysDeployForm sysDeployForm) + { + return baseMapper.selectSysDeployFormList(sysDeployForm); + } + + /** + * 新增流程实例关联表单 + * + * @param sysDeployForm 流程实例关联表单 + * @return 结果 + */ + public int insertSysDeployForm(SysDeployForm sysDeployForm) + { + return baseMapper.insertSysDeployForm(sysDeployForm); + } + + /** + * 修改流程实例关联表单 + * + * @param sysDeployForm 流程实例关联表单 + * @return 结果 + */ + public int updateSysDeployForm(SysDeployForm sysDeployForm) + { + return baseMapper.updateSysDeployForm(sysDeployForm); + } + + /** + * 批量删除流程实例关联表单 + * + * @param ids 需要删除的流程实例关联表单ID + * @return 结果 + */ + public int deleteSysDeployFormByIds(Long[] ids) + { + return baseMapper.deleteSysDeployFormByIds(ids); + } + + /** + * 删除流程实例关联表单信息 + * + * @param id 流程实例关联表单ID + * @return 结果 + */ + public int deleteSysDeployFormById(Long id) + { + return baseMapper.deleteSysDeployFormById(id); + } + + /** + * 查询流程挂着的表单 + * + * @param deployId + * @return + */ + public SysForm selectSysDeployFormByDeployId(String deployId) { + return baseMapper.selectSysDeployFormByDeployId(deployId); + } +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysform/SysFormController.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysform/SysFormController.java new file mode 100644 index 00000000..a9fa16b6 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysform/SysFormController.java @@ -0,0 +1,108 @@ +package com.yxt.anrui.flowable.biz.sysform; + +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.yxt.anrui.flowable.api.sysform.SysFormFeign; +import com.yxt.anrui.flowable.api.sysform.SysForm; +import com.yxt.anrui.flowable.api.sysform.SysFormQuery; +import com.yxt.anrui.flowable.api.sysdeployform.SysDeployForm; +import com.yxt.anrui.flowable.api.sysform.SysFormVo; +import com.yxt.anrui.flowable.biz.sysdeployform.SysDeployFormService; +import com.yxt.common.base.utils.PagerUtil; +import com.yxt.common.core.query.PagerQuery; +import com.yxt.common.core.result.ResultBean; +import com.yxt.common.core.vo.PagerVo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + * 流程表单Controller + * + * @author XuanXuan + * @date 2021-04-03 + */ +@RestController +@RequestMapping("v1/flowable/form") +public class SysFormController implements SysFormFeign { + @Autowired + private SysFormService sysFormService; + @Autowired + private SysDeployFormService sysDeployFormService; + + /* @Autowired + private ISysDeployFormService sysDeployFormService;*/ + + /** + * 查询流程表单列表 + */ + @Override + public ResultBean> list(PagerQuery pq) { + ResultBean> rb = ResultBean.fireFail(); + IPage page = sysFormService.selectSysFormList(pq); + PagerVo pv = new PagerVo<>(); + PagerVo pv1 = PagerUtil.pageToVo(page, pv); + return rb.success().setData(pv1); + } + + + /** + * 导出流程表单列表 + */ + @GetMapping("/export") + public ResultBean export(SysForm sysForm) { + /*List list = SysFormService.selectSysFormList(sysForm); + ExcelUtil util = new ExcelUtil(SysForm.class); + return util.exportExcel(list, "form");*/ + return null; + } + + /** + * 获取流程表单详细信息 + */ + @GetMapping(value = "/{formId}") + public String getInfo(@PathVariable("formId") Long formId) { + SysForm sysForm = sysFormService.selectSysFormById(formId); + return JSON.toJSONString(sysForm); + } + + /** + * 新增流程表单 + */ + @Override + public ResultBean add(@RequestBody SysForm sysForm) { + int i = sysFormService.insertSysForm(sysForm); + ResultBean rb = ResultBean.fireFail(); + return rb.success().setMsg("操作成功"); + } + + /** + * 修改流程表单 + */ + @PutMapping + public ResultBean edit(@RequestBody SysForm sysForm) { + // return toAjax(SysFormService.updateSysForm(sysForm)); + return null; + } + + /** + * 删除流程表单 + */ + @DeleteMapping("/{formIds}") + public ResultBean remove(@PathVariable Long[] formIds) { + sysFormService.deleteSysFormByIds(formIds); + ResultBean rb = ResultBean.fireFail(); + return rb.success().setMsg("操作成功"); + // return null; + } + + + /** + * 挂载流程表单 + */ + @PostMapping("/addDeployForm") + public ResultBean addDeployForm(@RequestBody SysDeployForm sysDeployForm) { + sysDeployFormService.insertSysDeployForm(sysDeployForm); + ResultBean rb = ResultBean.fireFail(); + return rb.success().setMsg("操作成功"); + } +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysform/SysFormMapper.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysform/SysFormMapper.java new file mode 100644 index 00000000..7a33ad96 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysform/SysFormMapper.java @@ -0,0 +1,77 @@ +package com.yxt.anrui.flowable.biz.sysform; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.yxt.anrui.flowable.api.sysform.SysForm; +import com.yxt.anrui.flowable.api.sysform.SysFormVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + + +/** + * 流程表单Mapper接口 + * + * @author XuanXuan Xuan + * @date 2021-03-30 + */ +@Mapper +public interface SysFormMapper extends BaseMapper { + /** + * 查询流程表单 + * + * @param formId 流程表单ID + * @return 流程表单 + */ + public SysForm selectSysFormById(Long formId); + + /** + * 查询流程表单列表 + * + * @return 流程表单集合 + */ +// public IPage selectSysFormVo(IPage page, @Param(Constants.WRAPPER) Wrapper qw); + List getSysFormVoList(IPage page, @Param(Constants.WRAPPER) Wrapper qw); + + /** + * 新增流程表单 + * + * @param sysForm 流程表单 + * @return 结果 + */ + public int insertSysForm(SysForm sysForm); + + /** + * 修改流程表单 + * + * @param sysForm 流程表单 + * @return 结果 + */ + public int updateSysForm(SysForm sysForm); + + /** + * 删除流程表单 + * + * @param formId 流程表单ID + * @return 结果 + */ + public int deleteSysFormById(Long formId); + + /** + * 批量删除流程表单 + * + * @param formIds 需要删除的数据ID + * @return 结果 + */ + public int deleteSysFormByIds(Long[] formIds); + + @Select("SELECT id AS formId, form_name AS formName, form_content AS formContent FROM sys_form ") + List selectListVo(); + + int getSysFormVoTotal(IPage page, QueryWrapper qw); +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysform/SysFormMapper.xml b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysform/SysFormMapper.xml new file mode 100644 index 00000000..cce1e070 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysform/SysFormMapper.xml @@ -0,0 +1,34 @@ + + + + + + + insert into sys_form + + form_name, + form_content, + + + #{formName}, + #{formContent}, + + + + delete from sys_form where id in + + #{formId} + + + + \ No newline at end of file diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysform/SysFormService.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysform/SysFormService.java new file mode 100644 index 00000000..a16ee00a --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysform/SysFormService.java @@ -0,0 +1,130 @@ +package com.yxt.anrui.flowable.biz.sysform; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yxt.anrui.flowable.api.sysform.SysForm; +import com.yxt.anrui.flowable.api.sysform.SysFormQuery; +import com.yxt.anrui.flowable.api.sysform.SysFormVo; +import com.yxt.common.base.service.MybatisBaseService; +import com.yxt.common.core.query.PagerQuery; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.Date; +import java.util.List; + +/** + * 流程表单Service业务层处理 + * + * @author XuanXuan Xuan + * @date 2021-04-03 + */ +@Service +//@Transactional +public class SysFormService extends MybatisBaseService { + + /** + * 查询流程表单 + * + * @param formId 流程表单ID + * @return 流程表单 + */ + public SysForm selectSysFormById(Long formId) + { + return baseMapper.selectSysFormById(formId); + } + + /** + * 查询流程表单列表 + * + * @return 流程表单 + */ +// public PagerVo selectSysFormList(PagerQuery pq) +// { +// /* List sysForms = baseMapper.selectListVo(); +// int size = sysForms.size(); +// SysFormQuery query = pq.getParams(); +// QueryWrapper qw = createQueryWrapper(query); +// IPage page = PagerUtil.queryToPage(pq); +// IPage pigging = baseMapper.selectSysFormVo(page,qw); +// PagerVo p = PagerUtil.pageToVo(pigging, null);*/ +// IPage page = PagerUtil.queryToPage(pq); +// QueryWrapper qw = createQueryWrapper(pq.getParams()); +// baseMapper.selectSysFormVo(page, qw); +// return null; +// } + + public IPage selectSysFormList(PagerQuery pagerQuery) { + List sysForms = baseMapper.selectListVo(); + IPage page =new Page<>();// PagerUtil.queryToPage(pagerQuery); + QueryWrapper qw = createQueryWrapper(pagerQuery.getParams()); + List sysFormVoList = baseMapper.getSysFormVoList(page, qw); + int total = baseMapper.getSysFormVoTotal(page, qw); + page.setTotal(total); + page.setRecords(sysFormVoList); + return page; + } + + /** + * 新增流程表单 + * + * @param sysForm 流程表单 + * @return 结果 + */ + public int insertSysForm(SysForm sysForm) + { + sysForm.setCreateTime(new Date()); + return baseMapper.insertSysForm(sysForm); + } + + /** + * 修改流程表单 + * + * @param sysForm 流程表单 + * @return 结果 + */ + public int updateSysForm(SysForm sysForm) + { + // sysForm.setUpdateTime(new Date()); + return 0;//sysFormMapper.updateSysForm(sysForm); + } + + /** + * 批量删除流程表单 + * + * @param formIds 需要删除的流程表单ID + * @return 结果 + */ + public int deleteSysFormByIds(Long[] formIds) + { + return baseMapper.deleteSysFormByIds(formIds); + } + + /** + * 删除流程表单信息 + * + * @param formId 流程表单ID + * @return 结果 + */ + public int deleteSysFormById(Long formId) + { + return 0;// sysFormMapper.deleteSysFormById(formId); + } + + private QueryWrapper createQueryWrapper(SysFormQuery query) { + // todo: 这里根据具体业务调整查询条件 + // 多字段Like示例:qw.and(wrapper -> wrapper.like("name", query.getName()).or().like("remark", query.getName())); + QueryWrapper qw = new QueryWrapper<>(); + + if (StringUtils.isNotBlank(query.getFormName())) { + qw.like("form_name", query.getFormName()); + } + + if (StringUtils.isNotBlank(query.getFormContent())) { + qw.eq("form_content", query.getFormContent()); + } + return qw; + } + +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysformlink/SysFormLinkMapper.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysformlink/SysFormLinkMapper.java new file mode 100644 index 00000000..59c3a25c --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysformlink/SysFormLinkMapper.java @@ -0,0 +1,37 @@ +package com.yxt.anrui.flowable.biz.sysformlink; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yxt.anrui.flowable.api.sysformlink.SysFormLink; +import com.yxt.anrui.flowable.api.sysformlink.SysFormStateVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.Map; + +/** + * Project: anrui-flowable(流程引擎)
+ * File: SysFormLinkMapper.java
+ * Class: com.yxt.anrui.flowable.biz.sysformlink.SysFormLinkMapper
+ * Description: 流程业务关联表.
+ * Copyright: Copyright (c) 2011
+ * Company: https://gitee.com/liuzp315
+ * Makedate: 2022-03-15 16:55:39
+ * + * @author liupopo + * @version 1.0 + * @since 1.0 + */ +@Mapper +public interface SysFormLinkMapper extends BaseMapper { + + int save(SysFormLink sysFormLink); + + @Select("select nodeState,flowState from sys_form_link where businessSid=#{businessSid}") + SysFormStateVo selectStateByBusinessSid(@Param("businessSid") String businessSid); + + int updateFiled(Map map); + + @Select("select count(1) from sys_form_link where businessSid=#{businessSid}") + int selectByBusinessSid(@Param("businessSid") String businessSid); +} \ No newline at end of file diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysformlink/SysFormLinkMapper.xml b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysformlink/SysFormLinkMapper.xml new file mode 100644 index 00000000..96301335 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysformlink/SysFormLinkMapper.xml @@ -0,0 +1,16 @@ + + + + + insert into sys_form_link(sid, businessSid, procInsId, taskDefKey, nodeState, flowState, formType) + values (#{sid},#{businessSid},#{procInsId},#{taskDefKey},#{nodeState},#{flowState},#{formType}) + + + + UPDATE sys_form_link SET nodeState=#{nodeState}, taskDefKey=#{taskDefKey} + + , flowState=#{flowState} + + WHERE businessSid=#{businessSid} + + \ No newline at end of file diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysformlink/SysFormLinkRest.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysformlink/SysFormLinkRest.java new file mode 100644 index 00000000..765cfa75 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysformlink/SysFormLinkRest.java @@ -0,0 +1,59 @@ +package com.yxt.anrui.flowable.biz.sysformlink; + +import com.yxt.anrui.flowable.api.sysformlink.SysFormLinkDto; +import com.yxt.anrui.flowable.api.sysformlink.SysFormLinkFeign; +import com.yxt.anrui.flowable.api.sysformlink.SysFormStateVo; +import com.yxt.common.core.result.ResultBean; +import io.swagger.annotations.Api; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Map; + +/** + * Project: anrui-flowable(流程引擎)
+ * File: SysFormLinkFeignFallback.java
+ * Class: com.yxt.anrui.flowable.biz.sysformlink.SysFormLinkRest
+ * Description: 流程业务关联表.
+ * Copyright: Copyright (c) 2011
+ * Company: https://gitee.com/liuzp315
+ * Makedate: 2022-03-15 16:55:39
+ * + * @author liupopo + * @version 1.0 + * @since 1.0 + */ +@Api(tags = "流程业务关联表") +@RestController +@RequestMapping("v1/sysformlink") +public class SysFormLinkRest implements SysFormLinkFeign { + + @Autowired + private SysFormLinkService sysFormLinkService; + + @Override + public ResultBean save(SysFormLinkDto dto) { + return sysFormLinkService.save(dto); + } + + @Override + public ResultBean selectStateByBusinessSid(String businessSid) { + return sysFormLinkService.selectStateByBusinessSid(businessSid); + } + + @Override + public ResultBean updateFiled(Map map) { + ResultBean resultBean = ResultBean.fireFail(); + int i = sysFormLinkService.updateFiled(map); + if (i == 0) { + return resultBean.setMsg("更新失败"); + } + return resultBean.success().setMsg("更新成功"); + } + + @Override + public ResultBean selectByBusinessSid(String sid) { + return sysFormLinkService.selectByBusinessSid(sid); + } +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysformlink/SysFormLinkService.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysformlink/SysFormLinkService.java new file mode 100644 index 00000000..7aeff439 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysformlink/SysFormLinkService.java @@ -0,0 +1,80 @@ +package com.yxt.anrui.flowable.biz.sysformlink; + +import com.yxt.anrui.flowable.api.sysformlink.SysFormLink; +import com.yxt.anrui.flowable.api.sysformlink.SysFormLinkDto; +import com.yxt.anrui.flowable.api.sysformlink.SysFormStateVo; +import com.yxt.common.base.service.MybatisBaseService; +import com.yxt.common.core.result.ResultBean; +import org.springframework.stereotype.Service; + +import java.util.Map; +import java.util.UUID; + +/** + * Project: anrui-flowable(流程引擎)
+ * File: SysFormLinkService.java
+ * Class: com.yxt.anrui.flowable.biz.sysformlink.SysFormLinkService
+ * Description: 流程业务关联表 业务逻辑.
+ * Copyright: Copyright (c) 2011
+ * Company: https://gitee.com/liuzp315
+ * Makedate: 2022-03-15 16:55:39
+ * + * @author liupopo + * @version 1.0 + * @since 1.0 + */ +@Service +public class SysFormLinkService extends MybatisBaseService { + + /** + * 保存流程业务关联表 + * @param dto + * @return + */ + public ResultBean save(SysFormLinkDto dto) { + ResultBean resultBean = ResultBean.fireFail(); + SysFormLink sysFormLink = new SysFormLink(); + dto.fillEntity(sysFormLink); + sysFormLink.setSid(UUID.randomUUID().toString()); + int i = baseMapper.save(sysFormLink); + if (i == 0) { + return resultBean.setMsg("保存失败"); + } + return resultBean.success().setMsg("保存成功"); + } + + /** + * 根据业务sid查询节点状态 + * @param business + * @return + */ + public ResultBean selectStateByBusinessSid(String business) { + SysFormStateVo sysFormStateVo = baseMapper.selectStateByBusinessSid(business); + if (sysFormStateVo == null) { + return new ResultBean().fail().setData(new SysFormStateVo()); + } + return new ResultBean().success().setData(sysFormStateVo); + } + + /** + * 更新关联表节点状态属性 + * @param map + * @return + */ + public int updateFiled(Map map) { + return baseMapper.updateFiled(map); + } + + /** + * + * @param businessSid + * @return + */ + public ResultBean selectByBusinessSid(String businessSid) { + int i = baseMapper.selectByBusinessSid(businessSid); + if (i == 0) { + return new ResultBean().fail().setMsg("查询此消息"); + } + return new ResultBean().success(); + } +} \ No newline at end of file diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysprourl/SysProUrlController.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysprourl/SysProUrlController.java new file mode 100644 index 00000000..839eb5b5 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysprourl/SysProUrlController.java @@ -0,0 +1,128 @@ +package com.yxt.anrui.flowable.biz.sysprourl; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.yxt.anrui.flowable.api.sysdeployform.SysDeployForm; +import com.yxt.anrui.flowable.api.sysform.SysForm; +import com.yxt.anrui.flowable.api.sysprourl.*; +import com.yxt.anrui.flowable.biz.sysdeployform.SysDeployFormService; +import com.yxt.common.base.utils.PagerUtil; +import com.yxt.common.core.query.PagerQuery; +import com.yxt.common.core.result.ResultBean; +import com.yxt.common.core.vo.PagerVo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 流程表单Controller + * + * @author XuanXuan + * @date 2021-04-03 + */ +@RestController +@RequestMapping("v1/flowable/proUrl") +public class SysProUrlController implements SysProUrlFeign { + @Autowired + private SysProUrlService sysProUrlService; + @Autowired + private SysDeployFormService sysDeployFormService; + + /** + * 查询流程表单列表 + */ + @Override + public ResultBean> list(PagerQuery pq) { + ResultBean> rb = ResultBean.fireFail(); + IPage page = sysProUrlService.selectSysProUrlList(pq); + PagerVo pv = new PagerVo<>(); + PagerVo pv1 = PagerUtil.pageToVo(page, pv); + return rb.success().setData(pv1); + } + + @Override + public ResultBean getSysProUrl(int formId) { + ResultBean rb = ResultBean.fireFail(); + SysProUrl sysProUrl = sysProUrlService.selectSysProUrlById(formId); + return rb.success().setData(sysProUrl); + } + + @Override + public ResultBean getForm(String proId) { + ResultBean rb = ResultBean.fireFail(); + SysForm sysForm = sysDeployFormService.selectSysDeployFormByDeployId(proId); + return rb.success().setData(sysForm); + } + + /** + * 新增流程表单 + */ + @Override + public ResultBean add(SysProUrlDto dto) { + return sysProUrlService.add(dto); + } + + /** + * 删除流程表单 + */ + @DeleteMapping("/{formIds}") + @Override + public ResultBean remove(@PathVariable Long[] formIds) { + sysProUrlService.deleteSysProUrlByIds(formIds); + ResultBean rb = ResultBean.fireFail(); + return rb.success().setMsg("操作成功"); + } + + + /** + * 挂载流程表单 + */ + @PostMapping("/addDeployForm") + public ResultBean addDeployForm(@RequestBody SysDeployForm sysDeployForm) { + sysDeployFormService.insertSysDeployForm(sysDeployForm); + ResultBean rb = ResultBean.fireFail(); + return rb.success().setMsg("操作成功"); + } + + @Override + public ResultBean selectPcUrlByTaskDefKey(SysProUrlQuery query) { + PcUrlVo urlVo = sysProUrlService.selectPcUrlByTaskDefKey(query); + if (urlVo == null) { + return new ResultBean().fail().setData(new PcUrlVo()); + } + return new ResultBean().success().setData(urlVo); + } + + @Override + public ResultBean selectAppUrlByTaskDefKey(AppSysProUrlQuery query) { + AppUrlVo appUrlVo = sysProUrlService.selectAppUrlByTaskDefKey(query); + if (appUrlVo == null) { + return new ResultBean().fail().setData(new AppUrlVo()); + } + return new ResultBean().success().setData(appUrlVo); + } + + @Override + public ResultBean> selectUrlByKey(String procDefId, String taskDefKey, String type) { + return sysProUrlService.selectUrlByKey(procDefId, taskDefKey, type,null); + } + + /** + * pc根据流程定义id,节点id,终端及类型查询流程与业务表单url + * + * @param procDefId 流程定义id + * @param taskDefKey 节点id + * @param type 类型:1办理,2详情 + * @return + */ + @Override + public ResultBean selectUrlByKey(String procDefId, String taskDefKey, String type,String terminal) { + ResultBean rb= ResultBean.fireFail(); + ResultBean> listResultBean = sysProUrlService.selectUrlByKey(procDefId, taskDefKey, type, terminal); + if(listResultBean.getData().size()==1){ + SysProUrlVo sysProUrlVo = listResultBean.getData().get(0); + return new ResultBean().success().setData(sysProUrlVo); + } + return rb.setMsg("查询不到数据"); + } +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysprourl/SysProUrlMapper.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysprourl/SysProUrlMapper.java new file mode 100644 index 00000000..8574a668 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysprourl/SysProUrlMapper.java @@ -0,0 +1,93 @@ +package com.yxt.anrui.flowable.biz.sysprourl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.yxt.anrui.flowable.api.sysprourl.SysProUrl; +import com.yxt.anrui.flowable.api.sysprourl.SysProUrlQuery; +import com.yxt.anrui.flowable.api.sysprourl.SysProUrlVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + + +/** + * 流程表单Mapper接口 + * + * @author XuanXuan Xuan + * @date 2021-03-30 + */ +@Mapper +public interface SysProUrlMapper extends BaseMapper { + /** + * 查询流程表单 + * + * @param formId 流程表单ID + * @return 流程表单 + */ + public SysProUrl selectSysProUrlById(int formId); + + /** + * 查询流程表单列表 + * + * @return 流程表单集合 + */ +// public IPage selectSysProUrlVo(IPage page, @Param(Constants.WRAPPER) Wrapper qw); + List getSysProUrlVoList(IPage page, @Param(Constants.WRAPPER) Wrapper qw); + + /** + * 新增流程表单 + * + * @param SysProUrl 流程表单 + * @return 结果 + */ + public int insertSysProUrl(SysProUrl SysProUrl); + + /** + * 修改流程表单 + * + * @param SysProUrl 流程表单 + * @return 结果 + */ + public int updateSysProUrl(SysProUrl SysProUrl); + + /** + * 删除流程表单 + * + * @param formId 流程表单ID + * @return 结果 + */ + public int deleteSysProUrlById(Long formId); + + /** + * 批量删除流程表单 + * + * @param formIds 需要删除的数据ID + * @return 结果 + */ + public int deleteSysProUrlByIds(Long[] formIds); + + @Select("SELECT id AS formId, form_name AS formName, form_content AS formContent FROM sys_form ") + List selectListVo(); + + int getSysProUrlVoTotal(IPage page, QueryWrapper qw); + + List selectListByProcDefId(@Param("proc_def_id") String proc_def_id, @Param("taskDefKey") String taskDefKey); + + SysProUrlVo selectUniByTaskDefKey(SysProUrlQuery query); + + /** + * pc根据流程定义id,节点id,终端及类型查询流程与业务表单url + * + * @param procDefId 流程id + * @param taskDefKey 节点iD + * @param type 类型:1办理,2详情 + * @return + */ + List selectUrlByKey(@Param("procDefId") String procDefId, @Param("taskDefKey") String taskDefKey, + @Param("type") String type,@Param("terminal") String terminal); +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysprourl/SysProUrlMapper.xml b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysprourl/SysProUrlMapper.xml new file mode 100644 index 00000000..4e14b1d8 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysprourl/SysProUrlMapper.xml @@ -0,0 +1,135 @@ + + + + + + + insert into sys_pro_url + + sid, + + url, + + + type, + + + terminal, + + + formId, + + + title, + + + proc_def_id, + + + taskDefKey, + + + modulePluginName, + + + taskName + + + + UUID(), + + #{url}, + + + #{type}, + + + #{terminal}, + + + #{formId}, + + + #{title}, + + + #{proc_def_id}, + + + #{taskDefKey}, + + + #{modulePluginName}, + + + #{taskName} + + + + + delete + from sys_pro_url where sid in + + #{sid} + + + + + + + + + + + + \ No newline at end of file diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysprourl/SysProUrlService.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysprourl/SysProUrlService.java new file mode 100644 index 00000000..d87517e9 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/sysprourl/SysProUrlService.java @@ -0,0 +1,206 @@ +package com.yxt.anrui.flowable.biz.sysprourl; + +import cn.hutool.core.bean.BeanUtil; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yxt.anrui.flowable.api.sysprourl.*; +import com.yxt.common.base.service.MybatisBaseService; +import com.yxt.common.core.query.PagerQuery; +import com.yxt.common.core.result.ResultBean; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 流程表单Service业务层处理 + * + * @author XuanXuan Xuan + * @date 2021-04-03 + */ +@Service +//@Transactional +public class SysProUrlService extends MybatisBaseService { + + /* @Resource + private AppSubsetVersionFeign appSubsetVersionFeign;*/ + + /** + * 查询流程表单 + * + * @param formId 流程表单ID + * @return 流程表单 + */ + public SysProUrl selectSysProUrlById(int formId) { + return baseMapper.selectSysProUrlById(formId); + } + + public IPage selectSysProUrlList(PagerQuery pagerQuery) { + List SysProUrls = baseMapper.selectListVo(); + IPage page = new Page<>();// PagerUtil.queryToPage(pagerQuery); + QueryWrapper qw = createQueryWrapper(pagerQuery.getParams()); + List SysProUrlVoList = baseMapper.getSysProUrlVoList(page, qw); + int total = baseMapper.getSysProUrlVoTotal(page, qw); + page.setTotal(total); + page.setRecords(SysProUrlVoList); + return page; + } + + /** + * 修改流程表单 + * + * @param SysProUrl 流程表单 + * @return 结果 + */ + public int updateSysProUrl(SysProUrl SysProUrl) { + return 0;//SysProUrlMapper.updateSysProUrl(SysProUrl); + } + + /** + * 批量删除流程表单 + * + * @param formIds 需要删除的流程表单ID + * @return 结果 + */ + public int deleteSysProUrlByIds(Long[] formIds) { + return baseMapper.deleteSysProUrlByIds(formIds); + } + + /** + * 删除流程表单信息 + * + * @param formId 流程表单ID + * @return 结果 + */ + public int deleteSysProUrlById(Long formId) { + return 0;// SysProUrlMapper.deleteSysProUrlById(formId); + } + + private QueryWrapper createQueryWrapper(SysProUrlQuery query) { + // todo: 这里根据具体业务调整查询条件 + // 多字段Like示例:qw.and(wrapper -> wrapper.like("name", query.getName()).or().like("remark", query.getName())); + QueryWrapper qw = new QueryWrapper<>(); + + if (StringUtils.isNotBlank(query.getType())) { + qw.like("type", query.getType()); + } + + if (StringUtils.isNotBlank(query.getTerminal())) { + qw.eq("teminal", query.getTerminal()); + } + return qw; + } + + /** + * 根据流程id及终端查询url + * + * @param proc_def_id + * @return + */ + public List selectListByProcDefId(String proc_def_id, String taskDefKey) { + return baseMapper.selectListByProcDefId(proc_def_id, taskDefKey); + } + + /** + * 根据流程定义id,节点id,终端及类型查询流程与业务表单url + * + * @param query + * @return + */ + public PcUrlVo selectPcUrlByTaskDefKey(SysProUrlQuery query) { + PcUrlVo urlVo = new PcUrlVo(); + query.setTerminal("1"); + SysProUrlVo sysProUrlVo = baseMapper.selectUniByTaskDefKey(query); + BeanUtil.copyProperties(sysProUrlVo, urlVo); + return urlVo; + } + + /** + * app根据流程定义id,节点id,终端及类型查询流程与业务表单url + * + * @param query + * @return + */ + public AppUrlVo selectAppUrlByTaskDefKey(AppSysProUrlQuery query) { + AppUrlVo appUrlVo = new AppUrlVo(); + query.setTerminal("2"); + SysProUrlVo sysProUrlVo = baseMapper.selectUniByTaskDefKey(query); + appUrlVo.setModuleAction(sysProUrlVo.getUrl()); + appUrlVo.setModulePluginName(sysProUrlVo.getModulePluginName()); + /* ResultBean resultBean = appSubsetVersionFeign.getLastBymodulePluginName(sysProUrlVo.getModulePluginName()); + if (resultBean.getSuccess() && resultBean.getData() != null) { + AppSubsetVersionVo subsetVersionVo = resultBean.getData(); + appUrlVo.setMsgSid(""); + appUrlVo.setType("2"); + appUrlVo.setPath(subsetVersionVo.getUpdateUrl()); + appUrlVo.setModuleVersion(subsetVersionVo.getVersionCode()); + appUrlVo.setModuleSid(""); + JSONObject json = new JSONObject(); + json.put("businessSid", query.getBusinessSid()); + json.put("taskId", query.getTaskId()); + json.put("deployId", query.getDeployId()); + json.put("procInsId", query.getProcInsId()); + appUrlVo.setJson(json.toJSONString()); + }*/ + return appUrlVo; + } + + /** + * pc根据流程定义id,节点id,终端及类型查询流程与业务表单url + * + * @param procDefId 流程id + * @param taskDefKey 节点iD + * @param type 类型:1办理,2详情 + * @param terminal 终端的类型 + * @return + */ + public ResultBean> selectUrlByKey(String procDefId, String taskDefKey, + String type, + String terminal) { + ResultBean> rb = ResultBean.fireFail(); + //验证参数 + if (StringUtils.isBlank(procDefId)) { + return rb.setMsg("流程定义id不能为空"); + } + if (StringUtils.isBlank(taskDefKey)) { + return rb.setMsg("节点id不能为空"); + } + if (StringUtils.isBlank(type)) { + return rb.setMsg("请指定要操作的类型"); + } + List url = baseMapper.selectUrlByKey(procDefId, taskDefKey, type,terminal); + if(url!=null&&url.size()>0){ + return rb.success().setData(url); + } + return rb.setMsg("查询不到数据"); + } + + public ResultBean add(SysProUrlDto dto) { + ResultBean rb = ResultBean.fireFail(); + String sid = dto.getSid(); + if (StringUtils.isBlank(sid)) {//新增 + SysProUrl sysProUrl = new SysProUrl(); + BeanUtil.copyProperties(dto, sysProUrl, "sid"); + int i = baseMapper.insertSysProUrl(sysProUrl); + if (i == 0) { + return rb.setMsg("新增失败"); + } + sid = sysProUrl.getSid(); + + } else {//修改 + SysProUrl sysProUrl = fetchBySid(sid); + if (sysProUrl == null) { + return rb.setMsg("该url不存在"); + } + BeanUtil.copyProperties(dto, sysProUrl); + int i = baseMapper.updateById(sysProUrl); + if (i == 0) { + return rb.setMsg("修改失败"); + } + } + return rb.success().setData(sid); + } +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/systaskform/SysTaskFormMapper.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/systaskform/SysTaskFormMapper.java new file mode 100644 index 00000000..a52a4224 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/systaskform/SysTaskFormMapper.java @@ -0,0 +1,65 @@ +package com.yxt.anrui.flowable.biz.systaskform; + + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yxt.anrui.flowable.api.sysform.SysTaskForm; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 流程任务关联单Mapper接口 + * + * @author XuanXuan Xuan + * @date 2021-04-03 + */ +@Mapper +public interface SysTaskFormMapper extends BaseMapper { + /** + * 查询流程任务关联单 + * + * @param id 流程任务关联单ID + * @return 流程任务关联单 + */ + public SysTaskForm selectSysTaskFormById(Long id); + + /** + * 查询流程任务关联单列表 + * + * @param sysTaskForm 流程任务关联单 + * @return 流程任务关联单集合 + */ + public List selectSysTaskFormList(SysTaskForm sysTaskForm); + + /** + * 新增流程任务关联单 + * + * @param sysTaskForm 流程任务关联单 + * @return 结果 + */ + public int insertSysTaskForm(SysTaskForm sysTaskForm); + + /** + * 修改流程任务关联单 + * + * @param sysTaskForm 流程任务关联单 + * @return 结果 + */ + public int updateSysTaskForm(SysTaskForm sysTaskForm); + + /** + * 删除流程任务关联单 + * + * @param id 流程任务关联单ID + * @return 结果 + */ + public int deleteSysTaskFormById(Long id); + + /** + * 批量删除流程任务关联单 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteSysTaskFormByIds(Long[] ids); +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/systaskform/SysTaskFormMapper.xml b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/systaskform/SysTaskFormMapper.xml new file mode 100644 index 00000000..0302700c --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/systaskform/SysTaskFormMapper.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + select id, form_id, task_id from sys_task_form + + + + + + + + insert into sys_task_form + + form_id, + task_id, + + + #{formId}, + #{taskId}, + + + + + update sys_task_form + + form_id = #{formId}, + task_id = #{taskId}, + + where id = #{id} + + + + delete from sys_task_form where id = #{id} + + + + delete from sys_task_form where id in + + #{id} + + + \ No newline at end of file diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/common/EnumResultBean.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/common/EnumResultBean.java new file mode 100644 index 00000000..c9e75f63 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/common/EnumResultBean.java @@ -0,0 +1,62 @@ +/********************************************************* + ********************************************************* + ******************** ******************* + ************* ************ + ******* _oo0oo_ ******* + *** o8888888o *** + * 88" . "88 * + * (| -_- |) * + * 0\ = /0 * + * ___/`---'\___ * + * .' \\| |// '. * + * / \\||| : |||// \ * + * / _||||| -:- |||||- \ * + * | | \\\ - /// | | * + * | \_| ''\---/'' |_/ | * + * \ .-\__ '-' ___/-. / * + * ___'. .' /--.--\ `. .'___ * + * ."" '< `.___\_<|>_/___.' >' "". * + * | | : `- \`.;`\ _ /`;.`/ - ` : | | * + * \ \ `_. \_ __\ /__ _/ .-` / / * + * =====`-.____`.___ \_____/___.-`___.-'===== * + * `=---=' * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * + *********__佛祖保佑__永无BUG__验收通过__钞票多多__********* + *********************************************************/ +package com.yxt.anrui.flowable.common; + +import com.yxt.common.core.constant.HttpStatus; +import com.yxt.common.core.result.ResultBean; + +/** + * Project: anrui-parent
+ * File: EnumResultBean.java
+ * Class: com.yxt.anrui.flowable.common.EnumResultBean
+ * Description: <描述类的功能>.
+ * Copyright: Copyright (c) 2011
+ * Company: https://gitee.com/liuzp315
+ * Makedate: 2021/9/11 下午10:18
+ * + * @author popo + * @version 1.0 + * @since 1.0 + */ +public class EnumResultBean extends ResultBean { + + + public static EnumResultBean fireSuccess() { + EnumResultBean rb = new EnumResultBean(); + rb.setSuccess(true); + rb.setCode(String.valueOf(HttpStatus.SUCCESS)); + rb.setMsg("操作成功!"); + return rb; + } + +// public static EnumResultBean fireFail() { +// EnumResultBean rb = new EnumResultBean(); +// rb.setSuccess(false); +// rb.setCode(String.valueOf(HttpStatus.ERROR)); +// rb.setMsg("操作失败!"); +// return rb; +// } +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/common/ProcessConstants.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/common/ProcessConstants.java new file mode 100644 index 00000000..a541c73b --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/common/ProcessConstants.java @@ -0,0 +1,73 @@ +package com.yxt.anrui.flowable.common; + +/** + * @author dimengzhe + * @date 2021/6/16 9:03 + * @description 流程常量信息 + */ + +public class ProcessConstants { + + /** + * 动态数据 + */ + public static final String DATA_TYPE = "dynamic"; + + /** + * 单个审批人 + */ + public static final String USER_TYPE_ASSIGNEE = "assignee"; + + + /** + * 候选人 + */ + public static final String USER_TYPE_USERS = "candidateUsers"; + + + /** + * 审批组 + */ + public static final String USER_TYPE_ROUPS = "candidateGroups"; + + /** + * 单个审批人 + */ + public static final String PROCESS_APPROVAL = "approval"; + + /** + * 会签人员 + */ + public static final String PROCESS_MULTI_INSTANCE_USER = "userList"; + + /** + * nameapace + */ + public static final String NAMASPASE = "http://flowable.org/bpmn"; + + /** + * 会签节点 + */ + public static final String PROCESS_MULTI_INSTANCE = "multiInstance"; + + /** + * 自定义属性 dataType + */ + public static final String PROCESS_CUSTOM_DATA_TYPE = "dataType"; + + /** + * 自定义属性 userType + */ + public static final String PROCESS_CUSTOM_USER_TYPE = "userType"; + + /** + * 初始化人员 + */ + public static final String PROCESS_INITIATOR = "INITIATOR"; + + + /** + * 流程跳过 + */ + public static final String FLOWABLE_SKIP_EXPRESSION_ENABLED = "_FLOWABLE_SKIP_EXPRESSION_ENABLED"; +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/DefaultProcessDiagramCanvasExt.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/DefaultProcessDiagramCanvasExt.java new file mode 100644 index 00000000..79552fdb --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/DefaultProcessDiagramCanvasExt.java @@ -0,0 +1,342 @@ +package com.yxt.anrui.flowable.config; + +import org.flowable.bpmn.model.AssociationDirection; +import org.flowable.bpmn.model.GraphicInfo; +import org.flowable.image.impl.DefaultProcessDiagramCanvas; +import org.flowable.image.util.ReflectUtil; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.font.FontRenderContext; +import java.awt.font.LineBreakMeasurer; +import java.awt.font.TextAttribute; +import java.awt.font.TextLayout; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.text.AttributedCharacterIterator; +import java.text.AttributedString; + +/** + * @author dimengzhe + * @date 2021/6/18 10:02 + * @description 自定义已经走过的流程高亮连接线和高亮图标, 重写DefaultProcessDiagramCanvas方法 + */ + +public class DefaultProcessDiagramCanvasExt extends DefaultProcessDiagramCanvas { + + //定义走过流程连线颜色为绿色 + protected static Color HIGHLIGHT_SequenceFlow_COLOR = Color.GREEN; + //设置未走过流程的连接线颜色 + protected static Color CONNECTION_COLOR = Color.BLACK; + //设置flows连接线字体颜色red + protected static Color LABEL_COLOR = new Color(0, 0, 0); + //高亮显示task框颜色 + protected static Color HIGHLIGHT_COLOR = Color.GREEN; + protected static Color HIGHLIGHT_COLOR1 = Color.RED; + + protected static Color EVENT_COLOR = new Color(255, 255, 255); + + public DefaultProcessDiagramCanvasExt(int width, int height, int minX, int minY, String imageType, String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader) { + super(width, height, minX, minY, imageType, activityFontName, labelFontName, annotationFontName, customClassLoader); + this.initialize(imageType); + } + + /** + * 重写绘制连线的方式,设置绘制颜色 + */ + @Override + public void drawConnection(int[] xPoints, int[] yPoints, boolean conditional, boolean isDefault, String connectionType, AssociationDirection associationDirection, boolean highLighted, double scaleFactor) { + Paint originalPaint = this.g.getPaint(); + Stroke originalStroke = this.g.getStroke(); + this.g.setPaint(CONNECTION_COLOR); + if (connectionType.equals("association")) { + this.g.setStroke(ASSOCIATION_STROKE); + } else if (highLighted) { + this.g.setPaint(HIGHLIGHT_SequenceFlow_COLOR); + this.g.setStroke(HIGHLIGHT_FLOW_STROKE); + } + for (int i = 1; i < xPoints.length; ++i) { + Integer sourceX = xPoints[i - 1]; + Integer sourceY = yPoints[i - 1]; + Integer targetX = xPoints[i]; + Integer targetY = yPoints[i]; + java.awt.geom.Line2D.Double line = new java.awt.geom.Line2D.Double((double) sourceX, (double) sourceY, (double) targetX, (double) targetY); + this.g.draw(line); + } + java.awt.geom.Line2D.Double line; + if (isDefault) { + line = new java.awt.geom.Line2D.Double((double) xPoints[0], (double) yPoints[0], (double) xPoints[1], (double) yPoints[1]); + this.drawDefaultSequenceFlowIndicator(line, scaleFactor); + } + + if (conditional) { + line = new java.awt.geom.Line2D.Double((double) xPoints[0], (double) yPoints[0], (double) xPoints[1], (double) yPoints[1]); + this.drawConditionalSequenceFlowIndicator(line, scaleFactor); + } + + if (associationDirection.equals(AssociationDirection.ONE) || associationDirection.equals(AssociationDirection.BOTH)) { + line = new java.awt.geom.Line2D.Double((double) xPoints[xPoints.length - 2], (double) yPoints[xPoints.length - 2], (double) xPoints[xPoints.length - 1], (double) yPoints[xPoints.length - 1]); + this.drawArrowHead(line, scaleFactor); + } + + if (associationDirection.equals(AssociationDirection.BOTH)) { + line = new java.awt.geom.Line2D.Double((double) xPoints[1], (double) yPoints[1], (double) xPoints[0], (double) yPoints[0]); + this.drawArrowHead(line, scaleFactor); + } + + this.g.setPaint(originalPaint); + this.g.setStroke(originalStroke); + } + + //设置字体大小图标颜色 + @Override + public void initialize(String imageType) { + if ("png".equalsIgnoreCase(imageType)) { + this.processDiagram = new BufferedImage(this.canvasWidth, this.canvasHeight, 2); + } else { + this.processDiagram = new BufferedImage(this.canvasWidth, this.canvasHeight, 1); + } + + this.g = this.processDiagram.createGraphics(); + if (!"png".equalsIgnoreCase(imageType)) { + this.g.setBackground(new Color(255, 255, 255, 0)); + this.g.clearRect(0, 0, this.canvasWidth, this.canvasHeight); + } + + this.g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + //修改图标颜色,修改图标字体大小 + this.g.setPaint(Color.black); + Font font = new Font(this.activityFontName, 10, 14); + this.g.setFont(font); + this.fontMetrics = this.g.getFontMetrics(); + //修改连接线字体大小 + LABEL_FONT = new Font(this.labelFontName, 10, 15); + ANNOTATION_FONT = new Font(this.annotationFontName, 0, 11); + try { + USERTASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/userTask.png", this.customClassLoader)); + SCRIPTTASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/scriptTask.png", this.customClassLoader)); + SERVICETASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/serviceTask.png", this.customClassLoader)); + RECEIVETASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/receiveTask.png", this.customClassLoader)); + SENDTASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/sendTask.png", this.customClassLoader)); + MANUALTASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/manualTask.png", this.customClassLoader)); + BUSINESS_RULE_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/businessRuleTask.png", this.customClassLoader)); + SHELL_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/shellTask.png", this.customClassLoader)); + DMN_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/dmnTask.png", this.customClassLoader)); + CAMEL_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/camelTask.png", this.customClassLoader)); + MULE_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/muleTask.png", this.customClassLoader)); + HTTP_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/httpTask.png", this.customClassLoader)); + TIMER_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/timer.png", this.customClassLoader)); + COMPENSATE_THROW_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/compensate-throw.png", this.customClassLoader)); + COMPENSATE_CATCH_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/compensate.png", this.customClassLoader)); + ERROR_THROW_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/error-throw.png", this.customClassLoader)); + ERROR_CATCH_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/error.png", this.customClassLoader)); + MESSAGE_THROW_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/message-throw.png", this.customClassLoader)); + MESSAGE_CATCH_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/message.png", this.customClassLoader)); + SIGNAL_THROW_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/signal-throw.png", this.customClassLoader)); + SIGNAL_CATCH_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/signal.png", this.customClassLoader)); + } catch (IOException var4) { + LOGGER.warn("Could not load image for process diagram creation: {}", var4.getMessage()); + } + + } + + /** + * 设置连接线字体 + * + * @param text + * @param graphicInfo + * @param centered + */ + @Override + public void drawLabel(String text, GraphicInfo graphicInfo, boolean centered) { + float interline = 1.0f; + + // text + if (text != null && text.length() > 0) { + Paint originalPaint = g.getPaint(); + Font originalFont = g.getFont(); + + g.setPaint(LABEL_COLOR); + g.setFont(LABEL_FONT); + + int wrapWidth = 100; + int textY = (int) graphicInfo.getY(); + + AttributedString as = new AttributedString(text); + as.addAttribute(TextAttribute.FOREGROUND, g.getPaint()); + as.addAttribute(TextAttribute.FONT, g.getFont()); + AttributedCharacterIterator aci = as.getIterator(); + FontRenderContext frc = new FontRenderContext(null, true, false); + LineBreakMeasurer lbm = new LineBreakMeasurer(aci, frc); + + while (lbm.getPosition() < text.length()) { + TextLayout tl = lbm.nextLayout(wrapWidth); + textY += tl.getAscent(); + + Rectangle2D bb = tl.getBounds(); + double tX = graphicInfo.getX(); + + if (centered) { + tX += (int) (graphicInfo.getWidth() / 2 - bb.getWidth() / 2); + } + tl.draw(g, (float) tX, textY); + textY += tl.getDescent() + tl.getLeading() + (interline - 1.0f) * tl.getAscent(); + } + + // restore originals + g.setFont(originalFont); + g.setPaint(originalPaint); + } + } + + /** + * 高亮显示task框完成的 + * + * @param x + * @param y + * @param width + * @param height + */ + @Override + public void drawHighLight(int x, int y, int width, int height) { + Paint originalPaint = g.getPaint(); + Stroke originalStroke = g.getStroke(); + + g.setPaint(HIGHLIGHT_COLOR); + g.setStroke(THICK_TASK_BORDER_STROKE); + + RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20); + g.draw(rect); + + g.setPaint(originalPaint); + g.setStroke(originalStroke); + } + + /** + * 自定义task框当前的位置 + * + * @param x + * @param y + * @param width + * @param height + */ + public void drawHighLight1(int x, int y, int width, int height) { + Paint originalPaint = g.getPaint(); + Stroke originalStroke = g.getStroke(); + + g.setPaint(HIGHLIGHT_COLOR1); + g.setStroke(THICK_TASK_BORDER_STROKE); + + RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20); + g.draw(rect); + + g.setPaint(originalPaint); + g.setStroke(originalStroke); + } + + /** + * task框自定义文字 + * + * @param name + * @param graphicInfo + * @param thickBorder + * @param scaleFactor + */ + @Override + protected void drawTask(String name, GraphicInfo graphicInfo, boolean thickBorder, double scaleFactor) { + Paint originalPaint = g.getPaint(); + int x = (int) graphicInfo.getX(); + int y = (int) graphicInfo.getY(); + int width = (int) graphicInfo.getWidth(); + int height = (int) graphicInfo.getHeight(); + + // Create a new gradient paint for every task box, gradient depends on x and y and is not relative + g.setPaint(TASK_BOX_COLOR); + + int arcR = 6; + if (thickBorder) { + arcR = 3; + } + + // shape + RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, arcR, arcR); + g.fill(rect); + g.setPaint(TASK_BORDER_COLOR); + + if (thickBorder) { + Stroke originalStroke = g.getStroke(); + g.setStroke(THICK_TASK_BORDER_STROKE); + g.draw(rect); + g.setStroke(originalStroke); + } else { + g.draw(rect); + } + + g.setPaint(originalPaint); + // text + if (scaleFactor == 1.0 && name != null && name.length() > 0) { + int boxWidth = width - (2 * TEXT_PADDING); + int boxHeight = height - 16 - ICON_PADDING - ICON_PADDING - MARKER_WIDTH - 2 - 2; + int boxX = x + width / 2 - boxWidth / 2; + int boxY = y + height / 2 - boxHeight / 2 + ICON_PADDING + ICON_PADDING - 2 - 2; + + drawMultilineCentredText(name, boxX, boxY, boxWidth, boxHeight); + } + } + + + /** + * 重写开始事件 + * + * @param graphicInfo + * @param image + * @param scaleFactor + */ + @Override + public void drawStartEvent(GraphicInfo graphicInfo, BufferedImage image, double scaleFactor) { + Paint originalPaint = g.getPaint(); + g.setPaint(EVENT_COLOR); + Ellipse2D circle = new Ellipse2D.Double(graphicInfo.getX(), graphicInfo.getY(), + graphicInfo.getWidth(), graphicInfo.getHeight()); + g.fill(circle); + g.setPaint(EVENT_BORDER_COLOR); + g.draw(circle); + g.setPaint(originalPaint); + if (image != null) { + // calculate coordinates to center image + int imageX = (int) Math.round(graphicInfo.getX() + (graphicInfo.getWidth() / 2) - (image.getWidth() / (2 * scaleFactor))); + int imageY = (int) Math.round(graphicInfo.getY() + (graphicInfo.getHeight() / 2) - (image.getHeight() / (2 * scaleFactor))); + g.drawImage(image, imageX, imageY, + (int) (image.getWidth() / scaleFactor), (int) (image.getHeight() / scaleFactor), null); + } + + } + + /** + * 重写结束事件 + * + * @param graphicInfo + * @param scaleFactor + */ + @Override + public void drawNoneEndEvent(GraphicInfo graphicInfo, double scaleFactor) { + Paint originalPaint = g.getPaint(); + Stroke originalStroke = g.getStroke(); + g.setPaint(EVENT_COLOR); + Ellipse2D circle = new Ellipse2D.Double(graphicInfo.getX(), graphicInfo.getY(), + graphicInfo.getWidth(), graphicInfo.getHeight()); + g.fill(circle); + g.setPaint(EVENT_BORDER_COLOR); + if (scaleFactor == 1.0) { + g.setStroke(END_EVENT_STROKE); + } else { + g.setStroke(new BasicStroke(2.0f)); + } + g.draw(circle); + g.setStroke(originalStroke); + g.setPaint(originalPaint); + } +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/DefaultProcessDiagramGeneratorExt.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/DefaultProcessDiagramGeneratorExt.java new file mode 100644 index 00000000..da79a3ea --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/DefaultProcessDiagramGeneratorExt.java @@ -0,0 +1,397 @@ +package com.yxt.anrui.flowable.config; + +import org.flowable.bpmn.model.*; +import org.flowable.bpmn.model.Process; +import org.flowable.image.impl.DefaultProcessDiagramCanvas; +import org.flowable.image.impl.DefaultProcessDiagramGenerator; + +import java.util.Iterator; +import java.util.List; + +/** + * @author dimengzhe + * @date 2021/6/18 10:09 + * @description + */ + +public class DefaultProcessDiagramGeneratorExt extends DefaultProcessDiagramGenerator { + + @Override + protected DefaultProcessDiagramCanvas generateProcessDiagram(BpmnModel bpmnModel, String imageType, List highLightedActivities, List highLightedFlows, String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader, double scaleFactor, boolean drawSequenceFlowNameWithNoLabelDI) { + this.prepareBpmnModel(bpmnModel); + DefaultProcessDiagramCanvas processDiagramCanvas = initProcessDiagramCanvas(bpmnModel, imageType, activityFontName, labelFontName, annotationFontName, customClassLoader); + Iterator var13 = bpmnModel.getPools().iterator(); + + while (var13.hasNext()) { + Pool process = (Pool) var13.next(); + GraphicInfo subProcesses = bpmnModel.getGraphicInfo(process.getId()); + processDiagramCanvas.drawPoolOrLane(process.getName(), subProcesses, scaleFactor); + } + + var13 = bpmnModel.getProcesses().iterator(); + + Process process1; + Iterator subProcesses1; + while (var13.hasNext()) { + process1 = (Process) var13.next(); + subProcesses1 = process1.getLanes().iterator(); + + while (subProcesses1.hasNext()) { + Lane artifact = (Lane) subProcesses1.next(); + GraphicInfo subProcess = bpmnModel.getGraphicInfo(artifact.getId()); + processDiagramCanvas.drawPoolOrLane(artifact.getName(), subProcess, scaleFactor); + } + } + + var13 = bpmnModel.getProcesses().iterator(); + + while (var13.hasNext()) { + process1 = (Process) var13.next(); + subProcesses1 = process1.findFlowElementsOfType(FlowNode.class).iterator(); + + while (subProcesses1.hasNext()) { + FlowNode artifact1 = (FlowNode) subProcesses1.next(); + if (!this.isPartOfCollapsedSubProcess(artifact1, bpmnModel)) { + this.drawActivity(processDiagramCanvas, bpmnModel, artifact1, highLightedActivities, highLightedFlows, scaleFactor, Boolean.valueOf(drawSequenceFlowNameWithNoLabelDI)); + } + } + } + + var13 = bpmnModel.getProcesses().iterator(); + + label75: + while (true) { + List subProcesses2; + do { + if (!var13.hasNext()) { + return processDiagramCanvas; + } + + process1 = (Process) var13.next(); + subProcesses1 = process1.getArtifacts().iterator(); + + while (subProcesses1.hasNext()) { + Artifact artifact2 = (Artifact) subProcesses1.next(); + this.drawArtifact(processDiagramCanvas, bpmnModel, artifact2); + } + + subProcesses2 = process1.findFlowElementsOfType(SubProcess.class, true); + } while (subProcesses2 == null); + + Iterator artifact3 = subProcesses2.iterator(); + + while (true) { + GraphicInfo graphicInfo; + SubProcess subProcess1; + do { + do { + if (!artifact3.hasNext()) { + continue label75; + } + + subProcess1 = (SubProcess) artifact3.next(); + graphicInfo = bpmnModel.getGraphicInfo(subProcess1.getId()); + } while (graphicInfo != null && graphicInfo.getExpanded() != null && !graphicInfo.getExpanded().booleanValue()); + } while (this.isPartOfCollapsedSubProcess(subProcess1, bpmnModel)); + + Iterator var19 = subProcess1.getArtifacts().iterator(); + + while (var19.hasNext()) { + Artifact subProcessArtifact = (Artifact) var19.next(); + this.drawArtifact(processDiagramCanvas, bpmnModel, subProcessArtifact); + } + } + } + } + + protected static DefaultProcessDiagramCanvas initProcessDiagramCanvas(BpmnModel bpmnModel, String imageType, String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader) { + double minX = 1.7976931348623157E308D; + double maxX = 0.0D; + double minY = 1.7976931348623157E308D; + double maxY = 0.0D; + + GraphicInfo nrOfLanes; + for (Iterator flowNodes = bpmnModel.getPools().iterator(); flowNodes.hasNext(); maxY = nrOfLanes.getY() + nrOfLanes.getHeight()) { + Pool artifacts = (Pool) flowNodes.next(); + nrOfLanes = bpmnModel.getGraphicInfo(artifacts.getId()); + minX = nrOfLanes.getX(); + maxX = nrOfLanes.getX() + nrOfLanes.getWidth(); + minY = nrOfLanes.getY(); + } + + List var23 = gatherAllFlowNodes(bpmnModel); + Iterator var24 = var23.iterator(); + + label155: + while (var24.hasNext()) { + FlowNode var26 = (FlowNode) var24.next(); + GraphicInfo artifact = bpmnModel.getGraphicInfo(var26.getId()); + if (artifact.getX() + artifact.getWidth() > maxX) { + maxX = artifact.getX() + artifact.getWidth(); + } + + if (artifact.getX() < minX) { + minX = artifact.getX(); + } + + if (artifact.getY() + artifact.getHeight() > maxY) { + maxY = artifact.getY() + artifact.getHeight(); + } + + if (artifact.getY() < minY) { + minY = artifact.getY(); + } + + Iterator process = var26.getOutgoingFlows().iterator(); + + while (true) { + List l; + do { + if (!process.hasNext()) { + continue label155; + } + + SequenceFlow graphicInfoList = (SequenceFlow) process.next(); + l = bpmnModel.getFlowLocationGraphicInfo(graphicInfoList.getId()); + } while (l == null); + + Iterator graphicInfo = l.iterator(); + + while (graphicInfo.hasNext()) { + GraphicInfo graphicInfo1 = (GraphicInfo) graphicInfo.next(); + if (graphicInfo1.getX() > maxX) { + maxX = graphicInfo1.getX(); + } + + if (graphicInfo1.getX() < minX) { + minX = graphicInfo1.getX(); + } + + if (graphicInfo1.getY() > maxY) { + maxY = graphicInfo1.getY(); + } + + if (graphicInfo1.getY() < minY) { + minY = graphicInfo1.getY(); + } + } + } + } + + List var25 = gatherAllArtifacts(bpmnModel); + Iterator var27 = var25.iterator(); + + GraphicInfo var37; + while (var27.hasNext()) { + Artifact var29 = (Artifact) var27.next(); + GraphicInfo var31 = bpmnModel.getGraphicInfo(var29.getId()); + if (var31 != null) { + if (var31.getX() + var31.getWidth() > maxX) { + maxX = var31.getX() + var31.getWidth(); + } + + if (var31.getX() < minX) { + minX = var31.getX(); + } + + if (var31.getY() + var31.getHeight() > maxY) { + maxY = var31.getY() + var31.getHeight(); + } + + if (var31.getY() < minY) { + minY = var31.getY(); + } + } + + List var33 = bpmnModel.getFlowLocationGraphicInfo(var29.getId()); + if (var33 != null) { + Iterator var35 = var33.iterator(); + + while (var35.hasNext()) { + var37 = (GraphicInfo) var35.next(); + if (var37.getX() > maxX) { + maxX = var37.getX(); + } + + if (var37.getX() < minX) { + minX = var37.getX(); + } + + if (var37.getY() > maxY) { + maxY = var37.getY(); + } + + if (var37.getY() < minY) { + minY = var37.getY(); + } + } + } + } + + int var28 = 0; + Iterator var30 = bpmnModel.getProcesses().iterator(); + + while (var30.hasNext()) { + Process var32 = (Process) var30.next(); + Iterator var34 = var32.getLanes().iterator(); + + while (var34.hasNext()) { + Lane var36 = (Lane) var34.next(); + ++var28; + var37 = bpmnModel.getGraphicInfo(var36.getId()); + if (var37.getX() + var37.getWidth() > maxX) { + maxX = var37.getX() + var37.getWidth(); + } + + if (var37.getX() < minX) { + minX = var37.getX(); + } + + if (var37.getY() + var37.getHeight() > maxY) { + maxY = var37.getY() + var37.getHeight(); + } + + if (var37.getY() < minY) { + minY = var37.getY(); + } + } + } + + if (var23.isEmpty() && bpmnModel.getPools().isEmpty() && var28 == 0) { + minX = 0.0D; + minY = 0.0D; + } + + return new DefaultProcessDiagramCanvasExt((int) maxX + 10, (int) maxY + 10, (int) minX, (int) minY, imageType, activityFontName, labelFontName, annotationFontName, customClassLoader); + } + + + private static void drawHighLight(DefaultProcessDiagramCanvas processDiagramCanvas, GraphicInfo graphicInfo) { + processDiagramCanvas.drawHighLight((int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo.getWidth(), (int) graphicInfo.getHeight()); + + } + + private static void drawHighLigh1(DefaultProcessDiagramCanvasExt processDiagramCanvas, GraphicInfo graphicInfo) { + processDiagramCanvas.drawHighLight1((int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo.getWidth(), (int) graphicInfo.getHeight()); + + } + + @Override + protected void drawActivity(DefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, + FlowNode flowNode, List highLightedActivities, List highLightedFlows, double scaleFactor, Boolean drawSequenceFlowNameWithNoLabelDI) { + + DefaultProcessDiagramGenerator.ActivityDrawInstruction drawInstruction = activityDrawInstructions.get(flowNode.getClass()); + if (drawInstruction != null) { + + drawInstruction.draw(processDiagramCanvas, bpmnModel, flowNode); + + // Gather info on the multi instance marker + boolean multiInstanceSequential = false; + boolean multiInstanceParallel = false; + boolean collapsed = false; + if (flowNode instanceof Activity) { + Activity activity = (Activity) flowNode; + MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = activity.getLoopCharacteristics(); + if (multiInstanceLoopCharacteristics != null) { + multiInstanceSequential = multiInstanceLoopCharacteristics.isSequential(); + multiInstanceParallel = !multiInstanceSequential; + } + } + + // Gather info on the collapsed marker + GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); + if (flowNode instanceof SubProcess) { + collapsed = graphicInfo.getExpanded() != null && !graphicInfo.getExpanded(); + } else if (flowNode instanceof CallActivity) { + collapsed = true; + } + + if (scaleFactor == 1.0) { + // Actually draw the markers + processDiagramCanvas.drawActivityMarkers((int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo.getWidth(), (int) graphicInfo.getHeight(), + multiInstanceSequential, multiInstanceParallel, collapsed); + } + + // Draw highlighted activities + if (highLightedActivities.contains(flowNode.getId())) { + + if (highLightedActivities.get(highLightedActivities.size() - 1).equals(flowNode.getId()) + && !flowNode.getId().equals("endenv")) { + //更改源码没有走的红色表示 + drawHighLigh1((DefaultProcessDiagramCanvasExt) processDiagramCanvas, bpmnModel.getGraphicInfo(flowNode.getId())); + } else { + drawHighLight(processDiagramCanvas, bpmnModel.getGraphicInfo(flowNode.getId())); + } + + + } + + } + + // Outgoing transitions of activity + for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) { + boolean highLighted = (highLightedFlows.contains(sequenceFlow.getId())); + String defaultFlow = null; + if (flowNode instanceof Activity) { + defaultFlow = ((Activity) flowNode).getDefaultFlow(); + } else if (flowNode instanceof Gateway) { + defaultFlow = ((Gateway) flowNode).getDefaultFlow(); + } + + boolean isDefault = false; + if (defaultFlow != null && defaultFlow.equalsIgnoreCase(sequenceFlow.getId())) { + isDefault = true; + } + boolean drawConditionalIndicator = sequenceFlow.getConditionExpression() != null && !(flowNode instanceof Gateway); + + String sourceRef = sequenceFlow.getSourceRef(); + String targetRef = sequenceFlow.getTargetRef(); + FlowElement sourceElement = bpmnModel.getFlowElement(sourceRef); + FlowElement targetElement = bpmnModel.getFlowElement(targetRef); + List graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(sequenceFlow.getId()); + if (graphicInfoList != null && graphicInfoList.size() > 0) { + graphicInfoList = connectionPerfectionizer(processDiagramCanvas, bpmnModel, sourceElement, targetElement, graphicInfoList); + int xPoints[] = new int[graphicInfoList.size()]; + int yPoints[] = new int[graphicInfoList.size()]; + + for (int i = 1; i < graphicInfoList.size(); i++) { + GraphicInfo graphicInfo = graphicInfoList.get(i); + GraphicInfo previousGraphicInfo = graphicInfoList.get(i - 1); + + if (i == 1) { + xPoints[0] = (int) previousGraphicInfo.getX(); + yPoints[0] = (int) previousGraphicInfo.getY(); + } + xPoints[i] = (int) graphicInfo.getX(); + yPoints[i] = (int) graphicInfo.getY(); + + } + + processDiagramCanvas.drawSequenceflow(xPoints, yPoints, drawConditionalIndicator, isDefault, highLighted, scaleFactor); + + + // Draw sequenceflow label + GraphicInfo labelGraphicInfo = bpmnModel.getLabelGraphicInfo(sequenceFlow.getId()); + if (labelGraphicInfo != null) { + processDiagramCanvas.drawLabel(sequenceFlow.getName(), labelGraphicInfo, false); + } else { + if (drawSequenceFlowNameWithNoLabelDI) { + GraphicInfo lineCenter = getLineCenter(graphicInfoList); + processDiagramCanvas.drawLabel(sequenceFlow.getName(), lineCenter, false); + } + + } + } + } + + // Nested elements + if (flowNode instanceof FlowElementsContainer) { + for (FlowElement nestedFlowElement : ((FlowElementsContainer) flowNode).getFlowElements()) { + if (nestedFlowElement instanceof FlowNode && !isPartOfCollapsedSubProcess(nestedFlowElement, bpmnModel)) { + drawActivity(processDiagramCanvas, bpmnModel, (FlowNode) nestedFlowElement, + highLightedActivities, highLightedFlows, scaleFactor, drawSequenceFlowNameWithNoLabelDI); + } + } + } + } +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/DiRemoteAccountResource.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/DiRemoteAccountResource.java new file mode 100644 index 00000000..2f3d4910 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/DiRemoteAccountResource.java @@ -0,0 +1,47 @@ +package com.yxt.anrui.flowable.config; + +import org.flowable.idm.engine.impl.persistence.entity.UserEntityImpl; +import org.flowable.ui.common.model.UserRepresentation; +import org.flowable.ui.common.security.SecurityUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author dimengzhe + * @date 2021/6/17 14:26 + * @description 内置用户登录 + */ +@RestController +@RequestMapping("/di") +public class DiRemoteAccountResource { + + /** + * GET /rest/account -> get the current user. + */ + @GetMapping(value = "/rest/account", produces = "application/json") + public UserRepresentation getAccount() { + + + UserEntityImpl userEntity = new UserEntityImpl(); + userEntity.setId("dimengzhe"); + SecurityUtils.assumeUser(userEntity); + + UserRepresentation userRepresentation = new UserRepresentation(); + userRepresentation.setId("tpp-flowable"); + userRepresentation.setFirstName("底"); + userRepresentation.setLastName("孟哲"); + List privileges = new ArrayList<>(); + privileges.add("flowable-idm"); + privileges.add("flowable-modeler"); + privileges.add("flowable-admin"); + privileges.add("flowable-task"); + privileges.add("flowable-rest"); + userRepresentation.setPrivileges(privileges); + return userRepresentation; + + } +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/FlowableConfig.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/FlowableConfig.java new file mode 100644 index 00000000..54215cdd --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/FlowableConfig.java @@ -0,0 +1,22 @@ +package com.yxt.anrui.flowable.config; + +import org.flowable.spring.SpringProcessEngineConfiguration; +import org.flowable.spring.boot.EngineConfigurationConfigurer; +import org.springframework.context.annotation.Configuration; + +/** + *flowable配置----为放置生成的流程图中中文乱码 + * @author dimengzhe + */ +@Configuration +public class FlowableConfig implements EngineConfigurationConfigurer { + + @Override + public void configure(SpringProcessEngineConfiguration engineConfiguration) { + System.out.println(">>>>>>>>>>>>>>>>>>>>>> 配置已经加载 >>>>>>>>>>>>>>>>>>>>>>>"); + engineConfiguration.setActivityFontName("宋体"); + engineConfiguration.setLabelFontName("宋体"); + engineConfiguration.setAnnotationFontName("宋体"); + } + +} \ No newline at end of file diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/P6spySqlFormatConfig.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/P6spySqlFormatConfig.java new file mode 100644 index 00000000..bae30c1c --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/P6spySqlFormatConfig.java @@ -0,0 +1,25 @@ +package com.yxt.anrui.flowable.config; + +import com.p6spy.engine.spy.appender.MessageFormattingStrategy; +import com.yxt.common.base.utils.DateUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.Date; + +/** + * @author dimengzhe + * @date 2021/10/11 21:02 + * @description 自定义 p6spy sql输出格式 + */ + +public class P6spySqlFormatConfig implements MessageFormattingStrategy { + + /** + * 过滤掉定时任务的 SQL + */ + @Override + public String formatMessage(int connectionId, String now, long elapsed, String category, String prepared, String sql, String url) { + return StringUtils.isNotBlank(sql) ? DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", new Date()) + + " | 耗时 " + elapsed + " ms | SQL 语句:" + StringUtils.LF + sql.replaceAll("[\\s]+", StringUtils.SPACE) + ";" : ""; + } +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/ProcessEngineConfig.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/ProcessEngineConfig.java new file mode 100644 index 00000000..49ca8bdb --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/ProcessEngineConfig.java @@ -0,0 +1,212 @@ +package com.yxt.anrui.flowable.config; + +import liquibase.Liquibase; +import liquibase.database.Database; +import liquibase.database.DatabaseConnection; +import liquibase.database.DatabaseFactory; +import liquibase.database.jvm.JdbcConnection; +import liquibase.exception.DatabaseException; +import liquibase.resource.ClassLoaderResourceAccessor; +import org.apache.ibatis.session.SqlSessionFactory; +import org.flowable.common.engine.api.FlowableException; +import org.flowable.engine.ProcessEngine; +import org.flowable.spring.SpringProcessEngineConfiguration; +import org.flowable.ui.common.service.exception.InternalServerErrorException; +import org.flowable.ui.modeler.properties.FlowableModelerAppProperties; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.mybatis.spring.SqlSessionTemplate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.core.io.ResourceLoader; +import org.springframework.core.io.support.ResourcePatternUtils; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.SQLException; +import java.util.Properties; + +/** + * @author dimengzhe + * @date 2021/6/17 14:24 + * @description 构造流程引擎配置类 + */ +@Configuration +public class ProcessEngineConfig { + + private static final Logger LOGGER = LoggerFactory.getLogger(ProcessEngine.class); + + @Autowired + protected ResourceLoader resourceLoader; + + protected static final String LIQUIBASE_CHANGELOG_PREFIX = "ACT_DE_"; + + @Autowired + private DataSource dataSource; + + @Bean + public DataSourceTransactionManager dataSourceTransactionManager(DataSource dataSource) { + DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(dataSource); + return dataSourceTransactionManager; + } + + @Bean + public SpringProcessEngineConfiguration springProcessEngineConfiguration() { + SpringProcessEngineConfiguration springProcessEngineConfiguration = new SpringProcessEngineConfiguration(); + springProcessEngineConfiguration.setDataSource(dataSource); + springProcessEngineConfiguration.setDatabaseSchemaUpdate("true"); + springProcessEngineConfiguration.setTransactionManager(dataSourceTransactionManager(dataSource)); + return springProcessEngineConfiguration; + } + + @Primary + @Bean + public SqlSessionTemplate SqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { + return new SqlSessionTemplate(sqlSessionFactory); + } + + @Bean + public SqlSessionFactory sqlSessionFactory(DataSource dataSource) { + SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); + sqlSessionFactoryBean.setDataSource(dataSource); + String databaseType = initDatabaseType(dataSource); + if (databaseType == null) { + throw new FlowableException("couldn't deduct database type"); + } + + try { + Properties properties = new Properties(); + properties.put("prefix", ""); + properties.put("blobType", "BLOB"); + properties.put("boolValue", "TRUE"); + + properties.load(this.getClass().getClassLoader().getResourceAsStream("properties/" + databaseType + ".properties")); + + sqlSessionFactoryBean.setConfigurationProperties(properties); + sqlSessionFactoryBean + .setMapperLocations(ResourcePatternUtils.getResourcePatternResolver(resourceLoader).getResources("classpath:/META-INF/modeler-mybatis-mappings/*.xml")); + sqlSessionFactoryBean.afterPropertiesSet(); + return sqlSessionFactoryBean.getObject(); + } catch (Exception e) { + throw new FlowableException("Could not create sqlSessionFactory", e); + } + + } + + protected String initDatabaseType(DataSource dataSource) { + String databaseType = null; + Connection connection = null; + try { + connection = dataSource.getConnection(); + DatabaseMetaData databaseMetaData = connection.getMetaData(); + String databaseProductName = databaseMetaData.getDatabaseProductName(); + LOGGER.info("database product name: '{}'", databaseProductName); + databaseType = databaseTypeMappings.getProperty(databaseProductName); + if (databaseType == null) { + throw new FlowableException("couldn't deduct database type from database product name '" + databaseProductName + "'"); + } + LOGGER.info("using database type: {}", databaseType); + + } catch (SQLException e) { + LOGGER.error("Exception while initializing Database connection", e); + } finally { + try { + if (connection != null) { + connection.close(); + } + } catch (SQLException e) { + LOGGER.error("Exception while closing the Database connection", e); + } + } + + return databaseType; + } + + protected static Properties databaseTypeMappings = getDefaultDatabaseTypeMappings(); + + public static final String DATABASE_TYPE_H2 = "h2"; + public static final String DATABASE_TYPE_HSQL = "hsql"; + public static final String DATABASE_TYPE_MYSQL = "mysql"; + public static final String DATABASE_TYPE_ORACLE = "oracle"; + public static final String DATABASE_TYPE_POSTGRES = "postgres"; + public static final String DATABASE_TYPE_MSSQL = "mssql"; + public static final String DATABASE_TYPE_DB2 = "db2"; + + public static Properties getDefaultDatabaseTypeMappings() { + Properties databaseTypeMappings = new Properties(); + databaseTypeMappings.setProperty("H2", DATABASE_TYPE_H2); + databaseTypeMappings.setProperty("HSQL Database Engine", DATABASE_TYPE_HSQL); + databaseTypeMappings.setProperty("MySQL", DATABASE_TYPE_MYSQL); + databaseTypeMappings.setProperty("MariaDB", DATABASE_TYPE_MYSQL); + databaseTypeMappings.setProperty("Oracle", DATABASE_TYPE_ORACLE); + databaseTypeMappings.setProperty("PostgreSQL", DATABASE_TYPE_POSTGRES); + databaseTypeMappings.setProperty("Microsoft SQL Server", DATABASE_TYPE_MSSQL); + databaseTypeMappings.setProperty(DATABASE_TYPE_DB2, DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/NT", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/NT64", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2 UDP", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/LINUX", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/LINUX390", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/LINUXX8664", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/LINUXZ64", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/LINUXPPC64", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/400 SQL", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/6000", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2 UDB iSeries", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/AIX64", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/HPUX", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/HP64", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/SUN", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/SUN64", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/PTX", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/2", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2 UDB AS400", DATABASE_TYPE_DB2); + return databaseTypeMappings; + } + + @Bean + public FlowableModelerAppProperties flowableModelerAppProperties() { + return new FlowableModelerAppProperties(); + } + + @Bean + public Liquibase liquibase(DataSource dataSource) { + LOGGER.info("Configuring Liquibase"); + + Liquibase liquibase = null; + try { + DatabaseConnection connection = new JdbcConnection(dataSource.getConnection()); + Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(connection); + database.setDatabaseChangeLogTableName(LIQUIBASE_CHANGELOG_PREFIX + database.getDatabaseChangeLogTableName()); + database.setDatabaseChangeLogLockTableName(LIQUIBASE_CHANGELOG_PREFIX + database.getDatabaseChangeLogLockTableName()); + + liquibase = new Liquibase("META-INF/liquibase/flowable-modeler-app-db-changelog.xml", new ClassLoaderResourceAccessor(), database); + liquibase.update("flowable"); + return liquibase; + + } catch (Exception e) { + throw new InternalServerErrorException("Error creating liquibase database", e); + } finally { + closeDatabase(liquibase); + } + } + + private void closeDatabase(Liquibase liquibase) { + if (liquibase != null) { + Database database = liquibase.getDatabase(); + if (database != null) { + try { + database.close(); + } catch (DatabaseException e) { + LOGGER.warn("Error closing database", e); + } + } + } + } +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/Swagger2Config.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/Swagger2Config.java new file mode 100644 index 00000000..b9d42153 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/config/Swagger2Config.java @@ -0,0 +1,36 @@ +package com.yxt.anrui.flowable.config; + +import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +/** + * @author dimengzhe + * @date 2020/9/9 16:42 + * @description + */ +@Configuration +@EnableSwagger2 +@EnableKnife4j +public class Swagger2Config { + + @Bean + public Docket createRestApi() { + return new Docket(DocumentationType.SWAGGER_2) + .apiInfo(apiInfo()).select() + .apis(RequestHandlerSelectors.basePackage("com.yxt")) + .paths(PathSelectors.any()).build(); + } + + private ApiInfo apiInfo() { + return new ApiInfoBuilder().title("安瑞/工作流").description("工作流接口").version("1.0") + .build(); + } +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/factory/FlowServiceFactory.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/factory/FlowServiceFactory.java new file mode 100644 index 00000000..7bfc8a4c --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/factory/FlowServiceFactory.java @@ -0,0 +1,41 @@ +package com.yxt.anrui.flowable.factory; + +import org.flowable.engine.*; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * @author dimengzhe + * @date 2021/6/16 10:41 + * @description flowable 引擎注入封装 + */ +@Component +public class FlowServiceFactory { + + @Resource + protected RepositoryService repositoryService; + + @Resource + protected RuntimeService runtimeService; + + @Resource + protected IdentityService identityService; + + @Resource + protected TaskService taskService; + + @Resource + protected FormService formService; + + @Resource + protected HistoryService historyService; + + @Resource + protected ManagementService managementService; + + @Qualifier("processEngine") + @Resource + protected ProcessEngine processEngine; +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/listener/BaseVehicleExecutionListener.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/listener/BaseVehicleExecutionListener.java new file mode 100644 index 00000000..9d7494a2 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/listener/BaseVehicleExecutionListener.java @@ -0,0 +1,23 @@ +package com.yxt.anrui.flowable.listener; + +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.ExecutionListener; +import org.springframework.stereotype.Component; + +/** + * @author liuguohui + * @version 1.0 + * @description 建立车辆库存台账 + * @date 2022/04/11 + */ +@Component +public class BaseVehicleExecutionListener implements ExecutionListener { + + @Override + public void notify(DelegateExecution execution) { + // 入账申请审批通过后,自动生成车辆库存台账 + // TODO + System.out.println("入账申请审批通过后,自动生成车辆库存台账"); + + } +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/listener/ManagerEndExecutionListener.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/listener/ManagerEndExecutionListener.java new file mode 100644 index 00000000..b8d567bc --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/listener/ManagerEndExecutionListener.java @@ -0,0 +1,21 @@ +package com.yxt.anrui.flowable.listener; + +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.ExecutionListener; +import org.springframework.stereotype.Component; + +/** + * @Description 执行监听器监听流程实例结束事件(抄送等) + * @Author liuguohui + * @Date 2022/2/8 + */ +@Component +public class ManagerEndExecutionListener implements ExecutionListener { + + @Override + public void notify(DelegateExecution execution) { + System.out.println("执行监听器:" + "抄送"); + String processInstanceId = execution.getProcessInstanceId(); + System.out.println(execution); + } +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/listener/ManagerTaskListener.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/listener/ManagerTaskListener.java new file mode 100644 index 00000000..539d1e92 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/listener/ManagerTaskListener.java @@ -0,0 +1,101 @@ +package com.yxt.anrui.flowable.listener; + +import com.alibaba.fastjson.JSONObject; +import com.yxt.common.base.utils.JPushServer; +import com.yxt.common.core.result.ResultBean; +import com.yxt.supervise.system.sysuserrole.SysUserRoleFeign; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.delegate.TaskListener; +import org.flowable.identitylink.api.IdentityLink; +import org.flowable.task.service.delegate.DelegateTask; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.kafka.support.SendResult; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; +import org.springframework.util.concurrent.ListenableFuture; +import org.springframework.util.concurrent.ListenableFutureCallback; + +import javax.annotation.PostConstruct; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * @Description 监听任务器监听各个环节,发出推送等消息 + * @Author liuguohui + * @Date 2022/2/7 + */ +@Component +public class ManagerTaskListener implements TaskListener { + + private static ManagerTaskListener taskListener; + + @Autowired + private SysUserRoleFeign sysUserRoleFeign; + + @Autowired + private KafkaTemplate kafkaTemplate; + + /** + * 监听器中无法获取spring bean配置 + * 注意调用方式:taskListener.sysUserRoleFeign + */ + @PostConstruct + public void init() { + taskListener = this; + taskListener.sysUserRoleFeign = this.sysUserRoleFeign; + } + + @Override + public void notify(DelegateTask delegateTask) { + System.out.println("任务监听"); +// String assignee = delegateTask.getAssignee(); + Set set = delegateTask.getCandidates(); + List groupIdList = set.stream().filter(item -> StringUtils.isNotBlank(item.getGroupId())).map(item -> item.getGroupId()).collect(Collectors.toList()); + JSONObject jsonObject = new JSONObject(); + jsonObject.put("msgType", "花花"); +// jsonObject.put("assignee", assignee); +// jsonObject.put("groupIdList", groupIdList); + send(jsonObject.toString()); +// if (StringUtils.isBlank(assignee)) { +// Set set = delegateTask.getCandidates(); +// List groupIdList = set.stream().filter(item -> StringUtils.isNotBlank(item.getGroupId())).map(item -> item.getGroupId()).collect(Collectors.toList()); +// if (CollectionUtils.isNotEmpty(groupIdList)) { +// ResultBean> resultBean = taskListener.sysUserRoleFeign.getUserIdListByRoleSid(groupIdList); +// if (resultBean.getSuccess() && resultBean.getData() != null) { +// List list = resultBean.getData(); +// // 保存消息体、保存消息列表 +// +// // TODO 与kafka集成 +// JPushServer.sendPushAlias("标题", "内容 ", "msg_type", "销售订单", list.toArray(list.toArray(new String[list.size()]))); +// } +// } +// } else { +// JPushServer.sendPushAlias("标题", "内容 ", "msg_type", "销售订单", assignee); +// } + } + + public void send(String obj2String) { +// String obj2String = JSONObject.toJSONString(obj); + //发送消息 + /* ListenableFuture> future = kafkaTemplate.send("aaa", obj2String); + future.addCallback(new ListenableFutureCallback>() { + @Override + public void onFailure(Throwable throwable) { + //发送失败的处理 + log.info("aaa" + " - 生产者 发送消息失败:" + throwable.getMessage()); + } + + @Override + public void onSuccess(SendResult stringObjectSendResult) { + //成功的处理 + log.info("aaa" + " - 生产者 发送消息成功:" + stringObjectSendResult.toString()); + } + });*/ + + + } +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/test/controller/HolidayTestController.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/test/controller/HolidayTestController.java new file mode 100644 index 00000000..de92b4bc --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/test/controller/HolidayTestController.java @@ -0,0 +1,53 @@ +package com.yxt.anrui.flowable.test.controller; + +import com.yxt.anrui.flowable.test.HolidayTestApi; +import com.yxt.anrui.flowable.test.HolidayVo; +import com.yxt.anrui.flowable.test.service.IHolidayTestService; +import com.yxt.common.core.result.ResultBean; +import io.swagger.annotations.Api; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +import javax.servlet.http.HttpServletResponse; + +/** + * @author dimengzhe + * @date 2021/6/18 10:36 + * @description 公司请假流程测试 + */ +@Api(tags = "公司请假流程测试") +@Controller +@RequestMapping("v1/flowable/holidaytest") +public class HolidayTestController implements HolidayTestApi { + + @Autowired + private IHolidayTestService holidayTestService; + + /** + * 提交请假 + * + * @param taskUser 申请人 + * @param day 申请天数 + * @return + */ + @Override + public ResultBean submit(String taskUser, Integer day) { + if (day == null || "".equals(day)) { + return new ResultBean().fail().setMsg("请写入请假天数........."); + } + HolidayVo holidayVo = holidayTestService.submit(taskUser, day); + return new ResultBean().setData(holidayVo); + } + + /** + * 生成图片 + * + * @param httpServletResponse + * @param processId 流程实例ID + */ + @Override + public void genProcessDiagram(HttpServletResponse httpServletResponse, String processId) { + holidayTestService.genProcessDiagram(httpServletResponse, processId); + } +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/test/controller/TestController.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/test/controller/TestController.java new file mode 100644 index 00000000..d068cea3 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/test/controller/TestController.java @@ -0,0 +1,41 @@ +package com.yxt.anrui.flowable.test.controller; + +import org.flowable.engine.ProcessEngine; +import org.flowable.engine.ProcessEngineConfiguration; +import org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration; + + +/** + * @author dimengzhe + * @date 2021/6/11 9:30 + * @description + */ + +public class TestController { + + /** + * @author dimengzhe + * @description 生成数据库表 + * @date 2021/6/11 9:47 + **/ +// @Test + public void test1() { + //1.创建ProcessEngineConfiguration对象 + ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("flowable.cfg.xml"); + //2.创建ProcessEngine对象 + ProcessEngine processEngine = configuration.buildProcessEngine(); + System.out.println(processEngine); + } + +// @Test + public void test2() { + ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration() + .setJdbcUrl("jdbc:mysql://localhost:3306/anrui_flowable?serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true") + .setJdbcUsername("root") + .setJdbcPassword("root") + .setJdbcDriver("com.mysql.jdbc.Driver") + .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE); + + ProcessEngine processEngine = cfg.buildProcessEngine(); + } +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/test/service/IHolidayTestService.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/test/service/IHolidayTestService.java new file mode 100644 index 00000000..22586bf5 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/test/service/IHolidayTestService.java @@ -0,0 +1,39 @@ +package com.yxt.anrui.flowable.test.service; + +import com.yxt.anrui.flowable.test.HolidayVo; + +import javax.servlet.http.HttpServletResponse; + +/** + * @author dimengzhe + * @date 2021/6/18 10:44 + * @description + */ + +public interface IHolidayTestService { + + /** + * 提交请假申请 + * + * @param taskUser 申请人 + * @param day 天数 + * @return + */ + HolidayVo submit(String taskUser, Integer day); + + /** + * 生成图片 + * + * @param httpServletResponse + * @param processId 流程实例ID + */ + void genProcessDiagram(HttpServletResponse httpServletResponse, String processId); + + /** + * 流程是否完成功能 + * + * @param processInstanceId 流程实例id + * @return + */ + boolean isFinished(String processInstanceId); +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/test/service/impl/HolidayTestService.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/test/service/impl/HolidayTestService.java new file mode 100644 index 00000000..6fb6aef6 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/test/service/impl/HolidayTestService.java @@ -0,0 +1,149 @@ +package com.yxt.anrui.flowable.test.service.impl; + +import com.yxt.anrui.flowable.CodeMsgEnum; +import com.yxt.anrui.flowable.config.DefaultProcessDiagramGeneratorExt; +import com.yxt.anrui.flowable.factory.FlowServiceFactory; +import com.yxt.anrui.flowable.test.HolidayVo; +import com.yxt.anrui.flowable.test.service.IHolidayTestService; +import com.yxt.common.core.result.ResultBean; +import org.apache.commons.io.IOUtils; +import org.flowable.bpmn.model.BpmnModel; +import org.flowable.engine.ProcessEngineConfiguration; +import org.flowable.engine.history.HistoricActivityInstance; +import org.flowable.engine.history.HistoricProcessInstance; +import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.image.ProcessDiagramGenerator; +import org.flowable.task.api.Task; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +/** + * @author dimengzhe + * @date 2021/6/18 10:45 + * @description + */ +@Service +public class HolidayTestService extends FlowServiceFactory implements IHolidayTestService { + + /** + * 提交请假申请 + * + * @param taskUser 申请人 + * @param day 天数 + * @return + */ + @Override + public HolidayVo submit(String taskUser, Integer day) { + List tasks = taskService.createTaskQuery().taskAssignee(taskUser).orderByTaskCreateTime().desc().list(); + //启动流程 + HashMap map = new HashMap<>(); + map.put("taskUser", taskUser); + map.put("user1", "mg"); + map.put("user2", "boss"); + ProcessInstance pi = runtimeService.startProcessInstanceByKey("holiday_test", map); + + //过排他网关 + Task task = taskService.createTaskQuery().processInstanceId(pi.getProcessInstanceId()).singleResult(); + taskService.setVariable(task.getId(), "day", day); + taskService.complete(task.getId()); + + //老板或经理审批根据请假天数 + Task task2 = taskService.createTaskQuery().processInstanceId(pi.getProcessInstanceId()).singleResult(); + if ("boss".equals(task2.getAssignee())) { + taskService.setVariable(task2.getId(), "outcome", "驳回"); + taskService.complete(task2.getId()); + } else { + taskService.setVariable(task2.getId(), "outcome", "通过"); + taskService.complete(task2.getId()); + } + HolidayVo holidayVo = new HolidayVo(); + holidayVo.setDay(day); + holidayVo.setTaskUser(taskUser); + holidayVo.setId(pi.getId()); +// String data = "{进程实例id:" + "\"" + pi.getId() + "\"" + "," + "请假申请人:" + "\"" + taskUser + "\"" + "," + "请假天数:" + "\"" + day + "\"" + "}"; + return holidayVo; + } + + /** + * 生成图片 + * + * @param httpServletResponse + * @param processId 流程实例id + */ + @Override + public void genProcessDiagram(HttpServletResponse httpServletResponse, String processId) { + /** + * 获得当前活动的节点 + */ + String processDefinitionId = ""; + if (this.isFinished(processId)) {// 如果流程已经结束,则得到结束节点 + HistoricProcessInstance pi = historyService.createHistoricProcessInstanceQuery().processInstanceId(processId).singleResult(); + processDefinitionId = pi.getProcessDefinitionId(); + } else {// 如果流程没有结束,则取当前活动节点 + // 根据流程实例ID获得当前处于活动状态的ActivityId合集 + ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult(); + processDefinitionId = pi.getProcessDefinitionId(); + } + List highLightedActivitis = new ArrayList(); + + /** + * 获得活动的节点 + */ + List highLightedActivitList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processId).orderByHistoricActivityInstanceStartTime().asc().list(); + //高亮节点 + for (HistoricActivityInstance tempActivity : highLightedActivitList) { + String activityId = tempActivity.getActivityId(); + highLightedActivitis.add(activityId); + } + + List highLightedflows = new ArrayList<>(); + //高亮线 + for (HistoricActivityInstance tempActivity : highLightedActivitList) { + if ("sequenceFlow".equals(tempActivity.getActivityType())) { + highLightedflows.add(tempActivity.getActivityId()); + } + } + //获取流程图 + BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId); + + ProcessEngineConfiguration engconf = processEngine.getProcessEngineConfiguration(); + //获取自定义图片生成器 + ProcessDiagramGenerator diagramGenerator = new DefaultProcessDiagramGeneratorExt(); + InputStream in = diagramGenerator.generateDiagram(bpmnModel, "bmp", highLightedActivitis, highLightedflows, engconf.getActivityFontName(), + engconf.getLabelFontName(), engconf.getAnnotationFontName(), engconf.getClassLoader(), 1.0, true); + OutputStream out = null; + byte[] buf = new byte[1024]; + int legth = 0; + try { + out = httpServletResponse.getOutputStream(); + while ((legth = in.read(buf)) != -1) { + out.write(buf, 0, legth); + } + } catch (IOException e) { + + } finally { + + IOUtils.closeQuietly(out); + IOUtils.closeQuietly(in); + } + } + + @Override + public boolean isFinished(String processInstanceId) { + return historyService.createHistoricProcessInstanceQuery().finished() + .processInstanceId(processInstanceId).count() > 0; + } + + public ResultBean doResultEnum() { + ResultBean rb = ResultBean.fireFail(); + + return rb.fail().setCode(CodeMsgEnum.AF_U_5001); + } +} diff --git a/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/utils/FlowableUtils.java b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/utils/FlowableUtils.java new file mode 100644 index 00000000..f8feca25 --- /dev/null +++ b/yxt_supervise/supervise-flowable/supervise-flowable-biz/src/main/java/com/yxt/anrui/flowable/utils/FlowableUtils.java @@ -0,0 +1,620 @@ +package com.yxt.anrui.flowable.utils; + +import lombok.extern.slf4j.Slf4j; +import org.flowable.bpmn.model.*; +import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior; +import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior; +import org.flowable.task.api.history.HistoricTaskInstance; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + +/** + * @author XuanXuan + * @date 2021-04-03 23:57 + */ +@Slf4j +public class FlowableUtils { + private static final Logger log = LoggerFactory.getLogger(FlowableUtils.class); + + /** + * 根据节点,获取入口连线 + * @param source + * @return + */ + public static List getElementIncomingFlows(FlowElement source) { + List sequenceFlows = null; + if (source instanceof FlowNode) { + sequenceFlows = ((FlowNode) source).getIncomingFlows(); + } else if (source instanceof Gateway) { + sequenceFlows = ((Gateway) source).getIncomingFlows(); + } else if (source instanceof SubProcess) { + sequenceFlows = ((SubProcess) source).getIncomingFlows(); + } else if (source instanceof StartEvent) { + sequenceFlows = ((StartEvent) source).getIncomingFlows(); + } else if (source instanceof EndEvent) { + sequenceFlows = ((EndEvent) source).getIncomingFlows(); + } + return sequenceFlows; + } + + /** + * 根据节点,获取出口连线 + * @param source + * @return + */ + public static List getElementOutgoingFlows(FlowElement source) { + List sequenceFlows = null; + if (source instanceof FlowNode) { + sequenceFlows = ((FlowNode) source).getOutgoingFlows(); + } else if (source instanceof Gateway) { + sequenceFlows = ((Gateway) source).getOutgoingFlows(); + } else if (source instanceof SubProcess) { + sequenceFlows = ((SubProcess) source).getOutgoingFlows(); + } else if (source instanceof StartEvent) { + sequenceFlows = ((StartEvent) source).getOutgoingFlows(); + } else if (source instanceof EndEvent) { + sequenceFlows = ((EndEvent) source).getOutgoingFlows(); + } + return sequenceFlows; + } + + /** + * 获取全部节点列表,包含子流程节点 + * @param flowElements + * @param allElements + * @return + */ + public static Collection getAllElements(Collection flowElements, Collection allElements) { + allElements = allElements == null ? new ArrayList<>() : allElements; + + for (FlowElement flowElement : flowElements) { + allElements.add(flowElement); + if (flowElement instanceof SubProcess) { + // 继续深入子流程,进一步获取子流程 + allElements = FlowableUtils.getAllElements(((SubProcess) flowElement).getFlowElements(), allElements); + } + } + return allElements; + } + + /** + * 迭代获取父级任务节点列表,向前找 + * @param source 起始节点 + * @param hasSequenceFlow 已经经过的连线的 ID,用于判断线路是否重复 + * @param userTaskList 已找到的用户任务节点 + * @return + */ + public static List iteratorFindParentUserTasks(FlowElement source, Set hasSequenceFlow, List userTaskList) { + userTaskList = userTaskList == null ? new ArrayList<>() : userTaskList; + hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow; + + // 如果该节点为开始节点,且存在上级子节点,则顺着上级子节点继续迭代 + if (source instanceof StartEvent && source.getSubProcess() != null) { + userTaskList = iteratorFindParentUserTasks(source.getSubProcess(), hasSequenceFlow, userTaskList); + } + + // 根据类型,获取入口连线 + List sequenceFlows = getElementIncomingFlows(source); + + if (sequenceFlows != null) { + // 循环找到目标元素 + for (SequenceFlow sequenceFlow: sequenceFlows) { + // 如果发现连线重复,说明循环了,跳过这个循环 + if (hasSequenceFlow.contains(sequenceFlow.getId())) { + continue; + } + // 添加已经走过的连线 + hasSequenceFlow.add(sequenceFlow.getId()); + // 类型为用户节点,则新增父级节点 + if (sequenceFlow.getSourceFlowElement() instanceof UserTask) { + userTaskList.add((UserTask) sequenceFlow.getSourceFlowElement()); + continue; + } + // 类型为子流程,则添加子流程开始节点出口处相连的节点 + if (sequenceFlow.getSourceFlowElement() instanceof SubProcess) { + // 获取子流程用户任务节点 + List childUserTaskList = findChildProcessUserTasks((StartEvent) ((SubProcess) sequenceFlow.getSourceFlowElement()).getFlowElements().toArray()[0], null, null); + // 如果找到节点,则说明该线路找到节点,不继续向下找,反之继续 + if (childUserTaskList != null && childUserTaskList.size() > 0) { + userTaskList.addAll(childUserTaskList); + continue; + } + } + // 继续迭代 + userTaskList = iteratorFindParentUserTasks(sequenceFlow.getSourceFlowElement(), hasSequenceFlow, userTaskList); + } + } + return userTaskList; + } + + /** + * 根据正在运行的任务节点,迭代获取子级任务节点列表,向后找 + * @param source 起始节点 + * @param runTaskKeyList 正在运行的任务 Key,用于校验任务节点是否是正在运行的节点 + * @param hasSequenceFlow 已经经过的连线的 ID,用于判断线路是否重复 + * @param userTaskList 需要撤回的用户任务列表 + * @return + */ + public static List iteratorFindChildUserTasks(FlowElement source, List runTaskKeyList, Set hasSequenceFlow, List userTaskList) { + hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow; + userTaskList = userTaskList == null ? new ArrayList<>() : userTaskList; + + // 如果该节点为开始节点,且存在上级子节点,则顺着上级子节点继续迭代 + if (source instanceof EndEvent && source.getSubProcess() != null) { + userTaskList = iteratorFindChildUserTasks(source.getSubProcess(), runTaskKeyList, hasSequenceFlow, userTaskList); + } + + // 根据类型,获取出口连线 + List sequenceFlows = getElementOutgoingFlows(source); + + if (sequenceFlows != null) { + // 循环找到目标元素 + for (SequenceFlow sequenceFlow: sequenceFlows) { + // 如果发现连线重复,说明循环了,跳过这个循环 + if (hasSequenceFlow.contains(sequenceFlow.getId())) { + continue; + } + // 添加已经走过的连线 + hasSequenceFlow.add(sequenceFlow.getId()); + // 如果为用户任务类型,且任务节点的 Key 正在运行的任务中存在,添加 + if (sequenceFlow.getTargetFlowElement() instanceof UserTask && runTaskKeyList.contains((sequenceFlow.getTargetFlowElement()).getId())) { + userTaskList.add((UserTask) sequenceFlow.getTargetFlowElement()); + continue; + } + // 如果节点为子流程节点情况,则从节点中的第一个节点开始获取 + if (sequenceFlow.getTargetFlowElement() instanceof SubProcess) { + List childUserTaskList = iteratorFindChildUserTasks((FlowElement) (((SubProcess) sequenceFlow.getTargetFlowElement()).getFlowElements().toArray()[0]), runTaskKeyList, hasSequenceFlow, null); + // 如果找到节点,则说明该线路找到节点,不继续向下找,反之继续 + if (childUserTaskList != null && childUserTaskList.size() > 0) { + userTaskList.addAll(childUserTaskList); + continue; + } + } + // 继续迭代 + userTaskList = iteratorFindChildUserTasks(sequenceFlow.getTargetFlowElement(), runTaskKeyList, hasSequenceFlow, userTaskList); + } + } + return userTaskList; + } + + /** + * 迭代获取子流程用户任务节点 + * @param source 起始节点 + * @param hasSequenceFlow 已经经过的连线的 ID,用于判断线路是否重复 + * @param userTaskList 需要撤回的用户任务列表 + * @return + */ + public static List findChildProcessUserTasks(FlowElement source, Set hasSequenceFlow, List userTaskList) { + hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow; + userTaskList = userTaskList == null ? new ArrayList<>() : userTaskList; + + // 根据类型,获取出口连线 + List sequenceFlows = getElementOutgoingFlows(source); + + if (sequenceFlows != null) { + // 循环找到目标元素 + for (SequenceFlow sequenceFlow: sequenceFlows) { + // 如果发现连线重复,说明循环了,跳过这个循环 + if (hasSequenceFlow.contains(sequenceFlow.getId())) { + continue; + } + // 添加已经走过的连线 + hasSequenceFlow.add(sequenceFlow.getId()); + // 如果为用户任务类型,且任务节点的 Key 正在运行的任务中存在,添加 + if (sequenceFlow.getTargetFlowElement() instanceof UserTask) { + userTaskList.add((UserTask) sequenceFlow.getTargetFlowElement()); + continue; + } + // 如果节点为子流程节点情况,则从节点中的第一个节点开始获取 + if (sequenceFlow.getTargetFlowElement() instanceof SubProcess) { + List childUserTaskList = findChildProcessUserTasks((FlowElement) (((SubProcess) sequenceFlow.getTargetFlowElement()).getFlowElements().toArray()[0]), hasSequenceFlow, null); + // 如果找到节点,则说明该线路找到节点,不继续向下找,反之继续 + if (childUserTaskList != null && childUserTaskList.size() > 0) { + userTaskList.addAll(childUserTaskList); + continue; + } + } + // 继续迭代 + userTaskList = findChildProcessUserTasks(sequenceFlow.getTargetFlowElement(), hasSequenceFlow, userTaskList); + } + } + return userTaskList; + } + + /** + * 从后向前寻路,获取所有脏线路上的点 + * @param source 起始节点 + * @param passRoads 已经经过的点集合 + * @param hasSequenceFlow 已经经过的连线的 ID,用于判断线路是否重复 + * @param targets 目标脏线路终点 + * @param dirtyRoads 确定为脏数据的点,因为不需要重复,因此使用 set 存储 + * @return + */ + public static Set iteratorFindDirtyRoads(FlowElement source, List passRoads, Set hasSequenceFlow, List targets, Set dirtyRoads) { + passRoads = passRoads == null ? new ArrayList<>() : passRoads; + dirtyRoads = dirtyRoads == null ? new HashSet<>() : dirtyRoads; + hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow; + + // 如果该节点为开始节点,且存在上级子节点,则顺着上级子节点继续迭代 + if (source instanceof StartEvent && source.getSubProcess() != null) { + dirtyRoads = iteratorFindDirtyRoads(source.getSubProcess(), passRoads, hasSequenceFlow, targets, dirtyRoads); + } + + // 根据类型,获取入口连线 + List sequenceFlows = getElementIncomingFlows(source); + + if (sequenceFlows != null) { + // 循环找到目标元素 + for (SequenceFlow sequenceFlow: sequenceFlows) { + // 如果发现连线重复,说明循环了,跳过这个循环 + if (hasSequenceFlow.contains(sequenceFlow.getId())) { + continue; + } + // 添加已经走过的连线 + hasSequenceFlow.add(sequenceFlow.getId()); + // 新增经过的路线 + passRoads.add(sequenceFlow.getSourceFlowElement().getId()); + // 如果此点为目标点,确定经过的路线为脏线路,添加点到脏线路中,然后找下个连线 + if (targets.contains(sequenceFlow.getSourceFlowElement().getId())) { + dirtyRoads.addAll(passRoads); + continue; + } + // 如果该节点为开始节点,且存在上级子节点,则顺着上级子节点继续迭代 + if (sequenceFlow.getSourceFlowElement() instanceof SubProcess) { + dirtyRoads = findChildProcessAllDirtyRoad((StartEvent) ((SubProcess) sequenceFlow.getSourceFlowElement()).getFlowElements().toArray()[0], null, dirtyRoads); + // 是否存在子流程上,true 是,false 否 + Boolean isInChildProcess = dirtyTargetInChildProcess((StartEvent) ((SubProcess) sequenceFlow.getSourceFlowElement()).getFlowElements().toArray()[0], null, targets, null); + if (isInChildProcess) { + // 已在子流程上找到,该路线结束 + continue; + } + } + // 继续迭代 + dirtyRoads = iteratorFindDirtyRoads(sequenceFlow.getSourceFlowElement(), passRoads, hasSequenceFlow, targets, dirtyRoads); + } + } + return dirtyRoads; + } + + /** + * 迭代获取子流程脏路线 + * 说明,假如回退的点就是子流程,那么也肯定会回退到子流程最初的用户任务节点,因此子流程中的节点全是脏路线 + * @param source 起始节点 + * @param hasSequenceFlow 已经经过的连线的 ID,用于判断线路是否重复 + * @param dirtyRoads 确定为脏数据的点,因为不需要重复,因此使用 set 存储 + * @return + */ + public static Set findChildProcessAllDirtyRoad(FlowElement source, Set hasSequenceFlow, Set dirtyRoads) { + hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow; + dirtyRoads = dirtyRoads == null ? new HashSet<>() : dirtyRoads; + + // 根据类型,获取出口连线 + List sequenceFlows = getElementOutgoingFlows(source); + + if (sequenceFlows != null) { + // 循环找到目标元素 + for (SequenceFlow sequenceFlow: sequenceFlows) { + // 如果发现连线重复,说明循环了,跳过这个循环 + if (hasSequenceFlow.contains(sequenceFlow.getId())) { + continue; + } + // 添加已经走过的连线 + hasSequenceFlow.add(sequenceFlow.getId()); + // 添加脏路线 + dirtyRoads.add(sequenceFlow.getTargetFlowElement().getId()); + // 如果节点为子流程节点情况,则从节点中的第一个节点开始获取 + if (sequenceFlow.getTargetFlowElement() instanceof SubProcess) { + dirtyRoads = findChildProcessAllDirtyRoad((FlowElement) (((SubProcess) sequenceFlow.getTargetFlowElement()).getFlowElements().toArray()[0]), hasSequenceFlow, dirtyRoads); + } + // 继续迭代 + dirtyRoads = findChildProcessAllDirtyRoad(sequenceFlow.getTargetFlowElement(), hasSequenceFlow, dirtyRoads); + } + } + return dirtyRoads; + } + + /** + * 判断脏路线结束节点是否在子流程上 + * @param source 起始节点 + * @param hasSequenceFlow 已经经过的连线的 ID,用于判断线路是否重复 + * @param targets 判断脏路线节点是否存在子流程上,只要存在一个,说明脏路线只到子流程为止 + * @param inChildProcess 是否存在子流程上,true 是,false 否 + * @return + */ + public static Boolean dirtyTargetInChildProcess(FlowElement source, Set hasSequenceFlow, List targets, Boolean inChildProcess) { + hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow; + inChildProcess = inChildProcess == null ? false : inChildProcess; + + // 根据类型,获取出口连线 + List sequenceFlows = getElementOutgoingFlows(source); + + if (sequenceFlows != null && !inChildProcess) { + // 循环找到目标元素 + for (SequenceFlow sequenceFlow: sequenceFlows) { + // 如果发现连线重复,说明循环了,跳过这个循环 + if (hasSequenceFlow.contains(sequenceFlow.getId())) { + continue; + } + // 添加已经走过的连线 + hasSequenceFlow.add(sequenceFlow.getId()); + // 如果发现目标点在子流程上存在,说明只到子流程为止 + if (targets.contains(sequenceFlow.getTargetFlowElement().getId())) { + inChildProcess = true; + break; + } + // 如果节点为子流程节点情况,则从节点中的第一个节点开始获取 + if (sequenceFlow.getTargetFlowElement() instanceof SubProcess) { + inChildProcess = dirtyTargetInChildProcess((FlowElement) (((SubProcess) sequenceFlow.getTargetFlowElement()).getFlowElements().toArray()[0]), hasSequenceFlow, targets, inChildProcess); + } + // 继续迭代 + inChildProcess = dirtyTargetInChildProcess(sequenceFlow.getTargetFlowElement(), hasSequenceFlow, targets, inChildProcess); + } + } + return inChildProcess; + } + + /** + * 迭代从后向前扫描,判断目标节点相对于当前节点是否是串行 + * 不存在直接回退到子流程中的情况,但存在从子流程出去到父流程情况 + * @param source 起始节点 + * @param isSequential 是否串行 + * @param hasSequenceFlow 已经经过的连线的 ID,用于判断线路是否重复 + * @param targetKsy 目标节点 + * @return + */ + public static Boolean iteratorCheckSequentialReferTarget(FlowElement source, String targetKsy, Set hasSequenceFlow, Boolean isSequential) { + isSequential = isSequential == null ? true : isSequential; + hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow; + + // 如果该节点为开始节点,且存在上级子节点,则顺着上级子节点继续迭代 + if (source instanceof StartEvent && source.getSubProcess() != null) { + isSequential = iteratorCheckSequentialReferTarget(source.getSubProcess(), targetKsy, hasSequenceFlow, isSequential); + } + + // 根据类型,获取入口连线 + List sequenceFlows = getElementIncomingFlows(source); + + if (sequenceFlows != null) { + // 循环找到目标元素 + for (SequenceFlow sequenceFlow: sequenceFlows) { + // 如果发现连线重复,说明循环了,跳过这个循环 + if (hasSequenceFlow.contains(sequenceFlow.getId())) { + continue; + } + // 添加已经走过的连线 + hasSequenceFlow.add(sequenceFlow.getId()); + // 如果目标节点已被判断为并行,后面都不需要执行,直接返回 + if (isSequential == false) { + break; + } + // 这条线路存在目标节点,这条线路完成,进入下个线路 + if (targetKsy.equals(sequenceFlow.getSourceFlowElement().getId())) { + continue; + } + if (sequenceFlow.getSourceFlowElement() instanceof StartEvent) { + isSequential = false; + break; + } + // 否则就继续迭代 + isSequential = iteratorCheckSequentialReferTarget(sequenceFlow.getSourceFlowElement(), targetKsy, hasSequenceFlow, isSequential); + } + } + return isSequential; + } + + /** + * 从后向前寻路,获取到达节点的所有路线 + * 不存在直接回退到子流程,但是存在回退到父级流程的情况 + * @param source 起始节点 + * @param passRoads 已经经过的点集合 + * @param roads 路线 + * @return + */ + public static List> findRoad(FlowElement source, List passRoads, Set hasSequenceFlow, List> roads) { + passRoads = passRoads == null ? new ArrayList<>() : passRoads; + roads = roads == null ? new ArrayList<>() : roads; + hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow; + + // 如果该节点为开始节点,且存在上级子节点,则顺着上级子节点继续迭代 + if (source instanceof StartEvent && source.getSubProcess() != null) { + roads = findRoad(source.getSubProcess(), passRoads, hasSequenceFlow, roads); + } + + // 根据类型,获取入口连线 + List sequenceFlows = getElementIncomingFlows(source); + + if (sequenceFlows != null && sequenceFlows.size() != 0) { + for (SequenceFlow sequenceFlow: sequenceFlows) { + // 如果发现连线重复,说明循环了,跳过这个循环 + if (hasSequenceFlow.contains(sequenceFlow.getId())) { + continue; + } + // 添加已经走过的连线 + hasSequenceFlow.add(sequenceFlow.getId()); + // 添加经过路线 + if (sequenceFlow.getSourceFlowElement() instanceof UserTask) { + passRoads.add((UserTask) sequenceFlow.getSourceFlowElement()); + } + // 继续迭代 + roads = findRoad(sequenceFlow.getSourceFlowElement(), passRoads, hasSequenceFlow, roads); + } + } else { + // 添加路线 + roads.add(passRoads); + } + return roads; + } + + /** + * 历史节点数据清洗,清洗掉又回滚导致的脏数据 + * @param allElements 全部节点信息 + * @param historicTaskInstanceList 历史任务实例信息,数据采用开始时间升序 + * @return + */ + public static List historicTaskInstanceClean(Collection allElements, List historicTaskInstanceList) { + // 会签节点收集 + List multiTask = new ArrayList<>(); + allElements.forEach(flowElement -> { + if (flowElement instanceof UserTask) { + // 如果该节点的行为为会签行为,说明该节点为会签节点 + if (((UserTask) flowElement).getBehavior() instanceof ParallelMultiInstanceBehavior || ((UserTask) flowElement).getBehavior() instanceof SequentialMultiInstanceBehavior) { + multiTask.add(flowElement.getId()); + } + } + }); + // 循环放入栈,栈 LIFO:后进先出 + Stack stack = new Stack<>(); + historicTaskInstanceList.forEach(item -> stack.push(item)); + // 清洗后的历史任务实例 + List lastHistoricTaskInstanceList = new ArrayList<>(); + // 网关存在可能只走了部分分支情况,且还存在跳转废弃数据以及其他分支数据的干扰,因此需要对历史节点数据进行清洗 + // 临时用户任务 key + StringBuilder userTaskKey = null; + // 临时被删掉的任务 key,存在并行情况 + List deleteKeyList = new ArrayList<>(); + // 临时脏数据线路 + List> dirtyDataLineList = new ArrayList<>(); + // 由某个点跳到会签点,此时出现多个会签实例对应 1 个跳转情况,需要把这些连续脏数据都找到 + // 会签特殊处理下标 + int multiIndex = -1; + // 会签特殊处理 key + StringBuilder multiKey = null; + // 会签特殊处理操作标识 + boolean multiOpera = false; + while (!stack.empty()) { + // 从这里开始 userTaskKey 都还是上个栈的 key + // 是否是脏数据线路上的点 + final boolean[] isDirtyData = {false}; + for (Set oldDirtyDataLine : dirtyDataLineList) { + if (oldDirtyDataLine.contains(stack.peek().getTaskDefinitionKey())) { + isDirtyData[0] = true; + } + } + // 删除原因不为空,说明从这条数据开始回跳或者回退的 + // MI_END:会签完成后,其他未签到节点的删除原因,不在处理范围内 + if (stack.peek().getDeleteReason() != null && !stack.peek().getDeleteReason().equals("MI_END")) { + // 可以理解为脏线路起点 + String dirtyPoint = ""; + if (stack.peek().getDeleteReason().indexOf("Change activity to ") >= 0) { + dirtyPoint = stack.peek().getDeleteReason().replace("Change activity to ", ""); + } + // 会签回退删除原因有点不同 + if (stack.peek().getDeleteReason().indexOf("Change parent activity to ") >= 0) { + dirtyPoint = stack.peek().getDeleteReason().replace("Change parent activity to ", ""); + } + FlowElement dirtyTask = null; + // 获取变更节点的对应的入口处连线 + // 如果是网关并行回退情况,会变成两条脏数据路线,效果一样 + for (FlowElement flowElement : allElements) { + if (flowElement.getId().equals(stack.peek().getTaskDefinitionKey())) { + dirtyTask = flowElement; + } + } + // 获取脏数据线路 + Set dirtyDataLine = FlowableUtils.iteratorFindDirtyRoads(dirtyTask, null, null, Arrays.asList(dirtyPoint.split(",")), null); + // 自己本身也是脏线路上的点,加进去 + dirtyDataLine.add(stack.peek().getTaskDefinitionKey()); + log.info(stack.peek().getTaskDefinitionKey() + "点脏路线集合:" + dirtyDataLine); + // 是全新的需要添加的脏线路 + boolean isNewDirtyData = true; + for (int i = 0; i < dirtyDataLineList.size(); i++) { + // 如果发现他的上个节点在脏线路内,说明这个点可能是并行的节点,或者连续驳回 + // 这时,都以之前的脏线路节点为标准,只需合并脏线路即可,也就是路线补全 + if (dirtyDataLineList.get(i).contains(userTaskKey.toString())) { + isNewDirtyData = false; + dirtyDataLineList.get(i).addAll(dirtyDataLine); + } + } + // 已确定时全新的脏线路 + if (isNewDirtyData) { + // deleteKey 单一路线驳回到并行,这种同时生成多个新实例记录情况,这时 deleteKey 其实是由多个值组成 + // 按照逻辑,回退后立刻生成的实例记录就是回退的记录 + // 至于驳回所生成的 Key,直接从删除原因中获取,因为存在驳回到并行的情况 + deleteKeyList.add(dirtyPoint + ","); + dirtyDataLineList.add(dirtyDataLine); + } + // 添加后,现在这个点变成脏线路上的点了 + isDirtyData[0] = true; + } + // 如果不是脏线路上的点,说明是有效数据,添加历史实例 Key + if (!isDirtyData[0]) { + lastHistoricTaskInstanceList.add(stack.peek().getTaskDefinitionKey()); + } + // 校验脏线路是否结束 + for (int i = 0; i < deleteKeyList.size(); i ++) { + // 如果发现脏数据属于会签,记录下下标与对应 Key,以备后续比对,会签脏数据范畴开始 + if (multiKey == null && multiTask.contains(stack.peek().getTaskDefinitionKey()) + && deleteKeyList.get(i).contains(stack.peek().getTaskDefinitionKey())) { + multiIndex = i; + multiKey = new StringBuilder(stack.peek().getTaskDefinitionKey()); + } + // 会签脏数据处理,节点退回会签清空 + // 如果在会签脏数据范畴中发现 Key改变,说明会签脏数据在上个节点就结束了,可以把会签脏数据删掉 + if (multiKey != null && !multiKey.toString().equals(stack.peek().getTaskDefinitionKey())) { + deleteKeyList.set(multiIndex , deleteKeyList.get(multiIndex).replace(stack.peek().getTaskDefinitionKey() + ",", "")); + multiKey = null; + // 结束进行下校验删除 + multiOpera = true; + } + // 其他脏数据处理 + // 发现该路线最后一条脏数据,说明这条脏数据线路处理完了,删除脏数据信息 + // 脏数据产生的新实例中是否包含这条数据 + if (multiKey == null && deleteKeyList.get(i).contains(stack.peek().getTaskDefinitionKey())) { + // 删除匹配到的部分 + deleteKeyList.set(i , deleteKeyList.get(i).replace(stack.peek().getTaskDefinitionKey() + ",", "")); + } + // 如果每组中的元素都以匹配过,说明脏数据结束 + if ("".equals(deleteKeyList.get(i))) { + // 同时删除脏数据 + deleteKeyList.remove(i); + dirtyDataLineList.remove(i); + break; + } + } + // 会签数据处理需要在循环外处理,否则可能导致溢出 + // 会签的数据肯定是之前放进去的所以理论上不会溢出,但还是校验下 + if (multiOpera && deleteKeyList.size() > multiIndex && "".equals(deleteKeyList.get(multiIndex))) { + // 同时删除脏数据 + deleteKeyList.remove(multiIndex); + dirtyDataLineList.remove(multiIndex); + multiIndex = -1; + multiOpera = false; + } + // pop() 方法与 peek() 方法不同,在返回值的同时,会把值从栈中移除 + // 保存新的 userTaskKey 在下个循环中使用 + userTaskKey = new StringBuilder(stack.pop().getTaskDefinitionKey()); + } + log.info("清洗后的历史节点数据:" + lastHistoricTaskInstanceList); + return lastHistoricTaskInstanceList; + } + /** + * 流程完成时间处理 + * + * @param ms + * @return + */ + public static String getDate(long ms) { + + long day = ms / (24 * 60 * 60 * 1000); + long hour = (ms / (60 * 60 * 1000) - day * 24); + long minute = ((ms / (60 * 1000)) - day * 24 * 60 - hour * 60); + long second = (ms / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60); + + if (day > 0) { + return day + "天" + hour + "小时" + minute + "分钟"; + } + if (hour > 0) { + return hour + "小时" + minute + "分钟"; + } + if (minute > 0) { + return minute + "分钟"; + } + if (second > 0) { + return second + "秒"; + } else { + return 0 + "秒"; + } + } +}