JEECG/SpringBoot集成flowable流程框架

news2024/11/20 16:29:34

IDEA安装Flowable BPMN visualizer插件

Flowable BPMN visualizer

pom.xml中引入flowable相关依赖

        <dependency>
            <groupId>org.flowable</groupId>
            <artifactId>flowable-spring-boot-starter</artifactId>
            <version>6.7.2</version>
        </dependency>
        <dependency>
            <groupId>org.flowable</groupId>
            <artifactId>flowable-ui-modeler-rest</artifactId>
            <version>6.7.2</version>
        </dependency>
        <dependency>
            <groupId>org.flowable</groupId>
            <artifactId>flowable-ui-modeler-conf</artifactId>
            <version>6.7.2</version>
        </dependency>

yml增加flowable配置

flowable:
  # 异步执行
  async-executor-activate: true
  # 自动更新数据库
  database-schema-update: true
  # 校验流程文件,默认校验resources下的processes文件夹里的流程文件
  process-definition-location-prefix: classpath*:/processes/
  process-definition-location-suffixes: "**.bpmn20.xml, **.bpmn"
  
  common:
    app:
      idm-admin:
        password: test
        user: test
      idm-url: http://localhost:8080/flowable-demo

项目中新增配置文件

FlowableConfig
package org.jeecg.config;

import org.flowable.spring.SpringProcessEngineConfiguration;
import org.flowable.spring.boot.EngineConfigurationConfigurer;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FlowableConfig implements EngineConfigurationConfigurer<SpringProcessEngineConfiguration> {

    @Override
    public void configure(SpringProcessEngineConfiguration springProcessEngineConfiguration) {
        springProcessEngineConfiguration.setActivityFontName("宋体");
        springProcessEngineConfiguration.setLabelFontName("宋体");
        springProcessEngineConfiguration.setAnnotationFontName("宋体");
    }
}
SecurityConfiguration
package org.jeecg.config;

import org.flowable.ui.common.security.SecurityConstants;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

/**
 * 绕过flowable的登录验证
 */
@Configuration
public class SecurityConfiguration {
    @Configuration(proxyBeanMethods = false)
    @Order(SecurityConstants.FORM_LOGIN_SECURITY_ORDER - 1)
    public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.headers().frameOptions().disable();
            http.csrf().disable().authorizeRequests().antMatchers("/modeler/**").permitAll();
        }
    }
}

流程Controller

package org.jeecg.controller;

import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.*;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;

@Slf4j
@RestController
@RequestMapping("askForLeave")
public class AskForLeaveFlowableController {
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private ProcessEngine processEngine;


    /**
     * 员工提交请假申请
     *
     * @param employeeNo 员工工号
     * @param name       姓名
     * @param reason     原因
     * @param days       天数
     * @return
     */
    @GetMapping("employeeSubmit")
    public String employeeSubmitAskForLeave(
            @RequestParam(value = "employeeNo") String employeeNo,
            @RequestParam(value = "name") String name,
            @RequestParam(value = "reason") String reason,
            @RequestParam(value = "days") Integer days) {
        HashMap<String, Object> map = new HashMap<>();
        /**
         * 员工编号字段来自于配置文件
         */
        map.put("employeeNo", employeeNo);
        map.put("name", name);
        map.put("reason", reason);
        map.put("days", days);
        /**
         *      key:配置文件中的下个处理流程id
         *      value:默认领导工号为002
         */
        map.put("leaderNo", "002");

        /**
         * askForLeave:为开启流程的id  与配置文件中的一致
         */
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("askForLeave", map);
        log.info("{},提交请假申请,流程id:{}", name, processInstance.getId());
        return "提交成功,流程id:"+processInstance.getId();
    }

    /**
     * 领导审核通过
     * @param employeeNo  员工工号
     * @return
     */
    @GetMapping("leaderExaminePass")
    public String leaderExamine(@RequestParam(value = "employeeNo") String employeeNo) {
        List<Task> taskList = taskService.createTaskQuery().taskAssignee(employeeNo).orderByTaskId().desc().list();
        if (null == taskList) {
            throw  new RuntimeException("当前员工没有任何申请");
        }
        for (Task task : taskList) {
            if (task == null) {
                log.info("任务不存在 ID:{};", task.getId());
                continue;
            }
            log.info("任务 ID:{};任务处理人:{};任务是否挂起:{}", task.getId(), task.getAssignee(), task.isSuspended());
            Map<String, Object> map = new HashMap<>();
            /**
             *      key:配置文件中的下个处理流程id
             *      value:默认老板工号为001
             */
            map.put("bossNo", "001");
            /**
             *      key:指定配置文件中的条件判断id
             *      value:指定配置文件中的审核条件
             */
            map.put("outcome", "通过");
            taskService.complete(task.getId(), map);
        }
        return "领导审核通过";
    }


