首页 >> 中医针灸

SpringBoot+Vue+Flowable,模拟一个返家审批流程

发布时间:2025年08月11日 12:21

件(start event),这声称一个东程序比如说是的交都能点。一个东程序启动此前,首再行驶离第一个有Gmail标志的方形中所,这个方形叫作一个 User Task,在这个 User Task 中所,副经理可以可落选择许可亦或者断然拒绝。UserTask 的下一步是一个直角,这个称作排他点对点(Exclusive Gateway),这个都能将立即路由到各不相同的偏远地区。再行说是许可,如果在第一个方形中所,副经理可落选择了许可,那么就都能转入到一个带有齿轮标志的方形中所,在这个方形中所我们我们可以额外好好一些好过错,然后又都能函数调加到一个 UserTask,就此进行整个东程序。如果副经理可落选择了断然拒绝,则都能转入到比如说是的发收件的方形中所,在这个中所我们可以给管理层发送一个告知,告知他因故从未通过。当系统走到最右边的弧线此前,就声称这个东程序指派终止了。

这个东程序图完全相同的 XML 收件座落在 src/main/resources/processes/holiday-request.bpmn20.xml 方位,其内容如下:

Request" isExecutable="true">

很多想研读东程序增压器的恰巧都都能被这个 XML 收件当面,但是!!!

如果你愿意静下心来仔细阅读这个 XML 收件,你都能发掘单单东程序增压器原来如此最简单!

我们来挨个看下这里的每一个终端:

process:这声称一个东程序,例如本文则和大家交友的因故就是一个东程序。startEvent:这声称东程序的开始,这就是一个开始过错件。userTask:这就是一个具体内容的东程序终端了,flowable:candidateGroups 要素声称这个终端该由哪个Gmail组中所的Gmail来妥善处理。sequenceFlow:这就是连结各个东程序终端错综复杂的弧线,这个里边一般有两个要素,sourceRef 和 targetRef,前者声称弧线的交都能点,后者声称弧线的终点。exclusiveGateway:声称一个实质上点对点,也就是那个直角可落选择框。从实质上点对点单单来的弧线有两个,大家警惕看右边的预定义,这两个弧线中所都关乎到一个表达式 approved,如果这个表达式为 true,则 targeRef 就是 externalSystemCall;如果这个表达式为 false,则 targetRef 就是 rejectLeave。serviceTask:这就是我们下定义的一个具体内容的外部增系数,如果在整个东程序指派的流程中所,你有一些必须自己进行的好过错,那么可以通过 serviceTask 来做到,这个终端都能有一个 flowable:class 要素,这个要素的系数就是一个自下定义类。另外,上文则中所之外终端中所还关乎到表达式 ${},这个表达式是在东程序指派的流程中所风行进来的。

总而言之,只要小卡比静下心来仔细阅读一下右边的 XML,你都能发掘单单 So Easy!

4. 因故申领

好了,年中我们就来看一个具体内容的因故申领。由于因故东程序只要不放对方位,就都能定时存储,所以我们并不必须手动存储因故东程序,必要开始一个因故申领东程序需。

4.1 增系数端终端

首再行我们必须一个实体类来接受后端惊醒的因故常量:Gmail名、因故起算以及因故这不:

