参考示例:RuoYi-flowable: 🌟 基于RuoYi-vue + flowable 6.7.2 的工作流管理 右上角点个 star、fork 🌟 持续关注更新哟 农业认养商城系统:https://gitee.com/tony2y/smart-breed 智慧景区管理系统 :https://gitee.com/tony2y/scenic-spot
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_41037490/article/details/130063627
先上图
1.0接入项目目录
2.0 项目集成配置
2.1 流程模型图
文件名称:demo-1.8.xml
<?xml version="1.0" encoding="UTF-8"?>
<startEvent id="start_event" name="开始">
<outgoing>Flow_0af0rkc</outgoing>
</startEvent>
<userTask id="Activity_0bmjsnr" name="发起" flowable:userType="assignee" flowable:dataType="dynamic" flowable:assignee="${assignee0}">
<documentation>用户发起</documentation>
<extensionElements>
<flowable:taskListener class="com.ruoyi.flowable.listener.FlowTaskServerListener" event="create" />
</extensionElements>
<incoming>Flow_0af0rkc</incoming>
<incoming>Flow_02hyd40</incoming>
<incoming>Flow_10h45lr</incoming>
<outgoing>Flow_189un8r</outgoing>
</userTask>
<sequenceFlow id="Flow_0af0rkc" sourceRef="start_event" targetRef="Activity_0bmjsnr" />
<userTask id="Activity_0svderh" name="上级组织处理" flowable:userType="assignee" flowable:dataType="dynamic" flowable:assignee="${assignee1}">
<extensionElements>
<flowable:executionListener class="com.ruoyi.flowable.listener.FlowExecutionStopListener" event="end" />
</extensionElements>
<incoming>Flow_1s8wcin</incoming>
<incoming>Flow_022awso</incoming>
<outgoing>Flow_10r6g5h</outgoing>
<outgoing>Flow_02hyd40</outgoing>
</userTask>
<endEvent id="Event_1lkkjby" name="结束">
<incoming>Flow_10r6g5h</incoming>
</endEvent>
<sequenceFlow id="Flow_10r6g5h" name="" sourceRef="Activity_0svderh" targetRef="Event_1lkkjby">
<conditionExpression xsi:type="tFormalExpression">${isTopReturn==fase}</conditionExpression>
</sequenceFlow>
<sequenceFlow id="Flow_02hyd40" name="退回" sourceRef="Activity_0svderh" targetRef="Activity_0bmjsnr">
<conditionExpression xsi:type="tFormalExpression">${isTopReturn==true}</conditionExpression>
</sequenceFlow>
<exclusiveGateway id="Gateway_16yvw2l" name="判断同级">
<extensionElements />
<incoming>Flow_189un8r</incoming>
<outgoing>Flow_1s8wcin</outgoing>
<outgoing>Flow_0rn1sdw</outgoing>
</exclusiveGateway>
<sequenceFlow id="Flow_1s8wcin" name="上级组织直接处理" sourceRef="Gateway_16yvw2l" targetRef="Activity_0svderh">
<conditionExpression xsi:type="tFormalExpression">${isAdmin==false}</conditionExpression>
</sequenceFlow>
<userTask id="Activity_11ipkd6" name="同级管理员" flowable:userType="assignee" flowable:dataType="dynamic" flowable:assignee="${assignee2}">
<extensionElements />
<incoming>Flow_0rn1sdw</incoming>
<outgoing>Flow_022awso</outgoing>
<outgoing>Flow_10h45lr</outgoing>
</userTask>
<sequenceFlow id="Flow_0rn1sdw" name="提交" sourceRef="Gateway_16yvw2l" targetRef="Activity_11ipkd6">
<extensionElements>
<flowable:executionListener class="com.ruoyi.flowable.listener.FlowExecutionListener" event="start" />
</extensionElements>
<conditionExpression xsi:type="tFormalExpression">${isAdmin==true}</conditionExpression>
</sequenceFlow>
<sequenceFlow id="Flow_022awso" name="" sourceRef="Activity_11ipkd6" targetRef="Activity_0svderh" />
<sequenceFlow id="Flow_10h45lr" name="退回" sourceRef="Activity_11ipkd6" targetRef="Activity_0bmjsnr" />
<sequenceFlow id="Flow_189un8r" name="" sourceRef="Activity_0bmjsnr" targetRef="Gateway_16yvw2l" />
<bpmndi:BPMNDiagram id="BPMNDiagram_flow">
<bpmndi:BPMNPlane id="BPMNPlane_flow" bpmnElement="flow_7cum4yyi">
<bpmndi:BPMNShape id="BPMNShape_start_event" bpmnElement="start_event" bioc:stroke="">
<omgdc:Bounds x="-125" y="185" width="30" height="30" />
<bpmndi:BPMNLabel>
<omgdc:Bounds x="-122" y="222" width="22" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0bmjsnr_di" bpmnElement="Activity_0bmjsnr">
<omgdc:Bounds x="-20" y="160" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0svderh_di" bpmnElement="Activity_0svderh">
<omgdc:Bounds x="390" y="160" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_1lkkjby_di" bpmnElement="Event_1lkkjby">
<omgdc:Bounds x="582" y="182" width="36" height="36" />
<bpmndi:BPMNLabel>
<omgdc:Bounds x="589" y="225" width="22" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_16yvw2l_di" bpmnElement="Gateway_16yvw2l" isMarkerVisible="true">
<omgdc:Bounds x="135" y="175" width="50" height="50" />
<bpmndi:BPMNLabel>
<omgdc:Bounds x="137" y="153" width="45" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_11ipkd6_di" bpmnElement="Activity_11ipkd6">
<omgdc:Bounds x="230" y="160" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_0af0rkc_di" bpmnElement="Flow_0af0rkc">
<di:waypoint x="-95" y="200" />
<di:waypoint x="-20" y="200" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_10r6g5h_di" bpmnElement="Flow_10r6g5h">
<di:waypoint x="490" y="200" />
<di:waypoint x="582" y="200" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_02hyd40_di" bpmnElement="Flow_02hyd40">
<di:waypoint x="440" y="160" />
<di:waypoint x="440" y="50" />
<di:waypoint x="30" y="50" />
<di:waypoint x="30" y="160" />
<bpmndi:BPMNLabel>
<omgdc:Bounds x="224" y="32" width="22" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1s8wcin_di" bpmnElement="Flow_1s8wcin">
<di:waypoint x="160" y="225" />
<di:waypoint x="160" y="310" />
<di:waypoint x="440" y="310" />
<di:waypoint x="440" y="240" />
<bpmndi:BPMNLabel>
<omgdc:Bounds x="256" y="292" width="89" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0rn1sdw_di" bpmnElement="Flow_0rn1sdw">
<di:waypoint x="185" y="200" />
<di:waypoint x="230" y="200" />
<bpmndi:BPMNLabel>
<omgdc:Bounds x="197" y="182" width="22" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_022awso_di" bpmnElement="Flow_022awso">
<di:waypoint x="330" y="200" />
<di:waypoint x="390" y="200" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_10h45lr_di" bpmnElement="Flow_10h45lr">
<di:waypoint x="280" y="160" />
<di:waypoint x="280" y="100" />
<di:waypoint x="30" y="100" />
<di:waypoint x="30" y="160" />
<bpmndi:BPMNLabel>
<omgdc:Bounds x="144" y="82" width="22" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_189un8r_di" bpmnElement="Flow_189un8r">
<di:waypoint x="80" y="200" />
<di:waypoint x="135" y="200" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
2.2 接入业务核心代码
启动自己配置的流程实例
/**
* 根据流程定义ID启动流程实例
*
* @param procDefId 流程模板ID
* @param variables 流程变量
* @return
*/
@Override
public AjaxResult startProcessInstanceById(String procDefId, Map<String, Object> variables) {
try {
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(procDefId)
.latestVersion().singleResult();
if (Objects.nonNull(processDefinition) && processDefinition.isSuspended()) {
return AjaxResult.error("流程已被挂起,请先激活流程");
}
// 设置流程发起人Id到流程中
SysUser sysUser = SecurityUtils.getLoginUser().getUser();
identityService.setAuthenticatedUserId(sysUser.getUserId().toString());
variables.put(ProcessConstants.PROCESS_INITIATOR, sysUser.getUserId());
runtimeService.startProcessInstanceById(procDefId, variables);
return AjaxResult.success("流程启动成功");
} catch (Exception e) {
e.printStackTrace();
return AjaxResult.error("流程启动错误");
}
}
2.2.1 流程发起
@Transactional
@Override
public AjaxResult flowStart(StartProcessPayloadVo startProcessPayloadVo/*, String procDefId*/) {
String businessModeUrl = startProcessPayloadVo.getBusinessModeUrl();
String businessModeCode = sysConfigService.selectConfigByKey(businessModeUrl);
TMisFunction tMisFunction = new TMisFunction();
String[] split = startProcessPayloadVo.getBusinessModeUrl().split("/");
String funNo = split[split.length - 1].substring(1, split[split.length - 1].length());
tMisFunction.setCtFunNo(funNo);
List<TMisFunction> tMisFunctionList = misFunctionMapper.selectTMisFunctionList(tMisFunction);
if (tMisFunctionList.size() < 1) {
return AjaxResult.error("功能号 businessModeCode 无效请仔细检查!");
}
String procDefId = "";
try {
startProcessPayloadVo.setBusinessModeCode(tMisFunctionList.get(0).getCtFunNo());
procDefId = JSON.parseObject(tMisFunctionList.get(0).getCtFlowConfig(), HashMap.class).get("nowProcdefIId").toString();
} catch (NullPointerException e) {
return AjaxResult.error("功能号 businessModeCode 无效请仔细检查!");
}
//校验单据已经审批中的拒绝发起审批
// TODO checkbusinessKeyInFlowIng(businessModeCode,startProcessPayloadVo.getBusinessKey());
//校验再次发起的单据进入流程前删除act_workflow_formdata 的原有的审批意见
//TODO delActWorkflowFormDataById(startProcessPayloadVo.getBusinessKey());
//校验单据重复发起审批
boolean isStart = checkbusinessKeyStartFlowIng(startProcessPayloadVo.getBusinessKey(), tMisFunctionList.get(0).getCtTable());
if (true == isStart) {
return AjaxResult.error("流程已经发起,请勿重复发起流程!");
}
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String now = df.format(DateUtils.getNowDate());
SysUser user = SecurityUtils.getLoginUser().getUser();
Map<String, Object> variabes = new HashMap<>();
variabes.put("assignee0", user.getUserId());
variabes.put("assignee1", user.getUserId());
variabes.put("assignee2", user.getUserId());//占位符 没有任何意义
//发起流程 写入act业务
//业务模块名称
String businessModeName = tMisFunctionList.get(0).getCtFunName();
try {
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(startProcessPayloadVo.getBusinessKey())
.latestVersion().singleResult();
if (Objects.nonNull(processDefinition) && processDefinition.isSuspended()) {
return AjaxResult.error("流程已被挂起,请先激活流程");
}
// 设置流程发起人Id到流程中
SysUser sysUser = SecurityUtils.getLoginUser().getUser();
identityService.setAuthenticatedUserId(sysUser.getUserId().toString());
variabes.put(ProcessConstants.PROCESS_INITIATOR, sysUser.getUserId());
runtimeService.startProcessInstanceById(procDefId, startProcessPayloadVo.getBusinessKey(), variabes);//启动流程实例 业务单据id 流程变量
List<Execution> list1 = runtimeService.createExecutionQuery().processInstanceBusinessKey(startProcessPayloadVo.getBusinessKey()).list();
String processInstanceId = list1.get(list1.size() - 1).getProcessInstanceId();
List<Execution> list2 = runtimeService.createExecutionQuery().processInstanceId(processInstanceId).list();
String execution_id = list2.get(list2.size() - 1).getId();
//结束填报单据的节点
Task task = taskService.createTaskQuery().executionId(execution_id).singleResult();
FlowTaskVo flowTaskVo = new FlowTaskVo();
flowTaskVo.setTaskId(task.getId());
flowTaskVo.setComment("流程发起人默认同意");
flowTaskService.complete(flowTaskVo);
//在业务单据中 记录流程是否发起
SysDeployFormMapper sysDeployFormMapper = ApplicationContextUtils.getBean(SysDeployFormMapper.class);
String deploymentId = sysDeployFormMapper.selectGenericString("UPDATE " + tMisFunctionList.get(0).getCtTable() + " SET ct_state = 2 WHERE ct_id = '" + startProcessPayloadVo.getBusinessKey() + "';");
//TODO 写入t_mis_sin
return AjaxResult.success("流程启动成功");
} catch (Exception e) {
e.printStackTrace();
return AjaxResult.error("流程启动错误");
}
}
2.2.2 查询我发起的流程任务待办
/**
* 我发起的流程
*
* @param queryVo 请求参数
* @return
*/
@Override
public AjaxResult myProcess(FlowQueryVo queryVo) {
Page<FlowTaskDto> page = new Page<>();
Long userId = SecurityUtils.getLoginUser().getUser().getUserId();
HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery()
.startedBy(userId.toString())
.orderByProcessInstanceStartTime()
.desc();
List<HistoricProcessInstance> historicProcessInstances = historicProcessInstanceQuery.listPage(queryVo.getPageSize() * (queryVo.getPageNum() - 1), queryVo.getPageSize());
page.setTotal(historicProcessInstanceQuery.count());
List<FlowTaskDto> flowList = new ArrayList<>();
List<FlowTaskDto> newFlowList = 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(getDate(time));
} else {
long time = System.currentTimeMillis() - hisIns.getStartTime().getTime();
flowTask.setDuration(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());
flowTask.setTaskName(taskList.get(0).getName());
if (StringUtils.isNotBlank(taskList.get(0).getAssignee())) {
// 当前任务节点办理人信息
//SysUser sysUser = sysUserService.selectUserById(Long.parseLong(taskList.get(0).getAssignee()));
//多个办理人时
String assignee = taskList.get(0).getAssignee();
SysUser user = SecurityUtils.getLoginUser().getUser();
String managementOrgLevel = user.getManagementOrgLevel();
String deptIdSql = "select dept_id from t_dw_branch where ct_code_p2='" + managementOrgLevel + "';";
SysDeployFormMapper sysDeployFormMapper = ApplicationContextUtils.getBean(SysDeployFormMapper.class);
String deptId = sysDeployFormMapper.selectGenericString(deptIdSql);
List<SysUser> sysUsersList = userMapper.selectUserListById("( " + assignee + " )");
/* if (Objects.nonNull(sysUser)) {
flowTask.setAssigneeId(sysUser.getUserId());
flowTask.setAssigneeName(sysUser.getNickName());
}*/
for (int i = 0; i < sysUsersList.size(); i++) {
FlowTaskDto newFlowTask = new FlowTaskDto();
BeanUtils.copyProperties(flowTask, newFlowTask);
newFlowTask.setAssigneeId(sysUsersList.get(i).getUserId());
newFlowTask.setAssigneeName(sysUsersList.get(i).getNickName());
newFlowList.add(newFlowTask);
}
}
} else {
List<HistoricTaskInstance> historicTaskInstance = historyService.createHistoricTaskInstanceQuery().processInstanceId(hisIns.getId()).orderByHistoricTaskInstanceEndTime().desc().list();
flowTask.setTaskId(historicTaskInstance.get(0).getId());
flowTask.setTaskName(historicTaskInstance.get(0).getName());
if (StringUtils.isNotBlank(historicTaskInstance.get(0).getAssignee())) {
// 当前任务节点办理人信息
SysUser sysUser = sysUserService.selectUserById(Long.parseLong(historicTaskInstance.get(0).getAssignee()));
if (Objects.nonNull(sysUser)) {
flowTask.setAssigneeId(sysUser.getUserId());
flowTask.setAssigneeName(sysUser.getNickName());
//flowTask.setAssigneeDeptName(Objects.nonNull(sysUser.getDept()) ? sysUser.getDept().getDeptName() : "");
}
}
}
// flowList.add(flowTask);
flowList.addAll(newFlowList);
}
page.setRecords(flowList);
return AjaxResult.success(page);
}
2.2.3 所有待办流程
/**
* 代办任务列表
* todo 这儿查询的数据 没有区分用户所属的 部门,待更改
*
* @param queryVo 请求参数
* @return
*/
@Override
public AjaxResult todoList(FlowQueryVo queryVo) {
Page<FlowTaskDto> page = new Page<>();
// 只查看自己的数据
SysUser sysUser = SecurityUtils.getLoginUser().getUser();
//safeCandidateGroups,candidateGroup 候选组 里面的值 是角色id
//代码原有
/* TaskQuery taskQuery = taskService.createTaskQuery()
.active()
.includeProcessVariables()
.taskCandidateGroupIn(sysUser.getRoles().stream().map(role -> role.getRoleId().toString()).collect(Collectors.toList()))
.taskCandidateOrAssigned(sysUser.getUserId().toString())
.orderByTaskCreateTime().desc();*/
//用户+部门 待办数据
//用户+角色数据
//用户在任何 管辖单位能看到的数据
SysDeployFormMapper sysDeployFormMapper = ApplicationContextUtils.getBean(SysDeployFormMapper.class);
String branchType = sysDeployFormMapper.selectGenericString("select ct_branch_category from t_dw_branch where dept_id='" + sysUser.getDeptId() + "';");
TaskQuery taskQuery = null;
if (PartyConstants.CATEGORY_COMMITTEE.equals(branchType)) {//上级组织能看到下级组织 提交的待办
taskQuery = taskService.createTaskQuery()
.active()
.includeProcessVariables()
.taskCandidateGroupIn(sysUser.getRoles().stream().map(role -> role.getRoleId().toString()).collect(Collectors.toList()))
.taskCandidateOrAssigned(sysUser.getUserId().toString())
.orderByTaskCreateTime().desc();
} else {
//用户+部门 待办数据
taskQuery = taskService.createTaskQuery()
.active()
.includeProcessVariables()
.taskOwner(sysUser.getDeptId().toString())
.taskCandidateOrAssigned(sysUser.getUserId().toString())
.orderByTaskCreateTime().desc();
}
// TODO 传入名称查询不到数据?
// if (StringUtils.isNotBlank(queryVo.getName())){
// taskQuery.processDefinitionNameLike(queryVo.getName());
// }
page.setTotal(taskQuery.count());
List<Task> taskList = taskQuery.listPage(queryVo.getPageSize() * (queryVo.getPageNum() - 1), queryVo.getPageSize());
List<FlowTaskDto> flowList = new ArrayList<>();
for (Task task : taskList) {
FlowTaskDto flowTask = new FlowTaskDto();
// 当前流程信息
flowTask.setTaskId(task.getId());
flowTask.setTaskDefKey(task.getTaskDefinitionKey());
flowTask.setCreateTime(task.getCreateTime());
flowTask.setProcDefId(task.getProcessDefinitionId());
flowTask.setExecutionId(task.getExecutionId());
flowTask.setTaskName(task.getName());
// 流程定义信息
ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
.processDefinitionId(task.getProcessDefinitionId())
.singleResult();
flowTask.setDeployId(pd.getDeploymentId());
flowTask.setProcDefName(pd.getName());
flowTask.setProcDefVersion(pd.getVersion());
flowTask.setProcInsId(task.getProcessInstanceId());
// 流程发起人信息
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
.processInstanceId(task.getProcessInstanceId())
.singleResult();
SysUser startUser = sysUserService.selectUserById(Long.parseLong(historicProcessInstance.getStartUserId()));
flowTask.setStartUserId(startUser.getUserId().toString());
flowTask.setStartUserName(startUser.getNickName());
//flowTask.setStartDeptName(Objects.nonNull(startUser.getDept()) ? startUser.getDept().getDeptName() : "");
flowList.add(flowTask);
}
page.setRecords(flowList);
return AjaxResult.success(page);
}
2.2.4 所有已办任务
/**
* 已办任务列表
*
* @param queryVo 请求参数
* @return
*/
@Override
public AjaxResult finishedList(FlowQueryVo queryVo) {
Page<FlowTaskDto> page = new Page<>();
Long userId = SecurityUtils.getLoginUser().getUser().getUserId();
HistoricTaskInstanceQuery taskInstanceQuery = historyService.createHistoricTaskInstanceQuery()
.includeProcessVariables()
.finished()
.taskAssignee(userId.toString())
.orderByHistoricTaskInstanceEndTime()
.desc();
List<HistoricTaskInstance> historicTaskInstanceList = taskInstanceQuery.listPage(queryVo.getPageSize() * (queryVo.getPageNum() - 1), queryVo.getPageSize());
List<FlowTaskDto> hisTaskList = new ArrayList<>();
for (HistoricTaskInstance histTask : historicTaskInstanceList) {
FlowTaskDto flowTask = new FlowTaskDto();
// 当前流程信息
flowTask.setTaskId(histTask.getId());
// 审批人员信息
flowTask.setCreateTime(histTask.getCreateTime());
flowTask.setFinishTime(histTask.getEndTime());
flowTask.setDuration(getDate(histTask.getDurationInMillis()));
flowTask.setProcDefId(histTask.getProcessDefinitionId());
flowTask.setTaskDefKey(histTask.getTaskDefinitionKey());
flowTask.setTaskName(histTask.getName());
// 流程定义信息
ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
.processDefinitionId(histTask.getProcessDefinitionId())
.singleResult();
flowTask.setDeployId(pd.getDeploymentId());
flowTask.setProcDefName(pd.getName());
flowTask.setProcDefVersion(pd.getVersion());
flowTask.setProcInsId(histTask.getProcessInstanceId());
flowTask.setHisProcInsId(histTask.getProcessInstanceId());
// 流程发起人信息
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
.processInstanceId(histTask.getProcessInstanceId())
.singleResult();
SysUser startUser = sysUserService.selectUserById(Long.parseLong(historicProcessInstance.getStartUserId()));
flowTask.setStartUserId(startUser.getNickName());
flowTask.setStartUserName(startUser.getNickName());
//flowTask.setStartDeptName(startUser.getDept().getDeptName());
hisTaskList.add(flowTask);
}
page.setTotal(taskInstanceQuery.count());
page.setRecords(hisTaskList);
return AjaxResult.success(page);
}
2.2.5 流程流转 处理记录
/**
* 流程历史流转记录
*
* @param procInsId 流程实例Id
* @return
*/
@Override
public AjaxResult flowRecord(String procInsId, String deployId) {
Map<String, Object> map = new HashMap<String, Object>();
if (StringUtils.isNotBlank(procInsId)) {
List<HistoricActivityInstance> list = historyService
.createHistoricActivityInstanceQuery()
.processInstanceId(procInsId)
.orderByHistoricActivityInstanceStartTime()
.desc().list();
List<FlowTaskDto> hisFlowList = new ArrayList<>();
for (HistoricActivityInstance histIns : list) {
// 展示开始节点
// if ("startEvent".equals(histIns.getActivityType())) {
// FlowTaskDto flowTask = new FlowTaskDto();
// // 流程发起人信息
// HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
// .processInstanceId(histIns.getProcessInstanceId())
// .singleResult();
// SysUser startUser = sysUserService.selectUserById(Long.parseLong(historicProcessInstance.getStartUserId()));
// flowTask.setTaskName(startUser.getNickName() + "(" + startUser.getDept().getDeptName() + ")发起申请");
// flowTask.setFinishTime(histIns.getEndTime());
// hisFlowList.add(flowTask);
// } else if ("endEvent".equals(histIns.getActivityType())) {
// FlowTaskDto flowTask = new FlowTaskDto();
// flowTask.setTaskName(StringUtils.isNotBlank(histIns.getActivityName()) ? histIns.getActivityName() : "结束");
// flowTask.setFinishTime(histIns.getEndTime());
// hisFlowList.add(flowTask);
// } else
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())) {
SysUser sysUser = sysUserService.selectUserById(Long.parseLong(histIns.getAssignee()));
if (sysUser != null) {
flowTask.setAssigneeId(sysUser.getUserId());
flowTask.setAssigneeName(sysUser.getNickName());
}
// flowTask.setDeptName(Objects.nonNull(sysUser.getDept()) ? sysUser.getDept().getDeptName() : "");
}
// 展示审批人员
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())) {
SysUser sysUser = sysUserService.selectUserById(Long.parseLong(identityLink.getUserId()));
stringBuilder.append(sysUser.getNickName()).append(",");
}
if (StringUtils.isNotBlank(identityLink.getGroupId())) {
SysRole sysRole = sysRoleService.selectRoleById(Long.parseLong(identityLink.getGroupId()));
stringBuilder.append(sysRole.getRoleName()).append(",");
}
} else if ("assignee".equals(identityLink.getType())) {//todo assignee uel表达式
if (StringUtils.isNotBlank(identityLink.getUserId())) {
SysUser sysUser = sysUserService.selectUserById(Long.parseLong(identityLink.getUserId()));
//stringBuilder.append(sysUser.getNickName()).append(","); java.lang.NullPointerException: null
}
if (StringUtils.isNotBlank(identityLink.getGroupId())) {
SysRole sysRole = sysRoleService.selectRoleById(Long.parseLong(identityLink.getGroupId()));
stringBuilder.append(sysRole.getRoleName()).append(",");
}
} else if ("assignee0".equals(identityLink.getType())) {//todo assignee0 uel表达式
if (StringUtils.isNotBlank(identityLink.getUserId())) {
SysUser sysUser = sysUserService.selectUserById(Long.parseLong(identityLink.getUserId()));
stringBuilder.append(sysUser.getNickName()).append(",");
}
if (StringUtils.isNotBlank(identityLink.getGroupId())) {
SysRole sysRole = sysRoleService.selectRoleById(Long.parseLong(identityLink.getGroupId()));
stringBuilder.append(sysRole.getRoleName()).append(",");
}
}/*else if("assignee1".equals(identityLink.getType())) {//todo assignee1 uel表达式
if (StringUtils.isNotBlank(identityLink.getUserId())) {
SysUser sysUser = sysUserService.selectUserById(Long.parseLong(identityLink.getUserId()));
stringBuilder.append(sysUser.getNickName()).append(",");
}
if (StringUtils.isNotBlank(identityLink.getGroupId())) {
SysRole sysRole = sysRoleService.selectRoleById(Long.parseLong(identityLink.getGroupId()));
stringBuilder.append(sysRole.getRoleName()).append(",");
}
}else if("assignee3".equals(identityLink.getType())) {//todo assignee1 uel表达式 加签处理人
if (StringUtils.isNotBlank(identityLink.getUserId())) {
SysUser sysUser = sysUserService.selectUserById(Long.parseLong(identityLink.getUserId()));
stringBuilder.append(sysUser.getNickName()).append(",");
}
if (StringUtils.isNotBlank(identityLink.getGroupId())) {
SysRole sysRole = sysRoleService.selectRoleById(Long.parseLong(identityLink.getGroupId()));
stringBuilder.append(sysRole.getRoleName()).append(",");
}
}*/
}
if (StringUtils.isNotBlank(stringBuilder)) {
flowTask.setCandidate(stringBuilder.substring(0, stringBuilder.length() - 1));
}
//解决流程发起时 发起人为null
SysUser user = SecurityUtils.getLoginUser().getUser();
if (StringUtils.isEmpty(flowTask.getCandidate())) {
flowTask.setCandidate(user.getUserName());
}
flowTask.setDuration(histIns.getDurationInMillis() == null || histIns.getDurationInMillis() == 0 ? null : 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);
}
//TODO 2023-03-23注释 第一次申请获取初始化表单
/* if (StringUtils.isNotBlank(deployId)) {
SysForm sysForm = sysInstanceFormService.selectSysDeployFormByDeployId(deployId);
if (Objects.isNull(sysForm)) {
return AjaxResult.error("请先配置流程表单");
}
map.put("formData", JSONObject.parseObject(sysForm.getFormContent()));
}*/
return AjaxResult.success(map);
}
2.2.6 流程节点 信息
/*
* 流程节点信息
* @param businessKey
* @return
*/
@Override
public AjaxResult misFlowXmlAndNode(String businessKey, String funNo) {
TMisFunction tMisFunction = new TMisFunction();
tMisFunction.setCtFunNo(funNo);
List<TMisFunction> tMisFunctionList = tMisFunctionMapper.selectTMisFunctionList(tMisFunction);
if (tMisFunctionList.size() < 1) {
return AjaxResult.error("业务功能号 funNo有误,请仔细检查!");
}
HashMap FlowConfhashMap = JSON.parseObject(tMisFunctionList.get(0).getCtFlowConfig(), HashMap.class);
RepositoryService repositoryService = ApplicationContextUtils.getBean(RepositoryService.class);
//流程定义id
String nowProcdefIId = "";
try {
nowProcdefIId = FlowConfhashMap.get("nowProcdefIId").toString();
} catch (NullPointerException e) {
return AjaxResult.error("业务功能号 funNo有误,请仔细检查!");
}
String ctTable = tMisFunctionList.get(0).getCtTable();
//校验单据 businessKey
String ctId = sysDeptMapper.selectGenericString("SELECT ct_id FROM " + ctTable + " WHERE ct_id ='" + businessKey + "';");
if (StringUtils.isEmpty(ctId) == true) {
return AjaxResult.error("业务单据 businessKey 有误,请仔细检查!");
}
//流程定义id 流程部署id
String deploymentId = repositoryService.createProcessDefinitionQuery()
.processDefinitionId(FlowConfhashMap.get("nowProcdefIId").toString()).singleResult().getDeploymentId();
HistoricProcessInstance historicProcessInstance = null;
String procInsId = "";
//流程没有发起 没有待办
try {
historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
.processInstanceBusinessKey(businessKey).singleResult();
procInsId = historicProcessInstance.getId();
} catch (NullPointerException e) {
e.printStackTrace();
}
try {
List<FlowViewerDto> flowViewerList = new ArrayList<>();
// 获取已经完成的节点
List<HistoricActivityInstance> listFinished = historyService.createHistoricActivityInstanceQuery()
.processInstanceId(procInsId)
.finished()
.list();
// 保存已经完成的流程节点编号
listFinished.forEach(s -> {
FlowViewerDto flowViewerDto = new FlowViewerDto();
flowViewerDto.setKey(s.getActivityId());
flowViewerDto.setCompleted(true);
flowViewerList.add(flowViewerDto);
});
// 获取代办节点
List<HistoricActivityInstance> listUnFinished = historyService.createHistoricActivityInstanceQuery()
.processInstanceId(procInsId)
.unfinished()
.list();
// 保存需要代办的节点编号
listUnFinished.forEach(s -> {
FlowViewerDto flowViewerDto = new FlowViewerDto();
flowViewerDto.setKey(s.getActivityId());
flowViewerDto.setCompleted(false);
flowViewerList.add(flowViewerDto);
});
Map<String, Object> result = new HashMap();
// xmlData 数据
ProcessDefinition newDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
InputStream inputStream = repositoryService.getResourceAsStream(newDefinition.getDeploymentId(), newDefinition.getResourceName());
String xmlData = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
// TODO 用户变量替换为当前登录人 ${assignee0}
SysUser user = SecurityUtils.getLoginUser().getUser();
String xmlData1 = xmlData.replace("${assignee0}", user.getUserId().toString());
result.put("nodeData", flowViewerList);
result.put("xmlData", xmlData1);
return AjaxResult.success(result);
} catch (Exception e) {
return AjaxResult.error("高亮历史任务失败");
}
}
2.2.7 任务转办
/**
* 任务转办
* @param flowTaskVo
*/
@Transactional
@Override
public AjaxResult msiAssignTask(FlowTaskVo flowTaskVo) {
SysUser sysUser = new SysUser();
sysUser.setUserName(flowTaskVo.getAssignee());
List<SysUser> sysUserList = userMapper.selectUserList(sysUser);
if (sysUserList.size() < 1) {
return AjaxResult.error("被提交的人员,没有维护系统账号信息!");
}
String nextTaskId = sysDeptMapper.selectGenericString("SELECT MAX(ID_) FROM act_hi_taskinst WHERE PROC_INST_ID_ in (SELECT id_ FROM act_hi_procinst WHERE BUSINESS_KEY_ = '" + flowTaskVo.getBusinessKey() + "');");
SysUser user = SecurityUtils.getLoginUser().getUser();
//设置提交人信息 提交人的人员id
taskService.setAssignee(nextTaskId, sysUserList.get(0).getUserId().toString());
//这里设置提交用户所属的组织
taskService.setOwner(nextTaskId, user.getDeptId().toString());
// // 删除指派人重新指派
// taskService.deleteCandidateUser(flowTaskVo.getTaskId(),flowTaskVo.getAssignee());
// taskService.addCandidateUser(flowTaskVo.getTaskId(),flowTaskVo.getAssignee());
// // 如果要查询转给他人处理的任务,可以同时将OWNER进行设置:
// taskService.setOwner(flowTaskVo.getTaskId(), flowTaskVo.getAssignee());
return AjaxResult.success();
}
2.2.8 执行监听器
import com.AAA.common.core.domain.entity.SysUser;
import com.AAA.common.utils.SecurityUtils;
import com.AAA.common.utils.bean.ApplicationContextUtils;
import com.AAA.flowable.factory.FlowServiceFactory;
import com.AAA.system.mapper.SysDeployFormMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.flowable.common.engine.api.delegate.Expression;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.ExecutionListener;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
/**
- 执行监听器
*
- 执行监听器允许在执行过程中执行Java代码。
- 执行监听器可以捕获事件的类型:
- 流程实例启动,结束
- 输出流捕获
- 获取启动,结束
- 路由开始,结束
- 中间事件开始,结束
- 触发开始事件,触发结束事件
*
- @author wangwei
- @date 2023-03-27-15:26:00
*
*/
@Slf4j
@Component
public class FlowExecutionListener implements ExecutionListener {
/**
* 流程设计器添加的参数
*/
private Expression param;
@Override
public void notify(DelegateExecution execution) {
//log.info("执行监听器:{}", JSON.toJSONString(execution));
SysUser user = SecurityUtils.getLoginUser().getUser();
RepositoryService repositoryService = ApplicationContextUtils.getBean(RepositoryService.class);
SysDeployFormMapper sysDeployFormMapper = ApplicationContextUtils.getBean(SysDeployFormMapper.class);
String deploymentIdSql = "SELECT DEPLOYMENT_ID_ FROM act_re_procdef WHERE id_ ='"+execution.getProcessDefinitionId()+"';";
String deploymentId = sysDeployFormMapper.selectGenericString(deploymentIdSql);
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
InputStream inputStream = repositoryService.getResourceAsStream(definition.getDeploymentId(), definition.getResourceName());
String xmlData = "";
try {
xmlData = IOUtils.toString(inputStream, StandardCharsets.UTF_8.name());
} catch (IOException e) {
e.printStackTrace();
}
execution.setVariable("assignee1","0");
}
}
2.2.9 任务监听器
import com.alibaba.fastjson2.JSON;
import com.AAA.common.core.domain.entity.SysUser;
import com.AAA.common.exception.BaseException;
import com.AAA.common.utils.SecurityUtils;
import com.AAA.common.utils.bean.ApplicationContextUtils;
import com.AAA.flowable.factory.FlowServiceFactory;
import com.AAA.flowable.service.IFlowTaskService;
import com.AAA.system.domain.vo.SysDeptUserBranchVo;
import com.AAA.system.mapper.SysDeployFormMapper;
import com.AAA.system.mapper.SysDeptMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.delegate.TaskListener;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.task.api.Task;
import org.flowable.task.service.delegate.DelegateTask;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
- 任务监听器
- create(创建):在任务被创建且所有的任务属性设置完成后才触发
- assignment(指派):在任务被分配给某个办理人之后触发
- complete(完成):在配置了监听器的上一个任务完成时触发
- delete(删除):在任务即将被删除前触发。请注意任务由completeTask正常完成时也会触发
*/
/*
- 服务直通 执行监听器
- 在 开始节点开始执行
- 在流程启动是设置 “上级组织”处理人,处理 在“上级组织” 流程步骤中的业务数据
*
*/
/*
- @author wangwei
- @date 2023-03-22 09:48:00
*/
@Slf4j
@Component
public class FlowTaskServerListener implements TaskListener {
@Override
public void notify(DelegateTask delegateTask) {
SysUser user = SecurityUtils.getLoginUser().getUser();
SysDeployFormMapper sysDeployFormMapper = ApplicationContextUtils.getBean(SysDeployFormMapper.class);
SysDeptMapper sysDeptMapper = ApplicationContextUtils.getBean(SysDeptMapper.class);
String managementOrg = user.getManagementOrgLevel();
//上级组织的 ct_code_p2
String ctCodeP1Sql = "select ct_code_p1 from t_dw_branch where ct_code_p2='"+managementOrg+"';";
String ctCodeP1 = sysDeployFormMapper.selectGenericString(ctCodeP1Sql);
StringBuffer stringBuffer = new StringBuffer();
if("admin".equals(user.getUserName()) || "rootadmin".equals(user.getUserName())){//admin 特殊处理
stringBuffer.append(user.getUserId());
}else {
SysDeptUserBranchVo sysDeptUserBranchVo = new SysDeptUserBranchVo();
sysDeptUserBranchVo.setCtCodeP2(ctCodeP1);
List<SysDeptUserBranchVo> sysDeptUserBranchVoList = sysDeptMapper.selectDeptUserpartymanBranch(sysDeptUserBranchVo);
if(sysDeptUserBranchVoList.size()<1){
throw new BaseException("上级组织 没有设置管理员,请运维人员设置管理员,再重新发起流程!");
}
//用户的部门id
for (SysDeptUserBranchVo sysDeptUserBranchVo1:sysDeptUserBranchVoList){
stringBuffer.append(sysDeptUserBranchVo1.getUserId()+",");
}
}
String userIdList = stringBuffer.toString();
String substring = userIdList.substring(0, userIdList.length() - 1);
log.info("执行监听器:{}", JSON.toJSONString(delegateTask));
// TODO 获取事件类型 delegateTask.getEventName(),可以通过监听器给任务执行人发送相应的通知消息
String deploymentIdSql = "SELECT DEPLOYMENT_ID_ FROM act_re_procdef WHERE id_ ='"+delegateTask.getProcessDefinitionId()+"';";
String deploymentId = sysDeployFormMapper.selectGenericString(deploymentIdSql);
RepositoryService repositoryService = ApplicationContextUtils.getBean(RepositoryService.class);
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
InputStream inputStream = repositoryService.getResourceAsStream(definition.getDeploymentId(), definition.getResourceName());
String xmlData = "";
try {
xmlData = IOUtils.toString(inputStream, StandardCharsets.UTF_8.name());
} catch (IOException e) {
e.printStackTrace();
}
// TODO
if ("发起".equals(delegateTask.getName()) || "create".equals(delegateTask.getEventName())) {
delegateTask.setVariable("assignee1",substring);
boolean isSubmit = xmlData.split("提交")[1].substring(0, 500).contains("isAdmin==true");
if(isSubmit==true){
delegateTask.setVariable("isAdmin", true, false);
//delegateTask.setVariable("assignee2","9999");
delegateTask.setAssignee(user.getUserId().toString());
}
} else {
delegateTask.setVariable("isAdmin", false, false);
}
}
}
3.0 数据库表,专业名词在这里不进行一一介绍, 请自行百度flowable官网