    /**
     * 老板审核通过
     * @param leaderNo  领导工号
     * @return
     */
    @GetMapping("bossExaminePass")
    public String bossExamine(@RequestParam(value = "leaderNo") String leaderNo) {
        List<Task> taskList = taskService.createTaskQuery().taskAssignee(leaderNo).orderByTaskId().desc().list();
        if (null == taskList) {
            throw  new RuntimeException("当前员工没有任何申请");
        }
        for (Task task : taskList) {
            if (task == null) {
                log.info("任务不存在 ID:{};", task.getId());
                continue;
            }
            log.info("任务 ID:{};任务处理人:{};任务是否挂起:{}", task.getId(), task.getAssignee(), task.isSuspended());
            Map<String, Object> map = new HashMap<>();
            /**
             *     老板是最后的审批人   无需指定下个流程
             */
//            map.put("boss", "001");
            /**
             *      key:指定配置文件中的条件判断id
             *      value:指定配置文件中的审核条件
             */
            map.put("outcome", "通过");
            taskService.complete(task.getId(), map);
        }
        return "老板审核通过";
    }

    /**
     * 驳回
     *
     * @param employeeNo  员工工号
     * @return
     */
    @GetMapping("reject")
    public String reject(@RequestParam(value = "employeeNo") String employeeNo) {
        List<Task> taskList = taskService.createTaskQuery().taskAssignee(employeeNo).orderByTaskId().desc().list();
        if (null == taskList) {
            throw  new RuntimeException("当前员工没有任何申请");
        }
        for (Task task : taskList) {
            if (task == null) {
                log.info("任务不存在 ID:{};", task.getId());
                continue;
            }
            log.info("任务 ID:{};任务处理人:{};任务是否挂起:{}", task.getId(), task.getAssignee(), task.isSuspended());
            Map<String, Object> map = new HashMap<>();
            /**
             *      key:指定配置文件中的领导id
             *      value:指定配置文件中的审核条件
             */
            map.put("outcome", "驳回");
            taskService.complete(task.getId(), map);
        }
        return "申请被驳回";
    }


    /**
     * 生成流程图
     *
     * @param processId 任务ID
     */
    @GetMapping(value = "processDiagram")
    public void genProcessDiagram(HttpServletResponse httpServletResponse, String processId) throws Exception {
        ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();

        //流程走完的不显示图
        if (pi == null) {
            return;
        }
        Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).singleResult();
        //使用流程实例ID,查询正在执行的执行对象表,返回流程实例对象
        String InstanceId = task.getProcessInstanceId();
        List<Execution> executions = runtimeService
                .createExecutionQuery()
                .processInstanceId(InstanceId)
                .list();

        //得到正在执行的Activity的Id
        List<String> activityIds = new ArrayList<>();
        List<String> flows = new ArrayList<>();
        for (Execution exe : executions) {
            List<String> ids = runtimeService.getActiveActivityIds(exe.getId());
            activityIds.addAll(ids);
        }

        //获取流程图
        BpmnModel bpmnModel = repositoryService.getBpmnModel(pi.getProcessDefinitionId());
        ProcessEngineConfiguration engconf = processEngine.getProcessEngineConfiguration();
        ProcessDiagramGenerator diagramGenerator = engconf.getProcessDiagramGenerator();
        InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", activityIds, flows,
                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);
            }
        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
    }
}

创建流程【*.bpmn20.xml】

image.png

