上个小节我们让折叠面板显示了审批任务的详情信息的文字部分,现在只差BPMN实时进度图了,这幅图是通过调用工作流项目获得的。但是禁止前端VUE页面直接调用工作流项目的Web方法,而是由emos-api
充当中介,来调用工作流项目。
说到这里,我得跟你讲讲分布式项目的设计原则,不应该把所有的子项目都直接暴露给外网。如果我们要在每个子项目的Web方法都要写权限验证和判断,系统也不太好维护,所以最好的办法就是有专门对接外网的Web方法,其他子项目的Web方法只提供内网调用。
为什么不在Service层发出HTTP请求调用工作流的Web方法?原因很简单,我不想让emos-api
项目在服务器上保存BPMN图片。如果是在Service层发出HTTP请求,我们势必要在Service层提取响应中的BPMN图片文件,然后把文件对象返回给Web层;如果直接在Web层发出HTTP请求,我们可以不用从工作流返回的响应里面提取出图片文件,直接通过IO流对拷,把工作流响应中的图片用IO流拷贝到Web方法的响应对象中。有的人可能觉得,通过IO流把数据读取到Byte数组里面,把Byte数组返回给Web层也没有在本地保存文件啊。你这种做法在Service层写代码操作了IO流,然后到Web层又写代码操作了一遍IO流,你不觉得很麻烦吗?一会儿你看看IO流对拷有多方便。
一、编写Web层代码
在ApprovalController.java
类中定义Web方法,获取BPMN图片。
public class ApprovalController {
……
@GetMapping("/searchApprovalBpmn")
@Operation(summary = "获取BPMN图形")
@SaCheckPermission(value = {"WORKFLOW:APPROVAL", "FILE:ARCHIVE"}, mode = SaMode.OR)
public void searchApprovalBpmn(String instanceId, HttpServletResponse response) {
if (StrUtil.isBlankIfStr(instanceId)) {
throw new EmosException("instanceId不能为空");
}
HashMap param = new HashMap() {{
put("code", code);
put("tcode", tcode);
put("instanceId", instanceId);
}};
String url = workflow + "/workflow/searchApprovalBpmn";
HttpResponse resp = HttpRequest.post(url).header("content-type", "application/json")
.body(JSONUtil.toJsonStr(param)).execute();
if (resp.getStatus() == 200) {
try (InputStream in = resp.bodyStream();
BufferedInputStream bin = new BufferedInputStream(in);
OutputStream out = response.getOutputStream();
BufferedOutputStream bout = new BufferedOutputStream(out)) {
IOUtils.copy(bin, bout);
} catch (Exception e) {
log.error("执行异常", e);
}
} else {
log.error("获取工作流BPMN失败");
throw new EmosException("获取工作流BPMN失败");
}
}
}
很多同学注意到了,Web方法接受GET请求,为什么不用POST呢?这是因为前端页面的<img>
标签调用Web方法加载图片的时候,它只能发出GET请求,所以Web方法我们要配合前端<img>
标签。
二、编写前端代码
因为有些工作流比较复杂,页面上又没有太大的空间放置BPMN图片,所以我们要引入ElementUI-PLUS的预览图功能。用户点击BPMN图片,将以幻灯片的形式观看图片,而且还可以放大缩小和旋转。默认情况下,预览图功能要求你不管显示多少张图片,都要用数组传入图片的地址。
<el-image class="bpmn" :src="bpmnUrl" :preview-src-list="bpmnList"></el-image>
在expand
函数里面添加一段JavaScript代码,为了避免浏览器缓存图片,我们还要给URL路径上面添加一个的毫秒值。
expand: function(row, expandedRows) {
……
if (expandedRows.length>0) {
that.bpmnUrl = this.$baseUrl +'approval/searchApprovalBpmn' +
'?instanceId='+row.processId + "&token="+ localStorage.getItem("token")+
'&time=' + new Date().getTime();
that.bpmnList = [that.bpmnUrl];
}