Przeglądaj źródła

工作流 Flowable 发布流程的部分实现

jason 3 lat temu
rodzic
commit
d6a6a01252
17 zmienionych plików z 331 dodań i 125 usunięć
  1. 56 0
      yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmAbstractModelService.java
  2. 22 0
      yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelCommonService.java
  3. 1 1
      yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmModelMetaInfoRespDTO.java
  4. 0 0
      yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmProcessDefinitionCreateReqDTO.java
  5. 2 2
      yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java
  6. 1 1
      yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java
  7. 0 23
      yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java
  8. 9 35
      yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java
  9. 1 1
      yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java
  10. 1 1
      yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java
  11. 9 0
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/FlowableModelController.java
  12. 18 0
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java
  13. 28 7
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/ModelConvert.java
  14. 75 15
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableModelServiceImpl.java
  15. 34 0
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableProcessDefinitionService.java
  16. 74 0
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableProcessDefinitionServiceImpl.java
  17. 0 39
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/ModelMetaInfoRespDTO.java

+ 56 - 0
yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmAbstractModelService.java

@@ -0,0 +1,56 @@
+package cn.iocoder.yudao.module.bpm.service.definition;
+
+import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
+import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
+import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
+import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
+
+import java.util.Objects;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
+/**
+ * 流程模型通用抽象类
+ * Activiti 和 flowable 通用的流程模型抽象类, Activiti 和 flowable 两边通用的方法
+ *
+ * @author yunlongn
+ * @author jason
+ */
+public abstract class BpmAbstractModelService {
+
+    protected final BpmFormService bpmFormService;
+
+    public BpmAbstractModelService(BpmFormService bpmFormService) {
+        this.bpmFormService = bpmFormService;
+    }
+
+    /**
+     * 校验流程表单已配置
+     *
+     * @param metaInfoStr 流程模型 metaInfo 字段
+     * @return 流程表单
+     */
+    protected BpmFormDO checkFormConfig(String  metaInfoStr) {
+        BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(metaInfoStr, BpmModelMetaInfoRespDTO.class);
+        if (metaInfo == null || metaInfo.getFormType() == null) {
+            throw exception(MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG);
+        }
+        // 校验表单存在
+        if (Objects.equals(metaInfo.getFormType(), BpmModelFormTypeEnum.NORMAL.getType())) {
+            BpmFormDO form = bpmFormService.getForm(metaInfo.getFormId());
+            if (form == null) {
+                throw exception(FORM_NOT_EXISTS);
+            }
+            return form;
+        }
+        return null;
+    }
+
+
+    protected void checkKeyNCName(String key) {
+        if (!ValidationUtils.isXmlNCName(key)) {
+            throw exception(MODEL_KEY_VALID);
+        }
+    }
+}

+ 22 - 0
yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelCommonService.java

@@ -44,4 +44,26 @@ public interface BpmModelCommonService {
      * @param updateReqVO 更新信息
      */
     void updateModel(@Valid BpmModelUpdateReqVO updateReqVO);
+
+    /**
+     * 将流程模型,部署成一个流程定义
+     *
+     * @param id 编号
+     */
+    void deployModel(String id);
+
+    /**
+     * 删除模型
+     *
+     * @param id 编号
+     */
+    void deleteModel(String id);
+
+    /**
+     * 修改模型的状态,实际更新的部署的流程定义的状态
+     *
+     * @param id 编号
+     * @param state 状态
+     */
+    void updateModelState(String id, Integer state);
 }

+ 1 - 1
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmModelMetaInfoRespDTO.java → yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmModelMetaInfoRespDTO.java

@@ -5,7 +5,7 @@ import lombok.Data;
 
 /**
  * BPM 流程 MetaInfo Response DTO
- * 主要用于 {@link org.activiti.engine.repository.Model#setMetaInfo(String)} 的存储
+ * 主要用于 { Model#setMetaInfo(String)} 的存储
  *
  * @author 芋道源码
  */