<?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:xsd="http://www.w3.org/2001/XMLSchema" xmlns:flowable="http://flowable.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.flowable.org/processdef">
    <process id="askForLeave" name="ask_for_leave_process" isExecutable="true">
        <startEvent id="sid-b3fcb298-124a-4dc3-b603-1397b392e1a5"/>
        <userTask id="employee" name="员工" flowable:assignee="#{employeeNo}" flowable:formFieldValidation="true">
            <documentation>员工提交申请</documentation>
        </userTask>
        <sequenceFlow id="sid-9a4f7da0-7df8-422c-8d93-fcfe6eed6454" sourceRef="sid-b3fcb298-124a-4dc3-b603-1397b392e1a5" targetRef="employee"/>
        <userTask id="leader" name="领导" flowable:assignee="#{leaderNo}" flowable:formFieldValidation="true"/>
        <sequenceFlow id="sid-cda53600-1fdd-4556-b1f4-434cdef4b44c" sourceRef="employee" targetRef="leader"/>
        <exclusiveGateway id="sid-53b678ee-c126-46be-9bb7-70efe235451c"/>
        <sequenceFlow id="sid-c18a730f-6932-4036-b105-a840204bbd1f" sourceRef="leader" targetRef="sid-53b678ee-c126-46be-9bb7-70efe235451c"/>
        <endEvent id="sid-dc057597-34a0-4835-bbbb-1b12f0e8e407"/>
        <sequenceFlow id="leaderExamine" sourceRef="sid-53b678ee-c126-46be-9bb7-70efe235451c" targetRef="sid-dc057597-34a0-4835-bbbb-1b12f0e8e407" name="领导审核不通过">
            <conditionExpression xsi:type="tFormalExpression">${outcome=='驳回'}</conditionExpression>
        </sequenceFlow>
        <userTask id="boss" name="老板" flowable:formFieldValidation="true" flowable:assignee="#{bossNo}"/>
        <sequenceFlow id="leaderExaminePass" sourceRef="sid-53b678ee-c126-46be-9bb7-70efe235451c" targetRef="boss" name="领导审核通过">
            <conditionExpression xsi:type="tFormalExpression">${outcome=='通过'}</conditionExpression>
        </sequenceFlow>
        <exclusiveGateway id="sid-17d3919b-99f0-4a2e-8914-3dfb7bc74046"/>
        <sequenceFlow id="sid-e4dd8e02-acc7-4e51-95d4-5a1ade5eb2fd" sourceRef="boss" targetRef="sid-17d3919b-99f0-4a2e-8914-3dfb7bc74046"/>
        <endEvent id="sid-311b83fa-5c04-48af-8491-4e2f9417c49c"/>
        <sequenceFlow id="bossExamine" sourceRef="sid-17d3919b-99f0-4a2e-8914-3dfb7bc74046" targetRef="sid-311b83fa-5c04-48af-8491-4e2f9417c49c" name="老板审核不通过">
            <conditionExpression xsi:type="tFormalExpression">${outcome=='驳回'}</conditionExpression>
        </sequenceFlow>
        <endEvent id="sid-3f6150ad-4b8c-47e9-a726-39f5dffd5e0a"/>
        <sequenceFlow id="bossExaminePass" sourceRef="sid-17d3919b-99f0-4a2e-8914-3dfb7bc74046" targetRef="sid-3f6150ad-4b8c-47e9-a726-39f5dffd5e0a" name="老板审核通过">
            <conditionExpression xsi:type="tFormalExpression">${outcome=='通过'}</conditionExpression>
        </sequenceFlow>
    </process>
    <bpmndi:BPMNDiagram id="BPMNDiagram_ask_for_leave">
        <bpmndi:BPMNPlane bpmnElement="askForLeave" id="BPMNPlane_ask_for_leave">
            <bpmndi:BPMNShape id="shape-c5da47a1-57a1-465c-a7f8-2aad63d19b47" bpmnElement="sid-b3fcb298-124a-4dc3-b603-1397b392e1a5">
                <omgdc:Bounds x="-203.0" y="-10.75" width="30.0" height="30.0"/>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape id="shape-71f351aa-e8f4-4656-9fa0-7979ddc1d916" bpmnElement="employee">
                <omgdc:Bounds x="-140.0" y="-10.5" width="61.0" height="29.5"/>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNEdge id="edge-a0cd4bce-af0a-40ce-8128-97629a5f4a23" bpmnElement="sid-9a4f7da0-7df8-422c-8d93-fcfe6eed6454">
                <omgdi:waypoint x="-173.0" y="4.25"/>
                <omgdi:waypoint x="-140.0" y="4.25"/>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNShape id="shape-6a814a53-e6e2-4453-bb4a-43a1167e5559" bpmnElement="leader">
                <omgdc:Bounds x="-46.5" y="-11.0" width="63.0" height="30.5"/>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNEdge id="edge-3a2944ef-43d6-4409-920d-9d3d1acd422f" bpmnElement="sid-cda53600-1fdd-4556-b1f4-434cdef4b44c">
                <omgdi:waypoint x="-79.0" y="4.25"/>
                <omgdi:waypoint x="-46.5" y="4.25"/>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNShape id="shape-bef28649-6416-4428-a3bd-43edb5c1b9c6" bpmnElement="sid-53b678ee-c126-46be-9bb7-70efe235451c">
                <omgdc:Bounds x="42.36" y="-15.75" width="40.0" height="40.0"/>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNEdge id="edge-fa69c266-5b3c-4e26-a4e2-3f58c271ebb4" bpmnElement="sid-c18a730f-6932-4036-b105-a840204bbd1f">
                <omgdi:waypoint x="16.5" y="4.25"/>
                <omgdi:waypoint x="42.36" y="4.25"/>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNShape id="shape-9d577a21-ca61-4e33-bf3e-c892557f1638" bpmnElement="sid-dc057597-34a0-4835-bbbb-1b12f0e8e407">
                <omgdc:Bounds x="47.36" y="54.97" width="30.0" height="30.0"/>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNEdge id="edge-5651dbf2-4118-4668-bbd6-0259282cc084" bpmnElement="leaderExamine">
                <omgdi:waypoint x="62.36" y="24.25"/>
                <omgdi:waypoint x="62.36" y="54.97"/>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNShape id="shape-1398abfb-fefc-4a16-881c-84a6c4b7b7f7" bpmnElement="boss">
                <omgdc:Bounds x="108.86" y="-12.75" width="68.0" height="34.0"/>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNEdge id="edge-3f5df081-8086-492f-a2c7-90aba1c1e4d7" bpmnElement="leaderExaminePass">
                <omgdi:waypoint x="82.36" y="4.25"/>
                <omgdi:waypoint x="108.86" y="4.25"/>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNShape id="shape-4932221b-736b-4e85-a319-0859dbeb3e6b" bpmnElement="sid-17d3919b-99f0-4a2e-8914-3dfb7bc74046">
                <omgdc:Bounds x="203.35999" y="-15.75" width="40.0" height="40.0"/>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNEdge id="edge-3daa1ef4-119f-4b98-a40e-0b9cb3b205ce" bpmnElement="sid-e4dd8e02-acc7-4e51-95d4-5a1ade5eb2fd">
                <omgdi:waypoint x="176.86" y="4.25"/>
                <omgdi:waypoint x="203.35999" y="4.25"/>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNShape id="shape-6becf929-e7e7-4153-a1d1-6175677742ca" bpmnElement="sid-311b83fa-5c04-48af-8491-4e2f9417c49c">
                <omgdc:Bounds x="208.35999" y="54.97" width="30.0" height="30.0"/>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNEdge id="edge-1f1a1414-f4f9-442a-97af-676878899415" bpmnElement="bossExamine">
                <omgdi:waypoint x="223.35999" y="24.25"/>
                <omgdi:waypoint x="223.35999" y="54.97"/>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNShape id="shape-919e70dd-5004-4066-8103-427901b5c1fd" bpmnElement="sid-3f6150ad-4b8c-47e9-a726-39f5dffd5e0a">
                <omgdc:Bounds x="275.86" y="-10.75" width="30.0" height="30.0"/>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNEdge id="edge-542631d7-42d7-4b2a-b467-da8fdba298a1" bpmnElement="bossExaminePass">
                <omgdi:waypoint x="243.35999" y="4.25"/>
                <omgdi:waypoint x="275.86" y="4.25"/>
            </bpmndi:BPMNEdge>
        </bpmndi:BPMNPlane>
    </bpmndi:BPMNDiagram>
