Browse Source

工作流 Flowable 发布流程, 删除模型 的实现

jason 3 năm trước cách đây
mục cha
commit
b1d6baaad8
17 tập tin đã thay đổi với 750 bổ sung272 xóa
  1. 27 1
      yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmAbstractModelService.java
  2. 69 0
      yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionCommonService.java
  3. 0 0
      yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java
  4. 2 26
      yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java
  5. 1 49
      yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java
  6. 22 5
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java
  7. 47 0
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java
  8. 2 2
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java
  9. 43 0
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java
  10. 32 0
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmTaskAssignRuleConvert.java
  11. 20 0
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java
  12. 65 28
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java
  13. 14 15
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java
  14. 265 0
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java
  15. 141 0
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java
  16. 0 10
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableModelService.java
  17. 0 136
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableProcessDefinitionServiceImpl.java

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

@@ -1,11 +1,14 @@
 package cn.iocoder.yudao.module.bpm.service.definition;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
 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.BpmModelMetaInfoRespDTO;
 
+import java.util.List;
 import java.util.Objects;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -21,8 +24,11 @@ public abstract class BpmAbstractModelService {
 
     protected final BpmFormService bpmFormService;
 
-    public BpmAbstractModelService(BpmFormService bpmFormService) {
+    protected final BpmTaskAssignRuleService taskAssignRuleService;
+
+    public BpmAbstractModelService(BpmFormService bpmFormService,BpmTaskAssignRuleService taskAssignRuleService) {
         this.bpmFormService = bpmFormService;
+        this.taskAssignRuleService = taskAssignRuleService;
     }
 
     /**
@@ -47,6 +53,26 @@ public abstract class BpmAbstractModelService {
         return null;
     }
 
+    /**
+     * 校验流程模型的任务分配规则全部都配置了
+     * 目的:如果有规则未配置,会导致流程任务找不到负责人,进而流程无法进行下去!
+     *
+     * @param id 流程模型编号
+     */
+    protected void checkTaskAssignRuleAllConfig(String id) {
+        // 一个用户任务都没配置,所以无需配置规则
+        List<BpmTaskAssignRuleRespVO> taskAssignRules = taskAssignRuleService.getTaskAssignRuleList(id, null);
+        if (CollUtil.isEmpty(taskAssignRules)) {
+            return;
+        }
+        // 校验未配置规则的任务
+        taskAssignRules.forEach(rule -> {
+            if (CollUtil.isEmpty(rule.getOptions())) {
+                throw exception(MODEL_DEPLOY_FAIL_TASK_ASSIGN_RULE_NOT_CONFIG, rule.getTaskDefinitionName());
+            }
+        });
+    }
+
 
     protected void checkKeyNCName(String key) {
         if (!ValidationUtils.isXmlNCName(key)) {

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

@@ -0,0 +1,69 @@
+package cn.iocoder.yudao.module.bpm.service.definition;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
+import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
+
+import javax.validation.Valid;
+
+/**
+ * 流程定义通用接口
+ * Activiti 和 flowable 通用的流程定义接口
+ *
+ * @author yunlong.li
+ * @author ZJQ
+ * @author 芋道源码
+ * @author jason
+ */
+public interface BpmProcessDefinitionCommonService {
+
+    /**
+     * 获得流程定义分页
+     *
+     * @param pageReqVO 分页入参
+     * @return 流程定义 Page
+     */
+    PageResult<BpmProcessDefinitionPageItemRespVO> getProcessDefinitionPage(BpmProcessDefinitionPageReqVO pageReqVO);
+
+    /**
+     * 创建流程定义
+     *
+     * @param createReqDTO 创建信息
+     * @return 流程编号
+     */
+    String createProcessDefinition(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO);
+
+    /**
+     * 更新流程定义状态
+     *
+     * @param id 流程定义的编号
+     * @param state 状态
+     */
+    void updateProcessDefinitionState(String id, Integer state);
+
+    /**
+     * 获得流程定义对应的 BPMN XML
+     *
+     * @param id 流程定义编号
+     * @return BPMN XML
+     */
+    String getProcessDefinitionBpmnXML(String id);
+
+    /**
+     * 获得需要创建的流程定义,是否和当前激活的流程定义相等
+     *
+     * @param createReqDTO 创建信息
+     * @return 是否相等
+     */
+    boolean isProcessDefinitionEquals(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO);
+
+    /**
+     * 获得编号对应的 BpmProcessDefinitionExtDO
+     *
+     * @param id 编号
+     * @return 流程定义拓展
+     */
+    BpmProcessDefinitionExtDO getProcessDefinitionExt(String id);
+}

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


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

@@ -52,13 +52,9 @@ public class BpmModelServiceImpl extends BpmAbstractModelService implements BpmM
 
     @Resource
     private BpmProcessDefinitionService processDefinitionService;
-    @Resource
-    @Lazy // 解决循环依赖
-    private BpmTaskAssignRuleService taskAssignRuleService;
-
 
-    public BpmModelServiceImpl(BpmFormService bpmFormService) {
-        super(bpmFormService);
+    public BpmModelServiceImpl(BpmFormService bpmFormService,BpmTaskAssignRuleService taskAssignRuleService) {
+        super(bpmFormService, taskAssignRuleService);
     }
 
     @Override
@@ -196,26 +192,6 @@ public class BpmModelServiceImpl extends BpmAbstractModelService implements BpmM
         taskAssignRuleService.copyTaskAssignRules(id, definition.getId());
     }
 
-    /**
-     * 校验流程模型的任务分配规则全部都配置了
-     * 目的:如果有规则未配置,会导致流程任务找不到负责人,进而流程无法进行下去!
-     *
-     * @param id 流程模型编号
-     */
-    private void checkTaskAssignRuleAllConfig(String id) {
-        // 一个用户任务都没配置,所以无需配置规则
-        List<BpmTaskAssignRuleRespVO> taskAssignRules = taskAssignRuleService.getTaskAssignRuleList(id, null);
-        if (CollUtil.isEmpty(taskAssignRules)) {
-            return;
-        }
-        // 校验未配置规则的任务
-        taskAssignRules.forEach(rule -> {
-            if (CollUtil.isEmpty(rule.getOptions())) {
-                throw exception(MODEL_DEPLOY_FAIL_TASK_ASSIGN_RULE_NOT_CONFIG, rule.getTaskDefinitionName());
-            }
-        });
-    }
-
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void deleteModel(String id) {

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

@@ -24,15 +24,7 @@ import java.util.Set;
  * @author ZJQ
  * @author 芋道源码
  */
-public interface BpmProcessDefinitionService {
-
-    /**
-     * 获得流程定义分页
-     *
-     * @param pageReqVO 分页入参
-     * @return 流程定义 Page
-     */
-    PageResult<BpmProcessDefinitionPageItemRespVO> getProcessDefinitionPage(BpmProcessDefinitionPageReqVO pageReqVO);
+public interface BpmProcessDefinitionService extends BpmProcessDefinitionCommonService {
 
     /**
      * 获得流程定义列表
@@ -42,14 +34,6 @@ public interface BpmProcessDefinitionService {
      */
     List<BpmProcessDefinitionRespVO> getProcessDefinitionList(BpmProcessDefinitionListReqVO listReqVO);
 
-    /**
-     * 获得流程定义对应的 BPMN XML
-     *
-     * @param id 流程定义编号
-     * @return BPMN XML
-     */
-    String getProcessDefinitionBpmnXML(String id);
-
     /**
      * 获得 Bpmn 模型
      *
@@ -84,14 +68,6 @@ public interface BpmProcessDefinitionService {
      */
     ProcessDefinition getActiveProcessDefinition(String key);
 
-    /**
-     * 获得编号对应的 BpmProcessDefinitionExtDO
-     *
-     * @param id 编号
-     * @return 流程定义拓展
-     */
-    BpmProcessDefinitionExtDO getProcessDefinitionExt(String id);
-
     /**
      * 获得 id 对应的 Deployment
      *
@@ -134,28 +110,4 @@ public interface BpmProcessDefinitionService {
      */
     List<ProcessDefinition> getProcessDefinitionListByDeploymentIds(Set<String> deploymentIds);
 
-    /**
-     * 获得需要创建的流程定义,是否和当前激活的流程定义相等
-     *
-     * @param createReqDTO 创建信息
-     * @return 是否相等
-     */
-    boolean isProcessDefinitionEquals(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO);
-
-    /**
-     * 创建流程定义
-     *
-     * @param createReqDTO 创建信息
-     * @return 流程编号
-     */
-    String createProcessDefinition(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO);
-
-    /**
-     * 更新流程定义的挂起状态
-     *
-     * @param id 流程定义的编号
-     * @param state 挂起状态 {@link org.activiti.engine.impl.persistence.entity.SuspensionState}
-     */
-    void updateProcessDefinitionState(String id, Integer state);
-
 }

+ 22 - 5
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/FlowableModelController.java → yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java

@@ -4,8 +4,8 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.io.IoUtils;
 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.service.definition.FlowableModelService;
+import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert;
+import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiOperation;
@@ -24,10 +24,10 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 @RestController
 @RequestMapping("/bpm/model")
 @Validated
-public class FlowableModelController {
+public class BpmModelController {
 
     @Resource
-    private FlowableModelService modelService;
+    private BpmModelService modelService;
 
     @GetMapping("/page")
     @ApiOperation(value = "获得模型分页")
@@ -62,7 +62,7 @@ public class FlowableModelController {
     @PostMapping("/import")
     @ApiOperation(value = "导入模型")
     public CommonResult<String> importModel(@Valid BpmModeImportReqVO importReqVO) throws IOException {
-        BpmModelCreateReqVO createReqVO = ModelConvert.INSTANCE.convert(importReqVO);
+        BpmModelCreateReqVO createReqVO = BpmModelConvert.INSTANCE.convert(importReqVO);
         // 读取文件
         String bpmnXml = IoUtils.readUtf8(importReqVO.getBpmnFile().getInputStream(), false);
         return success(modelService.createModel(createReqVO, bpmnXml));
@@ -76,4 +76,21 @@ public class FlowableModelController {
         modelService.deployModel(id);
         return success(true);
     }
+
+    @PutMapping("/update-state")
+    @ApiOperation(value = "修改模型的状态", notes = "实际更新的部署的流程定义的状态")
+    @PreAuthorize("@ss.hasPermission('bpm:model:update')")
+    public CommonResult<Boolean> updateModelState(@Valid @RequestBody BpmModelUpdateStateReqVO reqVO) {
+        modelService.updateModelState(reqVO.getId(), reqVO.getState());
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @ApiOperation("删除模型")
+    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = String.class)
+    @PreAuthorize("@ss.hasPermission('bpm:model:delete')")
+    public CommonResult<Boolean> deleteModel(@RequestParam("id") String id) {
+        modelService.deleteModel(id);
+        return success(true);
+    }
 }

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

@@ -0,0 +1,47 @@
+package cn.iocoder.yudao.module.bpm.controller.admin.definition;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO;
+import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Api(tags = "管理后台 - 流程定义")
+@RestController
+@RequestMapping("/bpm/process-definition")
+@Validated
+public class BpmProcessDefinitionController {
+
+    @Resource
+    private BpmProcessDefinitionService bpmDefinitionService;
+
+    @GetMapping("/page")
+    @ApiOperation(value = "获得流程定义分页")
+    @PreAuthorize("@ss.hasPermission('bpm:process-definition:query')")
+    public CommonResult<PageResult<BpmProcessDefinitionPageItemRespVO>> getProcessDefinitionPage(
+            BpmProcessDefinitionPageReqVO pageReqVO) {
+        return success(bpmDefinitionService.getProcessDefinitionPage(pageReqVO));
+    }
+
+    @GetMapping ("/get-bpmn-xml")
+    @ApiOperation(value = "获得流程定义的 BPMN XML")
+    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = String.class)
+    @PreAuthorize("@ss.hasPermission('bpm:process-definition:query')")
+    public CommonResult<String> getProcessDefinitionBpmnXML(@RequestParam("id") String id) {
+        String bpmnXML = bpmDefinitionService.getProcessDefinitionBpmnXML(id);
+        return success(bpmnXML);
+    }
+}

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

@@ -25,9 +25,9 @@ import java.util.Objects;
  * @author yunlongn
  */
 @Mapper
-public interface ModelConvert {
+public interface BpmModelConvert {
 
-    ModelConvert INSTANCE = Mappers.getMapper(ModelConvert.class);
+    BpmModelConvert INSTANCE = Mappers.getMapper(BpmModelConvert.class);
 
     default List<BpmModelPageItemRespVO> convertList(List<Model> list, Map<Long, BpmFormDO> formMap,
                                                      Map<String, Deployment> deploymentMap,

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

@@ -1,10 +1,22 @@
 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 org.flowable.common.engine.impl.db.SuspensionState;
+import org.flowable.engine.repository.Deployment;
+import org.flowable.engine.repository.ProcessDefinition;
 import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.MappingTarget;
 import org.mapstruct.factory.Mappers;
 
+import java.util.List;
+import java.util.Map;
+
 /**
  * Bpm 流程定义的 Convert
  *
@@ -12,7 +24,38 @@ import org.mapstruct.factory.Mappers;
  */
 @Mapper
 public interface BpmProcessDefinitionConvert {
+
     BpmProcessDefinitionConvert INSTANCE = Mappers.getMapper(BpmProcessDefinitionConvert.class);
 
+    BpmProcessDefinitionPageItemRespVO convert(ProcessDefinition bean);
+
     BpmProcessDefinitionExtDO convert2(BpmProcessDefinitionCreateReqDTO bean);
+
+    default List<BpmProcessDefinitionPageItemRespVO> convertList(List<ProcessDefinition> list, Map<String, Deployment> deploymentMap,
+                                                                 Map<String, BpmProcessDefinitionExtDO> processDefinitionDOMap, Map<Long, BpmFormDO> formMap) {
+        return CollectionUtils.convertList(list, definition -> {
+            Deployment deployment = definition.getDeploymentId() != null ? deploymentMap.get(definition.getDeploymentId()) : null;
+            BpmProcessDefinitionExtDO definitionDO = processDefinitionDOMap.get(definition.getId());
+            BpmFormDO form = definitionDO != null ? formMap.get(definitionDO.getFormId()) : null;
+            return convert(definition, deployment, definitionDO, form);
+        });
+    }
+
+    default BpmProcessDefinitionPageItemRespVO convert(ProcessDefinition bean, Deployment deployment,
+                                                       BpmProcessDefinitionExtDO processDefinitionExtDO, BpmFormDO form) {
+        BpmProcessDefinitionPageItemRespVO respVO = convert(bean);
+        respVO.setSuspensionState(bean.isSuspended() ? SuspensionState.SUSPENDED.getStateCode() : SuspensionState.ACTIVE.getStateCode());
+        if (deployment != null) {
+            respVO.setDeploymentTime(deployment.getDeploymentTime());
+        }
+        if (form != null) {
+            respVO.setFormName(form.getName());
+        }
+        // 复制通用属性
+        copyTo(processDefinitionExtDO, respVO);
+        return respVO;
+    }
+
+    @Mapping(source = "from.id", target = "to.id", ignore = true)
+    void copyTo(BpmProcessDefinitionExtDO from, @MappingTarget BpmProcessDefinitionRespVO to);
 }

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

@@ -0,0 +1,32 @@
+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.rule.BpmTaskAssignRuleRespVO;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
+import org.flowable.bpmn.model.UserTask;
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+import java.util.Map;
+
+@Mapper
+public interface BpmTaskAssignRuleConvert {
+    BpmTaskAssignRuleConvert INSTANCE = Mappers.getMapper(BpmTaskAssignRuleConvert.class);
+
+    default List<BpmTaskAssignRuleRespVO> convertList(List<UserTask> tasks, List<BpmTaskAssignRuleDO> rules) {
+        Map<String, BpmTaskAssignRuleDO> ruleMap = CollectionUtils.convertMap(rules, BpmTaskAssignRuleDO::getTaskDefinitionKey);
+        // 以 UserTask 为主维度,原因是:流程图编辑后,一些规则实际就没用了。
+        return CollectionUtils.convertList(tasks, task -> {
+            BpmTaskAssignRuleRespVO respVO = convert(ruleMap.get(task.getId()));
+            if (respVO == null) {
+                respVO = new BpmTaskAssignRuleRespVO();
+                respVO.setTaskDefinitionKey(task.getId());
+            }
+            respVO.setTaskDefinitionName(task.getName());
+            return respVO;
+        });
+    }
+
+    BpmTaskAssignRuleRespVO convert(BpmTaskAssignRuleDO bean);
+}

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

@@ -0,0 +1,20 @@
+package cn.iocoder.yudao.module.bpm.service.definition;
+
+import org.flowable.bpmn.model.BpmnModel;
+
+/**
+ * Flowable流程模型接口
+ *
+ * @author yunlongn
+ */
+public interface BpmModelService extends BpmModelCommonService {
+
+    /**
+     * 获得流程模型编号对应的 BPMN Model
+     *
+     * @param id 流程模型编号
+     * @return BPMN Model
+     */
+    BpmnModel getBpmnModel(String id);
+
+}

+ 65 - 28
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableModelServiceImpl.java → yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java

@@ -1,17 +1,21 @@
 package cn.iocoder.yudao.module.bpm.service.definition;
 
+import cn.hutool.core.util.ArrayUtil;
 import cn.hutool.core.util.StrUtil;
 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.module.bpm.controller.admin.definition.vo.model.*;
-import cn.iocoder.yudao.module.bpm.convert.definition.ModelConvert;
+import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert;
 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 lombok.extern.slf4j.Slf4j;
+import org.flowable.bpmn.converter.BpmnXMLConverter;
+import org.flowable.bpmn.model.BpmnModel;
 import org.flowable.common.engine.impl.db.SuspensionState;
+import org.flowable.common.engine.impl.util.io.BytesStreamSource;
 import org.flowable.engine.RepositoryService;
 import org.flowable.engine.repository.Deployment;
 import org.flowable.engine.repository.Model;
@@ -41,15 +45,15 @@ import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
 @Service
 @Validated
 @Slf4j
-public class FlowableModelServiceImpl extends BpmAbstractModelService implements FlowableModelService {
+public class BpmModelServiceImpl extends BpmAbstractModelService implements BpmModelService {
 
     @Resource
     private RepositoryService repositoryService;
     @Resource
-    private FlowableProcessDefinitionService processDefinitionService;
+    private BpmProcessDefinitionService processDefinitionService;
 
-    public FlowableModelServiceImpl(BpmFormService bpmFormService){
-        super(bpmFormService);
+    public BpmModelServiceImpl(BpmFormService bpmFormService, BpmTaskAssignRuleService taskAssignRuleService){
+        super(bpmFormService, taskAssignRuleService);
     }
 
     @Override
@@ -85,7 +89,7 @@ public class FlowableModelServiceImpl extends BpmAbstractModelService implements
 
         // 拼接结果
         long modelCount = modelQuery.count();
-        return new PageResult<>(ModelConvert.INSTANCE.convertList(models, formMap, deploymentMap, processDefinitionMap), modelCount);
+        return new PageResult<>(BpmModelConvert.INSTANCE.convertList(models, formMap, deploymentMap, processDefinitionMap), modelCount);
     }
 
     @Override
@@ -100,7 +104,7 @@ public class FlowableModelServiceImpl extends BpmAbstractModelService implements
 
         // 创建流程定义
         Model model = repositoryService.newModel();
-        ModelConvert.INSTANCE.copy(model, createReqVO);
+        BpmModelConvert.INSTANCE.copy(model, createReqVO);
         // 保存流程定义
         repositoryService.saveModel(model);
         // 保存 BPMN XML
@@ -108,13 +112,17 @@ public class FlowableModelServiceImpl extends BpmAbstractModelService implements
         return model.getId();
     }
 
+    private Model getModelByKey(String key) {
+        return repositoryService.createModelQuery().modelKey(key).singleResult();
+    }
+
     @Override
     public BpmModelRespVO getModel(String id) {
         Model model = repositoryService.getModel(id);
         if (model == null) {
             return null;
         }
-        BpmModelRespVO modelRespVO = ModelConvert.INSTANCE.convert(model);
+        BpmModelRespVO modelRespVO = BpmModelConvert.INSTANCE.convert(model);
         // 拼接 bpmn XML
         byte[] bpmnBytes = repositoryService.getModelEditorSource(id);
         modelRespVO.setBpmnXml(StrUtil.utf8Str(bpmnBytes));
@@ -130,7 +138,7 @@ public class FlowableModelServiceImpl extends BpmAbstractModelService implements
         }
 
         // 修改流程定义
-        ModelConvert.INSTANCE.copy(model, updateReqVO);
+        BpmModelConvert.INSTANCE.copy(model, updateReqVO);
         // 更新模型
         repositoryService.saveModel(model);
         // 更新 BPMN XML
@@ -152,17 +160,17 @@ public class FlowableModelServiceImpl extends BpmAbstractModelService implements
         // 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);
-//            }
-//        }
+        //校验任务分配规则已配置
+        checkTaskAssignRuleAllConfig(id);
+
+        BpmProcessDefinitionCreateReqDTO definitionCreateReqDTO = BpmModelConvert.INSTANCE.convert2(model, form).setBpmnBytes(bpmnBytes);
+        //校验模型是否发生修改。如果未修改,则不允许创建
+        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);
 
@@ -178,23 +186,38 @@ public class FlowableModelServiceImpl extends BpmAbstractModelService implements
         //taskAssignRuleService.copyTaskAssignRules(id, definition.getId());
     }
 
+
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public void deleteModel(String id) {
-
+        // 校验流程模型存在
+        Model model = repositoryService.getModel(id);
+        if (model == null) {
+            throw exception(MODEL_NOT_EXISTS);
+        }
+        // 执行删除
+        repositoryService.deleteModel(id);
+        // 禁用流程实例
+        updateProcessDefinitionSuspended(model.getDeploymentId());
     }
 
     @Override
     public void updateModelState(String id, Integer state) {
+        // 校验流程模型存在
+        Model model = repositoryService.getModel(id);
+        if (model == null) {
+            throw exception(MODEL_NOT_EXISTS);
+        }
+        // 校验流程定义存在
+        ProcessDefinition definition = processDefinitionService.getProcessDefinitionByDeploymentId(model.getDeploymentId());
+        if (definition == null) {
+            throw exception(PROCESS_DEFINITION_NOT_EXISTS);
+        }
 
+        // 更新状态
+        processDefinitionService.updateProcessDefinitionState(definition.getId(), state);
     }
 
-
-
-    private Model getModelByKey(String key) {
-        return repositoryService.createModelQuery().modelKey(key).singleResult();
-    }
-
-
     private void saveModelBpmnXml(Model model, String bpmnXml) {
         if (StrUtil.isEmpty(bpmnXml)) {
             return;
@@ -202,6 +225,10 @@ public class FlowableModelServiceImpl extends BpmAbstractModelService implements
         repositoryService.addModelEditorSource(model.getId(), StrUtil.utf8Bytes(bpmnXml));
     }
 
+    /**
+     * 挂起 deploymentId 对应的流程定义。 这里一个deploymentId 只关联一个流程定义
+     * @param deploymentId 流程发布Id.
+     */
     private void updateProcessDefinitionSuspended(String deploymentId) {
         if (StrUtil.isEmpty(deploymentId)) {
             return;
@@ -212,4 +239,14 @@ public class FlowableModelServiceImpl extends BpmAbstractModelService implements
         }
         processDefinitionService.updateProcessDefinitionState(oldDefinition.getId(), SuspensionState.SUSPENDED.getStateCode());
     }
+
+    @Override
+    public BpmnModel getBpmnModel(String id) {
+        byte[] bpmnBytes = repositoryService.getModelEditorSource(id);
+        if (ArrayUtil.isEmpty(bpmnBytes)) {
+            return null;
+        }
+        BpmnXMLConverter converter = new BpmnXMLConverter();
+        return converter.convertToBpmnModel(new BytesStreamSource(bpmnBytes), true, true);
+    }
 }

+ 14 - 15
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableProcessDefinitionService.java → yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java

@@ -1,11 +1,10 @@
 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.bpmn.model.BpmnModel;
 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,7 +15,7 @@ import java.util.Set;
  * @author ZJQ
  * @author 芋道源码
  */
-public interface FlowableProcessDefinitionService {
+public interface BpmProcessDefinitionService extends BpmProcessDefinitionCommonService {
 
     /**
      * 获得编号对应的 ProcessDefinition
@@ -42,6 +41,14 @@ public interface FlowableProcessDefinitionService {
      */
     List<ProcessDefinition> getProcessDefinitionListByDeploymentIds(Set<String> deploymentIds);
 
+    /**
+     * 获得流程定义标识对应的激活的流程定义
+     *
+     * @param key 流程定义的标识
+     * @return 流程定义
+     */
+    ProcessDefinition getActiveProcessDefinition(String key);
+
     /**
      * 获得 ids 对应的 Deployment Map
      *
@@ -69,18 +76,10 @@ public interface FlowableProcessDefinitionService {
     Deployment getDeployment(String id);
 
     /**
-     * 创建流程定义
-     *
-     * @param createReqDTO 创建信息
-     * @return 流程编号
-     */
-    String createProcessDefinition(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO);
-
-    /**
-     * 更新流程定义状态
+     * 获得 Bpmn 模型
      *
-     * @param id 流程定义的编号
-     * @param state 状态
+     * @param processDefinitionId 流程定义的编号
+     * @return Bpmn 模型
      */
-    void updateProcessDefinitionState(String id, Integer state);
+    BpmnModel getBpmnModel(String processDefinitionId);
 }

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

@@ -0,0 +1,265 @@
+package cn.iocoder.yudao.module.bpm.service.definition;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.PageUtils;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO;
+import cn.iocoder.yudao.module.bpm.convert.definition.BpmProcessDefinitionConvert;
+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.flowable.bpmn.converter.BpmnXMLConverter;
+import org.flowable.bpmn.model.BpmnModel;
+import org.flowable.common.engine.impl.db.SuspensionState;
+import org.flowable.common.engine.impl.util.io.BytesStreamSource;
+import org.flowable.engine.RepositoryService;
+import org.flowable.engine.repository.Deployment;
+import org.flowable.engine.repository.ProcessDefinition;
+import org.flowable.engine.repository.ProcessDefinitionQuery;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+import java.util.*;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
+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;
+
+/**
+ * 流程定义实现
+ * 主要进行 Flowable {@link ProcessDefinition} 和 {@link Deployment} 的维护
+ *
+ * @author yunlongn
+ * @author ZJQ
+ * @author 芋道源码
+ */
+@Service
+@Validated
+@Slf4j
+public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionService {
+
+    private static final String BPMN_FILE_SUFFIX = ".bpmn";
+
+    @Resource
+    private RepositoryService repositoryService;
+
+    @Resource
+    private BpmProcessDefinitionExtMapper processDefinitionMapper;
+
+    @Resource
+    private BpmFormService formService;
+
+    @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)) {
+            return emptyList();
+        }
+        return repositoryService.createProcessDefinitionQuery().deploymentIds(deploymentIds).list();
+    }
+
+    @Override
+    public ProcessDefinition getActiveProcessDefinition(String key) {
+        return repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).active().singleResult();
+    }
+
+    @Override
+    public List<Deployment> getDeployments(Set<String> ids) {
+        if (CollUtil.isEmpty(ids)) {
+            return emptyList();
+        }
+        List<Deployment> list = new ArrayList<>(ids.size());
+        for (String id : ids) {
+            addIfNotNull(list, getDeployment(id));
+        }
+        return list;
+    }
+
+    @Override
+    public Deployment getDeployment(String id) {
+        if (StrUtil.isEmpty(id)) {
+            return null;
+        }
+        return repositoryService.createDeploymentQuery().deploymentId(id).singleResult();
+    }
+
+    @Override
+    public BpmnModel getBpmnModel(String processDefinitionId) {
+        return repositoryService.getBpmnModel(processDefinitionId);
+    }
+
+    @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);
+    }
+
+    @Override
+    public String getProcessDefinitionBpmnXML(String id) {
+        BpmnModel bpmnModel = repositoryService.getBpmnModel(id);
+        if (bpmnModel == null) {
+            return null;
+        }
+        BpmnXMLConverter converter = new BpmnXMLConverter();
+        return StrUtil.utf8Str(converter.convertToXML(bpmnModel));
+    }
+
+    @Override
+    public boolean isProcessDefinitionEquals(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO) {
+        // 校验 name、description 是否更新
+        ProcessDefinition oldProcessDefinition = getActiveProcessDefinition(createReqDTO.getKey());
+        if (oldProcessDefinition == null) {
+            return false;
+        }
+        BpmProcessDefinitionExtDO oldProcessDefinitionExt = getProcessDefinitionExt(oldProcessDefinition.getId());
+        if (!StrUtil.equals(createReqDTO.getName(), oldProcessDefinition.getName())
+                || !StrUtil.equals(createReqDTO.getDescription(), oldProcessDefinitionExt.getDescription())
+                || !StrUtil.equals(createReqDTO.getCategory(), oldProcessDefinition.getCategory())) {
+            return false;
+        }
+        // 校验 form 信息是否更新
+        if (!ObjectUtil.equal(createReqDTO.getFormType(), oldProcessDefinitionExt.getFormType())
+                || !ObjectUtil.equal(createReqDTO.getFormId(), oldProcessDefinitionExt.getFormId())
+                || !ObjectUtil.equal(createReqDTO.getFormConf(), oldProcessDefinitionExt.getFormConf())
+                || !ObjectUtil.equal(createReqDTO.getFormFields(), oldProcessDefinitionExt.getFormFields())
+                || !ObjectUtil.equal(createReqDTO.getFormCustomCreatePath(), oldProcessDefinitionExt.getFormCustomCreatePath())
+                || !ObjectUtil.equal(createReqDTO.getFormCustomViewPath(), oldProcessDefinitionExt.getFormCustomViewPath())) {
+            return false;
+        }
+        // 校验 BPMN XML 信息
+        BpmnModel newModel = buildBpmnModel(createReqDTO.getBpmnBytes());
+        BpmnModel oldModel = getBpmnModel(oldProcessDefinition.getId());
+        //TODO  貌似 flowable 不修改这个也不同。需要看看。 sourceSystemId 不同
+        if (equals(oldModel, newModel)) {
+            return false;
+        }
+        // 最终发现都一致,则返回 true
+        return true;
+    }
+
+    /**
+     * 构建对应的 BPMN Model
+     *
+     * @param bpmnBytes 原始的 BPMN XML 字节数组
+     * @return BPMN Model
+     */
+    private  BpmnModel buildBpmnModel(byte[] bpmnBytes) {
+        // 转换成 BpmnModel 对象
+        BpmnXMLConverter converter = new BpmnXMLConverter();
+        return converter.convertToBpmnModel(new BytesStreamSource(bpmnBytes), true, true);
+    }
+    //TODO 移出去
+    public  boolean equals(BpmnModel oldModel, BpmnModel newModel) {
+        // 由于 BpmnModel 未提供 equals 方法,所以只能转成字节数组,进行比较
+        return Arrays.equals(getBpmnBytes(oldModel), getBpmnBytes(newModel));
+    }
+    //TODO 移出去
+    public  byte[] getBpmnBytes(BpmnModel model) {
+        if (model == null) {
+            return new byte[0];
+        }
+        BpmnXMLConverter converter = new BpmnXMLConverter();
+        return converter.convertToXML(model);
+    }
+
+    @Override
+    public BpmProcessDefinitionExtDO getProcessDefinitionExt(String id) {
+        return processDefinitionMapper.selectByProcessDefinitionId(id);
+    }
+
+    @Override
+    public PageResult<BpmProcessDefinitionPageItemRespVO> getProcessDefinitionPage(BpmProcessDefinitionPageReqVO pageVO) {
+        ProcessDefinitionQuery definitionQuery = repositoryService.createProcessDefinitionQuery();
+        if (StrUtil.isNotBlank(pageVO.getKey())) {
+            definitionQuery.processDefinitionKey(pageVO.getKey());
+        }
+
+        // 执行查询
+        List<ProcessDefinition> processDefinitions = definitionQuery.orderByProcessDefinitionVersion().desc()
+                .listPage(PageUtils.getStart(pageVO), pageVO.getPageSize());
+
+        if (CollUtil.isEmpty(processDefinitions)) {
+            return new PageResult<>(emptyList(), definitionQuery.count());
+        }
+        // 获得 Deployment Map
+        Set<String> deploymentIds = new HashSet<>();
+        processDefinitions.forEach(definition -> addIfNotNull(deploymentIds, definition.getDeploymentId()));
+        Map<String, Deployment> deploymentMap = getDeploymentMap(deploymentIds);
+
+        // 获得 BpmProcessDefinitionDO Map
+        List<BpmProcessDefinitionExtDO> processDefinitionDOs = processDefinitionMapper.selectListByProcessDefinitionIds(
+                convertList(processDefinitions, ProcessDefinition::getId));
+        Map<String, BpmProcessDefinitionExtDO> processDefinitionDOMap = convertMap(processDefinitionDOs,
+                BpmProcessDefinitionExtDO::getProcessDefinitionId);
+
+        // 获得 Form Map
+        Set<Long> formIds = convertSet(processDefinitionDOs, BpmProcessDefinitionExtDO::getFormId);
+        Map<Long, BpmFormDO> formMap = formService.getFormMap(formIds);
+
+        // 拼接结果
+        long definitionCount = definitionQuery.count();
+        return new PageResult<>(BpmProcessDefinitionConvert.INSTANCE.convertList(processDefinitions, deploymentMap,
+                processDefinitionDOMap, formMap), definitionCount);
+    }
+}

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

@@ -0,0 +1,141 @@
+package cn.iocoder.yudao.module.bpm.service.definition;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleCreateReqVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO;
+import cn.iocoder.yudao.module.bpm.convert.definition.BpmTaskAssignRuleConvert;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
+import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.flowable.bpmn.model.BpmnModel;
+import org.flowable.bpmn.model.FlowElement;
+import org.flowable.bpmn.model.UserTask;
+import org.springframework.context.annotation.Lazy;
+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.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * BPM 任务分配规则 Service 实现类
+ */
+@Service
+@Validated
+@Slf4j
+public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService{
+
+    @Resource
+    private BpmTaskAssignRuleMapper taskRuleMapper;
+
+    @Resource
+    @Lazy // 解决循环依赖
+    private BpmModelService modelService;
+
+    @Resource
+    private BpmProcessDefinitionService processDefinitionService;
+
+    @Override
+    public List<BpmTaskAssignRuleDO> getTaskAssignRuleListByProcessDefinitionId(String processDefinitionId, String taskDefinitionKey) {
+        return taskRuleMapper.selectListByProcessDefinitionId(processDefinitionId, taskDefinitionKey);
+    }
+
+    @Override
+    public List<BpmTaskAssignRuleDO> getTaskAssignRuleListByModelId(String modelId) {
+        return taskRuleMapper.selectListByModelId(modelId);
+    }
+
+    @Override
+    public List<BpmTaskAssignRuleRespVO> getTaskAssignRuleList(String modelId, String processDefinitionId) {
+        // 获得规则
+        List<BpmTaskAssignRuleDO> rules = Collections.emptyList();
+        BpmnModel model = null;
+        if (StrUtil.isNotEmpty(modelId)) {
+            rules = getTaskAssignRuleListByModelId(modelId);
+            model = modelService.getBpmnModel(modelId);
+        } else if (StrUtil.isNotEmpty(processDefinitionId)) {
+            rules = getTaskAssignRuleListByProcessDefinitionId(processDefinitionId, null);
+            model = processDefinitionService.getBpmnModel(processDefinitionId);
+        }
+        if (model == null) {
+            return Collections.emptyList();
+        }
+
+        // 获得用户任务,只有用户任务才可以设置分配规则
+        List<UserTask> userTasks = getBpmnModelElements(model, UserTask.class);
+        if (CollUtil.isEmpty(userTasks)) {
+            return Collections.emptyList();
+        }
+
+        // 转换数据
+        return BpmTaskAssignRuleConvert.INSTANCE.convertList(userTasks, rules);
+    }
+
+    /**
+     * TODO 需要移出去
+     * 获得 BPMN 流程中,指定的元素们
+     *
+     * @param model
+     * @param clazz 指定元素。例如说,{@link org.flowable.bpmn.model.UserTask}、{@link org.flowable.bpmn.model.Gateway} 等等
+     * @return 元素们
+     */
+    public static <T extends FlowElement> List<T> getBpmnModelElements(BpmnModel model, Class<T> clazz) {
+        List<T> result = new ArrayList<>();
+        model.getProcesses().forEach(process -> {
+            process.getFlowElements().forEach(flowElement -> {
+                if (flowElement.getClass().isAssignableFrom(clazz)) {
+                    result.add((T) flowElement);
+                }
+            });
+        });
+        return result;
+    }
+
+    @Override
+    public Long createTaskAssignRule(@Valid BpmTaskAssignRuleCreateReqVO reqVO) {
+        return null;
+    }
+
+    @Override
+    public void updateTaskAssignRule(@Valid BpmTaskAssignRuleUpdateReqVO reqVO) {
+
+    }
+
+    @Override
+    public boolean isTaskAssignRulesEquals(String modelId, String processDefinitionId) {
+        // 调用 VO 接口的原因是,过滤掉流程模型不需要的规则,保持和 copyTaskAssignRules 方法的一致性
+        List<BpmTaskAssignRuleRespVO> modelRules = getTaskAssignRuleList(modelId, null);
+        List<BpmTaskAssignRuleRespVO> processInstanceRules = getTaskAssignRuleList(null, processDefinitionId);
+        if (modelRules.size() != processInstanceRules.size()) {
+            return false;
+        }
+
+        // 遍历,匹配对应的规则
+        Map<String, BpmTaskAssignRuleRespVO> processInstanceRuleMap = CollectionUtils.convertMap(processInstanceRules,
+                BpmTaskAssignRuleRespVO::getTaskDefinitionKey);
+        for (BpmTaskAssignRuleRespVO modelRule : modelRules) {
+            BpmTaskAssignRuleRespVO processInstanceRule = processInstanceRuleMap.get(modelRule.getTaskDefinitionKey());
+            if (processInstanceRule == null) {
+                return false;
+            }
+            if (!ObjectUtil.equals(modelRule.getType(), processInstanceRule.getType())
+                    || !ObjectUtil.equal(modelRule.getOptions(), processInstanceRule.getOptions())) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public void copyTaskAssignRules(String fromModelId, String toProcessDefinitionId) {
+
+    }
+}

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

@@ -1,10 +0,0 @@
-package cn.iocoder.yudao.module.bpm.service.definition;
-
-/**
- * Flowable流程模型接口
- *
- * @author yunlongn
- */
-public interface FlowableModelService extends BpmModelCommonService {
-
-}

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

@@ -1,136 +0,0 @@
-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;
-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;
-
-/**
- * 流程定义实现
- * 主要进行 Flowable {@link ProcessDefinition} 和 {@link Deployment} 的维护
- *
- * @author yunlongn
- * @author ZJQ
- * @author 芋道源码
- */
-@Service
-@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)) {
-            return emptyList();
-        }
-        return repositoryService.createProcessDefinitionQuery().deploymentIds(deploymentIds).list();
-    }
-
-    @Override
-    public List<Deployment> getDeployments(Set<String> ids) {
-        if (CollUtil.isEmpty(ids)) {
-            return emptyList();
-        }
-        List<Deployment> list = new ArrayList<>(ids.size());
-        for (String id : ids) {
-            addIfNotNull(list, getDeployment(id));
-        }
-        return list;
-    }
-
-    @Override
-    public Deployment getDeployment(String id) {
-        if (StrUtil.isEmpty(id)) {
-            return null;
-        }
-        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);
-    }
-}