From fe7a68c41e0e1502483be2769c133be635ef4dad Mon Sep 17 00:00:00 2001
From: YunaiV <zhijiantianya@gmail.com>
Date: Sat, 22 Jan 2022 02:15:04 +0800
Subject: [PATCH] =?UTF-8?q?bpm=20=E5=A2=9E=E5=8A=A0=E6=B5=81=E7=A8=8B?=
 =?UTF-8?q?=E5=AE=9A=E4=B9=89=E7=9A=84=E4=BF=A1=E6=81=AF=E6=9C=AA=E5=8F=91?=
 =?UTF-8?q?=E7=94=9F=E5=8F=98=E5=8C=96=E6=97=B6=EF=BC=8C=E9=83=A8=E7=BD=B2?=
 =?UTF-8?q?=E4=B8=8D=E7=94=9F=E6=95=88?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../task/vo/activity/BpmActivityRespVO.java   | 16 -----
 .../convert/definition/BpmModelConvert.java   |  8 +--
 .../BpmProcessDefinitionConvert.java          |  4 +-
 .../bpm/convert/task/BpmActivityConvert.java  | 11 +---
 .../bpm/enums/BpmErrorCodeConstants.java      |  1 +
 .../BpmProcessDefinitionService.java          | 12 +++-
 .../definition/BpmTaskAssignRuleService.java  |  9 +++
 ... => BpmProcessDefinitionCreateReqDTO.java} |  4 +-
 .../definition/impl/BpmModelServiceImpl.java  | 16 ++---
 .../impl/BpmProcessDefinitionServiceImpl.java | 61 ++++++++++++++++---
 .../impl/BpmTaskAssignRuleServiceImpl.java    | 33 ++++++++--
 .../task/impl/BpmActivityServiceImpl.java     |  5 +-
 .../activiti/core/util/ActivitiUtils.java     | 17 +++++-
 13 files changed, 136 insertions(+), 61 deletions(-)
 rename yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/dto/{BpmDefinitionCreateReqDTO.java => BpmProcessDefinitionCreateReqDTO.java} (97%)

diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/activity/BpmActivityRespVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/activity/BpmActivityRespVO.java
index 23e1b8168..447c59000 100644
--- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/activity/BpmActivityRespVO.java
+++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/activity/BpmActivityRespVO.java
@@ -23,20 +23,4 @@ public class BpmActivityRespVO {
     @ApiModelProperty(value = "关联的流程任务的编号", example = "2048", notes = "关联的流程任务,只有 UserTask 等类型才有")
     private String taskId;
 
-    /**
-     * 关联的流程任务,只有 UserTask 类型才有
-     */
-    private Task task;
-
-    @ApiModel(value = "流程任务")
-    @Data
-    public static class Task {
-
-        @ApiModelProperty(value = "关联的流程任务的编号", required = true, example = "2048")
-        private String id;
-        @ApiModelProperty(value = "关联的流程任务的结果", required = true, example = "2", notes = "参见 bpm_process_instance_result 枚举")
-        private Integer result;
-
-    }
-
 }
diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmModelConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmModelConvert.java
index ceecfcfa4..eb3362ac6 100644
--- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmModelConvert.java
+++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmModelConvert.java
@@ -3,7 +3,7 @@ package cn.iocoder.yudao.adminserver.modules.bpm.convert.definition;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.model.*;
 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmFormDO;