</definitions>

<?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:xsd="http://www.w3.org/2001/XMLSchema" xmlns:flowable="http://flowable.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.flowable.org/processdef">
    <process id="askForLeave" name="ask_for_leave_process" isExecutable="true">
        <startEvent id="sid-b3fcb298-124a-4dc3-b603-1397b392e1a5"/>
        <userTask id="employee" name="员工" flowable:assignee="#{employeeNo}" flowable:formFieldValidation="true">
            <documentation>员工提交申请</documentation>
        </userTask>
        <sequenceFlow id="sid-9a4f7da0-7df8-422c-8d93-fcfe6eed6454" sourceRef="sid-b3fcb298-124a-4dc3-b603-1397b392e1a5" targetRef="employee"/>
        <userTask id="leader" name="领导" flowable:assignee="#{leaderNo}" flowable:formFieldValidation="true"/>
        <sequenceFlow id="sid-cda53600-1fdd-4556-b1f4-434cdef4b44c" sourceRef="employee" targetRef="leader"/>
        <exclusiveGateway id="sid-53b678ee-c126-46be-9bb7-70efe235451c"/>
        <sequenceFlow id="sid-c18a730f-6932-4036-b105-a840204bbd1f" sourceRef="leader" targetRef="sid-53b678ee-c126-46be-9bb7-70efe235451c"/>
        <endEvent id="sid-dc057597-34a0-4835-bbbb-1b12f0e8e407"/>
        <sequenceFlow id="leaderExamine" sourceRef="sid-53b678ee-c126-46be-9bb7-70efe235451c" targetRef="sid-dc057597-34a0-4835-bbbb-1b12f0e8e407" name="领导审核不通过">
            <conditionExpression xsi:type="tFormalExpression">${outcome=='驳回'}</conditionExpression>
        </sequenceFlow>
        <userTask id="boss" name="老板" flowable:formFieldValidation="true" flowable:assignee="#{bossNo}"/>
        <sequenceFlow id="leaderExaminePass" sourceRef="sid-53b678ee-c126-46be-9bb7-70efe235451c" targetRef="boss" name="领导审核通过">
            <conditionExpression xsi:type="tFormalExpression">${outcome=='通过'}</conditionExpression>
        </sequenceFlow>
        <exclusiveGateway id="sid-17d3919b-99f0-4a2e-8914-3dfb7bc74046"/>
        <sequenceFlow id="sid-e4dd8e02-acc7-4e51-95d4-5a1ade5eb2fd" sourceRef="boss" targetRef="sid-17d3919b-99f0-4a2e-8914-3dfb7bc74046"/>
        <endEvent id="sid-311b83fa-5c04-48af-8491-4e2f9417c49c"/>
        <sequenceFlow id="bossExamine" sourceRef="sid-17d3919b-99f0-4a2e-8914-3dfb7bc74046" targetRef="sid-311b83fa-5c04-48af-8491-4e2f9417c49c" name="老板审核不通过">
            <conditionExpression xsi:type="tFormalExpression">${outcome=='驳回'}</conditionExpression>
        </sequenceFlow>
        <endEvent id="sid-3f6150ad-4b8c-47e9-a726-39f5dffd5e0a"/>
        <sequenceFlow id="bossExaminePass" sourceRef="sid-17d3919b-99f0-4a2e-8914-3dfb7bc74046" targetRef="sid-3f6150ad-4b8c-47e9-a726-39f5dffd5e0a" name="老板审核通过">
            <conditionExpression xsi:type="tFormalExpression">${outcome=='通过'}</conditionExpression>
        </sequenceFlow>
    </process>
    <bpmndi:BPMNDiagram id="BPMNDiagram_ask_for_leave">
        <bpmndi:BPMNPlane bpmnElement="askForLeave" id="BPMNPlane_ask_for_leave">
            <bpmndi:BPMNShape id="shape-c5da47a1-57a1-465c-a7f8-2aad63d19b47" bpmnElement="sid-b3fcb298-124a-4dc3-b603-1397b392e1a5">
                <omgdc:Bounds x="-203.0" y="-10.75" width="30.0" height="30.0"/>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape id="shape-71f351aa-e8f4-4656-9fa0-7979ddc1d916" bpmnElement="employee">
                <omgdc:Bounds x="-140.0" y="-10.5" width="61.0" height="29.5"/>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNEdge id="edge-a0cd4bce-af0a-40ce-8128-97629a5f4a23" bpmnElement="sid-9a4f7da0-7df8-422c-8d93-fcfe6eed6454">
                <omgdi:waypoint x="-173.0" y="4.25"/>
                <omgdi:waypoint x="-140.0" y="4.25"/>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNShape id="shape-6a814a53-e6e2-4453-bb4a-43a1167e5559" bpmnElement="leader">
                <omgdc:Bounds x="-46.5" y="-11.0" width="63.0" height="30.5"/>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNEdge id="edge-3a2944ef-43d6-4409-920d-9d3d1acd422f" bpmnElement="sid-cda53600-1fdd-4556-b1f4-434cdef4b44c">
                <omgdi:waypoint x="-79.0" y="4.25"/>
                <omgdi:waypoint x="-46.5" y="4.25"/>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNShape id="shape-bef28649-6416-4428-a3bd-43edb5c1b9c6" bpmnElement="sid-53b678ee-c126-46be-9bb7-70efe235451c">
                <omgdc:Bounds x="42.36" y="-15.75" width="40.0" height="40.0"/>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNEdge id="edge-fa69c266-5b3c-4e26-a4e2-3f58c271ebb4" bpmnElement="sid-c18a730f-6932-4036-b105-a840204bbd1f">
                <omgdi:waypoint x="16.5" y="4.25"/>
                <omgdi:waypoint x="42.36" y="4.25"/>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNShape id="shape-9d577a21-ca61-4e33-bf3e-c892557f1638" bpmnElement="sid-dc057597-34a0-4835-bbbb-1b12f0e8e407">
                <omgdc:Bounds x="47.36" y="54.97" width="30.0" height="30.0"/>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNEdge id="edge-5651dbf2-4118-4668-bbd6-0259282cc084" bpmnElement="leaderExamine">
                <omgdi:waypoint x="62.36" y="24.25"/>
                <omgdi:waypoint x="62.36" y="54.97"/>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNShape id="shape-1398abfb-fefc-4a16-881c-84a6c4b7b7f7" bpmnElement="boss">
                <omgdc:Bounds x="108.86" y="-12.75" width="68.0" height="34.0"/>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNEdge id="edge-3f5df081-8086-492f-a2c7-90aba1c1e4d7" bpmnElement="leaderExaminePass">
                <omgdi:waypoint x="82.36" y="4.25"/>
                <omgdi:waypoint x="108.86" y="4.25"/>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNShape id="shape-4932221b-736b-4e85-a319-0859dbeb3e6b" bpmnElement="sid-17d3919b-99f0-4a2e-8914-3dfb7bc74046">
                <omgdc:Bounds x="203.35999" y="-15.75" width="40.0" height="40.0"/>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNEdge id="edge-3daa1ef4-119f-4b98-a40e-0b9cb3b205ce" bpmnElement="sid-e4dd8e02-acc7-4e51-95d4-5a1ade5eb2fd">
                <omgdi:waypoint x="176.86" y="4.25"/>
                <omgdi:waypoint x="203.35999" y="4.25"/>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNShape id="shape-6becf929-e7e7-4153-a1d1-6175677742ca" bpmnElement="sid-311b83fa-5c04-48af-8491-4e2f9417c49c">
                <omgdc:Bounds x="208.35999" y="54.97" width="30.0" height="30.0"/>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNEdge id="edge-1f1a1414-f4f9-442a-97af-676878899415" bpmnElement="bossExamine">
                <omgdi:waypoint x="223.35999" y="24.25"/>
                <omgdi:waypoint x="223.35999" y="54.97"/>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNShape id="shape-919e70dd-5004-4066-8103-427901b5c1fd" bpmnElement="sid-3f6150ad-4b8c-47e9-a726-39f5dffd5e0a">
                <omgdc:Bounds x="275.86" y="-10.75" width="30.0" height="30.0"/>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNEdge id="edge-542631d7-42d7-4b2a-b467-da8fdba298a1" bpmnElement="bossExaminePass">
                <omgdi:waypoint x="243.35999" y="4.25"/>
                <omgdi:waypoint x="275.86" y="4.25"/>
            </bpmndi:BPMNEdge>
        </bpmndi:BPMNPlane>
    </bpmndi:BPMNDiagram>