public class AskForLeaveVO { private String name; private Integer days; private String reason; // 省略 getter/setter}

日后拿著祖传的 RespBean,以便号召信息方便一些:

public class RespBean { private Integer status; private String msg; private Object data; public static RespBean ok(String msg, Object data) { return new RespBean(200, msg, data); } public static RespBean ok(String msg) { return new RespBean(200, msg, null); } public static RespBean error(String msg, Object data) { return new RespBean(500, msg, data); } public static RespBean error(String msg) { return new RespBean(500, msg, null); } private RespBean() { } private RespBean(Integer status, String msg, Object data) { this.status = status; this.msg = msg; this.data = data; } // 省略 getter/setter}

年中我们提供一个妥善处理因故申领的终端:

@RestControllerpublic class AskForLeaveController { @Autowired AskForLeaveService askForLeaveService; @PostMapping("/ask_for_leave") public RespBean askForLeave(@RequestBody AskForLeaveVO askForLeaveVO) { return askForLeaveService.askForLeave(askForLeaveVO); }}

核心范式在 AskForLeaveService 中所,来无限期看:

@Servicepublic class AskForLeaveService { @Autowired RuntimeService runtimeService; @Transactional public RespBean askForLeave(AskForLeaveVO askForLeaveVO) { Map variables = new HashMap<>(); variables.put("name", askForLeaveVO.getName()); variables.put("days", askForLeaveVO.getDays()); variables.put("reason", askForLeaveVO.getReason()); try { runtimeService.startProcessInstanceByKey("holidayRequest", askForLeaveVO.getName(), variables); return RespBean.ok("已草拟因故申领"); } catch (Exception e) { e.printStackTrace(); } return RespBean.error("草拟申领挫败"); }}

小卡比看一下,在草拟因故申领的时候,分别风行了 name、days 以及 reason 三个常量,我们将这三个常量不放入到一个 Map 中所,然后通过 RuntimeService#startProcessInstanceByKey 方式来重启一个东程序,重启东程序的时候将近风行了三个常量:

第一个常量声称东程序增压器的叫作,这就是我们居然在东程序的 XML 收件中所下定义的叫作。第二个常量声称理论上这个东程序的 key,我用了申领人的叫作,到时我们可以通过申领人的叫作检索这个人在此此前草拟的所有申领东程序。第三个常量就是我们的表达式了。

好了,这增系数端就撰写好了。

4.2 后端该网站

年中我们来整合后端该网站。

后端我适用 Vue+ElementUI+Axios,咱们这个个案比较最简单,就从未必要搭建单该网站了,必要用都可的 HTML 才行。另外,Vue 我是用了 Vue3:

charset="UTF-8"> Title script> 开始一个因故东程序 劝读写单单处: 劝读写因故起算: 劝读写因故这不: 草拟因故申领 Vue.createApp( { data() { return { afl: { name: 'javaboy', days: 3, reason: '往常一下' } } }, methods: { submit() { let _this = this; axios.post('/ask_for_leave', this.afl) .then(function (response) { if (response.data.status == 200) { //草拟就此 _this.$message.success(response.data.msg); } else { //草拟挫败 _this.$message.error(response.data.msg); } }) .catch(function (error) { console.log(error); }); } } } ).use(ElementPlus).mount('#app')

这个该网站有几个必须警惕的点:

通过 Vue.createApp 来创立一个 Vue 比如说是,这跟现在 Vue2 中所必要 new 一个 Vue 比如说是不一样。在最比如说是,通过 use 来备有 ElementPlus 的软件,这个跟 Vue2 也不一样。在 Vue2 中所,如果我们所谓的在 HTML 该网站中所引用 ElementUI 并不必须这个解决办法。仅剩的东西就比较最简单了,右边再行替换转成 Vue3、Axios 以及 ElementPlus,然后三个读写框,页面按钮草拟立即,常量就是三个读写框中所的信息,草拟就此或者挫败,分别弹个框单单来提示一下才行。

好啦,这就撰写好了。

然而,草拟进行后,从未一个准确的演示,虽然后端提示说是草拟就此了,但是只不过就此没,还得眼见为实。

5. 战斗任务演示

好了,年中我们要好好的好过错就是把Gmail草拟的东程序演示单单来。

按理说是,比如副经理写明就此此前,系统该网站就定时演示单单来副经理必须许可后的东程序,但是我们理论上这个举例来说是为了最简单,就从未写明这个系统设计了,必须必须Gmail到时在页面上落选一下自己的身为,年中就都能演示单单这个身为所完全相同的必须系统设计的东程序。

我们来看战斗任务终端:

@GetMapping("/list")public RespBean leaveList(String identity) { return askForLeaveService.leaveList(identity);}

这个立即常量 identity 就声称理论上Gmail的身为(从前应该是写明后定时得到,但是因为我们现今从未写明,所以这个常量是由后端发送到过来)。来无限期看 askForLeaveService 中所的方式:

@Servicepublic class AskForLeaveService { @Autowired TaskService taskService; public RespBean leaveList(String identity) { List tasks = taskService.createTaskQuery().taskCandidateGroup(identity).list(); List list = new ArrayList<>(); for (int i = 0; i < tasks.size(); i++) { Task task = tasks.get(i); Map variables = taskService.getVariables(task.getId()); variables.put("id", task.getId()); list.add(variables); } return RespBean.ok("存储就此", list); }}

Task 就是东程序中所要好好的就其好过错,我们首再行通过 TaskService,检索单单来这个Gmail必须妥善处理的战斗任务,例如后端前惊醒的是 managers,那么这里就是检索所有必须由 managers Gmail组妥善处理的战斗任务。

这段预定义要为基础东程序图一起来方法论化,小卡比回顾下我们东程序图中所有如下一句:

这意思就是说是这个 userTask 是由 managers 这个组中所的Gmail来妥善处理,所以右边 Java 预定义中所的检索就是检索 managers 这个组中所的Gmail必须许可后的战斗任务。

我们将所有必须许可后的战斗任务检索单单来后,通过 taskId 可以进一步检索到这个战斗任务中所此前风行的各种表达式,我们将这些信息封装转成一个单纯,并就此返回到后端。

再一,我们日后来看下后端该网站:

Title 劝可落选择你的身为: 刷新一下 许可 断然拒绝 Vue.createApp( { data() { return { tasks: [], identities: [ 'managers' ], identity: '' } }, methods: { initTasks() { let _this = this; axios.get('/list?identity=' + this.identity) .then(function (response) { _this.tasks = response.data.data; }) .catch(function (error) { console.log(error); }); } } } ).use(ElementPlus).mount('#app')

大家想到,首再行有一个下拉框,我们在这个下拉框中所来可落选择Gmail的身为。可落选择进行后,会有 initTasks 方式,然后在这个方式中所,发起因特网立即,就此将立即结果CGI单单来。

就此缺点如下:

当然Gmail也可以页面刷新按钮,刷新以下。

这样,当第五变奏中所,管理层草拟了一个因故许可后此前,我们在这个以下中所就可以拍照到管理层草拟的因故许可后了(在东程序图中所,我们必要设置了Gmail的因故许可后互换草拟给 managers,在全面性的文则章中所,松哥都能教大家如何把这个草拟的目标Gmail消失一个动态的)。

6. 因故许可后

年中副经理就可以可落选择许可或者是断然拒绝这因故了。

首再行我们封装一个实体类用来接受后端惊醒的立即:

public class ApproveRejectVO { private String taskId; private Boolean approve; private String name; // 省略 getter/setter}

常量都好方法论化,approve 为 true 声称申领通过,false 声称申领被断然拒绝。

年中我们来看终端:

@PostMapping("/handler")public RespBean askForLeaveHandler(@RequestBody ApproveRejectVO approveRejectVO) { return askForLeaveService.askForLeaveHandler(approveRejectVO);}

看具体内容的 askForLeaveHandler 方式:

@Servicepublic class AskForLeaveService { @Autowired TaskService taskService; public RespBean askForLeaveHandler(ApproveRejectVO approveRejectVO) { try { boolean approved = approveRejectVO.getApprove(); Map variables = new HashMap(); variables.put("approved", approved); variables.put("employee", approveRejectVO.getName()); Task task = taskService.createTaskQuery().taskId(approveRejectVO.getTaskId()).singleResult(); taskService.complete(task.getId(), variables); if (approved) { //如果是同意,还必须无限期走一步 Task t = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).singleResult(); taskService.complete(t.getId()); } return RespBean.ok("系统设计就此"); } catch (Exception e) { e.printStackTrace(); } return RespBean.error("系统设计挫败"); }}

大家警惕这个许可后东程序:

许可后时必须两个常量,approved 和 employee,approved 为 true,就都能定时转入到许可后通过的东程序中所,approved 为 false 则都能定时转入到断然拒绝东程序中所。通过 taskService,为基础 taskId,从东程序中所检索单单完全相同的 task,然后函数调用 taskService.complete 方式风行 taskId 和 表达式,以使东程序向下走。小卡比日后回顾一下我们前面的东程序图,如果立即被许可备了,那么在指派日后多自下定义的 Approve 范式后,就都能转入到 Holiday approved 这个 userTask 中所,警惕此时并不都能无限期向下走了(还差一步到终止过错件);如果是立即断然拒绝,则在指派日后多自下定义的 Reject 范式后,就转入到终止过错件了,这个东程序就终止了。针对第三条,所以预定义中所我们还必须额外日后加一步,如果是 approved 为 true,那么就日后从理论上东程序中所检索单单来必须指派的 task,日后函数调用 complete 无限期走一步,此时就到了终止过错件了,这个东程序就终止了。警惕这次的检索是根据理论上东程序的 ID 检索的,一个东程序就是路障,这条线上有很多 Task,我们可以从 Task 中所得到到东程序的 ID。

好啦,终端就撰写好了。

当然,这里还关乎到两个自下定义的范式,就是许可或者断然拒绝此前的自下定义范式,这个只不过很差撰写,如下:

public class Approve implements JavaDelegate { @Override public void execute(DelegateExecution execution) { System.out.println("申领通过:"+execution.getVariables()); }}

我们自下定义类做到 JavaDelegate 终端需,然后我们在 execute 方式中所好好自己想要好好的好过错需,execution 中所有这个东程序中所的所有表达式。我们可以在这里发收件(公众号金陵一点雨后台回复 666 有发收件入门)、发来电等等。Reject 的下定义方式也是类似的。这些自下定义类撰写好此前,到时备有到东程序图中所需(可拍照上文则的东程序图)。

再一日后来到底后端草拟方式就最简单了(该网站源码上文则早已列单单):

approveOrReject(taskId, approve,name) { let _this = this; axios.post('/handler', {taskId: taskId, approve: approve,name:name}) .then(function (response) { _this.initTasks(); }) .catch(function (error) { console.log(error); });}

这就一个都可的 Ajax 立即,许可的话第二个常量就为 true,断然拒绝的话第二个常量就为 false。

7. 结果检索

再一,每个Gmail都可以拍照自己在此此前的申领记录。从前这个写明此前就可以演示了,但是因为我们从未写明,所以这里也是必须手动读写检索的Gmail,然后根据Gmail名检索这个Gmail的上曾记录,我们再行来看检索终端:

@GetMapping("/search")public RespBean searchResult(String name) { return askForLeaveService.searchResult(name);}

常量就是要检索的Gmail名。具体内容的检索东程序如下:

public RespBean searchResult(String name) { List historyInfos = new ArrayList<>(); List historicProcessInstances = historyService.createHistoricProcessInstanceQuery().processInstanceBusinessKey(name).finished().orderByProcessInstanceEndTime().desc().list(); for (HistoricProcessInstance historicProcessInstance : historicProcessInstances) { HistoryInfo historyInfo = new HistoryInfo(); Date startTime = historicProcessInstance.getStartTime(); Date endTime = historicProcessInstance.getEndTime(); List historicVariableInstances = historyService.createHistoricVariableInstanceQuery() .processInstanceId(historicProcessInstance.getId()) .list(); for (HistoricVariableInstance historicVariableInstance : historicVariableInstances) { String variableName = historicVariableInstance.getVariableName(); Object value = historicVariableInstance.getValue(); if ("reason".equals(variableName)) { historyInfo.setReason((String) value); } else if ("days".equals(variableName)) { historyInfo.setDays(Integer.parseInt(value.toString())); } else if ("approved".equals(variableName)) { historyInfo.setStatus((Boolean) value); } else if ("name".equals(variableName)) { historyInfo.setName((String) value); } } historyInfo.setStartTime(startTime); historyInfo.setEndTime(endTime); historyInfos.add(historyInfo); } return RespBean.ok("ok", historyInfos);}我们此前在重启东程序的时候,风行了一个常量 key,这里就是日后次通过这个 key,也就是Gmail名去检索上曾东程序,检索的时候还加上了 finished 方式,这个声称要检索的东程序必需是指派日后多毕的东程序,对于从未指派日后多毕的东程序,这里不检索,查日后多此前,按照东程序再一的妥善处理一段时间进行先后顺序。遍历第一步的检索结果,从 HistoricProcessInstance 中所提取单单每一个东程序的的资讯,并借给到给定中所,并就此返回。这里关乎到两个上曾信息检索,createHistoricProcessInstanceQuery 用来检索上曾东程序,而 createHistoricVariableInstanceQuery 则主要是用来检索东程序表达式的。

再一,后端通过表格演示这个信息需:

Title 检索 已通过 已断然拒绝 Vue.createApp( { data() { return { historyInfos: [], name: 'zhangsan' } }, methods: { search() { let _this = this; axios.get('/search?name=' + this.name) .then(function (response) { if (response.data.status == 200) { _this.historyInfos=response.data.data; } else { _this.$message.error(response.data.msg); } }) .catch(function (error) { console.log(error); }); } } ).use(ElementPlus).mount('#app')

这个都是一些常规系统设计,我就不多说是了,就此演示缺点如下:

8. 小结

好啦,一个最简单的因故东程序,让大家对 Flowable 的的游戏有一个基本上的方法论化,下篇文则章松哥来和大家无限期日后多善本文则。Flowable 的图片将都能单单现在 TienChin 这两项中所,大家不用错过哦:TienChin 这两项扩容图片来啦。

河北包皮过长治疗哪家好
武汉妇科专科医院有哪些
南昌男科检查哪家医院好
长沙白癜风专业医院
上海看白癜风到哪家医院好

上一篇: 韩国先后有两个首都, 第二个是首尔, 第一个在近现代

下一篇: 腾讯这款APP将暂时运营!你可能正在用

友情链接