Bootstrap

springboot集成flowable

参考示例:RuoYi-flowable: 🌟 基于RuoYi-vue + flowable 6.7.2 的工作流管理 右上角点个 star、fork 🌟 持续关注更新哟 农业认养商城系统:https://gitee.com/tony2y/smart-breed智慧景区管理系统 :https://gitee.com/tony2y/scenic-spot

先上图

1.0接入项目目录 

2.0 项目集成配置

 2.1 流程模型图

  文件名称:demo-1.8.xml

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:bioc="http://bpmn.io/schema/bpmn/biocolor/1.0" xmlns:flowable="http://flowable.org/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.flowable.org/processdef">
  <process id="flow_7cum4yyi" name="flow_4km022rm" flowable:processCategory="null">
    <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" />
  </process>
  <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>
</definitions>

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;

/**
 * 任务监听器
 * <p>
 * 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官网

;