From 00f59fdc75b83c1e61e19cb7e810d62e81d0eee1 Mon Sep 17 00:00:00 2001 From: "yunlong.li" Date: Thu, 18 Nov 2021 10:55:43 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=AE=8C=E5=96=84=20bpm=20=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/workflow/ModelController.java | 32 +++++++++++- .../controller/workflow/TaskController.java | 7 ++- .../workflow/vo/model/ModelPageReqVo.java | 20 ++++++++ .../workflow/vo/model/ModelRespVo.java | 16 ++++++ .../bpm/convert/workflow/ModelConvert.java | 20 ++++++++ .../bpm/enums/BpmErrorCodeConstants.java | 1 + .../bpm/service/workflow/BpmModelService.java | 38 +++++++++++++- .../bpm/service/workflow/BpmTaskService.java | 1 + .../workflow/impl/BpmModelServiceImpl.java | 51 +++++++++++++++++++ .../workflow/impl/BpmTaskServiceImpl.java | 19 +++++-- yudao-admin-ui/src/api/oa/todo.js | 2 +- 11 files changed, 195 insertions(+), 12 deletions(-) create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/workflow/vo/model/ModelPageReqVo.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/workflow/vo/model/ModelRespVo.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/workflow/ModelConvert.java diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/workflow/ModelController.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/workflow/ModelController.java index fde29be48..c08cadec3 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/workflow/ModelController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/workflow/ModelController.java @@ -1,15 +1,20 @@ package cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow; import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo.FileResp; import cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo.TodoTaskRespVO; import cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo.model.ModelCreateVO; +import cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo.model.ModelPageReqVo; +import cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo.model.ModelRespVo; import cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo.model.ModelUpdateVO; import cn.iocoder.yudao.adminserver.modules.bpm.service.workflow.BpmModelService; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.activiti.engine.*; @@ -36,18 +41,41 @@ public class ModelController { private final BpmModelService bpmModelService; + @GetMapping ("/page") + @ApiOperation(value = "分页数据") + public PageResult pageList(ModelPageReqVo modelPageReqVo) { + return bpmModelService.pageList(modelPageReqVo); + } + @PostMapping("/create") + @ApiOperation(value = "新建模型") public CommonResult newModel(@RequestBody ModelCreateVO modelCreateVO) { return bpmModelService.newModel(modelCreateVO); } @PostMapping("/update") + @ApiOperation(value = "修改模型属性") public CommonResult updateModel(@RequestBody ModelUpdateVO modelUpdateVO) { return bpmModelService.updateModel(modelUpdateVO); } - @PostMapping("/deploy/{modelId}") - public CommonResult updateModel(@PathVariable String modelId) { + @PostMapping("/delete") + @ApiOperation(value = "删除模型") + public CommonResult deleteModel(@RequestParam String modelId) { + return bpmModelService.deleteModel(modelId); + } + + @PostMapping("/deploy") + @ApiOperation(value = "部署模型") + public CommonResult deploy(@RequestParam String modelId) { return bpmModelService.deploy(modelId); } + + @GetMapping("/exportBpmnXml") + @ApiOperation(value = "导出模型") + public void export(@RequestParam String deploymentId, HttpServletResponse response) throws IOException { + FileResp fileResp = bpmModelService.exportBpmnXml(deploymentId); + ServletUtils.writeAttachment(response, fileResp.getFileName(), fileResp.getFileByte()); + } + } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/workflow/TaskController.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/workflow/TaskController.java index 45ef6c9ce..2492bccf6 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/workflow/TaskController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/workflow/TaskController.java @@ -60,13 +60,12 @@ public class TaskController { return success(bpmTaskService.getHistorySteps(processInstanceId)); } - // TODO @Li: 项目里,暂时不使用 path 路径参数,监控等麻烦 /** * 返回高亮的流转图SVG - * @param processInstanceId + * @param processInstanceId 流程Id */ - @GetMapping("/process/highlight-img/{id}") - public void getHighlightImg(@PathVariable("id") String processInstanceId, HttpServletResponse response) throws IOException { + @GetMapping("/process/highlight-img") + public void getHighlightImg(@RequestParam String processInstanceId, HttpServletResponse response) throws IOException { FileResp fileResp = bpmTaskService.getHighlightImg(processInstanceId); ServletUtils.writeAttachment(response, fileResp.getFileName(), fileResp.getFileByte()); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/workflow/vo/model/ModelPageReqVo.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/workflow/vo/model/ModelPageReqVo.java new file mode 100644 index 000000000..476b85ced --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/workflow/vo/model/ModelPageReqVo.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo.model; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +/** + * @author yunlong.li + */ +@ApiModel("模型分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ModelPageReqVo extends PageParam { + @ApiModelProperty("模型名字") + private String name; +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/workflow/vo/model/ModelRespVo.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/workflow/vo/model/ModelRespVo.java new file mode 100644 index 000000000..13d59a008 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/workflow/vo/model/ModelRespVo.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo.model; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +/** + * @author yunlong.li + */ +@ApiModel("模型出口内容 Request VO") +@Data +@ToString(callSuper = true) +public class ModelRespVo { +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/workflow/ModelConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/workflow/ModelConvert.java new file mode 100644 index 000000000..cc11f9387 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/workflow/ModelConvert.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.adminserver.modules.bpm.convert.workflow; + +import cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo.TodoTaskRespVO; +import cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo.model.ModelRespVo; +import org.activiti.api.task.model.Task; +import org.activiti.engine.repository.Model; +import org.activiti.engine.repository.ProcessDefinition; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + + +/** + * @author yunlongn + */ +@Mapper +public interface ModelConvert { + ModelConvert INSTANCE = Mappers.getMapper(ModelConvert.class); + + ModelRespVo convert(Model model); +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/BpmErrorCodeConstants.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/BpmErrorCodeConstants.java index 48564d41e..4caab34e8 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/BpmErrorCodeConstants.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/BpmErrorCodeConstants.java @@ -28,5 +28,6 @@ public interface BpmErrorCodeConstants { ErrorCode BPMN_MODEL_EDITOR_SOURCE_NOT_EXISTS = new ErrorCode(1004001001, "模型数据为空,请先成功设计流程并保存"); ErrorCode BPMN_MODEL_ERROR = new ErrorCode(1004001002, "工作流模型异常"); ErrorCode BPMN_MODEL_PROCESS_NOT_EXISTS = new ErrorCode(1004001003, "流程数据为空"); + ErrorCode BPMN_PROCESS_DEFINITION_NOT_EXISTS = new ErrorCode(1004001004, "流程定义不存在"); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/workflow/BpmModelService.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/workflow/BpmModelService.java index ed2782a6d..f63bdca5a 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/workflow/BpmModelService.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/workflow/BpmModelService.java @@ -1,8 +1,15 @@ package cn.iocoder.yudao.adminserver.modules.bpm.service.workflow; +import cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo.FileResp; import cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo.model.ModelCreateVO; +import cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo.model.ModelPageReqVo; +import cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo.model.ModelRespVo; import cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo.model.ModelUpdateVO; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import org.activiti.engine.repository.Model; + +import javax.servlet.http.HttpServletResponse; /** * 工作流模型接口 @@ -10,16 +17,45 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; */ public interface BpmModelService { + + /** + * 模型数据分页返回 + * @param modelPageReqVo 分页入参 + * @return 分页model + */ + PageResult pageList(ModelPageReqVo modelPageReqVo); + /** * 新增一个模型 * @param modelCreateVO 模型对象 * @return 返回成功 */ CommonResult newModel(ModelCreateVO modelCreateVO); - + /** + * 修改模型属性,填充bpmn数据 + * @param modelUpdateVO 模型对象 + * @return 返回成功 + */ CommonResult updateModel(ModelUpdateVO modelUpdateVO); + /** + * 部署模型 使模型成为一个 process + * @param modelId 模型Id + * @return 返回成功 + */ CommonResult deploy(String modelId); + /** + * 导出模型 + * @param modelId 模型Id + * @return {@link FileResp} 返回文件 + */ + FileResp exportBpmnXml(String modelId); + /** + * 删除模型 + * @param modelId 模型Id + * @return 返回成功 + */ + CommonResult deleteModel(String modelId); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/workflow/BpmTaskService.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/workflow/BpmTaskService.java index 07d1f7f52..37d14d81f 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/workflow/BpmTaskService.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/workflow/BpmTaskService.java @@ -51,6 +51,7 @@ public interface BpmTaskService { /** * 返回高亮的流转进程 * @param processInstanceId 实例Id + * @return {@link FileResp} 返回文件 */ FileResp getHighlightImg(String processInstanceId); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/workflow/impl/BpmModelServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/workflow/impl/BpmModelServiceImpl.java index 750997301..adf637aca 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/workflow/impl/BpmModelServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/workflow/impl/BpmModelServiceImpl.java @@ -1,28 +1,42 @@ package cn.iocoder.yudao.adminserver.modules.bpm.service.workflow.impl; +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo.FileResp; import cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo.model.ModelCreateVO; +import cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo.model.ModelPageReqVo; +import cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo.model.ModelRespVo; import cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo.model.ModelUpdateVO; import cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants; import cn.iocoder.yudao.adminserver.modules.bpm.service.workflow.BpmModelService; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.activiti.api.runtime.shared.query.Pageable; import org.activiti.bpmn.converter.BpmnXMLConverter; import org.activiti.bpmn.model.BpmnModel; import org.activiti.engine.RepositoryService; import org.activiti.engine.repository.Deployment; import org.activiti.engine.repository.Model; +import org.activiti.engine.repository.ModelQuery; +import org.activiti.engine.repository.ProcessDefinition; import org.apache.commons.lang3.exception.ExceptionUtils; import org.springframework.stereotype.Service; import org.springframework.util.ObjectUtils; +import javax.servlet.http.HttpServletResponse; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamReader; import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; +import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import java.util.List; import java.util.Optional; /** @@ -36,6 +50,19 @@ public class BpmModelServiceImpl implements BpmModelService { private final RepositoryService repositoryService; + + @Override + public PageResult pageList(ModelPageReqVo modelPageReqVo) { + ModelQuery modelQuery = repositoryService.createModelQuery(); + String likeName = modelPageReqVo.getName(); + if (StrUtil.isNotBlank(likeName)){ + modelQuery.modelNameLike("%"+likeName+"%"); + } + List models = modelQuery.orderByCreateTime().desc() + .listPage((modelPageReqVo.getPageNo() - 1) * modelPageReqVo.getPageSize(), modelPageReqVo.getPageSize()); + return new PageResult<>(models, modelQuery.count()); + } + @Override public CommonResult newModel(ModelCreateVO modelCreateVO) { try { @@ -119,4 +146,28 @@ public class BpmModelServiceImpl implements BpmModelService { throw ServiceExceptionUtil.exception(BpmErrorCodeConstants.BPMN_MODEL_ERROR); } } + + @Override + public FileResp exportBpmnXml(String deploymentId) { + + // 查询流程定义 + ProcessDefinition pd = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult(); + if (ObjectUtils.isEmpty(pd)) { + throw ServiceExceptionUtil.exception(BpmErrorCodeConstants.BPMN_PROCESS_DEFINITION_NOT_EXISTS); + } + String resourceName = Optional.ofNullable(pd.getDiagramResourceName()).orElse(pd.getResourceName()); + InputStream inputStream = repositoryService.getResourceAsStream(deploymentId, + resourceName); + FileResp fileResp = new FileResp(); + + fileResp.setFileName(String.format("%s.bpmn", Optional.ofNullable(pd.getName()).orElse("流程图"))); + fileResp.setFileByte(IoUtil.readBytes(inputStream)); + return fileResp; + } + + @Override + public CommonResult deleteModel(String modelId) { + repositoryService.deleteModel(modelId); + return CommonResult.success("删除成功"); + } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/workflow/impl/BpmTaskServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/workflow/impl/BpmTaskServiceImpl.java index 973f929fd..8ca9bbb1c 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/workflow/impl/BpmTaskServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/workflow/impl/BpmTaskServiceImpl.java @@ -31,6 +31,7 @@ import org.activiti.image.ProcessDiagramGenerator; import org.apache.commons.lang3.exception.ExceptionUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.ObjectUtils; import javax.annotation.Resource; import java.io.IOException; @@ -174,6 +175,18 @@ public class BpmTaskServiceImpl implements BpmTaskService { if (hpi == null) { throw exception(PROCESS_INSTANCE_NOT_EXISTS); } + // 如果有结束时间 返回model的流程图 + if (!ObjectUtils.isEmpty(hpi.getEndTime())) { + ProcessDefinition pd = repositoryService.createProcessDefinitionQuery().processDefinitionId(hpi.getProcessDefinitionId()).singleResult(); + String resourceName = Optional.ofNullable(pd.getDiagramResourceName()).orElse(pd.getResourceName()); + BpmnModel bpmnModel = repositoryService.getBpmnModel(pd.getId()); + InputStream inputStream = processDiagramGenerator.generateDiagram(bpmnModel, new ArrayList<>(1), new ArrayList<>(1), + "宋体", "宋体", "宋体"); + FileResp fileResp = new FileResp(); + fileResp.setFileName( resourceName + ".svg"); + fileResp.setFileByte(IoUtil.readBytes(inputStream)); + return fileResp; + } // 没有结束时间。说明流程在执行过程中 // TODO @Li:一些 runtimeService 的查询,貌似比较通用,是不是抽一些小方法出来 ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); @@ -195,13 +208,11 @@ public class BpmTaskServiceImpl implements BpmTaskService { try (InputStream inputStream = processDiagramGenerator.generateDiagram(bpmnModel, highLightedActivities, highLightedFlowIds, "宋体", "宋体", "宋体")){ FileResp fileResp = new FileResp(); - String picName = hpi.getProcessDefinitionName() + ".svg"; // TODO @Li:一次性的变量,可以直接 set 的时候,直接拼接 - fileResp.setFileName(picName); + fileResp.setFileName( hpi.getProcessDefinitionName() + ".svg"); fileResp.setFileByte(IoUtil.readBytes(inputStream)); return fileResp; } catch (IOException e) { - // TODO @Li:log.error("[getHighlightImg][流程({}) 生成图表失败]", processInstanceId, e) - log.error(ExceptionUtils.getStackTrace(e)); + log.error("[getHighlightImg][流程({}) 生成图表失败]", processInstanceId, e); throw exception(HIGHLIGHT_IMG_ERROR); } } diff --git a/yudao-admin-ui/src/api/oa/todo.js b/yudao-admin-ui/src/api/oa/todo.js index cb98c466d..1a8bc26ab 100644 --- a/yudao-admin-ui/src/api/oa/todo.js +++ b/yudao-admin-ui/src/api/oa/todo.js @@ -85,7 +85,7 @@ export function processHistorySteps(id) { export function getHighlightImg(id) { return request({ - url: '/workflow/task/process/highlight-img/'+id, + url: '/workflow/task/process/highlight-img?processInstanceId='+id, method: 'get' }) }