-import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmDefinitionCreateReqDTO;
+import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
@@ -83,8 +83,8 @@ public interface BpmModelConvert {
 
     void copyTo(BpmModelMetaInfoRespDTO from, @MappingTarget BpmModelBaseVO to);
 
-    default BpmDefinitionCreateReqDTO convert2(Model model, BpmFormDO form) {
-        BpmDefinitionCreateReqDTO createReqDTO = new BpmDefinitionCreateReqDTO();
+    default BpmProcessDefinitionCreateReqDTO convert2(Model model, BpmFormDO form) {
+        BpmProcessDefinitionCreateReqDTO createReqDTO = new BpmProcessDefinitionCreateReqDTO();
         createReqDTO.setModelId(model.getId());
         createReqDTO.setName(model.getName());
         createReqDTO.setKey(model.getKey());
@@ -100,7 +100,7 @@ public interface BpmModelConvert {
         return createReqDTO;
     }
 
-    void copyTo(BpmModelMetaInfoRespDTO from, @MappingTarget BpmDefinitionCreateReqDTO to);
+    void copyTo(BpmModelMetaInfoRespDTO from, @MappingTarget BpmProcessDefinitionCreateReqDTO to);
 
     default void copy(Model model, BpmModelCreateReqVO bean) {
         model.setName(bean.getName());
diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmProcessDefinitionConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmProcessDefinitionConvert.java
index 8cb9fb356..fb11704e6 100644
--- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmProcessDefinitionConvert.java
+++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmProcessDefinitionConvert.java
@@ -4,7 +4,7 @@ import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process
 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionRespVO;
 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmFormDO;
-import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmDefinitionCreateReqDTO;
+import cn.iocoder.yudao.adminserver.modules.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;
@@ -55,7 +55,7 @@ public interface BpmProcessDefinitionConvert {
 
     BpmProcessDefinitionPageItemRespVO convert(ProcessDefinition bean);
 
-    BpmProcessDefinitionExtDO convert2(BpmDefinitionCreateReqDTO bean);
+    BpmProcessDefinitionExtDO convert2(BpmProcessDefinitionCreateReqDTO bean);
 
     default List<BpmProcessDefinitionRespVO> convertList3(List<ProcessDefinition> list,
                                                           Map<String, BpmProcessDefinitionExtDO> processDefinitionDOMap) {
diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/task/BpmActivityConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/task/BpmActivityConvert.java
index 8e9b1a9b3..b72e28ac6 100644
--- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/task/BpmActivityConvert.java
+++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/task/BpmActivityConvert.java
@@ -22,16 +22,7 @@ public interface BpmActivityConvert {
 
     BpmActivityConvert INSTANCE = Mappers.getMapper(BpmActivityConvert.class);
 
-    default List<BpmActivityRespVO> convertList(List<HistoricActivityInstance> list, Map<String, BpmTaskExtDO> taskExtMap) {
-        return CollectionUtils.convertList(list, bean -> {
-            BpmActivityRespVO respVO = convert(bean);
-            BpmTaskExtDO taskExt = taskExtMap.get(bean.getTaskId());
-            if (taskExt != null) {
-                respVO.setTask(new BpmActivityRespVO.Task().setId(taskExt.getTaskId()).setResult(taskExt.getResult()));
-            }
-            return respVO;
-        });
-    }
+    List<BpmActivityRespVO> convertList(List<HistoricActivityInstance> list);
 
     @Mappings({
             @Mapping(source = "activityId", target = "key"),
diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/BpmErrorCodeConstants.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/BpmErrorCodeConstants.java
index 6f762f04f..e2a0ff3d7 100644
--- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/BpmErrorCodeConstants.java
+++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/BpmErrorCodeConstants.java
@@ -28,6 +28,7 @@ public interface BpmErrorCodeConstants {
     ErrorCode MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG = new ErrorCode(1009002003, "部署流程失败,原因:流程表单未配置,请点击【修改流程】按钮进行配置");
     ErrorCode MODEL_DEPLOY_FAIL_TASK_ASSIGN_RULE_NOT_CONFIG = new ErrorCode(1009002004, "部署流程失败," +
             "原因:用户任务({})未配置分配规则,请点击【修改流程】按钮进行配置");
+    ErrorCode MODEL_DEPLOY_FAIL_TASK_INFO_EQUALS = new ErrorCode(1009003005, "流程定义部署失败,原因:信息未发生变化");
 
     // ========== 流程定义 1-009-003-000 ==========
     ErrorCode PROCESS_DEFINITION_KEY_NOT_MATCH = new ErrorCode(1009003000, "流程定义的标识期望是({}),当前是({}),请修改 BPMN 流程图");
diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmProcessDefinitionService.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmProcessDefinitionService.java
index 8579a4239..b7ebe80d6 100644
--- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmProcessDefinitionService.java
+++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmProcessDefinitionService.java
@@ -5,7 +5,7 @@ import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process
 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionPageReqVO;
 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionRespVO;
 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
-import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmDefinitionCreateReqDTO;
+import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import org.activiti.bpmn.model.BpmnModel;
@@ -125,13 +125,21 @@ public interface BpmProcessDefinitionService {
      */
     List<ProcessDefinition> getProcessDefinitionListByDeploymentIds(Set<String> deploymentIds);
 
+    /**
+     * 获得需要创建的流程定义,是否和当前激活的流程定义相等
+     *
+     * @param createReqDTO 创建信息
+     * @return 是否相等
+     */
+    boolean isProcessDefinitionEquals(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO);
+
     /**
      * 创建流程定义
      *
      * @param createReqDTO 创建信息
      * @return 流程编号
      */
-    String createProcessDefinition(@Valid BpmDefinitionCreateReqDTO createReqDTO);
+    String createProcessDefinition(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO);
 
     /**
      * 更新流程定义的挂起状态
diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmTaskAssignRuleService.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmTaskAssignRuleService.java
index 9dcfdb5a6..1105ddaa7 100644
--- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmTaskAssignRuleService.java
+++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmTaskAssignRuleService.java
@@ -59,6 +59,15 @@ public interface BpmTaskAssignRuleService {
      */
     void updateTaskAssignRule(@Valid BpmTaskAssignRuleUpdateReqVO reqVO);
 
+    /**
+     * 判断指定流程模型和流程定义的分配规则是否相等
+     *
+     * @param modelId 流程模型编号
+     * @param processDefinitionId 流程定义编号
+     * @return 是否相等
+     */
+    boolean isTaskAssignRulesEquals(String modelId, String processDefinitionId);
+
     /**
      * 将流程流程模型的任务分配规则,复制一份给流程定义
      * 目的:每次流程模型部署时,都会生成一个新的流程定义,此时考虑到每次部署的流程不可变性,所以需要复制一份给该流程定义
diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/dto/BpmDefinitionCreateReqDTO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/dto/BpmProcessDefinitionCreateReqDTO.java
similarity index 97%
rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/dto/BpmDefinitionCreateReqDTO.java
rename to yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/dto/BpmProcessDefinitionCreateReqDTO.java
index c36725061..559832c37 100644
--- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/dto/BpmDefinitionCreateReqDTO.java
+++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/dto/BpmProcessDefinitionCreateReqDTO.java
@@ -18,7 +18,7 @@ import java.util.Objects;
  * 流程定义创建 Request DTO
  */
 @Data
-public class BpmDefinitionCreateReqDTO {
+public class BpmProcessDefinitionCreateReqDTO {
 
     // ========== 模型相关 ==========
 
@@ -51,7 +51,7 @@ public class BpmDefinitionCreateReqDTO {
      * BPMN XML
      */
     @NotEmpty(message = "BPMN XML 不能为空")
-    private String bpmnXml;
+    private byte[] bpmnBytes;
 
     // ========== 表单相关 ==========
 
diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmModelServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmModelServiceImpl.java
index ca32a0e0c..60a313863 100644
--- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmModelServiceImpl.java
+++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmModelServiceImpl.java
@@ -10,7 +10,7 @@ import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmFor
 import cn.iocoder.yudao.adminserver.modules.bpm.enums.definition.BpmModelFormTypeEnum;
 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService;
 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmTaskAssignRuleService;
-import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmDefinitionCreateReqDTO;
+import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmFormService;
 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmModelService;
 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
@@ -21,11 +21,9 @@ 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 lombok.extern.slf4j.Slf4j;
-import org.activiti.bpmn.converter.BpmnXMLConverter;
 import org.activiti.bpmn.model.BpmnModel;
 import org.activiti.engine.RepositoryService;
 import org.activiti.engine.impl.persistence.entity.SuspensionState;
-import org.activiti.engine.impl.util.io.StringStreamSource;
 import org.activiti.engine.repository.Deployment;
 import org.activiti.engine.repository.Model;
 import org.activiti.engine.repository.ModelQuery;
@@ -38,7 +36,6 @@ import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
 import java.util.*;
-import java.util.function.Consumer;
 
 import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.*;
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -175,14 +172,19 @@ public class BpmModelServiceImpl implements BpmModelService {
         }
         // TODO 芋艿:校验流程图的有效性;例如说,是否有开始的元素,是否有结束的元素;
         // 校验表单已配
-        // 校验表单存在
         BpmFormDO form = checkFormConfig(model);
         // 校验任务分配规则已配置
         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);
+            }
+        }
         // 创建流程定义
-        BpmDefinitionCreateReqDTO definitionCreateReqDTO = BpmModelConvert.INSTANCE.convert2(model, form)
-                .setBpmnXml(StrUtil.utf8Str(bpmnBytes));
         String definitionId = processDefinitionService.createProcessDefinition(definitionCreateReqDTO);
 
         // 将老的流程定义进行挂起。也就是说,只有最新部署的流程定义,才可以发起任务。
diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmProcessDefinitionServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmProcessDefinitionServiceImpl.java
index a43e4589b..045fe2a71 100644
--- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmProcessDefinitionServiceImpl.java
+++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmProcessDefinitionServiceImpl.java
@@ -1,24 +1,23 @@
 package cn.iocoder.yudao.adminserver.modules.bpm.service.definition.impl;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionListReqVO;
 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionPageReqVO;
 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionRespVO;
 import cn.iocoder.yudao.adminserver.modules.bpm.convert.definition.BpmProcessDefinitionConvert;
-import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmFormDO;
+import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
 import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.definition.BpmProcessDefinitionExtMapper;
-import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService;
-import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmDefinitionCreateReqDTO;
 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmFormService;
+import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService;
+import cn.iocoder.yudao.adminserver.modules.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.object.PageUtils;
 import lombok.extern.slf4j.Slf4j;
-import org.activiti.bpmn.converter.BpmnXMLConverter;
 import org.activiti.bpmn.model.BpmnModel;
 import org.activiti.engine.RepositoryService;
 import org.activiti.engine.impl.persistence.entity.SuspensionState;
@@ -32,8 +31,7 @@ import org.springframework.validation.annotation.Validated;
 import javax.annotation.Resource;
 import java.util.*;
 
-import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.PROCESS_DEFINITION_KEY_NOT_MATCH;
-import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.PROCESS_DEFINITION_NAME_NOT_MATCH;
+import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.*;
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
 import static java.util.Collections.emptyList;
@@ -139,6 +137,16 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
         return repositoryService.createProcessDefinitionQuery().processDefinitionId(id).singleResult();
     }
 
+    /**
+     * 获得流程定义标识对应的激活的流程定义
+     *
+     * @param processDefinitionKey 流程定义的标识
+     * @return 流程定义
+     */
+    private ProcessDefinition getActiveProcessDefinition(String processDefinitionKey) {
+        return repositoryService.createProcessDefinitionQuery().processDefinitionKey(processDefinitionKey).active().singleResult();
+    }
+
     @Override
     public BpmProcessDefinitionExtDO getProcessDefinitionExt(String id) {
         return processDefinitionMapper.selectByProcessDefinitionId(id);
@@ -166,6 +174,9 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
 
     @Override
     public ProcessDefinition getProcessDefinitionByDeploymentId(String deploymentId) {
+        if (StrUtil.isEmpty(deploymentId)) {
+            return null;
+        }
         return repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
     }
 
@@ -177,13 +188,45 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
         return repositoryService.createProcessDefinitionQuery().deploymentIds(deploymentIds).list();
     }
 
+    @Override
+    public boolean isProcessDefinitionEquals(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 = ActivitiUtils.buildBpmnModel(createReqDTO.getBpmnBytes());
+        BpmnModel oldModel = getBpmnModel(oldProcessDefinition.getId());
+        if (!ActivitiUtils.equals(oldModel, newModel)) {
+            return false;
+        }
+        // 最终发现都一致,则返回 true
+        return true;
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class) // 因为进行多个 activiti 操作,所以开启事务
-    public String createProcessDefinition(BpmDefinitionCreateReqDTO createReqDTO) {
+    public String createProcessDefinition(BpmProcessDefinitionCreateReqDTO createReqDTO) {
         // 创建 Deployment 部署
         Deployment deploy = repositoryService.createDeployment()
                 .key(createReqDTO.getKey()).name(createReqDTO.getName()).category(createReqDTO.getCategory())
-                .addString(createReqDTO.getKey() + BPMN_FILE_SUFFIX, createReqDTO.getBpmnXml())
+                .addBytes(createReqDTO.getKey() + BPMN_FILE_SUFFIX, createReqDTO.getBpmnBytes())
                 .deploy();
 
         // 设置 ProcessDefinition 的 category 分类
diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmTaskAssignRuleServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmTaskAssignRuleServiceImpl.java
index cf01c701e..16ae1859a 100644
--- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmTaskAssignRuleServiceImpl.java
+++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmTaskAssignRuleServiceImpl.java
@@ -1,6 +1,9 @@
 package cn.iocoder.yudao.adminserver.modules.bpm.service.definition.impl;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.collection.ListUtil;
+import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.rule.BpmTaskAssignRuleCreateReqVO;
 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.rule.BpmTaskAssignRuleRespVO;
@@ -30,10 +33,7 @@ import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
+import java.util.*;
 
 import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.*;
 import static cn.iocoder.yudao.adminserver.modules.system.enums.SysDictTypeConstants.BPM_TASK_ASSIGN_RULE_TYPE;
@@ -142,6 +142,31 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
         taskRuleMapper.updateById(BpmTaskAssignRuleConvert.INSTANCE.convert(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) {
         List<BpmTaskAssignRuleRespVO> rules = getTaskAssignRuleList(fromModelId, null);
diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmActivityServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmActivityServiceImpl.java
index 8d4187b3a..7c4253ec6 100644
--- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmActivityServiceImpl.java
+++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmActivityServiceImpl.java
@@ -60,10 +60,7 @@ public class BpmActivityServiceImpl implements BpmActivityService {
     public List<BpmActivityRespVO> getActivityListByProcessInstanceId(String processInstanceId) {
         List<HistoricActivityInstance> activityList = historyService.createHistoricActivityInstanceQuery()
                 .processInstanceId(processInstanceId).list();
-        // 拼接数据
-        List<BpmTaskExtDO> taskExts = taskService.getTaskExtListByProcessInstanceId(processInstanceId);
-        Map<String, BpmTaskExtDO> taskExtMap = convertMap(taskExts, BpmTaskExtDO::getTaskId);
-        return BpmActivityConvert.INSTANCE.convertList(activityList, taskExtMap);
+        return BpmActivityConvert.INSTANCE.convertList(activityList);
     }
 
     @Override
diff --git a/yudao-framework/yudao-spring-boot-starter-activiti/src/main/java/cn/iocoder/yudao/framework/activiti/core/util/ActivitiUtils.java b/yudao-framework/yudao-spring-boot-starter-activiti/src/main/java/cn/iocoder/yudao/framework/activiti/core/util/ActivitiUtils.java
index eb051c0a0..89034fe85 100644
--- a/yudao-framework/yudao-spring-boot-starter-activiti/src/main/java/cn/iocoder/yudao/framework/activiti/core/util/ActivitiUtils.java
+++ b/yudao-framework/yudao-spring-boot-starter-activiti/src/main/java/cn/iocoder/yudao/framework/activiti/core/util/ActivitiUtils.java
@@ -1,5 +1,7 @@
 package cn.iocoder.yudao.framework.activiti.core.util;
 
+import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.ReflectUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
@@ -13,6 +15,7 @@ import org.activiti.engine.impl.util.io.BytesStreamSource;
 
 import javax.xml.bind.Element;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
 import java.util.function.Consumer;
@@ -88,8 +91,20 @@ public class ActivitiUtils {
         if (model == null) {
             return null;
         }
+        return StrUtil.utf8Str(getBpmnBytes(model));
+    }
+
+    public static byte[] getBpmnBytes(BpmnModel model) {
+        if (model == null) {
+            return new byte[0];
+        }
         BpmnXMLConverter converter = new BpmnXMLConverter();
-        return StrUtil.utf8Str(converter.convertToXML(model));
+        return converter.convertToXML(model);
+    }
+
+    public static boolean equals(BpmnModel oldModel, BpmnModel newModel) {
+        // 由于 BpmnModel 未提供 equals 方法,所以只能转成字节数组,进行比较
+        return Arrays.equals(getBpmnBytes(oldModel), getBpmnBytes(newModel));
     }
 
 }