</definitions>

排除冲突

MybatisPlusSaasConfig:

@MapperScan(value={"org.jeecg.modules.**.mapper*"}, sqlSessionFactoryRef = "sqlSessionFactory", sqlSessionTemplateRef = "sqlSessionTemplate")

替换为:

@MapperScan(value={"org.jeecg.modules.**.mapper*"}, sqlSessionFactoryRef = "sqlSessionFactory", sqlSessionTemplateRef = "sqlSessionTemplate")

测试

提交请假申请

http://localhost:8080/jeecg-boot/askForLeave/employeeSubmit?name=Bruce&reason=有事&days=3&employeeNo=213

查看流程

http://localhost:8080/jeecg-boot/askForLeave/processDiagram?processId={processId}

领导审批

http://localhost:8080/jeecg-boot/askForLeave/leaderExaminePass?employeeNo=213

老板审批

http://localhost:8080/jeecg-boot/askForLeave/bossExaminePass?leaderNo=001

参考:
SpringBoot集成Flowable工作流-CSDN博客
Flowable-ui-modeler和MybatisPlus冲突问题_modelerdatabaseconfiguration-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1628984.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

kotlin 编写一个简单的天气预报app (七)使用material design

一、优化思路 对之前的天气预报的app进行了优化&#xff0c;原先的天气预报程序逻辑是这样的。 使用text和button组合了一个输入城市&#xff0c;并请求openweathermap对应数据&#xff0c;并显示的功能。 但是搜索城市的时候&#xff0c;可能会有错误&#xff0c;比如大小写…

