From 3a5e34acc7497db30b0ba1d5af806f3c5d109d36 Mon Sep 17 00:00:00 2001 From: gssong <1742057357@qq.com> Date: Sun, 4 Jun 2023 18:03:40 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=A8=A1=E5=9E=8B=E9=83=A8?= =?UTF-8?q?=E7=BD=B2=EF=BC=8C=E5=AF=BC=E5=87=BA=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{domain/bo => common}/PageEntity.java | 2 +- .../common/constant/FlowConstant.java | 16 +++ .../controller/ActModelController.java | 31 ++++- .../dromara/workflow/domain/bo/ModelBo.java | 1 + .../workflow/service/IActModelService.java | 17 +++ .../service/impl/ActModelServiceImpl.java | 121 +++++++++++++++--- 6 files changed, 165 insertions(+), 23 deletions(-) rename ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/{domain/bo => common}/PageEntity.java (93%) create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/PageEntity.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/PageEntity.java similarity index 93% rename from ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/PageEntity.java rename to ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/PageEntity.java index 10b3236ff..f62a66ebc 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/PageEntity.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/PageEntity.java @@ -1,4 +1,4 @@ -package org.dromara.workflow.domain.bo; +package org.dromara.workflow.common; /** diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java new file mode 100644 index 000000000..e69e4e79a --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java @@ -0,0 +1,16 @@ +package org.dromara.workflow.common.constant; + + +/** + * 工作流常量 + * + * @author may + */ +public interface FlowConstant { + + /** + * 命名空间 + */ + String NAMESPACE = "http://b3mn.org/stencilset/bpmn2.0#"; + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActModelController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActModelController.java index 512ad58b5..06b750a0c 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActModelController.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActModelController.java @@ -1,6 +1,8 @@ package org.dromara.workflow.controller; import com.fasterxml.jackson.databind.node.ObjectNode; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotEmpty; import lombok.RequiredArgsConstructor; import org.dromara.common.core.domain.R; @@ -46,8 +48,7 @@ public class ActModelController extends BaseController { } /** - * 参考官方提供的响应数据 - * "{\"id\":\"admin\",\"firstName\":\"Test\",\"lastName\":\"Administrator\",\"email\":\"admin@flowable.org\",\"fullName\":\"Test Administrator\",\"groups\":[],\"privileges\":[\"access-idm\",\"access-rest-api\",\"access-task\",\"access-modeler\",\"access-admin\"]}"; + * 设计器登录信息 */ @GetMapping("/rest/account") public String getAccount() { @@ -65,6 +66,7 @@ public class ActModelController extends BaseController { * @param modelBo 模型请求对象 */ @Log(title = "模型管理", businessType = BusinessType.INSERT) + @RepeatSubmit() @PostMapping("/rest/models") public R saveNewModel(@Validated(AddGroup.class) @RequestBody ModelBo modelBo) { return toAjax(iActModelService.saveNewModel(modelBo)); @@ -88,6 +90,7 @@ public class ActModelController extends BaseController { * @param values 模型数据 */ @Log(title = "模型管理", businessType = BusinessType.UPDATE) + @RepeatSubmit() @PostMapping(value = "/rest/models/{modelId}/editor/json") public R editModel(@PathVariable String modelId, @RequestParam MultiValueMap values) { return toAjax(iActModelService.editModel(modelId, values)); @@ -109,4 +112,28 @@ public class ActModelController extends BaseController { return R.ok(); } + /** + * 模型部署 + * + * @param id 模型id + */ + @Log(title = "模型管理", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping("/modelDeploy/{id}") + public R deploy(@NotBlank(message = "模型id不能为空") @PathVariable("id") String id) { + return toAjax(iActModelService.modelDeploy(id)); + } + + /** + * 导出模型zip压缩包 + * + * @param modelId 模型id + * @param response 相应 + */ + @GetMapping("/export/zip/{modelId}") + public void exportZip(@NotEmpty(message = "模型id不能为空") @PathVariable String modelId, + HttpServletResponse response) { + iActModelService.exportZip(modelId, response); + } + } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ModelBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ModelBo.java index 0a5ca15bb..b89d78a2c 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ModelBo.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ModelBo.java @@ -4,6 +4,7 @@ import jakarta.validation.constraints.NotBlank; import lombok.Data; import lombok.EqualsAndHashCode; import org.dromara.common.core.validate.AddGroup; +import org.dromara.workflow.common.PageEntity; import java.io.Serial; import java.io.Serializable; diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActModelService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActModelService.java index 1e74a5331..bf9543c14 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActModelService.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActModelService.java @@ -1,6 +1,7 @@ package org.dromara.workflow.service; import com.fasterxml.jackson.databind.node.ObjectNode; +import jakarta.servlet.http.HttpServletResponse; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.workflow.domain.bo.ModelBo; import org.flowable.engine.repository.Model; @@ -44,4 +45,20 @@ public interface IActModelService { * @return 结果 */ boolean editModel(String modelId, MultiValueMap values); + + /** + * 模型部署 + * + * @param id 模型id + * @return 结果 + */ + boolean modelDeploy(String id); + + /** + * 导出模型zip压缩包 + * + * @param modelId 模型id + * @param response 相应 + */ + void exportZip(String modelId, HttpServletResponse response); } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActModelServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActModelServiceImpl.java index 1c9316d14..020aaa1a3 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActModelServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActModelServiceImpl.java @@ -5,9 +5,11 @@ import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.ZipUtil; import cn.hutool.json.JSONUtil; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; +import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import org.apache.commons.lang3.StringUtils; import org.dromara.common.core.exception.ServiceException; @@ -22,6 +24,7 @@ import org.flowable.bpmn.model.BpmnModel; import org.flowable.editor.constants.ModelDataJsonConstants; import org.flowable.editor.language.json.converter.BpmnJsonConverter; import org.flowable.engine.RepositoryService; +import org.flowable.engine.repository.Deployment; import org.flowable.engine.repository.Model; import org.flowable.engine.repository.ModelQuery; import org.springframework.stereotype.Service; @@ -31,11 +34,15 @@ import org.springframework.util.MultiValueMap; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamReader; import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Objects; -import java.util.stream.Collectors; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; +import static org.dromara.workflow.common.constant.FlowConstant.NAMESPACE; import static org.flowable.editor.constants.ModelDataJsonConstants.*; /** @@ -118,11 +125,10 @@ public class ActModelServiceImpl implements IActModelService { model.setMetaInfo(objectNode.toString()); // 保存初始化的模型基本信息数据 repositoryService.saveModel(model); - String namespace = "http://b3mn.org/stencilset/bpmn2.0#"; // 封装模型对象基础数据json串 ObjectNode editorNode = objectMapper.createObjectNode(); ObjectNode stencilSetNode = objectMapper.createObjectNode(); - stencilSetNode.put("namespace", namespace); + stencilSetNode.put("namespace", NAMESPACE); editorNode.replace("stencilset", stencilSetNode); // 标识key ObjectNode propertiesNode = objectMapper.createObjectNode(); @@ -206,10 +212,9 @@ public class ActModelServiceImpl implements IActModelService { // 获取唯一标识key String key = values.getFirst("key"); List list = repositoryService.createModelQuery().modelKey(key).modelTenantId(LoginHelper.getTenantId()).list(); - List modelList = list.stream().filter(e -> !e.getId().equals(model.getId())).collect(Collectors.toList()); - if (CollectionUtil.isNotEmpty(modelList)) { + list.stream().filter(e -> !e.getId().equals(model.getId())).findFirst().ifPresent(e -> { throw new ServiceException("模型key已存在!"); - } + }); model.setKey(key); repositoryService.saveModel(model); byte[] xmlBytes = WorkflowUtils.bpmnJsonToXmlBytes(Objects.requireNonNull(values.getFirst("json_xml")).getBytes(StandardCharsets.UTF_8)); @@ -217,24 +222,100 @@ public class ActModelServiceImpl implements IActModelService { throw new ServiceException("模型不能为空!"); } repositoryService.addModelEditorSource(model.getId(), xmlBytes); - - /*InputStream svgStream = new ByteArrayInputStream(values.getFirst("svg_xml").getBytes(StandardCharsets.UTF_8)); - TranscoderInput input = new TranscoderInput(svgStream); - - PNGTranscoder transcoder = new PNGTranscoder(); - // Setup output - ByteArrayOutputStream outStream = new ByteArrayOutputStream(); - TranscoderOutput output = new TranscoderOutput(outStream); - - // Do the transformation - transcoder.transcode(input, output); - final byte[] result = outStream.toByteArray(); - repositoryService.addModelEditorSourceExtra(model.getId(), result); - outStream.close();*/ return true; } catch (Exception e) { e.printStackTrace(); throw new ServiceException(e.getMessage()); } } + + /** + * 模型部署 + * + * @param id 模型id + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean modelDeploy(String id) { + try { + //查询流程定义模型xml + byte[] xmlBytes = repositoryService.getModelEditorSource(id); + if (ArrayUtil.isEmpty(xmlBytes)) { + throw new ServiceException("模型数据为空,请先设计流程定义模型,再进行部署!"); + } + // 查询模型的基本信息 + Model model = repositoryService.getModel(id); + // xml资源的名称 ,对应act_ge_bytearray表中的name_字段 + String processName = model.getName() + ".bpmn20.xml"; + //调用部署相关的api方法进行部署流程定义 + Deployment deployment = repositoryService.createDeployment() + // 部署名称 + .name(model.getName()) + // 部署标识key + .key(model.getKey()) + // 部署流程分类 + .category(model.getCategory()) + // bpmn20.xml资源 + .addBytes(processName, xmlBytes) + // 租户id + .tenantId(LoginHelper.getTenantId()) + .deploy(); + + // 更新 部署id 到流程定义模型数据表中 + model.setDeploymentId(deployment.getId()); + repositoryService.saveModel(model); + return true; + } catch (Exception e) { + e.printStackTrace(); + throw new ServiceException(e.getMessage()); + } + } + + /** + * 导出模型zip压缩包 + * + * @param modelId 模型id + * @param response 相应 + */ + @Override + public void exportZip(String modelId, HttpServletResponse response) { + ZipOutputStream zos = null; + try { + zos = ZipUtil.getZipOutputStream(response.getOutputStream(), StandardCharsets.UTF_8); + // 压缩包文件名 + String zipName = "模型不存在"; + //查询模型基本信息 + Model model = repositoryService.getModel(modelId); + if (ObjectUtil.isNotNull(model)) { + // 查询流程定义模型的json字节码 + byte[] xmlBytes = repositoryService.getModelEditorSource(modelId); + if (ArrayUtil.isEmpty(xmlBytes)) { + zipName = "模型数据为空,请先设计流程定义模型,再进行部署!"; + } else { + String fileName = model.getName() + "-" + model.getKey(); + // 压缩包文件名 + zipName = fileName + ".zip"; + // 将xml添加到压缩包中(指定xml文件名:请假流程.bpmn20.xml + zos.putNextEntry(new ZipEntry(fileName + ".bpmn20.xml")); + zos.write(xmlBytes); + } + } + response.setHeader("Content-Disposition", + "attachment; filename=" + URLEncoder.encode(zipName, StandardCharsets.UTF_8) + ".zip"); + // 刷出响应流 + response.flushBuffer(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (zos != null) { + try { + zos.closeEntry(); + zos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } }