activiti项目使用总结

  • activiti初始化配置
/**
 * Copyright (c) 2017 Avant-Port All Rights Reserved.
 */
package com.avp.mem.njpb.config;

import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.List;

/**
 * 初始化Activiti配置
 *  * @author Amber
 */
@Component
public class ActivitiInitConfig {

    protected static final Logger LOGGER = LoggerFactory.getLogger(ActivitiInitConfig.class);

    @Autowired
    protected RepositoryService repositoryService;

    @PostConstruct
    public void init() {
        initProcessDefinitions();
        initProcess();
    }

    /**
     * 为了让Activiti引擎知道这个流程,我们必须先进行“发布”。
     * 发布意味着引擎会把BPMN 2.0 xml解析成可以执行的东西, “发布包”中的所有流程定义都会添加到数据库中。
     * 这样,当引擎重启时,它依然可以获得“已发布”的流程。
     */
    protected void initProcessDefinitions() {
        String deploymentName = "workorder processes";
        List<Deployment> deploymentList = repositoryService.createDeploymentQuery().deploymentName(deploymentName).list();

        if (deploymentList == null || deploymentList.isEmpty()) {
            Deployment deployment = repositoryService.createDeployment()
                    .name(deploymentName)
                    .addClasspathResource("diagrams/workorder/workorder.bpmn")
                    .deploy();

            LOGGER.debug("流程【{}】发布成功,流程ID为:{}", deploymentName, deployment.getId());
        }
    }
}
  • 重写TaskListener
/**
 * Copyright (c) 2017 Avant-Port All Rights Reserved.
 */
package com.avp.mem.njpb.config.handler;

import org.activiti.engine.IdentityService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.TaskListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
 * Created by Amber Wang on 2017-08-18 下午 06:04.
 */
@Component
public class CustomCreateEventHandler implements TaskListener {

    private static final Logger LOGGER = LoggerFactory.getLogger(CustomCreateEventHandler.class);

    @Autowired
    private IdentityService identityService;

    @Autowired
    private RuntimeService runtimeService;

    @PostConstruct
    void init() {
        LOGGER.debug("bean customCreateEventHandler is creating...");
    }

    /**
     * 监听每个task的create事件
     *
     * @param delegateTask
     */
    @Override
    public void notify(DelegateTask delegateTask) {

        String assignEmployee = (String) runtimeService.getVariable(delegateTask.getExecutionId(), "taskAssignEmployee");

        String processInstanceId = delegateTask.getProcessInstanceId();

        String taskDefinitionKey = delegateTask.getTaskDefinitionKey();

        String currentActivityId = delegateTask.getExecution().getCurrentActivityId();

        LOGGER.debug("流程id为:{},taskDefinitionKey:{},currentActivityId:{},assignEmployee:{}", processInstanceId, taskDefinitionKey, currentActivityId, assignEmployee);

        delegateTask.setAssignee(assignEmployee);
    }
}
  • 重写ExecutionListener
/**
 * Copyright (c) 2017 Avant-Port All Rights Reserved.
 */
package com.avp.mem.njpb.config.handler;

import com.avp.mem.njpb.entity.workorder.ObjWorkOrder;
import com.avp.mem.njpb.repository.workorder.ObjWorkOrderRepository;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.ExecutionListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
 * Created by Amber Wang on 2017-08-18 下午 06:04.
 */
@Component
public class CustomTakeEventHandler implements ExecutionListener {

    private static final Logger LOGGER = LoggerFactory.getLogger(CustomTakeEventHandler.class);

    @Autowired
    private IdentityService identityService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private ObjWorkOrderRepository objWorkOrderRepository;

    @PostConstruct
    void init() {
        LOGGER.debug("bean customTakeEventHandler is creating...");
    }