SpringBoot项目启动,传参有哪些方式?

SpringBoot项目启动&#xff0c;传参有哪些方式&#xff1f; 1.Spring级别的参数 直接在启动 Spring Boot 应用的命令行中使用 -- 后跟参数名和值的方式来传递参数。 记住&#xff1a;一般是对于Spring Boot应用特有的配置参数&#xff0c;确保它们遵循Spring Boot的配置属性命…

Mediasoup-demo 本地启动步骤(超详细)

Mediasoup-demo 本地启动步骤&#xff08;超详细&#xff09; 一.本人环境 系统&#xff1a;macos13.6.3 node: v16.20.2 npm:8.19.4 python: 3.9.6 二.下载代码 git 下载代码&#xff1a; git clone gitgithub.com:versatica/mediasoup-demo.git 三.代码介绍 下载下来…

电磁仿真--基本操作-CST-(4)

目录 1. 简介 2. 建模过程 2.1 基本的仿真配置 2.2 构建两个圆环体和旋转轴 2.3 切分圆环体 2.4 衔接内外环 2.5 保留衔接部分 2.6 绘制内螺旋 2.7 绘制外螺旋 2.8 查看完整体 2.9 绘制引脚 2.10 设置端口 2.11 仿真结果 3. 使用Digilent AD2进行测试 3.1 进行…