+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmProcessDefinitionCreateReqDTO.java → yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmProcessDefinitionCreateReqDTO.java


+ 2 - 2
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java

@@ -2,11 +2,11 @@ package cn.iocoder.yudao.module.bpm.convert.definition;
 
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*;
-import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
-import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
+import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
+import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
 import org.activiti.engine.impl.persistence.entity.SuspensionState;
 import org.activiti.engine.repository.Deployment;
 import org.activiti.engine.repository.Model;

+ 1 - 1
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java

@@ -1,11 +1,11 @@
 package cn.iocoder.yudao.module.bpm.convert.definition;
 
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
 import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
-import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import org.activiti.engine.impl.persistence.entity.SuspensionState;
 import org.activiti.engine.repository.Deployment;
 import org.activiti.engine.repository.ProcessDefinition;

+ 0 - 23
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java

@@ -13,29 +13,6 @@ import javax.validation.Valid;
  */
 public interface BpmModelService extends BpmModelCommonService {
 
-
-    /**
-     * 将流程模型,部署成一个流程定义
-     *
-     * @param id 编号
-     */
-    void deployModel(String id);
-
-    /**
-     * 删除模型
-     *
-     * @param id 编号
-     */
-    void deleteModel(String id);
-
-    /**
-     * 修改模型的状态,实际更新的部署的流程定义的状态
-     *
-     * @param id 编号
-     * @param state 状态 {@link org.activiti.engine.impl.persistence.entity.SuspensionState}
-     */
-    void updateModelState(String id, Integer state);
-
     /**
      * 获得流程模型编号对应的 BPMN Model
      *

+ 9 - 35
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java

@@ -6,16 +6,14 @@ import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*;
 import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert;
 import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
-import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
 import cn.iocoder.yudao.framework.activiti.core.util.ActivitiUtils;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
 import cn.iocoder.yudao.framework.common.util.object.PageUtils;
-import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
+import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
 import lombok.extern.slf4j.Slf4j;
 import org.activiti.bpmn.model.BpmnModel;
 import org.activiti.engine.RepositoryService;
@@ -47,18 +45,22 @@ import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
 @Service
 @Validated
 @Slf4j
-public class BpmModelServiceImpl implements BpmModelService {
+public class BpmModelServiceImpl extends BpmAbstractModelService implements BpmModelService {
 
     @Resource
     private RepositoryService repositoryService;
-    @Resource
-    private BpmFormService bpmFormService;
+
     @Resource
     private BpmProcessDefinitionService processDefinitionService;
     @Resource
     @Lazy // 解决循环依赖
     private BpmTaskAssignRuleService taskAssignRuleService;
 
+
+    public BpmModelServiceImpl(BpmFormService bpmFormService) {
+        super(bpmFormService);
+    }
+
     @Override
     public PageResult<BpmModelPageItemRespVO> getModelPage(BpmModelPageReqVO pageVO) {
         ModelQuery modelQuery = repositoryService.createModelQuery();
@@ -167,7 +169,7 @@ public class BpmModelServiceImpl implements BpmModelService {
         }
         // TODO 芋艿:校验流程图的有效性;例如说,是否有开始的元素,是否有结束的元素;
         // 校验表单已配
-        BpmFormDO form = checkFormConfig(model);
+        BpmFormDO form = checkFormConfig(model.getMetaInfo());
         // 校验任务分配规则已配置
         checkTaskAssignRuleAllConfig(id);
 
@@ -214,28 +216,6 @@ public class BpmModelServiceImpl implements BpmModelService {
         });
     }
 
-    /**
-     * 校验流程表单已配置
-     *
-     * @param model 流程模型
-     * @return 流程表单
-     */
-    private BpmFormDO checkFormConfig(Model model) {
-        BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class);
-        if (metaInfo == null || metaInfo.getFormType() == null) {
-            throw exception(MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG);
-        }
-        // 校验表单存在
-        if (Objects.equals(metaInfo.getFormType(), BpmModelFormTypeEnum.NORMAL.getType())) {
-            BpmFormDO form = bpmFormService.getForm(metaInfo.getFormId());
-            if (form == null) {
-                throw exception(FORM_NOT_EXISTS);
-            }
-            return form;
-        }
-        return null;
-    }
-
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void deleteModel(String id) {
@@ -291,10 +271,4 @@ public class BpmModelServiceImpl implements BpmModelService {
         return repositoryService.createModelQuery().modelKey(key).singleResult();
     }
 
-    private void checkKeyNCName(String key) {
-        if (!ValidationUtils.isXmlNCName(key)) {
-            throw exception(MODEL_KEY_VALID);
-        }
-    }
-
 }