    @Override
    public void notify(DelegateExecution delegateExecution) throws Exception {

        String processInstanceId = delegateExecution.getProcessInstanceId();
        LOGGER.debug("take事件触发,流程id为:{}", processInstanceId);

        ObjWorkOrder objWorkOrder = objWorkOrderRepository.findByProcessInstanceId(processInstanceId);

        Integer assignEmployee = objWorkOrder.getAssignEmployee();
        LOGGER.debug("工单:{}的调度人为:{}", objWorkOrder.getId(), assignEmployee);

        delegateExecution.setVariable("taskAssignEmployee", assignEmployee);
    }
}
  • service中启动流程、获取流程下一步操作、完成节点task
/**
 * Copyright (c) 2017 Avant-Port All Rights Reserved.
 */
package com.avp.mem.njpb.service.activiti;

import com.avp.mem.njpb.entity.stock.ObjStockWorkOrder;
import com.avp.mem.njpb.entity.workorder.ObjWorkOrder;
import com.avp.mem.njpb.util.Validator;
import org.activiti.engine.FormService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmActivity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * 该部分功能点:启动维修工单流程、获取下一节点操作、完成节点任务
 * <p>
 * Created by Amber Wang on 2017-07-04 下午 03:56.
 */
@Service
@Transactional
public class ActivitiService {

    private static Logger LOGGER = LoggerFactory.getLogger(WorkOrderWorkflowService.class);

    @Autowired
    protected RepositoryService repositoryService;

    @Autowired
    protected FormService formService;

    @Autowired
    protected RuntimeService runtimeService;

    @Autowired
    protected TaskService taskService;

    @Autowired
    protected IdentityService identityService;

    @Value("${business.service.processKey}")
    private String repairWoProcessKey;

    @Value("${business.service.processKeyOfStock}")
    private String stockWoProcessKey;

    /**
     * 启动维修工单流程
     *
     * @param entity
     */
    public String startRepairWorkflow(ObjWorkOrder entity) {
        String businessKey = entity.getId().toString();

        ProcessInstance processInstance = null;
        String processInstanceId = "";
        try {
            // 用来设置启动流程的人员ID,引擎会自动把用户ID保存到activiti:initiator中
            identityService.setAuthenticatedUserId(entity.getCreateBy().toString());

            Map<String, Object> params = new HashMap<>();
            params.put("taskAssignEmployee", entity.getAssignEmployee().toString());

            processInstance = runtimeService.startProcessInstanceByKey(repairWoProcessKey, businessKey, params);

            processInstanceId = processInstance.getId();

            LOGGER.debug("start process of key={}, businessKey={}, processInstanceId={}", entity.getId(), businessKey, processInstanceId);

        } finally {
            identityService.setAuthenticatedUserId(null);
        }
        return processInstanceId;
    }

    /**
     * 获取下一节点操作
     *
     * @param processInstanceId
     * @return
     * @throws Exception
     */
    public List<String> getTaskOperation(String processInstanceId) throws Exception {
        List<String> nextOperation = new ArrayList<>();
        /*Execution execution = runtimeService.createExecutionQuery().executionId(processInstanceId).singleResult();//执行实例
        Object property = PropertyUtils.getProperty(execution, "activityId");
        String activityId = "";
        if (property != null) {
            activityId = property.toString();
        }
*/
        Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
        if (Validator.isNull(task)) {
            LOGGER.debug("该流程:{}已经完成", processInstanceId);
            return nextOperation;
        }

        String activityId = task.getTaskDefinitionKey();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId)
                .singleResult();
        ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
                .getDeployedProcessDefinition(processInstance.getProcessDefinitionId());

//            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId)
//                    .singleResult();
//            ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
//                    .getDeployedProcessDefinition(processInstance.getProcessDefinitionId());

        ActivityImpl activityImpl = processDefinition.findActivity(activityId);

        List<PvmTransition> outTransitions = activityImpl.getOutgoingTransitions();