十、多模态大语言模型(MLLM)

1 多模态大语言模型&#xff08;Multimodal Large Language Models&#xff09; 模态的定义 模态&#xff08;modal&#xff09;是事情经历和发生的方式&#xff0c;我们生活在一个由多种模态(Multimodal)信息构成的世界&#xff0c;包括视觉信息、听觉信息、文本信息、嗅觉信…

Java 提取HTML文件中的文本内容

从 HTML 文件中提取文本内容是数据抓取中的一个常见任务&#xff0c;你可以将提取的文本信息用于编制报告、进行数据分析或其他处理。本文分享如何使用免费 Java API 从HTML 文件中提取文本内容。 安装免费Java库&#xff1a; 要通过Java提取HTML文本&#xff0c;需要用到Free…

基于车载点云数据的城市道路特征目标提取与三维重构

作者&#xff1a;邓宇彤&#xff0c;李峰&#xff0c;周思齐等 来源&#xff1a;《北京工业大学学报》 编辑&#xff1a;东岸因为一点人工一点智能公众号 基于车载点云数据的城市道路特征目标提取与三维重构本研究旨在弥补现有研究在处理复杂环境和大数据量上的不足&#xf…

灯塔:MySQL笔记 (1)

数据库相关概念 名称全称简称数据库存储数据的仓库&#xff0c;数据有组织的进行存储DateBase(DB)数据库管理系统操控和管理数据据库的大型软件DateBase Management System (DBSM)SQL操作关系型数据库的编程语言&#xff0c;定义了一套操作关系型数据库——标准Structured Que…

python生成二维码及进度条源代码

一、进度条 1、利用time模块实现 import time for i in range(0, 101, 2):time.sleep(0.3)num i // 2if i 100:process "\r[%3s%% ]: |%-50s|\n" % (i, # * num)else:process "\r[%3s%% ]: |%-50s|" % (i, # * num)print(process, end, flushTrue)2、使…

CentOS/Anolis的Linux系统如何通过VNC登录远程桌面?

