
56 changed files with 8832 additions and 0 deletions
@ -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; |
|||
} |
|||
} |
@ -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); |
|||
} |
|||
} |
@ -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<Flowable> { |
|||
void insetFlowableTask(Map<String,Object> params); |
|||
FlowProcinst getFlowProcinstById(@Param("id") String id); |
|||
@Select("select * from act_hi_procinst where proc_inst_id_=#{id}") |
|||
Map<String, String> getProcessInstanceById(@Param("id") String procInsId); |
|||
} |
@ -0,0 +1,63 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
|||
<mapper namespace="com.yxt.anrui.flowable.biz.flow.FlowableMapper"> |
|||
<insert id="insetFlowableTask" parameterType="com.yxt.anrui.flowable.api.flow.Flowable"> |
|||
insert into `act_ru_task` ( `days`, `zd`,initiator,outcome) |
|||
VALUES |
|||
( |
|||
#{days,jdbcType=VARCHAR}, |
|||
#{zd,jdbcType=VARCHAR} |
|||
#{initiator,jdbcType=VARCHAR} |
|||
#{outcome,jdbcType=VARCHAR} |
|||
) |
|||
</insert> |
|||
|
|||
<select id="getFlowProcinstById" resultType="com.yxt.anrui.flowable.api.flow.FlowProcinst"> |
|||
select * from act_hi_procinst where ID_=#{id} |
|||
</select> |
|||
<!-- |
|||
<insert id="insetFlowableTask"> |
|||
insert into `act_ru_task` (`REV`, `EXECUTION_ID`, `PROC_INST_ID`, `PROC_DEF_ID`, |
|||
`TASK_DEF_ID`, `SCOPE_ID`, `SUB_SCOPE_ID`, `SCOPE_TYPE`, `SCOPE_DEFINITION_ID`, |
|||
`PROPAGATED_STAGE_INST_ID`, `NAME`, `PARENT_TASK_ID`, `DESCRIPTION`, |
|||
`TASK_DEF_KEY`, `OWNER`, `ASSIGNEE`, `DELEGATION`, `PRIORITY`, |
|||
`CREATE_TIME`, `DUE_DATE`, `CATEGORY`, `SUSPENSION_STATE`, `TENANT_ID`, |
|||
`FORM_KEY`, `CLAIM_TIME`, `IS_COUNT_ENABLED`, `VAR_COUNT`, `ID_LINK_COUNT`, |
|||
`SUB_TASK_COUNT`, `days`, `reason`) |
|||
VALUES |
|||
( |
|||
#{item.modelSid,jdbcType=VARCHAR},<!–sid–> |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR}, |
|||
#{item.modelSid,jdbcType=VARCHAR} |
|||
) |
|||
</insert> |
|||
--> |
|||
</mapper> |
@ -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 <br/> |
|||
* File: FlowableRest.java <br/> |
|||
* Class: com.yxt.anrui.portal.biz.flow.FlowableRest <br/> |
|||
* Description: <描述类的功能>. <br/> |
|||
* Copyright: Copyright (c) 2011 <br/> |
|||
* Company: https://gitee.com/liuzp315 <br/>
|
|||
* Makedate: 2021/10/23 上午11:13 <br/> |
|||
* |
|||
* @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<FlowTaskQuery> 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<UserAndOrgPath> getNextNodeUserSidsOfCreate(BusinessVariables bv) { |
|||
//根据业务参数取流程流转的环节 信息
|
|||
return flowtaskService.getNextNodeUserSidsOfCreate(bv) ; |
|||
} |
|||
|
|||
@Override |
|||
public ResultBean<UserAndOrgPath> getNextNodeUserSidsOfSubmit(BusinessVariables bv) { |
|||
ResultBean<UserAndOrgPath> rb = ResultBean.fireSuccess(); |
|||
String orgSidPath=bv.getOrgSidPath(); |
|||
String taskDefKey=bv.getTaskDefKey(); |
|||
//根据业务参数取流程流转的环节 信息
|
|||
List<Map<String, Object>> list = (List<Map<String, Object>>) |
|||
flowtaskService.getProcessCirculationNodesByMap(bv).getData(); |
|||
Map<String, Object> 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<list.size()){ |
|||
task_map=list.get(i+1); |
|||
endTask=false; |
|||
} |
|||
} |
|||
if(endTask){ |
|||
task_map.put("name","结束"); |
|||
return rb.setData(new UserAndOrgPath()); |
|||
}else{ |
|||
Object o = task_map.get("candidateGroups"); |
|||
return flowtaskService.getNextUserSids(rb, orgSidPath, o); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public ResultBean<UpdateFlowFieldVo> 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<String, Object>()); |
|||
Map<String, Object> 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<UserAndOrgPath> 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<String, String> map = (Map<String, String>) 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<UpdateFlowFieldVo> handleProsess(BusinessVariables dto) { |
|||
return handleProsess(dto,true); |
|||
} |
|||
|
|||
/** |
|||
* |
|||
* @param dto |
|||
* @param b 是否连续跳转环节 |
|||
* @return |
|||
*/ |
|||
public ResultBean<UpdateFlowFieldVo> handleProsess(BusinessVariables dto,boolean b) { |
|||
log.info("BusinessVariables:{}", JSONObject.toJSONString(dto)); |
|||
log.info("b:{}", b); |
|||
UpdateFlowFieldVo vo = new UpdateFlowFieldVo(); |
|||
ResultBean rb = ResultBean.fireFail(); |
|||
// Map<String, Object> 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<String, Object>()); |
|||
Map<String, Object> formVariables = dto.getFormVariables(); |
|||
formVariables.put("businessSid",dto.getBusinessSid()); |
|||
|
|||
String nextUserSid = dto.getNextNodeUserSids(); |
|||
if(StringUtils.isBlank(nextUserSid)){ |
|||
ResultBean<UserAndOrgPath> 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<String,Object> values =(Map<String,Object>) 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<String, Object> entry:formVariables.entrySet()){ |
|||
taskService.setVariable(taskId,entry.getKey(),entry.getValue()); |
|||
System.out.println(entry.getKey()+"--->"+entry.getValue()); |
|||
}*/ |
|||
taskService.complete(taskId, formVariables); |
|||
//根据流程实例的id取最新的待办环节,给环节设置上用户sid
|
|||
ResultBean<List<LatestTaskVo>> 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<String, Object> 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<FlowRecordVo> flowRecordVoResultBean = flowableService.flowRecord(dto.getInstanceId(), dto.getModelId());
|
|||
List<FlowElement> flowElements = processService.calApprovePath(dto.getModelId(), dto.getModelId(), |
|||
dto.getFormVariables()); |
|||
boolean contains=false; |
|||
for(int i=0;i<flowElements.size();i++){ |
|||
FlowElement flowElement = flowElements.get(i); |
|||
String id = flowElement.getId(); |
|||
if(taskDefKey.equals(id)&&i+1<flowElements.size()){ |
|||
FlowElement flowElement1 = flowElements.get(i + 1); |
|||
if(flowElement1 instanceof UserTask){ |
|||
UserTask userTask=(UserTask)flowElement1; |
|||
List<String> candidateGroups = userTask.getCandidateGroups(); |
|||
List<SysUserVo> sysUserVoLists=new ArrayList<>(); |
|||
//根据角色查询用户
|
|||
for(String roleSid:candidateGroups){ |
|||
UserQuery userQuery = new UserQuery(); |
|||
userQuery.setRoleSid(roleSid); |
|||
userQuery.setOrgSidPath(dto.getOrgSidPath()); |
|||
ResultBean<List<SysUserVo>> 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<UpdateFlowFieldVo> 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<String,Object>()); |
|||
} |
|||
fl.getValues().put("businessSid",fl.getBusinessSid()); |
|||
UpdateFlowFieldVo vo = new UpdateFlowFieldVo(); |
|||
ResultBean<FlowProcinst> flowProcinstById = flowableService.getFlowProcinstById(fl.getInstanceId()); |
|||
if(!StringUtils.isBlank(flowProcinstById.getData().getEND_TIME_())){ |
|||
return rb.setMsg("撤回失败,流程已办结或终止"); |
|||
} |
|||
ResultBean<List<LatestTaskVo>> 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<UpdateFlowFieldVo> 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<String,Object>()); |
|||
} |
|||
fl.getValues().put("businessSid",fl.getBusinessSid()); |
|||
|
|||
ResultBean<List<LatestTaskVo>> 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<String, Object> 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<UpdateFlowFieldVo> breakProcess(com.yxt.anrui.flowable.api.flowtask.FlowTaskVo fl) { |
|||
ResultBean<UpdateFlowFieldVo> rb = ResultBean.fireFail(); |
|||
if (StringUtils.isBlank(fl.getBusinessSid())) { |
|||
return rb.setMsg("businessSid 不能为空!"); |
|||
} |
|||
if( fl.getValues()==null){ |
|||
fl.setValues(new HashMap<String,Object>()); |
|||
} |
|||
fl.getValues().put("businessSid",fl.getBusinessSid()); |
|||
UpdateFlowFieldVo vo = new UpdateFlowFieldVo(); |
|||
ResultBean<UpdateFlowFieldVo> 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); |
|||
} |
|||
} |
@ -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<FlowableMapper, Flowable> { |
|||
@Autowired |
|||
private FlowDefinitionService flowDefinitionService; |
|||
@Autowired |
|||
private FlowTaskService flowTaskService; |
|||
@Autowired |
|||
private TaskService taskService; |
|||
|
|||
public ResultBean<FlowProcinst> getFlowProcinstById(String id) { |
|||
ResultBean<FlowProcinst> 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<String, Object>()); |
|||
bv.getFormVariables().put("businessSid",bv.getBusinessSid()); |
|||
ResultBean<FlowTask> rb = flowDefinitionService.businessStart(bv); |
|||
if (!rb.getSuccess()) { |
|||
return rb; |
|||
} |
|||
String procId = rb.getData().getProcInsId(); |
|||
List<LatestTaskVo> list = flowTaskService.getLatestTasks(procId); |
|||
String nodeState = list.get(0).getName_(); |
|||
String task_def_key_ = list.get(0).getTask_def_key_(); |
|||
Map<String, String> 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<FlowTaskQuery> taskQueryPagerQuery) { |
|||
PagerQuery<BusinessTaskQuery> 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<TaskQuery> pQuery) { |
|||
TaskQuery params = pQuery.getParams(); |
|||
if (StringUtils.isBlank(userSid)) { |
|||
return ResultBean.fireFail().setMsg("用户SID为空"); |
|||
} |
|||
PagerQuery<BusinessTaskQuery> 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<BusinessTaskParam> 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<TaskQuery> pQuery) { |
|||
TaskQuery params = pQuery.getParams(); |
|||
if (StringUtils.isBlank(userSid)) { |
|||
return ResultBean.fireFail().setMsg("用户SID为空"); |
|||
} |
|||
PagerQuery<BusinessTaskQuery> 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<BusinessTaskParam> 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<String, Object> variables) { |
|||
BusinessVariables bv = BusinessVariables.builder().build(); |
|||
bv.setFormVariables(variables); |
|||
ResultBean<FlowTask> resultBean = flowTaskService.businessComplete(bv); |
|||
if (!resultBean.getSuccess()) { |
|||
return resultBean; |
|||
} |
|||
String nodeState = ""; |
|||
if (resultBean.getData() != null) { |
|||
ResultBean<List<LatestTaskVo>> 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<String, String> 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<List<LatestTaskVo>> resultBean = flowTaskService.revokeProcess(fl); |
|||
if (!resultBean.getSuccess()) { |
|||
return resultBean; |
|||
} |
|||
String nodeState = resultBean.getData().get(0).getName_(); |
|||
Map<String, String> 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<List<LatestTaskVo>> resultBean = flowTaskService.taskReject(fl); |
|||
if (!resultBean.getSuccess()) { |
|||
return resultBean; |
|||
} |
|||
String nodeState = resultBean.getData().get(0).getName_(); |
|||
Map<String, String> map = new HashMap<>(); |
|||
map.put("nodeState", nodeState); |
|||
return new ResultBean().success().setData(map); |
|||
} |
|||
|
|||
/** |
|||
* 终止流程 |
|||
* |
|||
* @param flowTaskVo |
|||
* @return |
|||
*/ |
|||
public ResultBean<UpdateFlowFieldVo> 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<UpdateFlowFieldVo> 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<String, String> getProcessInstanceById(String procInsId) { |
|||
return baseMapper.getProcessInstanceById(procInsId); |
|||
} |
|||
} |
@ -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<SysUserVo>> list = sysUserFeign.list(); |
|||
return list; |
|||
} |
|||
|
|||
@Override |
|||
public ResultBean roleList() { |
|||
ResultBean<List<SysRoleVo>> list = sysRoleFeign.list(); |
|||
return list; |
|||
} |
|||
|
|||
@Override |
|||
public ResultBean start(@ApiParam(value = "流程定义id") @PathVariable(value = "procDefId") String procDefId, |
|||
@ApiParam(value = "变量集合,json对象") @RequestBody Map<String, Object> variables) { |
|||
return flowDefinitionService.startProcessInstanceById(procDefId, variables); |
|||
} |
|||
|
|||
/* @Override |
|||
public ResultBean<FlowTask> businessStart(@ApiParam(value = "变量集合") @RequestBody BusinessVariables dto) { |
|||
return flowDefinitionService.businessStart(dto); |
|||
}*/ |
|||
} |
@ -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<FlowDefinitionVo> list(Integer pageNum, Integer pageSize) { |
|||
Page<FlowDefinitionVo> page = new Page<>(); |
|||
// 流程定义列表数据查询
|
|||
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery() |
|||
.orderByProcessDefinitionKey().asc(); |
|||
page.setTotal(processDefinitionQuery.count()); |
|||
List<ProcessDefinition> processDefinitionList = processDefinitionQuery.listPage((pageNum - 1) * pageSize, pageSize); |
|||
|
|||
List<FlowDefinitionVo> 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<String, Object> 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<FlowTask> businessStartProcessInstanceById(String procDefId, String userSid, String nextNodeUserSids, Map<String, Object> 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<SysUserVo> 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<String, Object> 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<List<LatestTaskVo>> latestTasksNew = flowTaskService.getLatestTasksNew(processInstance.getId()); |
|||
List<LatestTaskVo> data = latestTasksNew.getData(); |
|||
LatestTaskVo latestTaskVo = data.get(0); |
|||
String id_ = latestTaskVo.getId_(); |
|||
taskService.setAssignee(id_,nextNodeUserSids); |
|||
ResultBean<FlowTask> 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<FlowTask> businessStart(BusinessVariables dto) { |
|||
ResultBean<FlowTask> resultBean = new ResultBean<>(); |
|||
Map<String, Object> 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<FlowDefinitionVo> pageList = list(pageNum, pageSize); |
|||
return ResultBean.fireSuccess().setData(pageList); |
|||
} |
|||
|
|||
} |
@ -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<FlowInstanceVo> startProcess(FlowInstanceDto flowTaskDto) { |
|||
FlowInstanceVo flowTaskVo = new FlowInstanceVo(); |
|||
ResultBean<FlowInstanceVo> 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(); |
|||
} |
|||
|
|||
|
|||
} |
@ -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; |
|||
} |
|||
} |
@ -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; |
|||
|
|||
|
|||
/** |
|||
* <p>工作流任务管理<p> |
|||
* |
|||
* @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<String> startProcessInstanceByKey(StartProcessInstanceQuery startProcessInstanceQuery) { |
|||
return null; |
|||
} |
|||
|
|||
@Override |
|||
public ResultBean<FlowTask> businessComplete(@RequestBody BusinessVariables dto) { |
|||
return flowTaskService.businessComplete(dto); |
|||
} |
|||
|
|||
@Override |
|||
public ResultBean<String> complete(@RequestBody FlowTaskVo flowTaskVo) { |
|||
return flowTaskService.complete(flowTaskVo); |
|||
} |
|||
|
|||
@Override |
|||
public ResultBean todoList(PagerQuery<FlowTaskQuery> taskQueryPagerQuery) { |
|||
int size = Integer.valueOf(taskQueryPagerQuery.getSize() + ""); |
|||
int current = Integer.valueOf(taskQueryPagerQuery.getCurrent() + ""); |
|||
ResultBean<Page<FlowTaskDto>> resultBean = flowTaskService.todoList(current, size); |
|||
return resultBean; |
|||
} |
|||
|
|||
@Override |
|||
public ResultBean<Page<FlowTaskDto>> businessTodoList(String userSid, PagerQuery<BusinessTaskQuery> businessTaskQuery) { |
|||
int size = Integer.valueOf(businessTaskQuery.getSize() + ""); |
|||
int current = Integer.valueOf(businessTaskQuery.getCurrent() + ""); |
|||
List<BusinessTaskParam> fields = businessTaskQuery.getParams().getFields(); |
|||
/* AtomicReference<String> 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<Page<FlowTaskDto>> resultBean = flowTaskService.businessTodoList(userSid, orgPath, fields, current, size); |
|||
return resultBean; |
|||
} |
|||
|
|||
@Override |
|||
public ResultBean<Page<FlowTaskDto>> businessTodoListForApp(String userSid, PagerQuery<BusinessTaskQuery> businessTaskQuery) { |
|||
int size = Integer.valueOf(businessTaskQuery.getSize() + ""); |
|||
int current = Integer.valueOf(businessTaskQuery.getCurrent() + ""); |
|||
List<BusinessTaskParam> fields = businessTaskQuery.getParams().getFields(); |
|||
String companySid=""; |
|||
if(fields.size()>0){ |
|||
for(BusinessTaskParam b:fields){ |
|||
if(b.getField().equals(BusinessVariables.ORGPATH)){ |
|||
companySid=b.getValue(); |
|||
} |
|||
} |
|||
} |
|||
ResultBean<Page<FlowTaskDto>> resultBean = flowTaskService.businessTodoListForApp(userSid,companySid, fields, current, size); |
|||
return resultBean; |
|||
} |
|||
|
|||
@Override |
|||
public ResultBean<Integer> getTodoNum(String userSid) { |
|||
return flowTaskService.getTodoNum(userSid,null); |
|||
} |
|||
|
|||
@Override |
|||
public ResultBean<Integer> getTodoNum(UserAndOrgPath uaop) { |
|||
String userSid=uaop.getUserSid(); |
|||
String orgPath=uaop.getOrgPath(); |
|||
return flowTaskService.getTodoNum(userSid,orgPath); |
|||
} |
|||
|
|||
@Override |
|||
public ResultBean doneList(PagerQuery<FlowTaskQuery> 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<BusinessTaskQuery> taskQueryPagerQuery) { |
|||
return flowTaskService.businessDoneListNew(userSid, taskQueryPagerQuery); |
|||
} |
|||
@Override |
|||
public ResultBean<Page<FlowTaskDto>> businessDoneListForApp(String userSid, PagerQuery<BusinessTaskQuery> 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<FlowTaskQuery> 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<FlowTaskDto> page = new Page<>(); |
|||
// Long userId =5001L;// SecurityUtils.getLoginUser().getUser().getUserId();
|
|||
HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery() |
|||
.startedBy(userSid) |
|||
.orderByProcessInstanceStartTime() |
|||
.desc(); |
|||
List<HistoricProcessInstance> historicProcessInstances = query |
|||
.listPage(currentPage, 10); |
|||
page.setTotal(query.count()); |
|||
List<FlowTaskDto> 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<Task> taskList = taskService.createTaskQuery().processInstanceId(hisIns.getId()).list(); |
|||
if (CollectionUtils.isNotEmpty(taskList)) { |
|||
flowTask.setTaskId(taskList.get(0).getId()); |
|||
} else { |
|||
List<HistoricTaskInstance> 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> 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<List<LatestTaskVo>> taskReject(FlowTaskVo flowTaskVo) { |
|||
return flowTaskService.taskReject(flowTaskVo); |
|||
} |
|||
|
|||
@Override |
|||
public ResultBean<List<LatestTaskVo>> 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<FlowRecordVo> 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<List<LatestTaskVo>> getLatestTasks(String procId) { |
|||
return flowTaskService.getLatestTasksNew(procId); |
|||
} |
|||
|
|||
@Override |
|||
public ResultBean<List<FlowElement>> getProcessCirculationNodes(String procId, |
|||
String modelId, |
|||
String k, |
|||
String v, String outcome) { |
|||
Map<String, Object> map = new HashMap<>(); |
|||
map.put(k, v); |
|||
map.put("outcome", outcome); |
|||
List<FlowElement> flowElements = processService.calApprovePath(procId, modelId, map); |
|||
List<FlowElement> 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<List<FlowElement>> rb = new ResultBean<List<FlowElement>>(); |
|||
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); |
|||
} |
|||
} |
@ -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<FlowTask> { |
|||
|
|||
IPage<TaskVo> getApplyedTasksPagerModel(IPage<TaskVo> page, @Param("params") TaskQueryParamsVo params); |
|||
|
|||
/*取消*/ |
|||
List<Map<String,Object>> finishedList(@Param("userSid")String userSid, |
|||
@Param("list")List<Map<String,Object>> list, @Param("page")int page, @Param("size")int size); |
|||
|
|||
List<Map<String,Object>> finishedList1(Map<String, Object> map); |
|||
|
|||
int finishedListCount(Map<String, Object> map); |
|||
|
|||
/** |
|||
* 根据流程实例的id查询最新的待办环节 |
|||
* @param procId |
|||
* @return |
|||
*/ |
|||
List<LatestTaskVo> getLatestTasks(@Param("procId")String procId); |
|||
|
|||
Map<String,Object> getHistTaskByID(@Param("procId")String procId,@Param("taskId")String id); |
|||
|
|||
Map<String, Object> getTaskByDefKey(@Param("procId")String processInstanceId, @Param("taskId")String id); |
|||
Map<String, Object> getActHiVarinstForOrgPath(@Param("taskId")String taskId); |
|||
} |
@ -0,0 +1,236 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<!DOCTYPE mapper |
|||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" |
|||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
|||
<mapper namespace="com.yxt.anrui.flowable.biz.flowtask.FlowTaskMapper"> |
|||
<resultMap id="TaskVoMap" type="com.yxt.anrui.flowable.api.flowtask.TaskVo"> |
|||
<id column="ID_" property="taskId" jdbcType="VARCHAR"/> |
|||
<result column="NAME_" property="name" jdbcType="VARCHAR"/> |
|||
<result column="ASSIGNEE_" property="assignee" jdbcType="VARCHAR"/> |
|||
<result column="PROC_INST_ID_" property="processInstanceId" jdbcType="VARCHAR"/> |
|||
<result column="PARENT_ID_" property="parentId" jdbcType="VARCHAR"/> |
|||
<result column="model_key" property="processDefinitionKey" jdbcType="VARCHAR"/> |
|||
<result column="BUSINESS_KEY_" property="businessKey" jdbcType="VARCHAR"/> |
|||
<result column="proc_inst_name" property="formName" jdbcType="VARCHAR"/> |
|||
<result column="CATEGORY_" property="taskType" jdbcType="VARCHAR"/> |
|||
<result column="END_TIME_" property="finishedTime" jdbcType="TIMESTAMP"/> |
|||
<result column="START_TIME_" property="startTime" jdbcType="TIMESTAMP"/> |
|||
<result column="CREATE_TIME_" property="createTime" jdbcType="TIMESTAMP"/> |
|||
<result column="TASK_END_TIME_" property="endTime" jdbcType="TIMESTAMP"/> |
|||
<result column="start_person" property="startPersonName" jdbcType="VARCHAR"/> |
|||
<result column="app_name" property="appName" jdbcType="VARCHAR"/> |
|||
<result column="form_type" property="formType" jdbcType="INTEGER"/> |
|||
<result column="PROC_DEF_ID_" property="processDefinitionId" jdbcType="VARCHAR"/> |
|||
<result column="start_person_code" property="startPersonCode" jdbcType="VARCHAR"/> |
|||
<result column="applied_range" property="processDefinitionType" jdbcType="INTEGER"/> |
|||
<result column="process_status" property="processStatus" jdbcType="VARCHAR"/> |
|||
<result column="form_name" property="formName" jdbcType="VARCHAR"/> |
|||
<result column="TASK_DEF_KEY_" property="taskDefKey" jdbcType="VARCHAR"/> |
|||
<result column="end_act_id_" property="endActId" jdbcType="VARCHAR"/> |
|||
<result column="end_time_" property="endTime" jdbcType="VARCHAR"/> |
|||
</resultMap> |
|||
<select id="getApplyedTasksPagerModel" resultMap="TaskVoMap"> |
|||
SELECT DISTINCT |
|||
t1.ID_, |
|||
t1.NAME_, |
|||
t1.START_TIME_ as CREATE_TIME_, |
|||
t1.ASSIGNEE_, |
|||
t1.DESCRIPTION_, |
|||
t1.TASK_DEF_KEY_, |
|||
t1.DURATION_, |
|||
t2.BUSINESS_KEY_, |
|||
t2.PROC_INST_ID_, |
|||
t2.PROC_DEF_ID_, |
|||
t2.NAME_ AS proc_inst_name, |
|||
t2.START_TIME_, |
|||
t2.END_TIME_ |
|||
|
|||
FROM act_hi_taskinst t1 |
|||
INNER JOIN act_hi_procinst t2 |
|||
ON t1.PROC_INST_ID_ = t2.PROC_INST_ID_ |
|||
INNER JOIN act_re_procdef t8 ON t2.PROC_DEF_ID_=t8.ID_ |
|||
LEFT JOIN act_hi_identitylink t6 |
|||
ON t6.TASK_ID_ = t1.ID_ |
|||
<where> |
|||
<if test="params.userCode!=null and params.userCode!=''"> |
|||
AND ( |
|||
t1.ASSIGNEE_ = #{params.userCode,jdbcType=VARCHAR} |
|||
OR ( |
|||
( |
|||
t1.ASSIGNEE_ IS NULL |
|||
OR t1.ASSIGNEE_ = '' |
|||
) |
|||
AND ( |
|||
t6.USER_ID_ = #{params.userCode,jdbcType=VARCHAR} |
|||
OR t6.GROUP_ID_ IN ( |
|||
SELECT |
|||
g.group_id_ |
|||
FROM |
|||
act_id_membership g |
|||
WHERE |
|||
g.user_id_ = #{params.userCode,jdbcType=VARCHAR}) |
|||
) |
|||
) |
|||
) |
|||
</if> |
|||
<if test="params.keyword!=null and params.keyword!=''"> |
|||
AND t2.NAME_ LIKE CONCAT('%',#{params.keyword},'%') |
|||
</if> |
|||
<if test="params.startTime!=null and params.startTime!=''"> |
|||
AND t2.START_TIME_ <![CDATA[ >= ]]> #{params.startTime} |
|||
</if> |
|||
<if test="params.endTime!=null and params.endTime!=''"> |
|||
AND t2.START_TIME_ <![CDATA[ <= ]]> #{params.endTime} |
|||
</if> |
|||
<if test="params.businessKey!=null and params.businessKey!=''"> |
|||
AND t2.BUSINESS_KEY_ LIKE CONCAT('%',#{params.businessKey},'%') |
|||
</if> |
|||
</where> |
|||
ORDER BY t1.START_TIME_ DESC |
|||
</select> |
|||
<select id="finishedList" resultType="java.util.Map"> |
|||
SELECT * FROM ( |
|||
SELECT DISTINCT |
|||
ahti.ID_, |
|||
ahti.NAME_, |
|||
ahti.ASSIGNEE_, |
|||
ahti.START_TIME_, |
|||
ahpi.END_ACT_ID_, |
|||
ahpi.END_TIME_, |
|||
ahpi.PROC_DEF_ID_, |
|||
ahpi.PROC_INST_ID_, |
|||
arpd.KEY_ AS PROC_DEF_KEY_, |
|||
arpd.NAME_ AS PROC_DEF_NAME_, |
|||
arpd.VERSION_ AS PROC_DEF_VERSION_, |
|||
arpd.DEPLOYMENT_ID_ AS DEPLOYMENT_ID_ |
|||
FROM ACT_HI_PROCINST ahpi |
|||
INNER JOIN (SELECT PROC_INST_ID_ from ACT_HI_TASKINST WHERE ASSIGNEE_=#{userSid} AND END_TIME_ IS NOT NULL) |
|||
temp ON ahpi.PROC_INST_ID_=temp.PROC_INST_ID_ |
|||
LEFT JOIN ACT_HI_TASKINST ahti on ahti.PROC_INST_ID_=temp.PROC_INST_ID_ |
|||
INNER JOIN `ACT_HI_VARINST` A0 ON ahpi.PROC_INST_ID_ = A0.PROC_INST_ID_ |
|||
LEFT JOIN ACT_RE_PROCDEF arpd ON ahpi.PROC_DEF_ID_ = arpd.ID_ |
|||
<where> |
|||
<foreach item="item" index="index" collection="list" separator=","> |
|||
<if test="item.symbol != null and item.symbol != ''"> |
|||
AND a0.name_= #{item.filed} AND a0.text_ = #{item.value} |
|||
</if> |
|||
</foreach> |
|||
</where> |
|||
ORDER BY ahti.START_TIME_ DESC |
|||
) flow |
|||
GROUP BY flow.PROC_INST_ID_ |
|||
LIMIT #{page},#{size} |
|||
</select> |
|||
<select id="finishedList1" parameterType="java.util.Map" resultType="java.util.Map"> |
|||
SELECT * FROM ( |
|||
SELECT DISTINCT |
|||
ahti.ID_, |
|||
ahti.NAME_, |
|||
ahti.ASSIGNEE_, |
|||
ahti.START_TIME_, |
|||
ahti.TASK_DEF_KEY_ taskDefKey, |
|||
ahpi.START_USER_ID_, |
|||
ahpi.END_ACT_ID_, |
|||
ahpi.END_TIME_, |
|||
ahpi.PROC_DEF_ID_, |
|||
ahpi.PROC_INST_ID_, |
|||
ahpi.START_TIME_ processCreateTime, |
|||
arpd.KEY_ AS PROC_DEF_KEY_, |
|||
arpd.NAME_ AS PROC_DEF_NAME_, |
|||
arpd.VERSION_ AS PROC_DEF_VERSION_, |
|||
arpd.DEPLOYMENT_ID_ AS DEPLOYMENT_ID_ |
|||
/*sfl.taskDefKey AS taskDefKey,*/ |
|||
/*sfl.nodeState NAME_*/ |
|||
FROM ACT_HI_PROCINST ahpi |
|||
INNER JOIN (SELECT PROC_INST_ID_ from ACT_HI_TASKINST WHERE ASSIGNEE_=#{userSid} AND END_TIME_ IS NOT NULL) |
|||
temp ON ahpi.PROC_INST_ID_=temp.PROC_INST_ID_ |
|||
/*LEFT JOIN ACT_HI_TASKINST ahti on ahti.PROC_INST_ID_=temp.PROC_INST_ID_*/ |
|||
LEFT JOIN (SELECT * FROM (SELECT DISTINCT(ID_) ID_,NAME_,ASSIGNEE_,START_TIME_,TASK_DEF_KEY_,PROC_INST_ID_ FROM ACT_HI_TASKINST ORDER BY START_TIME_ DESC) t1 GROUP BY t1.PROC_INST_ID_) ahti ON ahti.PROC_INST_ID_ = temp.PROC_INST_ID_ |
|||
INNER JOIN `ACT_HI_VARINST` A0 ON ahpi.PROC_INST_ID_ = A0.PROC_INST_ID_ |
|||
LEFT JOIN ACT_RE_PROCDEF arpd ON ahpi.PROC_DEF_ID_ = arpd.ID_ |
|||
LEFT JOIN sys_form_link sfl ON ahpi.PROC_INST_ID_ = sfl.procInsId |
|||
<where> |
|||
<if test="proDefName != null and proDefName != ''"> |
|||
AND arpd.NAME_ LIKE concat('%',#{proDefName},'%') |
|||
</if> |
|||
<if test="startDate != null and startDate != ''"> |
|||
AND ahpi.START_TIME_ <![CDATA[ >= ]]> #{startDate} |
|||
</if> |
|||
<if test="endDate != null and endDate != ''"> |
|||
AND ahpi.START_TIME_ <![CDATA[ <= ]]> #{endDate} |
|||
</if> |
|||
</where> |
|||
) flow |
|||
GROUP BY flow.PROC_INST_ID_ |
|||
ORDER BY flow.START_TIME_ DESC |
|||
LIMIT #{page},#{size} |
|||
</select> |
|||
<select id="finishedListCount" parameterType="java.util.Map" resultType="int"> |
|||
SELECT COUNT(DISTINCT ahpi.PROC_INST_ID_) |
|||
FROM ACT_HI_PROCINST ahpi |
|||
INNER JOIN ( SELECT PROC_INST_ID_ FROM ACT_HI_TASKINST WHERE ASSIGNEE_ =#{userSid} AND END_TIME_ IS NOT NULL ) temp ON ahpi.PROC_INST_ID_ = temp.PROC_INST_ID_ |
|||
LEFT JOIN ACT_HI_TASKINST ahti ON ahti.PROC_INST_ID_ = temp.PROC_INST_ID_ |
|||
INNER JOIN `ACT_HI_VARINST` A0 ON ahpi.PROC_INST_ID_ = A0.PROC_INST_ID_ |
|||
LEFT JOIN ACT_RE_PROCDEF arpd ON ahpi.PROC_DEF_ID_ = arpd.ID_ |
|||
<where> |
|||
<if test="proDefName != null and proDefName != ''"> |
|||
AND arpd.NAME_ LIKE concat('%',#{proDefName},'%') |
|||
</if> |
|||
<if test="startDate != null and startDate != ''"> |
|||
AND ahpi.START_TIME_ <![CDATA[ >= ]]> #{startDate} |
|||
</if> |
|||
<if test="endDate != null and endDate != ''"> |
|||
AND ahpi.START_TIME_ <![CDATA[ <= ]]> #{endDate} |
|||
</if> |
|||
</where> |
|||
</select> |
|||
|
|||
|
|||
<select id="getLatestTasks" resultType="com.yxt.anrui.flowable.api.flowtask.LatestTaskVo"> |
|||
SELECT |
|||
task.name_ , |
|||
task.task_def_key_ , |
|||
task.id_, |
|||
task.ASSIGNEE_, |
|||
a.TEXT_ orgpath |
|||
FROM |
|||
act_ru_task task |
|||
LEFT JOIN `act_ru_variable` a ON task.id_= a.task_id_ AND a.name_='orgPath' |
|||
WHERE |
|||
task.proc_inst_id_= #{procId} |
|||
</select> |
|||
|
|||
<select id="getHistTaskByID" resultType="java.util.Map"> |
|||
SELECT |
|||
task.name_ , |
|||
task.task_def_key_ , |
|||
task.id_, |
|||
task.ASSIGNEE_ |
|||
FROM |
|||
act_hi_taskinst task |
|||
WHERE |
|||
task.task_def_key_= #{taskId} and task.PROC_INST_ID_= #{procId} order by task.id_ desc limit 1,1 |
|||
</select> |
|||
|
|||
<select id="getTaskByDefKey" resultType="java.util.Map"> |
|||
SELECT |
|||
task.name_ , |
|||
task.task_def_key_ , |
|||
task.id_, |
|||
task.ASSIGNEE_, |
|||
arv.text_ orgPath |
|||
FROM |
|||
act_ru_task task |
|||
left join act_ru_variable arv on task.id_=arv.task_id_ and arv.name_="orgPath" |
|||
WHERE |
|||
task.task_def_key_= #{taskId} and task.PROC_INST_ID_= #{procId} order by task.id_ desc limit 0,1 |
|||
</select> |
|||
<select id="getActHiVarinstForOrgPath" resultType="java.util.Map"> |
|||
SELECT |
|||
ahv.* |
|||
FROM |
|||
act_hi_varinst ahv |
|||
WHERE |
|||
ahv.task_id_= #{taskId} and ahv.name_="orgPath" order by ahv.id_ desc limit 0,1 |
|||
</select> |
|||
</mapper> |
File diff suppressed because it is too large
@ -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<Boolean>, Serializable { |
|||
protected RuntimeService runtimeService; |
|||
|
|||
protected ProcessEngineConfigurationImpl processEngineConfiguration; |
|||
|
|||
protected String processInstanceId; |
|||
|
|||
protected String exp; |
|||
|
|||
protected Map<String, Object> variableMap; |
|||
|
|||
public ExpressionCmd(RuntimeService runtimeService, ProcessEngineConfigurationImpl processEngineConfiguration, String processInstanceId, String exp, Map<String, Object> 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()); |
|||
} |
|||
} |
@ -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<FlowElement> calApprovePath(String processInstanceId, String modelId, Map<String, Object> 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<FlowElement> flowElements =new ArrayList<>(); |
|||
Collection<FlowElement> flowElements2 = bpmnModel.getMainProcess().getFlowElements(); |
|||
flowElements.addAll(flowElements2); |
|||
List<FlowElement> passElements = new ArrayList<>(); |
|||
dueStartElement(passElements, flowElements, variableMap); |
|||
return passElements; |
|||
} |
|||
|
|||
/** |
|||
* 2. 找到开始节点,通过它的目标节点,然后再不断往下找。 |
|||
*/ |
|||
private void dueStartElement(List<FlowElement> passElements, Collection<FlowElement> flowElements, Map<String, Object> variableMap){ |
|||
Optional<FlowElement> startElementOpt = flowElements.stream().filter(flowElement -> flowElement instanceof StartEvent).findFirst(); |
|||
startElementOpt.ifPresent(startElement -> { |
|||
flowElements.remove(startElement); |
|||
List<SequenceFlow> 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<FlowElement> passElements, Collection<FlowElement> flowElements, FlowElement curFlowElement, Map<String, Object> 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<FlowElement> passElements, Collection<FlowElement> flowElements, |
|||
FlowElement curFlowElement, Map<String, Object> variableMap){ |
|||
passElements.add(curFlowElement); |
|||
List<SequenceFlow> 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<FlowElement> passElements, Collection<FlowElement> flowElements, FlowElement curFlowElement, Map<String, Object> variableMap){ |
|||
// 获取符合条件的sequenceFlow的目标FlowElement
|
|||
List<SequenceFlow> 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<FlowElement> passElements, Collection<FlowElement> flowElements, FlowElement curFlowElement, Map<String, Object> variableMap){ |
|||
FlowElement targetElement; |
|||
List<SequenceFlow> parallelGatewayOutgoingFlows = ((ParallelGateway) curFlowElement).getOutgoingFlows(); |
|||
for(SequenceFlow sequenceFlow : parallelGatewayOutgoingFlows){ |
|||
targetElement = getFlowElement(flowElements, sequenceFlow.getTargetRef()); |
|||
this.getPassElementList(passElements, flowElements, targetElement, variableMap); |
|||
} |
|||
} |
|||
|
|||
private FlowElement getFlowElement(Collection<FlowElement> 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<String, Object> variableMap, List<SequenceFlow> outgoingFlows) { |
|||
Optional<SequenceFlow> 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<String, Object> variableMap){ |
|||
return managementService.executeCommand(new ExpressionCmd(runtimeService, processEngineConfiguration, null, exp, variableMap)); |
|||
} |
|||
|
|||
public Map<String, String> getProcessInstanceById(String procInsId) { |
|||
return flowableService.getProcessInstanceById(procInsId); |
|||
} |
|||
} |
@ -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(流程评论) <br/> |
|||
* File: ProcessCommentMapper.java <br/> |
|||
* Class: com.yxt.anrui.flowable.api.processcomment.biz.processcomment.ProcessCommentMapper <br/> |
|||
* Description: process_comment. <br/> |
|||
* Copyright: Copyright (c) 2011 <br/> |
|||
* Company: https://gitee.com/liuzp315 <br/>
|
|||
* Makedate: 2023-01-30 14:40:37 <br/> |
|||
* |
|||
* @author liupopo |
|||
* @version 1.0 |
|||
* @since 1.0 |
|||
*/ |
|||
@Mapper |
|||
public interface ProcessCommentMapper extends BaseMapper<ProcessComment> { |
|||
|
|||
//@Update("update process_comment set name=#{msg} where id=#{id}")
|
|||
//IPage<ProcessCommentVo> voPage(IPage<ProcessComment> page, @Param(Constants.WRAPPER) QueryWrapper<ProcessComment> qw);
|
|||
|
|||
IPage<ProcessCommentVo> selectPageVo(IPage<ProcessComment> page, @Param(Constants.WRAPPER) Wrapper<ProcessComment> qw); |
|||
|
|||
List<ProcessCommentVo> selectListAllVo(@Param(Constants.WRAPPER) Wrapper<ProcessComment> qw); |
|||
|
|||
@Select("select * from process_comment") |
|||
List<ProcessCommentVo> selectListVo(); |
|||
|
|||
List<ProcessCommentVo> getCommentList(@Param("processId")String processId); |
|||
@Select("select * from process_comment where sid=#{sid}") |
|||
ProcessComment fetchBySid(@Param("sid")String sid); |
|||
|
|||
void insertByDto(ProcessCommentDto dto); |
|||
} |
@ -0,0 +1,20 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
|||
<mapper namespace="com.yxt.anrui.flowable.biz.processcomment.ProcessCommentMapper"> |
|||
<!-- <where> ${ew.sqlSegment} </where>--> |
|||
<!-- ${ew.customSqlSegment} --> |
|||
<select id="selectPageVo" resultType="com.yxt.anrui.flowable.api.processcomment.ProcessCommentVo"> |
|||
SELECT * FROM process_comment <where> ${ew.sqlSegment} </where> |
|||
</select> |
|||
|
|||
<select id="selectListAllVo" resultType="com.yxt.anrui.flowable.api.processcomment.ProcessCommentVo"> |
|||
SELECT * FROM process_comment <where> ${ew.sqlSegment} </where> |
|||
</select> |
|||
<select id="getCommentList" resultType="com.yxt.anrui.flowable.api.processcomment.ProcessCommentVo"> |
|||
select * from process_comment where processId=#{processId} |
|||
</select> |
|||
<insert id="insertByDto" parameterType="com.yxt.anrui.flowable.api.processcomment.ProcessCommentDto"> |
|||
insert into `process_comment` ( `sid`, `reviewer`, `reviewerSid`, `time`, `content`, `processId`, `processInstSid`) |
|||
values(#{sid},#{reviewer},#{reviewerSid},#{time},#{content},#{processId},#{processInstSid}); |
|||
</insert> |
|||
</mapper> |
@ -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(流程评论) <br/> |
|||
* File: ProcessCommentFeignFallback.java <br/> |
|||
* Class: com.yxt.anrui.flowable.api.processcomment.biz.processcomment.ProcessCommentRest <br/> |
|||
* Description: process_comment. <br/> |
|||
* Copyright: Copyright (c) 2011 <br/> |
|||
* Company: https://gitee.com/liuzp315 <br/>
|
|||
* Makedate: 2023-01-30 14:40:37 <br/> |
|||
* |
|||
* @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<PagerVo<ProcessCommentVo>> listPage(@RequestBody PagerQuery<ProcessCommentQuery> pq){ |
|||
ResultBean rb = ResultBean.fireFail(); |
|||
PagerVo<ProcessCommentVo> 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<ProcessCommentDetailsVo> fetchDetailsBySid(@PathVariable("sid") String sid){ |
|||
ResultBean rb = ResultBean.fireFail(); |
|||
ProcessCommentDetailsVo vo = processCommentService.fetchDetailsVoBySid(sid); |
|||
return rb.success().setData(vo); |
|||
} |
|||
|
|||
@Override |
|||
public ResultBean<List<ProcessCommentVo>> getCommentList(String processId) { |
|||
ResultBean rb = ResultBean.fireFail(); |
|||
List<ProcessCommentVo> vo = processCommentService.getCommentList(processId); |
|||
return rb.success().setData(vo); |
|||
} |
|||
} |
@ -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(流程评论) <br/> |
|||
* File: ProcessCommentService.java <br/> |
|||
* Class: com.yxt.anrui.flowable.api.processcomment.biz.processcomment.ProcessCommentService <br/> |
|||
* Description: process_comment 业务逻辑. <br/> |
|||
* Copyright: Copyright (c) 2011 <br/> |
|||
* Company: https://gitee.com/liuzp315 <br/>
|
|||
* Makedate: 2023-01-30 14:40:37 <br/> |
|||
* |
|||
* @author liupopo |
|||
* @version 1.0 |
|||
* @since 1.0 |
|||
*/ |
|||
@Service |
|||
public class ProcessCommentService extends MybatisBaseService<ProcessCommentMapper, ProcessComment> { |
|||
@Resource |
|||
private SysUserFeign sysUserFeign; |
|||
@Resource |
|||
private FileUploadComponent fileUploadComponent; |
|||
private QueryWrapper<ProcessComment> createQueryWrapper(ProcessCommentQuery query) { |
|||
// todo: 这里根据具体业务调整查询条件
|
|||
// 多字段Like示例:qw.and(wrapper -> wrapper.like("name", query.getName()).or().like("remark", query.getName()));
|
|||
QueryWrapper<ProcessComment> qw = new QueryWrapper<>(); |
|||
return qw; |
|||
} |
|||
|
|||
public PagerVo<ProcessCommentVo> listPageVo(PagerQuery<ProcessCommentQuery> pq) { |
|||
ProcessCommentQuery query = pq.getParams(); |
|||
QueryWrapper<ProcessComment> qw = createQueryWrapper(query); |
|||
IPage<ProcessComment> page = PagerUtil.queryToPage(pq); |
|||
IPage<ProcessCommentVo> pagging = baseMapper.selectPageVo(page, qw); |
|||
PagerVo<ProcessCommentVo> 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<ProcessCommentVo> getCommentList(String processId) { |
|||
List<ProcessCommentVo> commentList = baseMapper.getCommentList(processId); |
|||
for(ProcessCommentVo histIns:commentList){ |
|||
ResultBean<List<SysUserVo>> sysUserVoResultBean = sysUserFeign.fetchBySids(histIns.getReviewerSid());// sysUserService.selectUserById(Long.parseLong(histIns.getAssignee()));
|
|||
List<SysUserVo> 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; |
|||
} |
|||
} |
@ -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<ProcessInstance> startProcessInstanceByKey(StartProcessInstanceQuery params) { |
|||
ResultBean<ProcessInstance> 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<ProcessInstance>().fail().setMsg("此流程已经挂起,请联系系统管理员!"); |
|||
return returnVo; |
|||
} |
|||
ResultBean<SysUserVo> user = sysUserFeign.fetchBySid(params.getUserSid()); |
|||
if (!user.getSuccess()) { |
|||
returnVo = new ResultBean<ProcessInstance>().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<ProcessInstance>().fail().setMsg("Parameters should not be null"); |
|||
} |
|||
return returnVo; |
|||
} |
|||
|
|||
|
|||
public ResultBean todoList(PagerQuery<FlowTaskQuery> taskQueryPagerQuery) { |
|||
int pageNum = (int) taskQueryPagerQuery.getCurrent();//当前页
|
|||
int pageSize = (int) taskQueryPagerQuery.getSize();//每页条数
|
|||
String userSid = taskQueryPagerQuery.getParams().getUserSid(); |
|||
Page<FlowTaskDto> page = new Page<>(); |
|||
TaskQuery taskQuery = taskService.createTaskQuery() |
|||
.processVariableValueEquals("zd","12") |
|||
// .taskVariableValueEquals("zd","12")
|
|||
.active() |
|||
.includeProcessVariables() |
|||
.taskAssignee(userSid) |
|||
.orderByTaskCreateTime().desc(); |
|||
page.setTotal(taskQuery.count()); |
|||
List<Task> taskList = taskQuery.listPage(pageNum - 1, pageSize); |
|||
List<FlowTaskDto> 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<SysUserVo> 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<FlowTaskQuery> taskQueryPagerQuery) { |
|||
int pageNum = (int) taskQueryPagerQuery.getCurrent();//当前页
|
|||
int pageSize = (int) taskQueryPagerQuery.getSize();//每页条数
|
|||
String userSid = taskQueryPagerQuery.getParams().getUserSid(); |
|||
Page<FlowTaskDto> page = new Page<>(); |
|||
HistoricTaskInstanceQuery taskInstanceQuery = historyService.createHistoricTaskInstanceQuery() |
|||
.includeProcessVariables() |
|||
.finished() |
|||
.taskAssignee(userSid) |
|||
.orderByHistoricTaskInstanceEndTime() |
|||
.desc(); |
|||
List<HistoricTaskInstance> historicTaskInstanceList = taskInstanceQuery.listPage(pageNum - 1, pageSize); |
|||
List<FlowTaskDto> 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<SysUserVo> 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<SysUserVo> 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<String, Object> map = new HashMap(); |
|||
if (org.apache.commons.lang3.StringUtils.isNotBlank(procInsId)) { |
|||
List<HistoricActivityInstance> list = historyService |
|||
.createHistoricActivityInstanceQuery() |
|||
.processInstanceId(procInsId) |
|||
.orderByHistoricActivityInstanceStartTime() |
|||
.desc().list(); |
|||
List<FlowTaskDto> 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<SysUserVo> 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<HistoricIdentityLink> linksForTask = historyService.getHistoricIdentityLinksForTask(histIns.getTaskId()); |
|||
StringBuilder stringBuilder = new StringBuilder(); |
|||
for (HistoricIdentityLink identityLink : linksForTask) { |
|||
if ("candidate".equals(identityLink.getType())) { |
|||
if (StringUtils.isNotBlank(identityLink.getUserId())) { |
|||
ResultBean<SysUserVo> 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<Comment> 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> task = taskService.createTaskQuery().processInstanceId(flowTaskQueryOne.getInstanceId()).list(); |
|||
if (CollectionUtils.isEmpty(task)) { |
|||
return ResultBean.fireFail().setMsg("流程未启动或已执行完成,取消申请失败"); |
|||
} |
|||
ResultBean<SysUserVo> 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<EndEvent> endNodes = process.findFlowElementsOfType(EndEvent.class, false); |
|||
if (CollectionUtils.isNotEmpty(endNodes)) { |
|||
Authentication.setAuthenticatedUserId(sysUserVoResultBean.getData().getSid()); |
|||
String endId = endNodes.get(0).getId(); |
|||
List<Execution> executions = |
|||
runtimeService.createExecutionQuery().parentId(processInstance.getProcessInstanceId()).list(); |
|||
List<String> executionIds = new ArrayList<>(); |
|||
executions.forEach(execution -> executionIds.add(execution.getId())); |
|||
runtimeService.createChangeActivityStateBuilder().moveExecutionsToSingleActivityId(executionIds, |
|||
endId).changeState(); |
|||
} |
|||
} |
|||
|
|||
return ResultBean.fireSuccess(); |
|||
} |
|||
|
|||
|
|||
public ResultBean myprocess(PagerQuery<FlowTaskQuery> taskQueryPagerQuery) { |
|||
int pageNum = (int) taskQueryPagerQuery.getCurrent();//当前页
|
|||
int pageSize = (int) taskQueryPagerQuery.getSize();//每页条数
|
|||
String userSid = taskQueryPagerQuery.getParams().getUserSid(); |
|||
Page<FlowTaskDto> page = new Page<>(); |
|||
List<HistoricProcessInstance> historicProcessInstances = historyService.createHistoricProcessInstanceQuery() |
|||
.startedBy(userSid) |
|||
.orderByProcessInstanceStartTime() |
|||
.desc() |
|||
.listPage(pageNum - 1, pageSize); |
|||
page.setTotal(historicProcessInstances.size()); |
|||
List<FlowTaskDto> 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<Task> taskList = taskService.createTaskQuery().processInstanceId(hisIns.getId()).list(); |
|||
if (CollectionUtils.isNotEmpty(taskList)) { |
|||
flowTask.setTaskId(taskList.get(0).getId()); |
|||
} else { |
|||
List<HistoricTaskInstance> 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<String, Object> variables = taskService.getVariables(taskId); |
|||
return ResultBean.fireSuccess().setData(variables); |
|||
} |
|||
} |
|||
|
|||
|
|||
public ResultBean getNextFlowNode(FlowTaskQueryOne flowTaskQueryOne) { |
|||
return null; |
|||
} |
|||
} |
@ -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<SysDeployForm> { |
|||
/** |
|||
* 查询流程实例关联表单 |
|||
* |
|||
* @param id 流程实例关联表单ID |
|||
* @return 流程实例关联表单 |
|||
*/ |
|||
public SysDeployForm selectSysDeployFormById(Long id); |
|||
|
|||
/** |
|||
* 查询流程实例关联表单列表 |
|||
* |
|||
* @param SysDeployForm 流程实例关联表单 |
|||
* @return 流程实例关联表单集合 |
|||
*/ |
|||
public List<SysDeployForm> 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); |
|||
} |
@ -0,0 +1,66 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<!DOCTYPE mapper |
|||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" |
|||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
|||
<mapper namespace="com.yxt.anrui.flowable.biz.sysdeployform.SysDeployFormMapper"> |
|||
|
|||
<resultMap type="com.yxt.anrui.flowable.api.sysdeployform.SysDeployForm" id="SysDeployFormResult"> |
|||
<result property="id" column="id" /> |
|||
<result property="formId" column="form_id" /> |
|||
<result property="deployId" column="deploy_id" /> |
|||
</resultMap> |
|||
|
|||
<sql id="selectSysDeployFormVo"> |
|||
select id, form_id, deploy_id from sys_deploy_form |
|||
</sql> |
|||
|
|||
<select id="selectSysDeployFormList" parameterType="com.yxt.anrui.flowable.api.sysdeployform.SysDeployForm" resultMap="SysDeployFormResult"> |
|||
<include refid="selectSysDeployFormVo"/> |
|||
<where> |
|||
<if test="formId != null "> and form_id = #{formId}</if> |
|||
<if test="deployId != null and deployId != ''"> and deploy_id = #{deployId}</if> |
|||
</where> |
|||
</select> |
|||
|
|||
<select id="selectSysDeployFormById" parameterType="Long" resultMap="SysDeployFormResult"> |
|||
<include refid="selectSysDeployFormVo"/> |
|||
where id = #{id} |
|||
</select> |
|||
|
|||
<select id="selectSysDeployFormByDeployId" resultType="com.yxt.anrui.flowable.api.sysform.SysForm"> |
|||
select t1.form_content as formContent,t1.form_name as formName,t1.id as id from sys_form t1 left join sys_deploy_form t2 on t1.id = t2.form_id |
|||
where t2.deploy_id = #{deployId} |
|||
</select> |
|||
|
|||
<insert id="insertSysDeployForm" parameterType="com.yxt.anrui.flowable.api.sysdeployform.SysDeployForm" useGeneratedKeys="true" keyProperty="id"> |
|||
insert into sys_deploy_form |
|||
<trim prefix="(" suffix=")" suffixOverrides=","> |
|||
<if test="formId != null">form_id,</if> |
|||
<if test="deployId != null">deploy_id,</if> |
|||
</trim> |
|||
<trim prefix="values (" suffix=")" suffixOverrides=","> |
|||
<if test="formId != null">#{formId},</if> |
|||
<if test="deployId != null">#{deployId},</if> |
|||
</trim> |
|||
</insert> |
|||
|
|||
<update id="updateSysDeployForm" parameterType="com.yxt.anrui.flowable.api.sysdeployform.SysDeployForm"> |
|||
update sys_deploy_form |
|||
<trim prefix="SET" suffixOverrides=","> |
|||
<if test="formId != null">form_id = #{formId},</if> |
|||
<if test="deployId != null">deploy_id = #{deployId},</if> |
|||
</trim> |
|||
where id = #{id} |
|||
</update> |
|||
|
|||
<delete id="deleteSysDeployFormById" parameterType="Long"> |
|||
delete from sys_deploy_form where id = #{id} |
|||
</delete> |
|||
|
|||
<delete id="deleteSysDeployFormByIds" parameterType="String"> |
|||
delete from sys_deploy_form where id in |
|||
<foreach item="id" collection="array" open="(" separator="," close=")"> |
|||
#{id} |
|||
</foreach> |
|||
</delete> |
|||
</mapper> |
@ -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<SysDeployFormMapper, SysDeployForm> { |
|||
|
|||
/** |
|||
* 查询流程实例关联表单 |
|||
* |
|||
* @param id 流程实例关联表单ID |
|||
* @return 流程实例关联表单 |
|||
*/ |
|||
public SysDeployForm selectSysDeployFormById(Long id) |
|||
{ |
|||
return baseMapper.selectSysDeployFormById(id); |
|||
} |
|||
|
|||
/** |
|||
* 查询流程实例关联表单列表 |
|||
* |
|||
* @param sysDeployForm 流程实例关联表单 |
|||
* @return 流程实例关联表单 |
|||
*/ |
|||
public List<SysDeployForm> 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); |
|||
} |
|||
} |
@ -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<PagerVo<SysFormVo>> list(PagerQuery<SysFormQuery> pq) { |
|||
ResultBean<PagerVo<SysFormVo>> rb = ResultBean.fireFail(); |
|||
IPage<SysFormVo> page = sysFormService.selectSysFormList(pq); |
|||
PagerVo<SysFormVo> pv = new PagerVo<>(); |
|||
PagerVo<SysFormVo> pv1 = PagerUtil.pageToVo(page, pv); |
|||
return rb.success().setData(pv1); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 导出流程表单列表 |
|||
*/ |
|||
@GetMapping("/export") |
|||
public ResultBean<String> export(SysForm sysForm) { |
|||
/*List<SysForm> list = SysFormService.selectSysFormList(sysForm); |
|||
ExcelUtil<SysForm> util = new ExcelUtil<SysForm>(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<String> add(@RequestBody SysForm sysForm) { |
|||
int i = sysFormService.insertSysForm(sysForm); |
|||
ResultBean<String> rb = ResultBean.fireFail(); |
|||
return rb.success().setMsg("操作成功"); |
|||
} |
|||
|
|||
/** |
|||
* 修改流程表单 |
|||
*/ |
|||
@PutMapping |
|||
public ResultBean<String> edit(@RequestBody SysForm sysForm) { |
|||
// return toAjax(SysFormService.updateSysForm(sysForm));
|
|||
return null; |
|||
} |
|||
|
|||
/** |
|||
* 删除流程表单 |
|||
*/ |
|||
@DeleteMapping("/{formIds}") |
|||
public ResultBean<String> remove(@PathVariable Long[] formIds) { |
|||
sysFormService.deleteSysFormByIds(formIds); |
|||
ResultBean<String> rb = ResultBean.fireFail(); |
|||
return rb.success().setMsg("操作成功"); |
|||
// return null;
|
|||
} |
|||
|
|||
|
|||
/** |
|||
* 挂载流程表单 |
|||
*/ |
|||
@PostMapping("/addDeployForm") |
|||
public ResultBean<String> addDeployForm(@RequestBody SysDeployForm sysDeployForm) { |
|||
sysDeployFormService.insertSysDeployForm(sysDeployForm); |
|||
ResultBean<String> rb = ResultBean.fireFail(); |
|||
return rb.success().setMsg("操作成功"); |
|||
} |
|||
} |
@ -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<SysForm> { |
|||
/** |
|||
* 查询流程表单 |
|||
* |
|||
* @param formId 流程表单ID |
|||
* @return 流程表单 |
|||
*/ |
|||
public SysForm selectSysFormById(Long formId); |
|||
|
|||
/** |
|||
* 查询流程表单列表 |
|||
* |
|||
* @return 流程表单集合 |
|||
*/ |
|||
// public IPage<SysFormVo> selectSysFormVo(IPage<SysFormQuery> page, @Param(Constants.WRAPPER) Wrapper<SysFormVo> qw);
|
|||
List<SysFormVo> getSysFormVoList(IPage<SysFormVo> page, @Param(Constants.WRAPPER) Wrapper<SysFormVo> 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<SysFormVo> selectListVo(); |
|||
|
|||
int getSysFormVoTotal(IPage<SysFormVo> page, QueryWrapper<SysFormVo> qw); |
|||
} |
@ -0,0 +1,34 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
|||
<mapper namespace="com.yxt.anrui.flowable.biz.sysform.SysFormMapper"> |
|||
<select id="getSysFormVoList" resultType="com.yxt.anrui.flowable.api.sysform.SysForm"> |
|||
select id as formId, form_name as formName, form_content as formContent |
|||
from sys_form |
|||
|
|||
</select> |
|||
<select id="getSysFormVoTotal" resultType="int"> |
|||
select count(*) as total from sys_form |
|||
|
|||
</select> |
|||
<insert id="insertSysForm" parameterType="com.yxt.anrui.flowable.api.sysform.SysForm" useGeneratedKeys="true" keyProperty="formId"> |
|||
insert into sys_form |
|||
<trim prefix="(" suffix=")" suffixOverrides=","> |
|||
<if test="formName != null">form_name,</if> |
|||
<if test="formContent != null">form_content,</if> |
|||
</trim> |
|||
<trim prefix="values (" suffix=")" suffixOverrides=","> |
|||
<if test="formName != null">#{formName},</if> |
|||
<if test="formContent != null">#{formContent},</if> |
|||
</trim> |
|||
</insert> |
|||
<delete id="deleteSysFormByIds" parameterType="String"> |
|||
delete from sys_form where id in |
|||
<foreach item="formId" collection="array" open="(" separator="," close=")"> |
|||
#{formId} |
|||
</foreach> |
|||
</delete> |
|||
<select id="selectSysFormById" parameterType="Long" resultType="com.yxt.anrui.flowable.api.sysform.SysForm"> |
|||
select id as formId, form_name as formName, form_content as formContent, remark as remarks from sys_form |
|||
where id = #{formId} |
|||
</select> |
|||
</mapper> |
@ -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<SysFormMapper, SysForm> { |
|||
|
|||
/** |
|||
* 查询流程表单 |
|||
* |
|||
* @param formId 流程表单ID |
|||
* @return 流程表单 |
|||
*/ |
|||
public SysForm selectSysFormById(Long formId) |
|||
{ |
|||
return baseMapper.selectSysFormById(formId); |
|||
} |
|||
|
|||
/** |
|||
* 查询流程表单列表 |
|||
* |
|||
* @return 流程表单 |
|||
*/ |
|||
// public PagerVo<SysFormVo> selectSysFormList(PagerQuery<SysFormQuery> pq)
|
|||
// {
|
|||
// /* List<SysFormVo> sysForms = baseMapper.selectListVo();
|
|||
// int size = sysForms.size();
|
|||
// SysFormQuery query = pq.getParams();
|
|||
// QueryWrapper<SysFormVo> qw = createQueryWrapper(query);
|
|||
// IPage<SysFormVo> page = PagerUtil.queryToPage(pq);
|
|||
// IPage<SysFormVo> pigging = baseMapper.selectSysFormVo(page,qw);
|
|||
// PagerVo<SysFormVo> p = PagerUtil.pageToVo(pigging, null);*/
|
|||
// IPage<SysFormQuery> page = PagerUtil.queryToPage(pq);
|
|||
// QueryWrapper<SysFormVo> qw = createQueryWrapper(pq.getParams());
|
|||
// baseMapper.selectSysFormVo(page, qw);
|
|||
// return null;
|
|||
// }
|
|||
|
|||
public IPage<SysFormVo> selectSysFormList(PagerQuery<SysFormQuery> pagerQuery) { |
|||
List<SysFormVo> sysForms = baseMapper.selectListVo(); |
|||
IPage<SysFormVo> page =new Page<>();// PagerUtil.queryToPage(pagerQuery);
|
|||
QueryWrapper<SysFormVo> qw = createQueryWrapper(pagerQuery.getParams()); |
|||
List<SysFormVo> 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<SysFormVo> createQueryWrapper(SysFormQuery query) { |
|||
// todo: 这里根据具体业务调整查询条件
|
|||
// 多字段Like示例:qw.and(wrapper -> wrapper.like("name", query.getName()).or().like("remark", query.getName()));
|
|||
QueryWrapper<SysFormVo> 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; |
|||
} |
|||
|
|||
} |
@ -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(流程引擎) <br/> |
|||
* File: SysFormLinkMapper.java <br/> |
|||
* Class: com.yxt.anrui.flowable.biz.sysformlink.SysFormLinkMapper <br/> |
|||
* Description: 流程业务关联表. <br/> |
|||
* Copyright: Copyright (c) 2011 <br/> |
|||
* Company: https://gitee.com/liuzp315 <br/>
|
|||
* Makedate: 2022-03-15 16:55:39 <br/> |
|||
* |
|||
* @author liupopo |
|||
* @version 1.0 |
|||
* @since 1.0 |
|||
*/ |
|||
@Mapper |
|||
public interface SysFormLinkMapper extends BaseMapper<SysFormLink> { |
|||
|
|||
int save(SysFormLink sysFormLink); |
|||
|
|||
@Select("select nodeState,flowState from sys_form_link where businessSid=#{businessSid}") |
|||
SysFormStateVo selectStateByBusinessSid(@Param("businessSid") String businessSid); |
|||
|
|||
int updateFiled(Map<String, Object> map); |
|||
|
|||
@Select("select count(1) from sys_form_link where businessSid=#{businessSid}") |
|||
int selectByBusinessSid(@Param("businessSid") String businessSid); |
|||
} |
@ -0,0 +1,16 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
|||
<mapper namespace="com.yxt.anrui.flowable.biz.sysformlink.SysFormLinkMapper"> |
|||
<insert id="save" parameterType="com.yxt.anrui.flowable.api.sysformlink.SysFormLink"> |
|||
insert into sys_form_link(sid, businessSid, procInsId, taskDefKey, nodeState, flowState, formType) |
|||
values (#{sid},#{businessSid},#{procInsId},#{taskDefKey},#{nodeState},#{flowState},#{formType}) |
|||
</insert> |
|||
|
|||
<update id="updateFiled" parameterType="java.util.Map"> |
|||
UPDATE sys_form_link SET nodeState=#{nodeState}, taskDefKey=#{taskDefKey} |
|||
<if test="flowState != null and flowState !=''"> |
|||
, flowState=#{flowState} |
|||
</if> |
|||
WHERE businessSid=#{businessSid} |
|||
</update> |
|||
</mapper> |
@ -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(流程引擎) <br/> |
|||
* File: SysFormLinkFeignFallback.java <br/> |
|||
* Class: com.yxt.anrui.flowable.biz.sysformlink.SysFormLinkRest <br/> |
|||
* Description: 流程业务关联表. <br/> |
|||
* Copyright: Copyright (c) 2011 <br/> |
|||
* Company: https://gitee.com/liuzp315 <br/>
|
|||
* Makedate: 2022-03-15 16:55:39 <br/> |
|||
* |
|||
* @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<SysFormStateVo> selectStateByBusinessSid(String businessSid) { |
|||
return sysFormLinkService.selectStateByBusinessSid(businessSid); |
|||
} |
|||
|
|||
@Override |
|||
public ResultBean updateFiled(Map<String, Object> map) { |
|||
ResultBean<Object> 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); |
|||
} |
|||
} |
@ -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(流程引擎) <br/> |
|||
* File: SysFormLinkService.java <br/> |
|||
* Class: com.yxt.anrui.flowable.biz.sysformlink.SysFormLinkService <br/> |
|||
* Description: 流程业务关联表 业务逻辑. <br/> |
|||
* Copyright: Copyright (c) 2011 <br/> |
|||
* Company: https://gitee.com/liuzp315 <br/>
|
|||
* Makedate: 2022-03-15 16:55:39 <br/> |
|||
* |
|||
* @author liupopo |
|||
* @version 1.0 |
|||
* @since 1.0 |
|||
*/ |
|||
@Service |
|||
public class SysFormLinkService extends MybatisBaseService<SysFormLinkMapper, SysFormLink> { |
|||
|
|||
/** |
|||
* 保存流程业务关联表 |
|||
* @param dto |
|||
* @return |
|||
*/ |
|||
public ResultBean save(SysFormLinkDto dto) { |
|||
ResultBean<Object> 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<SysFormStateVo> selectStateByBusinessSid(String business) { |
|||
SysFormStateVo sysFormStateVo = baseMapper.selectStateByBusinessSid(business); |
|||
if (sysFormStateVo == null) { |
|||
return new ResultBean<SysFormStateVo>().fail().setData(new SysFormStateVo()); |
|||
} |
|||
return new ResultBean<SysFormStateVo>().success().setData(sysFormStateVo); |
|||
} |
|||
|
|||
/** |
|||
* 更新关联表节点状态属性 |
|||
* @param map |
|||
* @return |
|||
*/ |
|||
public int updateFiled(Map<String, Object> 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(); |
|||
} |
|||
} |
@ -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<PagerVo<SysProUrlVo>> list(PagerQuery<SysProUrlQuery> pq) { |
|||
ResultBean<PagerVo<SysProUrlVo>> rb = ResultBean.fireFail(); |
|||
IPage<SysProUrlVo> page = sysProUrlService.selectSysProUrlList(pq); |
|||
PagerVo<SysProUrlVo> pv = new PagerVo<>(); |
|||
PagerVo<SysProUrlVo> pv1 = PagerUtil.pageToVo(page, pv); |
|||
return rb.success().setData(pv1); |
|||
} |
|||
|
|||
@Override |
|||
public ResultBean getSysProUrl(int formId) { |
|||
ResultBean<SysProUrl> rb = ResultBean.fireFail(); |
|||
SysProUrl sysProUrl = sysProUrlService.selectSysProUrlById(formId); |
|||
return rb.success().setData(sysProUrl); |
|||
} |
|||
|
|||
@Override |
|||
public ResultBean getForm(String proId) { |
|||
ResultBean<SysForm> rb = ResultBean.fireFail(); |
|||
SysForm sysForm = sysDeployFormService.selectSysDeployFormByDeployId(proId); |
|||
return rb.success().setData(sysForm); |
|||
} |
|||
|
|||
/** |
|||
* 新增流程表单 |
|||
*/ |
|||
@Override |
|||
public ResultBean<String> add(SysProUrlDto dto) { |
|||
return sysProUrlService.add(dto); |
|||
} |
|||
|
|||
/** |
|||
* 删除流程表单 |
|||
*/ |
|||
@DeleteMapping("/{formIds}") |
|||
@Override |
|||
public ResultBean<String> remove(@PathVariable Long[] formIds) { |
|||
sysProUrlService.deleteSysProUrlByIds(formIds); |
|||
ResultBean<String> rb = ResultBean.fireFail(); |
|||
return rb.success().setMsg("操作成功"); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 挂载流程表单 |
|||
*/ |
|||
@PostMapping("/addDeployForm") |
|||
public ResultBean<String> addDeployForm(@RequestBody SysDeployForm sysDeployForm) { |
|||
sysDeployFormService.insertSysDeployForm(sysDeployForm); |
|||
ResultBean<String> rb = ResultBean.fireFail(); |
|||
return rb.success().setMsg("操作成功"); |
|||
} |
|||
|
|||
@Override |
|||
public ResultBean<PcUrlVo> selectPcUrlByTaskDefKey(SysProUrlQuery query) { |
|||
PcUrlVo urlVo = sysProUrlService.selectPcUrlByTaskDefKey(query); |
|||
if (urlVo == null) { |
|||
return new ResultBean<PcUrlVo>().fail().setData(new PcUrlVo()); |
|||
} |
|||
return new ResultBean<PcUrlVo>().success().setData(urlVo); |
|||
} |
|||
|
|||
@Override |
|||
public ResultBean<AppUrlVo> selectAppUrlByTaskDefKey(AppSysProUrlQuery query) { |
|||
AppUrlVo appUrlVo = sysProUrlService.selectAppUrlByTaskDefKey(query); |
|||
if (appUrlVo == null) { |
|||
return new ResultBean<AppUrlVo>().fail().setData(new AppUrlVo()); |
|||
} |
|||
return new ResultBean<AppUrlVo>().success().setData(appUrlVo); |
|||
} |
|||
|
|||
@Override |
|||
public ResultBean<List<SysProUrlVo>> 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<SysProUrlVo> selectUrlByKey(String procDefId, String taskDefKey, String type,String terminal) { |
|||
ResultBean<SysProUrlVo> rb= ResultBean.fireFail(); |
|||
ResultBean<List<SysProUrlVo>> listResultBean = sysProUrlService.selectUrlByKey(procDefId, taskDefKey, type, terminal); |
|||
if(listResultBean.getData().size()==1){ |
|||
SysProUrlVo sysProUrlVo = listResultBean.getData().get(0); |
|||
return new ResultBean<SysProUrlVo>().success().setData(sysProUrlVo); |
|||
} |
|||
return rb.setMsg("查询不到数据"); |
|||
} |
|||
} |
@ -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<SysProUrl> { |
|||
/** |
|||
* 查询流程表单 |
|||
* |
|||
* @param formId 流程表单ID |
|||
* @return 流程表单 |
|||
*/ |
|||
public SysProUrl selectSysProUrlById(int formId); |
|||
|
|||
/** |
|||
* 查询流程表单列表 |
|||
* |
|||
* @return 流程表单集合 |
|||
*/ |
|||
// public IPage<SysProUrlVo> selectSysProUrlVo(IPage<SysProUrlQuery> page, @Param(Constants.WRAPPER) Wrapper<SysProUrlVo> qw);
|
|||
List<SysProUrlVo> getSysProUrlVoList(IPage<SysProUrlVo> page, @Param(Constants.WRAPPER) Wrapper<SysProUrlVo> 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<SysProUrlVo> selectListVo(); |
|||
|
|||
int getSysProUrlVoTotal(IPage<SysProUrlVo> page, QueryWrapper<SysProUrlVo> qw); |
|||
|
|||
List<SysProUrlVo> 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<SysProUrlVo> selectUrlByKey(@Param("procDefId") String procDefId, @Param("taskDefKey") String taskDefKey, |
|||
@Param("type") String type,@Param("terminal") String terminal); |
|||
} |
@ -0,0 +1,135 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
|||
<mapper namespace="com.yxt.anrui.flowable.biz.sysprourl.SysProUrlMapper"> |
|||
<select id="getSysProUrlVoList" resultType="com.yxt.anrui.flowable.api.sysprourl.SysProUrl"> |
|||
select id as id, url as url, type as type, terminal as terminal, formId as formId, title as title |
|||
from sys_pro_url |
|||
</select> |
|||
<select id="getSysProUrlVoTotal" resultType="int"> |
|||
select count(*) as total |
|||
from sys_pro_url |
|||
</select> |
|||
<insert id="insertSysProUrl" parameterType="com.yxt.anrui.flowable.api.sysprourl.SysProUrl" useGeneratedKeys="true" |
|||
keyProperty="sid"> |
|||
insert into sys_pro_url |
|||
<trim prefix="(" suffix=")" suffixOverrides=","> |
|||
sid, |
|||
<if test="url != null"> |
|||
url, |
|||
</if> |
|||
<if test="type != null"> |
|||
type, |
|||
</if> |
|||
<if test="terminal != null"> |
|||
terminal, |
|||
</if> |
|||
<if test="formId != null"> |
|||
formId, |
|||
</if> |
|||
<if test="title != null"> |
|||
title, |
|||
</if> |
|||
<if test="proc_def_id != null"> |
|||
proc_def_id, |
|||
</if> |
|||
<if test="taskDefKey != null"> |
|||
taskDefKey, |
|||
</if> |
|||
<if test="modulePluginName != null"> |
|||
modulePluginName, |
|||
</if> |
|||
<if test="taskName != null"> |
|||
taskName |
|||
</if> |
|||
</trim> |
|||
<trim prefix="values (" suffix=")" suffixOverrides=","> |
|||
UUID(), |
|||
<if test="url != null"> |
|||
#{url}, |
|||
</if> |
|||
<if test="type != null"> |
|||
#{type}, |
|||
</if> |
|||
<if test="terminal != null"> |
|||
#{terminal}, |
|||
</if> |
|||
<if test="formId != null"> |
|||
#{formId}, |
|||
</if> |
|||
<if test="title != null"> |
|||
#{title}, |
|||
</if> |
|||
<if test="proc_def_id != null"> |
|||
#{proc_def_id}, |
|||
</if> |
|||
<if test="taskDefKey != null"> |
|||
#{taskDefKey}, |
|||
</if> |
|||
<if test="modulePluginName != null"> |
|||
#{modulePluginName}, |
|||
</if> |
|||
<if test="taskName != null"> |
|||
#{taskName} |
|||
</if> |
|||
</trim> |
|||
</insert> |
|||
<delete id="deleteSysProUrlByIds" parameterType="String"> |
|||
delete |
|||
from sys_pro_url where sid in |
|||
<foreach item="formId" collection="array" open="(" separator="," close=")"> |
|||
#{sid} |
|||
</foreach> |
|||
</delete> |
|||
<select id="selectSysProUrlById" parameterType="Integer" |
|||
resultType="com.yxt.anrui.flowable.api.sysprourl.SysProUrl"> |
|||
select id as id, url as url, type as type, terminal as terminal, formId as formId, title as title |
|||
from sys_pro_url |
|||
where formId = #{formId} |
|||
</select> |
|||
|
|||
<select id="selectListByProcDefId" resultType="com.yxt.anrui.flowable.api.sysprourl.SysProUrlVo"> |
|||
SELECT url, |
|||
type, |
|||
terminal, |
|||
formId, |
|||
title, |
|||
proc_def_id, |
|||
taskDefKey, |
|||
modulePluginName |
|||
FROM sys_pro_url |
|||
WHERE proc_def_id = #{proc_def_id} |
|||
AND (taskDefKey = #{taskDefKey} OR taskDefKey IS NULL OR taskDefKey = '') |
|||
ORDER BY terminal DESC, id ASC |
|||
</select> |
|||
|
|||
<select id="selectUniByTaskDefKey" parameterType="com.yxt.anrui.flowable.api.sysprourl.SysProUrlQuery" |
|||
resultType="com.yxt.anrui.flowable.api.sysprourl.SysProUrlVo"> |
|||
SELECT url, modulePluginName |
|||
FROM sys_pro_url |
|||
WHERE proc_def_id = #{proc_def_id} |
|||
AND type = #{type} |
|||
AND terminal = #{terminal} |
|||
AND taskDefKey = #{taskDefKey} |
|||
</select> |
|||
|
|||
<select id="selectUrlByKey" resultType="com.yxt.anrui.flowable.api.sysprourl.SysProUrlVo"> |
|||
select * |
|||
from sys_pro_url |
|||
where proc_def_id = #{procDefId} |
|||
and type = #{type} |
|||
and taskDefKey = #{taskDefKey} |
|||
<if test="terminal != null"> |
|||
and terminal = #{terminal} |
|||
</if> |
|||
|
|||
</select> |
|||
|
|||
<!--<select id="selectUrlByKey"> |
|||
select url |
|||
from sys_pro_url |
|||
where proc_def_id = #{procDefId} |
|||
and type = #{type} |
|||
and taskDefKey = #{taskDefKey} |
|||
and terminal = 1 |
|||
</select>--> |
|||
</mapper> |
@ -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<SysProUrlMapper, SysProUrl> { |
|||
|
|||
/* @Resource |
|||
private AppSubsetVersionFeign appSubsetVersionFeign;*/ |
|||
|
|||
/** |
|||
* 查询流程表单 |
|||
* |
|||
* @param formId 流程表单ID |
|||
* @return 流程表单 |
|||
*/ |
|||
public SysProUrl selectSysProUrlById(int formId) { |
|||
return baseMapper.selectSysProUrlById(formId); |
|||
} |
|||
|
|||
public IPage<SysProUrlVo> selectSysProUrlList(PagerQuery<SysProUrlQuery> pagerQuery) { |
|||
List<SysProUrlVo> SysProUrls = baseMapper.selectListVo(); |
|||
IPage<SysProUrlVo> page = new Page<>();// PagerUtil.queryToPage(pagerQuery);
|
|||
QueryWrapper<SysProUrlVo> qw = createQueryWrapper(pagerQuery.getParams()); |
|||
List<SysProUrlVo> 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<SysProUrlVo> createQueryWrapper(SysProUrlQuery query) { |
|||
// todo: 这里根据具体业务调整查询条件
|
|||
// 多字段Like示例:qw.and(wrapper -> wrapper.like("name", query.getName()).or().like("remark", query.getName()));
|
|||
QueryWrapper<SysProUrlVo> 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<SysProUrlVo> 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<AppSubsetVersionVo> 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<List<SysProUrlVo>> selectUrlByKey(String procDefId, String taskDefKey, |
|||
String type, |
|||
String terminal) { |
|||
ResultBean<List<SysProUrlVo>> 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<SysProUrlVo> url = baseMapper.selectUrlByKey(procDefId, taskDefKey, type,terminal); |
|||
if(url!=null&&url.size()>0){ |
|||
return rb.success().setData(url); |
|||
} |
|||
return rb.setMsg("查询不到数据"); |
|||
} |
|||
|
|||
public ResultBean<String> add(SysProUrlDto dto) { |
|||
ResultBean<String> 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); |
|||
} |
|||
} |
@ -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<SysTaskForm> { |
|||
/** |
|||
* 查询流程任务关联单 |
|||
* |
|||
* @param id 流程任务关联单ID |
|||
* @return 流程任务关联单 |
|||
*/ |
|||
public SysTaskForm selectSysTaskFormById(Long id); |
|||
|
|||
/** |
|||
* 查询流程任务关联单列表 |
|||
* |
|||
* @param sysTaskForm 流程任务关联单 |
|||
* @return 流程任务关联单集合 |
|||
*/ |
|||
public List<SysTaskForm> 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); |
|||
} |
@ -0,0 +1,61 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<!DOCTYPE mapper |
|||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" |
|||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
|||
<mapper namespace="com.yxt.anrui.flowable.biz.systaskform.SysTaskFormMapper"> |
|||
|
|||
<resultMap type="com.yxt.anrui.flowable.api.sysform.SysTaskForm" id="SysTaskFormResult"> |
|||
<result property="id" column="id" /> |
|||
<result property="formId" column="form_id" /> |
|||
<result property="taskId" column="task_id" /> |
|||
</resultMap> |
|||
|
|||
<sql id="selectSysTaskFormVo"> |
|||
select id, form_id, task_id from sys_task_form |
|||
</sql> |
|||
|
|||
<select id="selectSysTaskFormList" parameterType="com.yxt.anrui.flowable.api.sysform.SysTaskForm" resultMap="SysTaskFormResult"> |
|||
<include refid="selectSysTaskFormVo"/> |
|||
<where> |
|||
<if test="formId != null "> and form_id = #{formId}</if> |
|||
<if test="taskId != null and taskId != ''"> and task_id = #{taskId}</if> |
|||
</where> |
|||
</select> |
|||
|
|||
<select id="selectSysTaskFormById" parameterType="Long" resultMap="SysTaskFormResult"> |
|||
<include refid="selectSysTaskFormVo"/> |
|||
where id = #{id} |
|||
</select> |
|||
|
|||
<insert id="insertSysTaskForm" parameterType="com.yxt.anrui.flowable.api.sysform.SysTaskForm" useGeneratedKeys="true" keyProperty="id"> |
|||
insert into sys_task_form |
|||
<trim prefix="(" suffix=")" suffixOverrides=","> |
|||
<if test="formId != null">form_id,</if> |
|||
<if test="taskId != null">task_id,</if> |
|||
</trim> |
|||
<trim prefix="values (" suffix=")" suffixOverrides=","> |
|||
<if test="formId != null">#{formId},</if> |
|||
<if test="taskId != null">#{taskId},</if> |
|||
</trim> |
|||
</insert> |
|||
|
|||
<update id="updateSysTaskForm" parameterType="com.yxt.anrui.flowable.api.sysform.SysTaskForm"> |
|||
update sys_task_form |
|||
<trim prefix="SET" suffixOverrides=","> |
|||
<if test="formId != null">form_id = #{formId},</if> |
|||
<if test="taskId != null">task_id = #{taskId},</if> |
|||
</trim> |
|||
where id = #{id} |
|||
</update> |
|||
|
|||
<delete id="deleteSysTaskFormById" parameterType="Long"> |
|||
delete from sys_task_form where id = #{id} |
|||
</delete> |
|||
|
|||
<delete id="deleteSysTaskFormByIds" parameterType="String"> |
|||
delete from sys_task_form where id in |
|||
<foreach item="id" collection="array" open="(" separator="," close=")"> |
|||
#{id} |
|||
</foreach> |
|||
</delete> |
|||
</mapper> |
@ -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 <br/> |
|||
* File: EnumResultBean.java <br/> |
|||
* Class: com.yxt.anrui.flowable.common.EnumResultBean <br/> |
|||
* Description: <描述类的功能>. <br/> |
|||
* Copyright: Copyright (c) 2011 <br/> |
|||
* Company: https://gitee.com/liuzp315 <br/>
|
|||
* Makedate: 2021/9/11 下午10:18 <br/> |
|||
* |
|||
* @author popo |
|||
* @version 1.0 |
|||
* @since 1.0 |
|||
*/ |
|||
public class EnumResultBean<T> extends ResultBean<T> { |
|||
|
|||
|
|||
public static <T> EnumResultBean<T> fireSuccess() { |
|||
EnumResultBean<T> rb = new EnumResultBean<T>(); |
|||
rb.setSuccess(true); |
|||
rb.setCode(String.valueOf(HttpStatus.SUCCESS)); |
|||
rb.setMsg("操作成功!"); |
|||
return rb; |
|||
} |
|||
|
|||
// public static <T> EnumResultBean<T> fireFail() {
|
|||
// EnumResultBean<T> rb = new EnumResultBean<T>();
|
|||
// rb.setSuccess(false);
|
|||
// rb.setCode(String.valueOf(HttpStatus.ERROR));
|
|||
// rb.setMsg("操作失败!");
|
|||
// return rb;
|
|||
// }
|
|||
} |
@ -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"; |
|||
} |
@ -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); |
|||
} |
|||
} |
@ -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<String> highLightedActivities, List<String> 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<String> highLightedActivities, List<String> 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<GraphicInfo> 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); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -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<String> 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; |
|||
|
|||
} |
|||
} |
@ -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<SpringProcessEngineConfiguration> { |
|||
|
|||
@Override |
|||
public void configure(SpringProcessEngineConfiguration engineConfiguration) { |
|||
System.out.println(">>>>>>>>>>>>>>>>>>>>>> 配置已经加载 >>>>>>>>>>>>>>>>>>>>>>>"); |
|||
engineConfiguration.setActivityFontName("宋体"); |
|||
engineConfiguration.setLabelFontName("宋体"); |
|||
engineConfiguration.setAnnotationFontName("宋体"); |
|||
} |
|||
|
|||
} |
@ -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) + ";" : ""; |
|||
} |
|||
} |
@ -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); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -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(); |
|||
} |
|||
} |
@ -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; |
|||
} |
@ -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("入账申请审批通过后,自动生成车辆库存台账"); |
|||
|
|||
} |
|||
} |
@ -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); |
|||
} |
|||
} |
@ -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<String, Object> 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<IdentityLink> set = delegateTask.getCandidates(); |
|||
List<String> 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<IdentityLink> set = delegateTask.getCandidates();
|
|||
// List<String> groupIdList = set.stream().filter(item -> StringUtils.isNotBlank(item.getGroupId())).map(item -> item.getGroupId()).collect(Collectors.toList());
|
|||
// if (CollectionUtils.isNotEmpty(groupIdList)) {
|
|||
// ResultBean<List<String>> resultBean = taskListener.sysUserRoleFeign.getUserIdListByRoleSid(groupIdList);
|
|||
// if (resultBean.getSuccess() && resultBean.getData() != null) {
|
|||
// List<String> 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<SendResult<String, Object>> future = kafkaTemplate.send("aaa", obj2String); |
|||
future.addCallback(new ListenableFutureCallback<SendResult<String, Object>>() { |
|||
@Override |
|||
public void onFailure(Throwable throwable) { |
|||
//发送失败的处理
|
|||
log.info("aaa" + " - 生产者 发送消息失败:" + throwable.getMessage()); |
|||
} |
|||
|
|||
@Override |
|||
public void onSuccess(SendResult<String, Object> stringObjectSendResult) { |
|||
//成功的处理
|
|||
log.info("aaa" + " - 生产者 发送消息成功:" + stringObjectSendResult.toString()); |
|||
} |
|||
});*/ |
|||
|
|||
|
|||
} |
|||
} |
@ -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<HolidayVo> submit(String taskUser, Integer day) { |
|||
if (day == null || "".equals(day)) { |
|||
return new ResultBean<HolidayVo>().fail().setMsg("请写入请假天数........."); |
|||
} |
|||
HolidayVo holidayVo = holidayTestService.submit(taskUser, day); |
|||
return new ResultBean<HolidayVo>().setData(holidayVo); |
|||
} |
|||
|
|||
/** |
|||
* 生成图片 |
|||
* |
|||
* @param httpServletResponse |
|||
* @param processId 流程实例ID |
|||
*/ |
|||
@Override |
|||
public void genProcessDiagram(HttpServletResponse httpServletResponse, String processId) { |
|||
holidayTestService.genProcessDiagram(httpServletResponse, processId); |
|||
} |
|||
} |
@ -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(); |
|||
} |
|||
} |
@ -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); |
|||
} |
@ -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<Task> tasks = taskService.createTaskQuery().taskAssignee(taskUser).orderByTaskCreateTime().desc().list(); |
|||
//启动流程
|
|||
HashMap<String, Object> 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<String> highLightedActivitis = new ArrayList<String>(); |
|||
|
|||
/** |
|||
* 获得活动的节点 |
|||
*/ |
|||
List<HistoricActivityInstance> highLightedActivitList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processId).orderByHistoricActivityInstanceStartTime().asc().list(); |
|||
//高亮节点
|
|||
for (HistoricActivityInstance tempActivity : highLightedActivitList) { |
|||
String activityId = tempActivity.getActivityId(); |
|||
highLightedActivitis.add(activityId); |
|||
} |
|||
|
|||
List<String> 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); |
|||
} |
|||
} |
@ -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<SequenceFlow> getElementIncomingFlows(FlowElement source) { |
|||
List<SequenceFlow> 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<SequenceFlow> getElementOutgoingFlows(FlowElement source) { |
|||
List<SequenceFlow> 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<FlowElement> getAllElements(Collection<FlowElement> flowElements, Collection<FlowElement> 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<UserTask> iteratorFindParentUserTasks(FlowElement source, Set<String> hasSequenceFlow, List<UserTask> 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<SequenceFlow> 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<UserTask> 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<UserTask> iteratorFindChildUserTasks(FlowElement source, List<String> runTaskKeyList, Set<String> hasSequenceFlow, List<UserTask> 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<SequenceFlow> 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<UserTask> 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<UserTask> findChildProcessUserTasks(FlowElement source, Set<String> hasSequenceFlow, List<UserTask> userTaskList) { |
|||
hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow; |
|||
userTaskList = userTaskList == null ? new ArrayList<>() : userTaskList; |
|||
|
|||
// 根据类型,获取出口连线
|
|||
List<SequenceFlow> 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<UserTask> 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<String> iteratorFindDirtyRoads(FlowElement source, List<String> passRoads, Set<String> hasSequenceFlow, List<String> targets, Set<String> 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<SequenceFlow> 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<String> findChildProcessAllDirtyRoad(FlowElement source, Set<String> hasSequenceFlow, Set<String> dirtyRoads) { |
|||
hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow; |
|||
dirtyRoads = dirtyRoads == null ? new HashSet<>() : dirtyRoads; |
|||
|
|||
// 根据类型,获取出口连线
|
|||
List<SequenceFlow> 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<String> hasSequenceFlow, List<String> targets, Boolean inChildProcess) { |
|||
hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow; |
|||
inChildProcess = inChildProcess == null ? false : inChildProcess; |
|||
|
|||
// 根据类型,获取出口连线
|
|||
List<SequenceFlow> 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<String> 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<SequenceFlow> 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<List<UserTask>> findRoad(FlowElement source, List<UserTask> passRoads, Set<String> hasSequenceFlow, List<List<UserTask>> 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<SequenceFlow> 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<String> historicTaskInstanceClean(Collection<FlowElement> allElements, List<HistoricTaskInstance> historicTaskInstanceList) { |
|||
// 会签节点收集
|
|||
List<String> 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<HistoricTaskInstance> stack = new Stack<>(); |
|||
historicTaskInstanceList.forEach(item -> stack.push(item)); |
|||
// 清洗后的历史任务实例
|
|||
List<String> lastHistoricTaskInstanceList = new ArrayList<>(); |
|||
// 网关存在可能只走了部分分支情况,且还存在跳转废弃数据以及其他分支数据的干扰,因此需要对历史节点数据进行清洗
|
|||
// 临时用户任务 key
|
|||
StringBuilder userTaskKey = null; |
|||
// 临时被删掉的任务 key,存在并行情况
|
|||
List<String> deleteKeyList = new ArrayList<>(); |
|||
// 临时脏数据线路
|
|||
List<Set<String>> 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<String> 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<String> 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 + "秒"; |
|||
} |
|||
} |
|||
} |
Loading…
Reference in new issue