        for (PvmTransition tr : outTransitions) {

            String type = (String) tr.getDestination().getProperty("type");

            if ("exclusiveGateway".equals(type)) {
                //说明是网关
                PvmActivity ac = tr.getDestination(); //获取线路的终点节点
                System.out.println("下一步任务任务:" + ac.getProperty("name"));

                List<PvmTransition> pvmTransitions = ac.getOutgoingTransitions();

                pvmTransitions.forEach(pvmTransition -> {
                    LOGGER.debug("网关的操作为:{}", pvmTransition.getId());
                    nextOperation.add(pvmTransition.getId());
                });
            } else if ("userTask".equals(type) || "endEvent".equals(type)) {
                //TODO 判断是task获取当前的flowid
                LOGGER.debug("节点类型是userTask或者endEvent,flow ID是:{}", tr.getId());
                nextOperation.add(tr.getId());
            }
        }
        return nextOperation;

    }

    /**
     * 完成节点任务
     *
     * @param taskVariables
     * @param processInstanceId
     */
    public void completeTask(Map<String, Object> taskVariables, String processInstanceId) {
        taskVariables.forEach((k, v) -> System.out.println("task参数----> key : " + k + " value : " + v));

        // 设置当前任务信息
        Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).active().orderByTaskCreateTime().desc().singleResult();
        LOGGER.debug("task:{},名称为:{}", task.getId(), task.getName());

        taskService.complete(task.getId(), taskVariables);

        LOGGER.debug("Task:{}完成,参数为:{}", task.getId(), taskVariables.toString());

    }
}
  • ActivitiController(使用不大,只用于重新部署流程)
/**
 * Copyright (c) 2017 Avant-Port All Rights Reserved.
 */
package com.avp.mem.njpb.controller;

import com.avp.mem.njpb.api.rest.ResponseBuilder;
import com.avp.mem.njpb.api.rest.ResponseCode;
import com.avp.mem.njpb.api.rest.RestBody;
import com.avp.mem.njpb.config.ExtensionOperation;
import com.avp.mem.njpb.entity.workorder.ObjWorkOrder;
import com.avp.mem.njpb.service.activiti.ActivitiService;
import com.avp.mem.njpb.util.Validator;
import org.activiti.engine.FormService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.form.FormProperty;
import org.activiti.engine.form.TaskFormData;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmActivity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.beanutils.PropertyUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Amber Wang on 2017-07-07 下午 04:41.
 */
@RestController
public class ActivitiController {

    private static final Logger LOGGER = LoggerFactory.getLogger(ActivitiController.class);

    @Autowired
    protected RepositoryService repositoryService;

    @Autowired
    protected FormService formService;

    @Autowired
    protected RuntimeService runtimeService;

    @Autowired
    protected TaskService taskService;

    @Autowired
    protected IdentityService identityService;

    @Autowired
    private ActivitiService activitiService;

    /**
     * 重新部署流程
     *
     * @return
     */
    @RequestMapping(value = "workflows/redeploy")
    public ResponseEntity<RestBody> redeployAll() {
        ResponseBuilder build = ResponseBuilder.createBuilder();
        try {
            String deploymentName = "workorder processes";

            Deployment deployment = repositoryService.createDeployment()
                    .name(deploymentName)
                    .addClasspathResource("diagrams/workorder/workorder.bpmn")
                    .deploy();

            String deploymentId = deployment.getId();

            LOGGER.debug("流程重新部署成功,流程ID:{}", deploymentId);

            build.setResponseCode(ResponseCode.UPDATE_SUCCEED, "流程【" + deploymentId + "】重新部署成功");
        } catch (Exception e) {
            e.printStackTrace();
            build.setResponseCode(ResponseCode.BAD_REQUEST, "流程重新部署失败");
        }

        return build.getResponseEntity();
    }

    /**
     * 重新部署流程
     *
     * @return
     */
    @RequestMapping(value = "stockWorkflows/redeploy")
    public ResponseEntity<RestBody> redeployStockAll() {
        ResponseBuilder build = ResponseBuilder.createBuilder();
        try {
            String deploymentNameOfStock = "stockWorkOrder processes";

            Deployment deployment = repositoryService.createDeployment()
                    .name(deploymentNameOfStock)
                    .addClasspathResource("diagrams/workorder/stockWorkOrder.bpmn")
                    .deploy();

            String deploymentId = deployment.getId();

            LOGGER.debug("流程重新部署成功,流程ID:{}", deploymentId);

            build.setResponseCode(ResponseCode.UPDATE_SUCCEED, "流程【" + deploymentId + "】重新部署成功");
        } catch (Exception e) {
            e.printStackTrace();
            build.setResponseCode(ResponseCode.BAD_REQUEST, "流程重新部署失败");
        }

        return build.getResponseEntity();
    }