+ 1 - 1
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java

@@ -5,9 +5,9 @@ import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmPro
 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO;
 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
-import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
 import org.activiti.bpmn.model.BpmnModel;
 import org.activiti.engine.repository.Deployment;
 import org.activiti.engine.repository.ProcessDefinition;

+ 1 - 1
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java

@@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.module.bpm.convert.definition.BpmProcessDefinitionConvert;
-import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
 import cn.iocoder.yudao.framework.activiti.core.util.ActivitiUtils;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.PageUtils;
@@ -15,6 +14,7 @@ import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmPro
 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
 import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmProcessDefinitionExtMapper;
+import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
 import lombok.extern.slf4j.Slf4j;
 import org.activiti.bpmn.model.BpmnModel;
 import org.activiti.engine.RepositoryService;

+ 9 - 0
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/FlowableModelController.java

@@ -67,4 +67,13 @@ public class FlowableModelController {
         String bpmnXml = IoUtils.readUtf8(importReqVO.getBpmnFile().getInputStream(), false);
         return success(modelService.createModel(createReqVO, bpmnXml));
     }
+
+    @PostMapping("/deploy")
+    @ApiOperation(value = "部署模型")
+    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = String.class)
+    @PreAuthorize("@ss.hasPermission('bpm:model:deploy')")
+    public CommonResult<Boolean> deployModel(@RequestParam("id") String id) {
+        modelService.deployModel(id);
+        return success(true);
+    }
 }

+ 18 - 0
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java

@@ -0,0 +1,18 @@
+package cn.iocoder.yudao.module.bpm.convert.definition;
+
+import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
+import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+/**
+ * Bpm 流程定义的 Convert
+ *
+ * @author yunlong.li
+ */
+@Mapper
+public interface BpmProcessDefinitionConvert {
+    BpmProcessDefinitionConvert INSTANCE = Mappers.getMapper(BpmProcessDefinitionConvert.class);
+
+    BpmProcessDefinitionExtDO convert2(BpmProcessDefinitionCreateReqDTO bean);
+}

+ 28 - 7
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/ModelConvert.java

@@ -5,7 +5,8 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
-import cn.iocoder.yudao.module.bpm.service.definition.dto.ModelMetaInfoRespDTO;
+import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
+import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
 import org.flowable.common.engine.impl.db.SuspensionState;
 import org.flowable.engine.repository.Deployment;
 import org.flowable.engine.repository.Model;
@@ -32,7 +33,7 @@ public interface ModelConvert {
                                                      Map<String, Deployment> deploymentMap,
                                                      Map<String, ProcessDefinition> processDefinitionMap) {
         return CollectionUtils.convertList(list, model -> {
-            ModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), ModelMetaInfoRespDTO.class);
+            BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class);
             BpmFormDO form = metaInfo != null ? formMap.get(metaInfo.getFormId()) : null;
             Deployment deployment = model.getDeploymentId() != null ? deploymentMap.get(model.getDeploymentId()) : null;
             ProcessDefinition processDefinition = model.getDeploymentId() != null ? processDefinitionMap.get(model.getDeploymentId()) : null;
@@ -75,12 +76,32 @@ public interface ModelConvert {
         to.setKey(model.getKey());
         to.setCategory(model.getCategory());
         // metaInfo
-        ModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), ModelMetaInfoRespDTO.class);
+        BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class);
         copyTo(metaInfo, to);
     }
