diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java index eadfc24394..4825e5f5a9 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.validation.InEnum; import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum; import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelTypeEnum; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -65,4 +66,30 @@ public class BpmModelMetaInfoVO { @Schema(description = "允许撤销审批中的申请", example = "true") private Boolean allowCancelRunningProcess; + @Schema(description = "流程 Id 规则", example = "{}") + private ProcessIdRule processIdRule; + + @Schema(description = "流程 Id 规则") + @Data + @Valid + public static class ProcessIdRule { + + @Schema(description = "是否启用", example = "false") + @NotNull(message = "是否启用不能为空") + private Boolean enable; + + @Schema(description = "前缀", example = "xx") + private String prefix; + + @Schema(description = "前缀", example = "20250120") + private String infix; + + @Schema(description = "前缀", example = "xx") + private String postfix; + + @Schema(description = "序列长度", example = "5") + @NotNull(message = "序列长度不能为空") + private Integer length; + } + } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java index 132d79b143..5369127c16 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.bpm.dal.dataobject.definition; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler; import cn.iocoder.yudao.framework.mybatis.core.type.StringListTypeHandler; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.BpmModelMetaInfoVO; import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum; import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelTypeEnum; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; @@ -155,4 +156,10 @@ public class BpmProcessDefinitionInfoDO extends BaseDO { */ private Boolean allowCancelRunningProcess; + /** + * 流程 Id 规则 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private BpmModelMetaInfoVO.ProcessIdRule processIdRule; + } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/redis/BpmProcessIdRedisDAO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/redis/BpmProcessIdRedisDAO.java new file mode 100644 index 0000000000..48666f4373 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/redis/BpmProcessIdRedisDAO.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.bpm.dal.redis; + +import cn.hutool.core.date.DateUtil; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.BpmModelMetaInfoVO; +import jakarta.annotation.Resource; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Repository; + +import java.time.Duration; +import java.time.LocalDateTime; + +/** + * BPM 流程 Id 编码的 Redis DAO + * + * @author Lesan + */ +@Repository +public class BpmProcessIdRedisDAO { + + public static final String BPM_PROCESS_ID_PREFIX = "BPMPID"; + + @Resource + private StringRedisTemplate stringRedisTemplate; + + /** + * 生成序号,使用定义的 processIdRule 规则生成 + * + * @param processIdRule 规则 + * @return 序号 + */ + public String generate(BpmModelMetaInfoVO.ProcessIdRule processIdRule) { + String infix = ""; + switch (processIdRule.getInfix()) { + case "DAY": + infix = DateUtil.format(LocalDateTime.now(), "yyyyMMDD"); + break; + case "HOUR": + infix = DateUtil.format(LocalDateTime.now(), "yyyyMMDDHH"); + break; + case "MINUTE": + infix = DateUtil.format(LocalDateTime.now(), "yyyyMMDDHHmm"); + break; + case "SECOND": + infix = DateUtil.format(LocalDateTime.now(), "yyyyMMDDHHmmss"); + break; + } + String noPrefix = processIdRule.getPrefix() + infix + processIdRule.getPostfix(); + String key = BPM_PROCESS_ID_PREFIX + noPrefix; + Long no = stringRedisTemplate.opsForValue().increment(key); + stringRedisTemplate.expire(key, Duration.ofDays(1L)); + return noPrefix + String.format("%0" + processIdRule.getLength() + "d", no); + } + +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index 6d9168e145..a0a581eecd 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -12,12 +12,14 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.framework.common.util.object.PageUtils; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.BpmModelMetaInfoVO; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmApprovalDetailRespVO.ActivityNodeTask; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO; import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO; +import cn.iocoder.yudao.module.bpm.dal.redis.BpmProcessIdRedisDAO; import cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants; import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelTypeEnum; import cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType; @@ -50,6 +52,7 @@ import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.history.HistoricProcessInstanceQuery; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.engine.runtime.ProcessInstanceBuilder; import org.flowable.task.api.history.HistoricTaskInstance; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; @@ -109,6 +112,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @Resource private BpmTaskCandidateInvoker taskCandidateInvoker; + @Resource + private BpmProcessIdRedisDAO processIdRedisDAO; + // ========== Query 查询相关方法 ========== @Override @@ -599,12 +605,19 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService if (CollUtil.isNotEmpty(startUserSelectAssignees)) { variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES, startUserSelectAssignees); } - ProcessInstance instance = runtimeService.createProcessInstanceBuilder() + + // 3. 流程 Id + ProcessInstanceBuilder processInstanceBuilder = runtimeService.createProcessInstanceBuilder() .processDefinitionId(definition.getId()) .businessKey(businessKey) .name(definition.getName().trim()) - .variables(variables) - .start(); + .variables(variables); + BpmModelMetaInfoVO.ProcessIdRule processIdRule = processDefinitionInfo.getProcessIdRule(); + if (processIdRule != null && processIdRule.getEnable()) { + String id = processIdRedisDAO.generate(processIdRule); + processInstanceBuilder.predefineProcessInstanceId(id); + } + ProcessInstance instance = processInstanceBuilder.start(); return instance.getId(); }