综述 需要在server端启动vncserver&#xff0c;推荐tigervnc的server 然后再本地点来启动client进行访问&#xff0c;访问方式是IPport&#xff08;本质是传递数据包到某个ip的某个port&#xff09; 然后需要防火墙开启端口 服务器上&#xff1a;安装和启动服务 安装服务 y…

vivado Aurora 8B/10B IP核(1)

Aurora 8B/10B IP 支持 Kintex -7, Virtex -7 FPGA GTP 和 GTH 收发器&#xff0c;Artix -7 FPGA GTP 收发器, Zynq -7000 GTP and GTP 收发器。Aurora 8B/10B IP core 可以工作于单工或者全双工模式。IP CODE的使用也非常简单&#xff0c;支持 AMBA总线的 AXI4-Stream 协议。…

2024蓝桥杯CTF--逆向

蓝桥杯付费CT--逆向 题目&#xff1a;RC4题目&#xff1a;happytime总结&#xff1a; 题目&#xff1a;RC4 先查壳&#xff0c;无壳&#xff0c;并且是32位&#xff1a; 用32位的ida打开&#xff0c;直接定位到main函数&#xff1a; 重点关注sub_401005函数&#xff0c;这个应…

编程学习系列(1):计算机发展及应用(1)

前言&#xff1a; 最近我在整理书籍时&#xff0c;发现了一些有关于编程的学习资料&#xff0c;我派蒙也不是个吝啬的人&#xff0c;从今天开始就陆续分享给大家。 计算机发展及应用&#xff08;1&#xff09; 1944 年美国数学家冯诺依曼&#xff08;现代计算机之父&#xff…

【Redis 开发】Redis持久化(RDB和AOF)

Redis持久化 RDBAOFRDB和AOF的区别 RDB RDB全称Redis DataBase Backup file &#xff08;Redis数据备份文件&#xff09;&#xff0c;也被称为Redis数据快照&#xff0c;简单来说就是把内存中的所有数据都记录到磁盘中&#xff0c;当Redis实例故障重启后&#xff0c;从磁盘读取…

GPU:使用gpu-burn压测GPU

简介&#xff1a;在测试GPU的性能问题时&#xff0c;通常需要考虑电力和散热问题。使用压力测试工具&#xff0c;可以测试GPU满载时的状态参数&#xff08;如温度等&#xff09;。gpu_burn是一个有效的压力测试工具。通过以下步骤可以进行测试。 官网&#xff1a; http://www…

Xline中区间树实现小结

Table of Contents 实现区间树的起因区间树实现简介 插入/删除查询重叠操作使用Safe Rust实现区间树 问题Rc<RefCell<T>> i. 线程安全问题其他智能指针 i. Arc<Mutex<T>>? ii. QCell数组模拟指针总结 01、实现区间树的起因 在Xline最近的一次重构中…

基于PI控制器的DC-DC结构PWM系统simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 基于PI控制器的DC-DC结构PWM系统simulink建模与仿真。包括IGBT结构&#xff0c;PI控制器结构&#xff0c;PWM模块等。 2.系统仿真结果 3.核心程序与模型 版本&#xff1a;MA…

【yolov8算法道路-墙面裂缝检测-汽车车身凹陷-抓痕-损伤检测】

yolo算法道路-墙面裂缝检测-汽车车身凹陷-抓痕-损伤检测 1. yolo算法裂缝检测-汽车车身凹陷-抓痕检测-汽车车身损伤检测2. yolo房屋墙面路面裂缝-发霉-油漆脱落-渗水-墙皮脱落检测3. 水泥墙面裂缝检测 YOLOv8算法是一种先进的目标检测技术&#xff0c;它基于YOLO系列算法的改进…

上位机图像处理和嵌入式模块部署(树莓派4b之wifi切换)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前期我们在烧录镜像的时候&#xff0c;一般会配置一个默认的、带wifi配置的镜像。这主要是为了通过局域网扫描&#xff0c;或者输入arp -a的方式&a…

PySide6 GUI 学习笔记——Python文件编译打包

前面编写的软件工具都必须运行在Python环境中&#xff0c;且通过命令行的方式运行&#xff0c;通过Python打包工具&#xff0c;我们可以把.py文件封装成对应平台的运行文件&#xff0c;供用户执行。 常见Python打包工具 工具简介官网/文档地址py2exe将Python脚本转换为Window…