+
     BpmModelCreateReqVO convert(BpmModeImportReqVO bean);
 
-    void copyTo(ModelMetaInfoRespDTO from, @MappingTarget BpmModelBaseVO to);
+    default BpmProcessDefinitionCreateReqDTO convert2(Model model, BpmFormDO form) {
+        BpmProcessDefinitionCreateReqDTO createReqDTO = new BpmProcessDefinitionCreateReqDTO();
+        createReqDTO.setModelId(model.getId());
+        createReqDTO.setName(model.getName());
+        createReqDTO.setKey(model.getKey());
+        createReqDTO.setCategory(model.getCategory());
+        BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class);
+        // metaInfo
+        copyTo(metaInfo, createReqDTO);
+        // form
+        if (form != null) {
+            createReqDTO.setFormConf(form.getConf());
+            createReqDTO.setFormFields(form.getFields());
+        }
+        return createReqDTO;
+    }
+
+    void copyTo(BpmModelMetaInfoRespDTO from, @MappingTarget BpmProcessDefinitionCreateReqDTO to);
+
+    void copyTo(BpmModelMetaInfoRespDTO from, @MappingTarget BpmModelBaseVO to);
 
     BpmModelPageItemRespVO.ProcessDefinition convert(ProcessDefinition bean);
 