    /**
     * 查询角色的待办事项--暂不使用
     *
     * @param role
     * @return
     */
    @RequestMapping(value = "workflows/getTaskByRole")
    public ResponseEntity<RestBody> getTaskByRole(String role) {
        ResponseBuilder build = ResponseBuilder.createBuilder();
        try {
            List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup(role).list();

            for (Task task : tasks) {
                LOGGER.debug("Following task is available for sales group:{},group is :{}", task.getName(), role);
                //为工单表中存放的id
                String processInstanceId = task.getProcessInstanceId();

                LOGGER.debug("工单中的流程id为:{}", processInstanceId);
            }
        } catch (Exception e) {
            e.printStackTrace();
            build.setResponseCode(ResponseCode.BAD_REQUEST, "流程重新部署失败");
        }

        return build.getResponseEntity();
    }

    //获取当前人的任务
    @RequestMapping(value = "/tasks", method = RequestMethod.GET)
    public List<Map<String, Object>> getTasks(@RequestParam String assignee) {
        List<Task> tasks = taskService.createTaskQuery().taskAssignee(assignee).list();

        List<Map<String, Object>> dtos = new ArrayList<>();

        for (Task task : tasks) {
            Map<String, Object> map = new HashMap<>();
            map.put(task.getId(), task.getName());
            dtos.add(map);
        }
        return dtos;
    }
}
  • 附录配置文件代码