@@ -94,15 +115,15 @@ public interface ModelConvert {
     default void copy(Model model, BpmModelUpdateReqVO bean) {
         model.setName(bean.getName());
         model.setCategory(bean.getCategory());
-        model.setMetaInfo(buildMetaInfoStr(JsonUtils.parseObject(model.getMetaInfo(), ModelMetaInfoRespDTO.class),
+        model.setMetaInfo(buildMetaInfoStr(JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class),
                 bean.getDescription(), bean.getFormType(), bean.getFormId(),
                 bean.getFormCustomCreatePath(), bean.getFormCustomViewPath()));
     }
 
-    default String buildMetaInfoStr(ModelMetaInfoRespDTO metaInfo, String description, Integer formType,
+    default String buildMetaInfoStr(BpmModelMetaInfoRespDTO metaInfo, String description, Integer formType,
                                     Long formId, String formCustomCreatePath, String formCustomViewPath) {
         if (metaInfo == null) {
-            metaInfo = new ModelMetaInfoRespDTO();
+            metaInfo = new BpmModelMetaInfoRespDTO();
         }
         // 只有非空,才进行设置,避免更新时的覆盖
         if (StrUtil.isNotEmpty(description)) {

+ 75 - 15
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableModelServiceImpl.java

@@ -5,12 +5,13 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
 import cn.iocoder.yudao.framework.common.util.object.PageUtils;
-import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*;
 import cn.iocoder.yudao.module.bpm.convert.definition.ModelConvert;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
-import cn.iocoder.yudao.module.bpm.service.definition.dto.ModelMetaInfoRespDTO;
+import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
+import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
 import lombok.extern.slf4j.Slf4j;
+import org.flowable.common.engine.impl.db.SuspensionState;
 import org.flowable.engine.RepositoryService;
 import org.flowable.engine.repository.Deployment;
 import org.flowable.engine.repository.Model;
@@ -18,14 +19,12 @@ import org.flowable.engine.repository.ModelQuery;
 import org.flowable.engine.repository.ProcessDefinition;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.ObjectUtils;
 import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
 import javax.validation.Valid;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
@@ -42,15 +41,17 @@ import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
 @Service
 @Validated
 @Slf4j
-public class FlowableModelServiceImpl implements FlowableModelService {
+public class FlowableModelServiceImpl extends BpmAbstractModelService implements FlowableModelService {
 
     @Resource
     private RepositoryService repositoryService;
     @Resource
-    private BpmFormService bpmFormService;
-    @Resource
     private FlowableProcessDefinitionService processDefinitionService;
 
+    public FlowableModelServiceImpl(BpmFormService bpmFormService){
+        super(bpmFormService);
+    }
+
     @Override
     public PageResult<BpmModelPageItemRespVO> getModelPage(BpmModelPageReqVO pageVO) {
         ModelQuery modelQuery = repositoryService.createModelQuery();
@@ -69,7 +70,7 @@ public class FlowableModelServiceImpl implements FlowableModelService {
 
         // 获得 Form Map
         Set<Long> formIds = CollectionUtils.convertSet(models, model -> {
-            ModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), ModelMetaInfoRespDTO.class);
+            BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class);
             return metaInfo != null ? metaInfo.getFormId() : null;
         });
         Map<Long, BpmFormDO> formMap = bpmFormService.getFormMap(formIds);
@@ -136,15 +137,63 @@ public class FlowableModelServiceImpl implements FlowableModelService {
         saveModelBpmnXml(model, updateReqVO.getBpmnXml());
     }
 
+    @Override
+    public void deployModel(String id) {
+        // 校验流程模型存在
+        Model model = repositoryService.getModel(id);
+        if (ObjectUtils.isEmpty(model)) {
+            throw exception(MODEL_NOT_EXISTS);
+        }
+        // 校验流程图
+        byte[] bpmnBytes = repositoryService.getModelEditorSource(model.getId());
+        if (bpmnBytes == null) {
+            throw exception(MODEL_NOT_EXISTS);
+        }
+        // TODO 芋艿:校验流程图的有效性;例如说,是否有开始的元素,是否有结束的元素;
+        // 校验表单已配
+        BpmFormDO form = checkFormConfig(model.getMetaInfo());
+        //TODO 校验任务分配规则已配置
+        //checkTaskAssignRuleAllConfig(id);
+
+        BpmProcessDefinitionCreateReqDTO definitionCreateReqDTO = ModelConvert.INSTANCE.convert2(model, form).setBpmnBytes(bpmnBytes);
+        // TODO 校验模型是否发生修改。如果未修改,则不允许创建
+//        if (processDefinitionService.isProcessDefinitionEquals(definitionCreateReqDTO)) { // 流程定义的信息相等
+//            ProcessDefinition oldProcessInstance = processDefinitionService.getProcessDefinitionByDeploymentId(model.getDeploymentId());
+//            if (oldProcessInstance != null && taskAssignRuleService.isTaskAssignRulesEquals(model.getId(), oldProcessInstance.getId())) {
+//                throw exception(MODEL_DEPLOY_FAIL_TASK_INFO_EQUALS);
+//            }
+//        }
+        // 创建流程定义
+        String definitionId = processDefinitionService.createProcessDefinition(definitionCreateReqDTO);
+
+        // 将老的流程定义进行挂起。也就是说,只有最新部署的流程定义,才可以发起任务。
+        updateProcessDefinitionSuspended(model.getDeploymentId());
+
+        // 更新 model 的 deploymentId,进行关联
+        ProcessDefinition definition = processDefinitionService.getProcessDefinition(definitionId);
+        model.setDeploymentId(definition.getDeploymentId());
+        repositoryService.saveModel(model);
+
+        //TODO 复制任务分配规则
+        //taskAssignRuleService.copyTaskAssignRules(id, definition.getId());
+    }
+
+    @Override
+    public void deleteModel(String id) {
+
+    }
+
+    @Override
+    public void updateModelState(String id, Integer state) {
+
+    }
+
+
+
     private Model getModelByKey(String key) {
         return repositoryService.createModelQuery().modelKey(key).singleResult();
     }
 
-    private void checkKeyNCName(String key) {
-        if (!ValidationUtils.isXmlNCName(key)) {
-            throw exception(MODEL_KEY_VALID);
-        }
-    }
 
     private void saveModelBpmnXml(Model model, String bpmnXml) {
         if (StrUtil.isEmpty(bpmnXml)) {
@@ -152,4 +201,15 @@ public class FlowableModelServiceImpl implements FlowableModelService {
         }
         repositoryService.addModelEditorSource(model.getId(), StrUtil.utf8Bytes(bpmnXml));
     }
+
+    private void updateProcessDefinitionSuspended(String deploymentId) {
+        if (StrUtil.isEmpty(deploymentId)) {
+            return;
+        }
+        ProcessDefinition oldDefinition = processDefinitionService.getProcessDefinitionByDeploymentId(deploymentId);
+        if (oldDefinition == null) {
+            return;
+        }
+        processDefinitionService.updateProcessDefinitionState(oldDefinition.getId(), SuspensionState.SUSPENDED.getStateCode());
+    }
 }

+ 34 - 0
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableProcessDefinitionService.java

@@ -1,9 +1,11 @@
 package cn.iocoder.yudao.module.bpm.service.definition;
 
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
 import org.flowable.engine.repository.Deployment;
 import org.flowable.engine.repository.ProcessDefinition;
 
+import javax.validation.Valid;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -16,6 +18,22 @@ import java.util.Set;
  */
 public interface FlowableProcessDefinitionService {
 
+    /**
+     * 获得编号对应的 ProcessDefinition
+     *
+     * @param id 编号
+     * @return 流程定义
+     */
+    ProcessDefinition getProcessDefinition(String id);
+
+    /**
+     * 获得 deploymentId 对应的 ProcessDefinition
+     *
+     * @param deploymentId 部署编号
+     * @return 流程定义
+     */
+    ProcessDefinition getProcessDefinitionByDeploymentId(String deploymentId);
+
     /**
      * 获得 deploymentIds 对应的 ProcessDefinition 数组
      *
@@ -49,4 +67,20 @@ public interface FlowableProcessDefinitionService {
      * @return 流程部署
      */
     Deployment getDeployment(String id);
+
+    /**
+     * 创建流程定义
+     *
+     * @param createReqDTO 创建信息
+     * @return 流程编号
+     */
+    String createProcessDefinition(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO);
+
+    /**
+     * 更新流程定义状态
+     *
+     * @param id 流程定义的编号
+     * @param state 状态
+     */
+    void updateProcessDefinitionState(String id, Integer state);
 }

+ 74 - 0
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableProcessDefinitionServiceImpl.java

@@ -2,7 +2,12 @@ package cn.iocoder.yudao.module.bpm.service.definition;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.module.bpm.convert.definition.BpmProcessDefinitionConvert;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
+import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmProcessDefinitionExtMapper;
+import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
 import lombok.extern.slf4j.Slf4j;
+import org.flowable.common.engine.impl.db.SuspensionState;
 import org.flowable.engine.RepositoryService;
 import org.flowable.engine.repository.Deployment;
 import org.flowable.engine.repository.ProcessDefinition;
@@ -10,11 +15,16 @@ import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
+import javax.validation.Valid;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.addIfNotNull;
+import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_DEFINITION_KEY_NOT_MATCH;
+import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_DEFINITION_NAME_NOT_MATCH;
 import static java.util.Collections.emptyList;
 
 /**
@@ -29,9 +39,28 @@ import static java.util.Collections.emptyList;
 @Validated
 @Slf4j
 public class FlowableProcessDefinitionServiceImpl implements FlowableProcessDefinitionService {
+
+    private static final String BPMN_FILE_SUFFIX = ".bpmn";
+
     @Resource
     private RepositoryService repositoryService;
 
+    @Resource
+    private BpmProcessDefinitionExtMapper processDefinitionMapper;
+
+    @Override
+    public ProcessDefinition getProcessDefinition(String id) {
+        return repositoryService.getProcessDefinition(id);
+    }
+
+    @Override
+    public ProcessDefinition getProcessDefinitionByDeploymentId(String deploymentId) {
+        if (StrUtil.isEmpty(deploymentId)) {
+            return null;
+        }
+        return repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
+    }
+
     @Override
     public List<ProcessDefinition> getProcessDefinitionListByDeploymentIds(Set<String> deploymentIds) {
         if (CollUtil.isEmpty(deploymentIds)) {
@@ -59,4 +88,49 @@ public class FlowableProcessDefinitionServiceImpl implements FlowableProcessDefi
         }
         return repositoryService.createDeploymentQuery().deploymentId(id).singleResult();
     }
+
+    @Override
+    public String createProcessDefinition(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO) {
+        // 创建 Deployment 部署
+        Deployment deploy = repositoryService.createDeployment()
+                .key(createReqDTO.getKey()).name(createReqDTO.getName()).category(createReqDTO.getCategory())
+                .addBytes(createReqDTO.getKey() + BPMN_FILE_SUFFIX, createReqDTO.getBpmnBytes())
+                .deploy();
+
+        // 设置 ProcessDefinition 的 category 分类
+        ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deploy.getId()).singleResult();
+        repositoryService.setProcessDefinitionCategory(definition.getId(), createReqDTO.getCategory());
+        // 注意 1,ProcessDefinition 的 key 和 name 是通过 BPMN 中的 <bpmn2:process /> 的 id 和 name 决定
+        // 注意 2,目前该项目的设计上,需要保证 Model、Deployment、ProcessDefinition 使用相同的 key,保证关联性。
+        //          否则,会导致 ProcessDefinition 的分页无法查询到。
+        if (!Objects.equals(definition.getKey(), createReqDTO.getKey())) {
+            throw exception(PROCESS_DEFINITION_KEY_NOT_MATCH, createReqDTO.getKey(), definition.getKey());
+        }
+        if (!Objects.equals(definition.getName(), createReqDTO.getName())) {
+            throw exception(PROCESS_DEFINITION_NAME_NOT_MATCH, createReqDTO.getName(), definition.getName());
+        }
+
+        // 插入拓展表
+        BpmProcessDefinitionExtDO definitionDO = BpmProcessDefinitionConvert.INSTANCE.convert2(createReqDTO)
+                .setProcessDefinitionId(definition.getId());
+        processDefinitionMapper.insert(definitionDO);
+        return definition.getId();
+    }
+
+    @Override
+    public void updateProcessDefinitionState(String id, Integer state) {
+        // 激活
+        if (Objects.equals(SuspensionState.ACTIVE.getStateCode(), state)) {
+            repositoryService.activateProcessDefinitionById(id, false, null);
+            return;
+        }
+        // 挂起
+        if (Objects.equals(SuspensionState.SUSPENDED.getStateCode(), state)) {
+            // suspendProcessInstances = false,进行中的任务,不进行挂起。
+            // 原因:只要新的流程不允许发起即可,老流程继续可以执行。
+            repositoryService.suspendProcessDefinitionById(id, false, null);
+            return;
+        }
+        log.error("[updateProcessDefinitionState][流程定义({}) 修改未知状态({})]", id, state);
+    }
 }

+ 0 - 39
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/ModelMetaInfoRespDTO.java

@@ -1,39 +0,0 @@
-package cn.iocoder.yudao.module.bpm.service.definition.dto;
-
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
-import lombok.Data;
-
-/**
- * BPM 流程 MetaInfo Response DTO
- * 主要用于 {@link org.flowable.engine.repository.Model#setMetaInfo(String)} 的存储
- *
- * @author 芋道源码
- */
-@Data
-public class ModelMetaInfoRespDTO {
-
-    /**
-     * 流程描述
-     */
-    private String description;
-    /**
-     * 表单类型
-     */
-    private Integer formType;
-    /**
-     * 表单编号
-     * 在表单类型为 {@link BpmModelFormTypeEnum#NORMAL} 时
-     */
-    private Long formId;
-    /**
-     * 自定义表单的提交路径,使用 Vue 的路由地址
-     * 在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时
-     */
-    private String formCustomCreatePath;
-    /**
-     * 自定义表单的查看路径,使用 Vue 的路由地址
-     * 在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时
-     */
-    private String formCustomViewPath;
-
-}