<?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:activiti="http://activiti.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.activiti.org/test">
    <process id="process-workorder" name="工单流程" isExecutable="true">
        <startEvent id="startevent" name="Start"></startEvent>
        <userTask id="usertask_report_check" name="报修审核">
            <extensionElements>
                <activiti:taskListener event="create"
                                       delegateExpression="${customCreateEventHandler}"></activiti:taskListener>
            </extensionElements>
        </userTask>
        <userTask id="usertask_modify_report" name="调整报修内容">
            <extensionElements>
                <activiti:taskListener event="create"
                                       delegateExpression="${customCreateEventHandler}"></activiti:taskListener>
            </extensionElements>
        </userTask>
        <userTask id="usertask_repair_check" name="维修审核">
            <extensionElements>
                <activiti:taskListener event="create"
                                       delegateExpression="${customCreateEventHandler}"></activiti:taskListener>
            </extensionElements>
        </userTask>
        <userTask id="usertask_confirm_wo" name="工单确认">
            <extensionElements>
                <activiti:taskListener event="create"
                                       delegateExpression="${customCreateEventHandler}"></activiti:taskListener>
            </extensionElements>
        </userTask>
        <userTask id="usertask_reAssign" name="工单再次派发" activiti:assignee="${woAssignEmployee}">
            <!--<extensionElements>-->
            <!--<activiti:taskListener event="create" delegateExpression="${customCreateEventHandler}"></activiti:taskListener>-->
            <!--</extensionElements>-->
        </userTask>
        <userTask id="usertask_repair" name="工单维修">
            <extensionElements>
                <activiti:taskListener event="create"
                                       delegateExpression="${customCreateEventHandler}"></activiti:taskListener>
            </extensionElements>
        </userTask>
        <userTask id="usertask_sign_in" name="工单签到">
            <extensionElements>
                <activiti:taskListener event="create"
                                       delegateExpression="${customCreateEventHandler}"></activiti:taskListener>
            </extensionElements>
        </userTask>
        <endEvent id="endevent" name="End"></endEvent>
        <exclusiveGateway id="exclusivegateway_reportCheck" name="Exclusive Gateway1"></exclusiveGateway>
        <exclusiveGateway id="exclusivegateway_reReport" name="Parallel Gateway"></exclusiveGateway>
        <sequenceFlow id="flow_reportWo" name="报修" sourceRef="startevent"
                      targetRef="usertask_report_check"></sequenceFlow>
        <sequenceFlow id="flow_report_agree" name="报修审核同意" sourceRef="exclusivegateway_reportCheck"
                      targetRef="usertask_confirm_wo">
            <conditionExpression xsi:type="tFormalExpression"><![CDATA[${groupLeaderPassReport}]]></conditionExpression>
        </sequenceFlow>
        <sequenceFlow id="flow2" sourceRef="usertask_report_check"
                      targetRef="exclusivegateway_reportCheck"></sequenceFlow>
        <sequenceFlow id="flow_report_reject" name="报修审核不同意" sourceRef="exclusivegateway_reportCheck"
                      targetRef="usertask_modify_report">
            <conditionExpression xsi:type="tFormalExpression">
                <![CDATA[${!groupLeaderPassReport}]]></conditionExpression>
        </sequenceFlow>
        <sequenceFlow id="flow_endReport" name="结束报修流程" sourceRef="exclusivegateway_reReport" targetRef="endevent">
            <conditionExpression xsi:type="tFormalExpression"><![CDATA[${!repeatReport}]]></conditionExpression>
        </sequenceFlow>
        <sequenceFlow id="flow6" sourceRef="usertask_modify_report"
                      targetRef="exclusivegateway_reReport"></sequenceFlow>
        <sequenceFlow id="flow_reReport" name="重新报修" sourceRef="exclusivegateway_reReport"
                      targetRef="usertask_report_check">
            <conditionExpression xsi:type="tFormalExpression"><![CDATA[${repeatReport}]]></conditionExpression>
        </sequenceFlow>
        <sequenceFlow id="flow_reAssign" name="再次派发" sourceRef="usertask_reAssign"
                      targetRef="usertask_confirm_wo"></sequenceFlow>
        <sequenceFlow id="flow_repair_check" name="工单完成" sourceRef="usertask_repair_check" targetRef="endevent"></sequenceFlow>
        <sequenceFlow id="flow_repair_complete" name="维修完成或遗留" sourceRef="usertask_repair"
                      targetRef="usertask_repair_check"></sequenceFlow>
        <sequenceFlow id="flow_confirm_wo" name="工单确认" sourceRef="usertask_confirm_wo"
                      targetRef="usertask_sign_in"></sequenceFlow>
        <sequenceFlow id="flow_sign_in" name="签到" sourceRef="usertask_sign_in"
                      targetRef="usertask_repair"></sequenceFlow>
        <boundaryEvent id="boundarytimer2" name="Timer" attachedToRef="usertask_confirm_wo" cancelActivity="true">
            <timerEventDefinition>
                <timeDuration>${responseTimeOut_time}</timeDuration>
            </timerEventDefinition>
        </boundaryEvent>
        <sequenceFlow id="flow_response_timeout" name="响应超时" sourceRef="boundarytimer2" targetRef="usertask_reAssign">
            <!--<extensionElements>-->
            <!--<activiti:executionListener event="start" delegateExpression="${customTaskEventHandler}" ></activiti:executionListener>-->
            <!--</extensionElements>-->
        </sequenceFlow>
    </process>
    <bpmndi:BPMNDiagram id="BPMNDiagram_process-workorder">
        <bpmndi:BPMNPlane bpmnElement="process-workorder" id="BPMNPlane_process-workorder">
            <bpmndi:BPMNShape bpmnElement="startevent" id="BPMNShape_startevent">
                <omgdc:Bounds height="35.0" width="35.0" x="1.0" y="120.0"></omgdc:Bounds>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape bpmnElement="usertask_report_check" id="BPMNShape_usertask_report_check">
                <omgdc:Bounds height="60.0" width="100.0" x="113.0" y="108.0"></omgdc:Bounds>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape bpmnElement="usertask_modify_report" id="BPMNShape_usertask_modify_report">
                <omgdc:Bounds height="60.0" width="100.0" x="357.0" y="335.0"></omgdc:Bounds>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape bpmnElement="usertask_repair_check" id="BPMNShape_usertask_repair_check">
                <omgdc:Bounds height="60.0" width="100.0" x="1050.0" y="478.0"></omgdc:Bounds>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape bpmnElement="usertask_confirm_wo" id="BPMNShape_usertask_confirm_wo">
                <omgdc:Bounds height="60.0" width="100.0" x="640.0" y="106.0"></omgdc:Bounds>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape bpmnElement="boundarytimer2" id="BPMNShape_boundarytimer2">
                <omgdc:Bounds height="30.0" width="30.0" x="712.0" y="132.0"></omgdc:Bounds>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape bpmnElement="usertask_reAssign" id="BPMNShape_usertask_reAssign">
                <omgdc:Bounds height="60.0" width="100.0" x="677.0" y="310.0"></omgdc:Bounds>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape bpmnElement="usertask_repair" id="BPMNShape_usertask_repair">
                <omgdc:Bounds height="60.0" width="100.0" x="1090.0" y="255.0"></omgdc:Bounds>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape bpmnElement="usertask_sign_in" id="BPMNShape_usertask_sign_in">
                <omgdc:Bounds height="60.0" width="100.0" x="1240.0" y="108.0"></omgdc:Bounds>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape bpmnElement="endevent" id="BPMNShape_endevent">
                <omgdc:Bounds height="35.0" width="35.0" x="649.0" y="490.0"></omgdc:Bounds>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape bpmnElement="exclusivegateway_reportCheck" id="BPMNShape_exclusivegateway_reportCheck">
                <omgdc:Bounds height="40.0" width="40.0" x="392.0" y="115.0"></omgdc:Bounds>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape bpmnElement="exclusivegateway_reReport" id="BPMNShape_exclusivegateway_reReport">
                <omgdc:Bounds height="40.0" width="40.0" x="142.0" y="487.0"></omgdc:Bounds>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNEdge bpmnElement="flow_reportWo" id="BPMNEdge_flow_reportWo">
                <omgdi:waypoint x="36.0" y="137.0"></omgdi:waypoint>
                <omgdi:waypoint x="113.0" y="138.0"></omgdi:waypoint>
                <bpmndi:BPMNLabel>
                    <omgdc:Bounds height="14.0" width="24.0" x="59.0" y="115.0"></omgdc:Bounds>
                </bpmndi:BPMNLabel>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNEdge bpmnElement="flow_report_agree" id="BPMNEdge_flow_report_agree">
                <omgdi:waypoint x="432.0" y="135.0"></omgdi:waypoint>
                <omgdi:waypoint x="640.0" y="136.0"></omgdi:waypoint>
                <bpmndi:BPMNLabel>
                    <omgdc:Bounds height="14.0" width="72.0" x="488.0" y="115.0"></omgdc:Bounds>
                </bpmndi:BPMNLabel>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
                <omgdi:waypoint x="213.0" y="138.0"></omgdi:waypoint>
                <omgdi:waypoint x="392.0" y="135.0"></omgdi:waypoint>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNEdge bpmnElement="flow_report_reject" id="BPMNEdge_flow_report_reject">
                <omgdi:waypoint x="412.0" y="155.0"></omgdi:waypoint>
                <omgdi:waypoint x="407.0" y="335.0"></omgdi:waypoint>
                <bpmndi:BPMNLabel>
                    <omgdc:Bounds height="14.0" width="84.0" x="363.0" y="241.0"></omgdc:Bounds>
                </bpmndi:BPMNLabel>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNEdge bpmnElement="flow_endReport" id="BPMNEdge_flow_endReport">
                <omgdi:waypoint x="182.0" y="507.0"></omgdi:waypoint>
                <omgdi:waypoint x="649.0" y="507.0"></omgdi:waypoint>
                <bpmndi:BPMNLabel>
                    <omgdc:Bounds height="14.0" width="72.0" x="357.0" y="491.0"></omgdc:Bounds>
                </bpmndi:BPMNLabel>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6">
                <omgdi:waypoint x="407.0" y="395.0"></omgdi:waypoint>
                <omgdi:waypoint x="162.0" y="487.0"></omgdi:waypoint>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNEdge bpmnElement="flow_reReport" id="BPMNEdge_flow_reReport">
                <omgdi:waypoint x="162.0" y="487.0"></omgdi:waypoint>
                <omgdi:waypoint x="163.0" y="168.0"></omgdi:waypoint>
                <bpmndi:BPMNLabel>
                    <omgdc:Bounds height="14.0" width="48.0" x="110.0" y="395.0"></omgdc:Bounds>
                </bpmndi:BPMNLabel>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNEdge bpmnElement="flow_reAssign" id="BPMNEdge_flow_reAssign">
                <omgdi:waypoint x="677.0" y="340.0"></omgdi:waypoint>
                <omgdi:waypoint x="605.0" y="344.0"></omgdi:waypoint>
                <omgdi:waypoint x="690.0" y="166.0"></omgdi:waypoint>
                <bpmndi:BPMNLabel>
                    <omgdc:Bounds height="14.0" width="48.0" x="588.0" y="273.0"></omgdc:Bounds>
                </bpmndi:BPMNLabel>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNEdge bpmnElement="flow_repair_check" id="BPMNEdge_flow_repair_check">
                <omgdi:waypoint x="1050.0" y="508.0"></omgdi:waypoint>
                <omgdi:waypoint x="684.0" y="507.0"></omgdi:waypoint>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNEdge bpmnElement="flow_repair_complete" id="BPMNEdge_flow_repair_complete">
                <omgdi:waypoint x="1140.0" y="315.0"></omgdi:waypoint>
                <omgdi:waypoint x="1100.0" y="478.0"></omgdi:waypoint>
                <bpmndi:BPMNLabel>
                    <omgdc:Bounds height="14.0" width="84.0" x="1116.0" y="395.0"></omgdc:Bounds>
                </bpmndi:BPMNLabel>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNEdge bpmnElement="flow_confirm_wo" id="BPMNEdge_flow_confirm_wo">
                <omgdi:waypoint x="740.0" y="136.0"></omgdi:waypoint>
                <omgdi:waypoint x="1240.0" y="138.0"></omgdi:waypoint>
                <bpmndi:BPMNLabel>
                    <omgdc:Bounds height="14.0" width="48.0" x="950.0" y="115.0"></omgdc:Bounds>
                </bpmndi:BPMNLabel>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNEdge bpmnElement="flow_sign_in" id="BPMNEdge_flow_sign_in">
                <omgdi:waypoint x="1290.0" y="168.0"></omgdi:waypoint>
                <omgdi:waypoint x="1140.0" y="255.0"></omgdi:waypoint>
                <bpmndi:BPMNLabel>
                    <omgdc:Bounds height="14.0" width="24.0" x="1241.0" y="202.0"></omgdc:Bounds>
                </bpmndi:BPMNLabel>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNEdge bpmnElement="flow_response_timeout" id="BPMNEdge_flow_response_timeout">
                <omgdi:waypoint x="727.0" y="162.0"></omgdi:waypoint>
                <omgdi:waypoint x="820.0" y="344.0"></omgdi:waypoint>
                <omgdi:waypoint x="777.0" y="340.0"></omgdi:waypoint>
                <bpmndi:BPMNLabel>
                    <omgdc:Bounds height="14.0" width="48.0" x="752.0" y="255.0"></omgdc:Bounds>
                </bpmndi:BPMNLabel>
            </bpmndi:BPMNEdge>
        </bpmndi:BPMNPlane>
    </bpmndi:BPMNDiagram>
</definitions>

  • 附录工作流流程图
    activiti流程图
  • activiti版本
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>spring-boot-starter-basic</artifactId>
            <version>5.17.0</version>
        </dependency>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值