Merge branch 'feature/REQ-4196' into feature/REQ-3647

# Conflicts:
#	workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/listener/activity/RocketMqBpmActivityEvent_100_Listener.java
#	workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/listener/notice/RocketMqMessagePushEventListener.java
#	workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/listener/process/RocketMqBpmnProcessEventListener.java
#	workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/listener/task/RocketMqBpmnTaskEvent_102_Listener.java
This commit is contained in:
wangli 2025-06-06 14:55:21 +08:00
commit 7c8d00d934
61 changed files with 1488 additions and 945 deletions

View File

@ -26,10 +26,11 @@ public enum BpmnInstanceRespCode implements IModuleRespCode {
PROCESS_INSTANCE_CANT_START("011", "流程实例不能启动"),
TASK_CANT_COMMENT_INSTANCE_NOT_EXISTS("012", "流程实例【{}】不存在, 不能评论"),
RUNNING_INSTANCE_ONLY_FORECAST("013", "仅运行中的实例可以推测"),
ENGINE_EXEC_EXCEPTION("014", "引擎内部异常"),
ENGINE_EXEC_EXCEPTION("014", "引擎内部异常:【{}】"),
PROCESS_TASK_NOT_EXISTS("015", "流程任务不存在或已处理"),
PROCESS_DOC_READ_PARAM_ERROR("016", "查询审批人阅读状态参数丢失自然人 ID 数据"),
PROCESS_DOC_ID_NOT_IN_MODEL("017", "当前流程中,不存在指定文档"),
PROCESS_SIGN_DATA_NOT_EXISTS("018", "签署业务审批未获取到初始模板复制数据"),
;
private final String code;
private final String message;

View File

@ -22,6 +22,7 @@ public enum FormInstanceRespCode implements IModuleRespCode {
FORM_DATA_PARSE_ERROR_BY_UPLOAD("007", "表单上传组件的数据解析异常"),
FORM_DATA_PARSE_ERROR_BY_IMAGE("008", "表单图片组件的数据解析异常"),
FORM_DATA_PARSE_ERROR_BY_CUSTOM_COMPONENT("009", "表单自定义组件的数据解析异常"),
FORM_DATA_PARSE_ERROR_BY_AMOUNT("010", "表单金额组件的数据解析异常"),
;
private final String code;

View File

@ -9,6 +9,7 @@ public interface BpmnConstants {
/**
* 引擎自己的隐藏指令
*/
String ADSCRIPTION_TENANT_ID = "adscriptionTenantId";
String FLOWABLE_SKIP_EXPRESSION_ENABLE = "[_FLOWABLE_SKIP_EXPRESSION_ENABLED_]";
String MQ_UNIQUE_ID = "[_MQ_UNIQUE_ID_]";
String PROCESS_OWNERSHIP_APPLICATION = "[_PROCESS_OWNERSHIP_APPLICATION_]";

View File

@ -28,20 +28,37 @@ public interface VariableConstants {
//=============== 打印时的变量集合中 key 的命名 =================
String VAR_PREFIX = "业务变量";
String PRINT_VAR_PROCESS_DEFINITION_KEY = "processDefinitionKey";
String PRINT_VAR_PROCESS_DEFINITION_KEY_DESC = "业务名称";
String PRINT_VAR_PROCESS_INSTANCE_ID = "processInstanceId";
String PRINT_VAR_PROCESS_INSTANCE_ID_DESC = "审批编号";
String PRINT_VAR_PROCESS_START_TIME = "startTime";
String PRINT_VAR_PROCESS_START_TIME_DESC = "发起时间";
String PRINT_VAR_PROCESS_END_TIME = "endTime";
String PRINT_VAR_PROCESS_END_TIME_DESC = "审批结束时间";
String PRINT_VAR_PROCESS_INITIATOR = "initiator";
String PRINT_VAR_PROCESS_INITIATOR_DESC = "发起者";
String PRINT_VAR_PROCESS_INITIATOR_NAME = "initiatorName";
String PRINT_VAR_PROCESS_INITIATOR_NAME_DESC = "发起人姓名";
String PRINT_VAR_PROCESS_INITIATOR_POSITION = "initiatorPosition";
String PRINT_VAR_PROCESS_INITIATOR_POSITION_DESC = "发起人岗位";
String PRINT_VAR_PROCESS_INITIATOR_PHONE = "initiatorPhone";
String PRINT_VAR_PROCESS_INITIATOR_PHONE_DESC = "发起人联系方式";
String PRINT_VAR_PROCESS_LOGS = "processLogs";
String PRINT_VAR_PROCESS_LOGS_DESC = "审批日志";
String PRINT_VAR_PROCESS_LOG_ACTIVITY_NAME = "activityName";
String PRINT_VAR_PROCESS_LOG_ACTIVITY_NAME_DESC = "节点名称";
String PRINT_VAR_PROCESS_LOG_APPROVER_NAME = "approverName";
String PRINT_VAR_PROCESS_LOG_APPROVER_NAME_DESC = "审批人";
String PRINT_VAR_PROCESS_LOG_UNIT = "unit";
String PRINT_VAR_PROCESS_LOG_UNIT_DESC = "单位";
String PRINT_VAR_PROCESS_LOG_POSITION = "position";
String PRINT_VAR_PROCESS_LOG_POSITION_DESC = "岗位";
String PRINT_VAR_PROCESS_LOG_ADVICE = "advice";
String PRINT_VAR_PROCESS_LOG_ADVICE_DESC = "审批意见";
String PRINT_VAR_PROCESS_LOG_OPERATION_TIME = "operationTime";
String PRINT_VAR_PROCESS_LOG_OPERATION_TIME_DESC = "审批时间";
String PRINT_VAR_PROCESS_LOG_SIGNATURE = "signature";
String PRINT_VAR_PROCESS_LOG_SIGNATURE_DESC = "电子签名";
}

View File

@ -16,6 +16,8 @@ public enum ApproverSpecifyEnum {
fixedPerson("fixedPerson", "固定人员"),
preNodeSpecified("preNodeSpecified", "上级节点指定"),
initiatorSpecified("initiatorSpecified", "发起时指定"),
// 该枚举目前主要为了区别签署业务与审批业务的不同配法选择该项时意味着该节点是由二方后端自由消费 BpmnSignApproverLimit 配置
signerRelated("signerRelated", "签署人相关组织"),
;
private String type;
private String desc;

View File

@ -1,6 +1,13 @@
package cn.axzo.workflow.common.enums;
import com.google.common.collect.Lists;
import java.util.List;
import static cn.axzo.workflow.common.enums.BusinessTypeEnum.APPROVAL;
import static cn.axzo.workflow.common.enums.BusinessTypeEnum.SIGN;
/**
* Flowable Event Enum For RocketMQ
*
@ -11,39 +18,47 @@ public enum BpmnButtonEnum {
/**
* 同意按钮
*/
BPMN_APPROVE(1, "BPMN_APPROVE", "同意"),
BPMN_APPROVE(1, "BPMN_APPROVE", "同意", Lists.newArrayList(APPROVAL, SIGN)),
/**
* 驳回按钮
*/
BPMN_REJECT(2, "BPMN_REJECT", "驳回"),
BPMN_REJECT(2, "BPMN_REJECT", "驳回", Lists.newArrayList(APPROVAL, SIGN)),
/**
* 确认签署
*/
BPMN_CONFIRM_SIGN(3, "BPMN_CONFIRM_SIGN", "确认签署", Lists.newArrayList(SIGN)),
/**
* 查看文档
*/
BPMN_VIEW_DOC(4, "BPMN_VIEW_DOC", "查看文档", Lists.newArrayList(SIGN)),
/**
* 撤回按钮
*/
BPMN_REVOCATION(3, "BPMN_REVOCATION", "撤回"),
BPMN_REVOCATION(5, "BPMN_REVOCATION", "撤回", Lists.newArrayList(APPROVAL, SIGN)),
/**
* 转交按钮
*/
BPMN_TRANSFER(4, "BPMN_TRANSFER", "转交"),
BPMN_TRANSFER(6, "BPMN_TRANSFER", "转交", Lists.newArrayList(APPROVAL, SIGN)),
/**
* 加签按钮
*/
BPMN_COUNTERSIGN(5, "BPMN_COUNTERSIGN", "加签"),
BPMN_COUNTERSIGN(7, "BPMN_COUNTERSIGN", "加签", Lists.newArrayList(APPROVAL, SIGN)),
/**
* 评论按钮
*/
BPMN_COMMENT(6, "BPMN_COMMENT", "评论"),
BPMN_COMMENT(8, "BPMN_COMMENT", "评论", Lists.newArrayList(APPROVAL, SIGN)),
/**
* 回退按钮
*/
BPMN_ROLLBACK(7, "BPMN_ROLLBACK", "回退"),
BPMN_ROLLBACK(9, "BPMN_ROLLBACK", "回退", Lists.newArrayList(APPROVAL, SIGN)),
/**
* 抄送按钮
*/
BPMN_COPY(8, "BPMN_COPY", "抄送"),
BPMN_COPY(10, "BPMN_COPY", "抄送", Lists.newArrayList(APPROVAL, SIGN)),
/**
* 管理员转交按钮
*/
BPMN_ADMIN_TRANSFER(9, "BPMN_ADMIN_TRANSFER", "管理员转交");
BPMN_ADMIN_TRANSFER(11, "BPMN_ADMIN_TRANSFER", "管理员转交", Lists.newArrayList());
public int getOrder() {
@ -58,15 +73,21 @@ public enum BpmnButtonEnum {
return btnName;
}
public List<BusinessTypeEnum> getSupportBizType() {
return supportBizType;
}
private final int order;
private final String btnKey;
private final String btnName;
private final List<BusinessTypeEnum> supportBizType;
BpmnButtonEnum(int order, String btnKey, String btnName) {
BpmnButtonEnum(int order, String btnKey, String btnName, List<BusinessTypeEnum> supportBizType) {
this.order = order;
this.btnKey = btnKey;
this.btnName = btnName;
this.supportBizType = supportBizType;
}
}

View File

@ -22,6 +22,7 @@ public enum BpmnFlowNodeType {
NODE_ROBOT("NODE_ROBOT", "机器人节点"),
NODE_COMMENT("NODE_COMMENT", "评论节点"),
NODE_ABORT("NODE_ABORT", "中止节点"),
NODE_ALTER("NODE_ALTER", "告警节点"),
NODE_CANCEL("NODE_CANCEL", "撤回节点"),
NODE_EMPTY("NODE_EMPTY", "空节点"),
;

View File

@ -19,6 +19,11 @@ public class WorkflowEngineException extends ServiceException {
this.code = code.getRespCode();
}
public WorkflowEngineException(IRespCode code, Throwable cause, String... params) {
super(doFormat(code.getCode(), code.getMessage(), params), cause);
this.code = code.getRespCode();
}
@Override
public String getCode() {
return this.code;

View File

@ -0,0 +1,33 @@
package cn.axzo.workflow.common.model.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 金额字段值类型
*
* @author wangli
* @since 2025-05-16 17:21
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class AmountFieldDTO implements Serializable {
private static final long serialVersionUID = -3519991080707599177L;
/**
* 小写
*/
private BigDecimal standardNumerals;
/**
* 大写
*/
private String uppercaseNumerals;
}

View File

@ -0,0 +1,69 @@
package cn.axzo.workflow.common.model.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 通讯录组件返回的人员信息模型
*
* @author wangli
* @since 2025-05-15 14:04
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class ContactsPersonDTO {
/**
* xx:xx:xx
*/
private String nodeId;
/**
* 身份 ID
*/
private Long identityId;
/**
* 身份类型
*/
private Integer identityType;
/**
* 真实姓名
*/
private String realName;
/**
* 自然人 ID
*/
private Long personId;
/**
* 人员所在的节点 ID
*/
private Long orgNodeId;
/**
* 人员所在的单位 ID
*/
private Long ouId;
/**
* 人员所在的单位名称
*/
private String ouName;
/**
* 人员所在的工作台 ID
*/
private Long workspaceId;
/**
* 人员所在的工作台类型
*/
private Integer workspaceType;
}

View File

@ -26,6 +26,11 @@ public class VariableObjectDTO {
*/
private String key;
/**
* 变量中文名
*/
private String desc;
/**
* 变量值
*/

View File

@ -1,9 +1,12 @@
package cn.axzo.workflow.common.model.request.bpmn;
import cn.axzo.workflow.common.enums.BusinessTypeEnum;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* 按钮元数据
@ -50,4 +53,9 @@ public class BpmnButtonMetaInfo implements Serializable {
*/
private String type;
/**
* 按钮支持的业务类型
*/
private List<BusinessTypeEnum> supportBizType = new ArrayList<>();
}

View File

@ -45,10 +45,10 @@ public class BpmnJsonNodeProperty {
//************* 审批人指定Start **************//
/**
* 审批人指定: position(指定岗位), role(指定角色), identity(指定身份), initiatorLeader(发起人主管), initiatorLeaderRecursion(发起人多级主管),
* fixedPerson(固定人员) initiatorSpecified(发起人自选)
* fixedPerson(固定人员) initiatorSpecified(发起人自选) signerRelated(签署人相关组织)
*/
@ApiModelProperty(value = "任务节点: 审批人指定", notes = "position: 指定岗位, role: 指定角色, identity: 指定身份, initiatorLeader: " +
"发起人主管, initiatorLeaderRecursion: 发起人多级主管, fixedPerson: 固定人员, initiatorSpecified: 发起人自选")
"发起人主管, initiatorLeaderRecursion: 发起人多级主管, fixedPerson: 固定人员, initiatorSpecified: 发起人自选, signerRelated: 签署人相关组织")
@NotBlank(message = "审批人指定不能为空")
private ApproverSpecifyEnum approverSpecify;

View File

@ -36,6 +36,7 @@ public class BpmnSignApproverLimit {
/**
* 签署确认节点下人的角色限定规则
* <p>
* INITIATOR_SPECIFIED("INITIATOR_SPECIFIED", "发起人自选"),
* LEADER("LEADER", "负责人"),
*/
@ApiModelProperty(value = "签署确认节点下人的角色限定规则")

View File

@ -1,5 +1,6 @@
package cn.axzo.workflow.common.model.request.bpmn.process;
import cn.axzo.workflow.common.constant.BpmnConstants;
import cn.axzo.workflow.common.model.dto.CooperationOrgDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import io.swagger.annotations.ApiModel;
@ -64,10 +65,10 @@ public class BpmnProcessInstanceCreateDTO extends BpmnProcessInstanceCreateWithF
private Map<String, Object> variables = new HashMap<>();
/**
* 签署业务定义变量的入参
* 业务管理中定义变量的入参
*/
@Builder.Default
private Map<String, Object> signVariables = new HashMap<>();
private Map<String, Object> bizCustomVariables = new HashMap<>();
/**
* 待办相关的变量,如路由参数, 模板参数等等
@ -119,7 +120,7 @@ public class BpmnProcessInstanceCreateDTO extends BpmnProcessInstanceCreateWithF
private List<Long> docIds;
/**
* 签署业务最终签署人列表
* 仅针对签署业务设置审批完成后的最终签署人列表该属性仅为透传业务消费时请从 MQ 广播事件中的 variables 中通过 key= {@link BpmnConstants#SIGNATORIES } 获取
*/
@ApiModelProperty(value = "签署业务,最终签署人")
private List<BpmnTaskDelegateAssigner> signatories;

View File

@ -106,7 +106,7 @@ public class BpmnTaskDelegateAssigner implements Serializable {
private String avatar;
/**
* 人员对应的 nodeId 这里的数据是根据创建流程传入的组织关系自动填充的业务无需传参
* 人员对应的 nodeId如果在审批模板中对应节点未使用流程自主查询审批人的功能(如指定岗位/身份/角色之类),则需要业务方主动传入
*/
private String nodeId;

View File

@ -46,13 +46,13 @@ public class FormPermissionMetaInfo implements Serializable {
* 只读
*/
@Builder.Default
private Boolean readonly = false;
private Boolean readonly = true;
/**
* 隐藏
*/
@Builder.Default
private Boolean hidden = true;
private Boolean hidden = false;
/**
* 前端回显字段后端不做任何消费逻辑
*/
@ -61,10 +61,10 @@ public class FormPermissionMetaInfo implements Serializable {
// 将对象的属性转换为对应的整数表示
public int toBinary() {
int binaryValue = 0;
binaryValue |= (required? 1 : 0) << 3;
binaryValue |= (editable? 1 : 0) << 2;
binaryValue |= (readonly? 1 : 0) << 1;
binaryValue |= (hidden? 1 : 0);
binaryValue |= (required ? 1 : 0) << 3;
binaryValue |= (editable ? 1 : 0) << 2;
binaryValue |= (readonly ? 1 : 0) << 1;
binaryValue |= (hidden ? 1 : 0);
return binaryValue;
}
@ -76,8 +76,9 @@ public class FormPermissionMetaInfo implements Serializable {
boolean hidden = (binaryValue & 1) == 1;
return new FormPermissionMetaInfo(fieldId, fieldName, required, editable, readonly, hidden, null);
}
public FormPermissionMetaInfo toReadonly() {
if(required || editable || readonly) {
if (required || editable || readonly) {
setRequired(false);
setEditable(false);
setReadonly(true);

View File

@ -39,6 +39,8 @@ public class FormFieldDTO {
* { label: "任务单", value: "taskOrder" },
* { label: "整改单", value: "rectifyOrder" },
* { label: "变洽签单", value: "changeSignatureOrder" },
* { label: "通讯录", value: "contacts" },
* { label: "金额", value: "amount" },
*/
@ApiModelProperty(value = "前端的组件类型")
private String type;

View File

@ -31,6 +31,11 @@ public class MessagePushDTO implements Serializable {
*/
private String processInstanceId;
/**
* 流程归属的租户 ID
*/
private String adscriptionTenantId;
/**
* 业务 ID
*/

View File

@ -68,7 +68,7 @@ public class FormHelper {
}
oldParams.put(FIELD_PROPERTY_DEFAULT_VALUE, defaultValue);
if (injectDefaultValue(formField) && StringUtils.hasText(defaultValue)) {
formField.setValue(Lists.newArrayList(defaultValue));
formField.setValue(defaultValue);
}
}
formField.setParams(oldParams);

View File

@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.JdbcType;
@ -26,6 +27,10 @@ import java.util.List;
public class ButtonConfTypeHandler extends AbstractJsonTypeHandler<BpmnButtonConf> {
private static ObjectMapper objectMapper = new ObjectMapper();
static {
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
public ButtonConfTypeHandler(Class<?> type) {
if (log.isTraceEnabled()) {
log.trace("JacksonTypeHandler(" + type + ")");

View File

@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.JdbcType;
@ -26,6 +27,10 @@ import java.util.List;
public class ListAssigneeTypeHandler extends AbstractJsonTypeHandler<List<BpmnTaskDelegateAssigner>> {
private static ObjectMapper objectMapper = new ObjectMapper();
static {
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
public ListAssigneeTypeHandler(Class<?> type) {
if (log.isTraceEnabled()) {
log.trace("JacksonTypeHandler(" + type + ")");

View File

@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.JdbcType;
@ -26,6 +27,10 @@ import java.util.List;
public class ListFormFieldPermissionTypeHandler extends AbstractJsonTypeHandler<List<FormPermissionMetaInfo>> {
private static ObjectMapper objectMapper = new ObjectMapper();
static {
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
public ListFormFieldPermissionTypeHandler(Class<?> type) {
if (log.isTraceEnabled()) {
log.trace("JacksonTypeHandler(" + type + ")");

View File

@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.JdbcType;
@ -26,6 +27,10 @@ import java.util.List;
public class ListSignFileDTOHandler extends AbstractJsonTypeHandler<List<SignFileDTO>> {
private static ObjectMapper objectMapper = new ObjectMapper();
static {
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
public ListSignFileDTOHandler(Class<?> type) {
if (log.isTraceEnabled()) {
log.trace("JacksonTypeHandler(" + type + ")");

View File

@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.JdbcType;
@ -26,6 +27,10 @@ import java.util.List;
public class ListSimpleDocDTOHandler extends AbstractJsonTypeHandler<List<SimpleDocDTO>> {
private static ObjectMapper objectMapper = new ObjectMapper();
static {
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
public ListSimpleDocDTOHandler(Class<?> type) {
if (log.isTraceEnabled()) {
log.trace("JacksonTypeHandler(" + type + ")");

View File

@ -197,7 +197,8 @@ public class UserTaskJsonConverter extends AbstractBpmnJsonConverter<UserTask> {
// 签署确认节点特有的配置
BpmnSignApproverLimit signApproverLimit = property.getSignApproverLimit();
if (Objects.equals(NODE_SIGN, node.getType()) && Objects.nonNull(signApproverLimit)) {
if (Objects.equals(NODE_SIGN, node.getType()) && Objects.nonNull(signApproverLimit)
&& Objects.nonNull(signApproverLimit.getOrgLimit()) && Objects.nonNull(signApproverLimit.getRoleLimit())) {
ExtensionElement signApproveElement = new ExtensionElement();
signApproveElement.setName(CONFIG_SIGN_APPROVER_LIMIT);
@ -227,11 +228,13 @@ public class UserTaskJsonConverter extends AbstractBpmnJsonConverter<UserTask> {
userTask.addExtensionElement(signApproveElement);
property.setApproverSpecify(ApproverSpecifyEnum.initiatorSpecified);
if (Objects.isNull(property.getApproverSpecify())) {
property.setApproverSpecify(ApproverSpecifyEnum.signerRelated);
}
}
// TODO 签署确认节点的一些额外配置需要在此处处理
if (Objects.nonNull(property.getApproverScope()) && !Objects.equals(NODE_SIGN, node.getType())) {
if (Objects.nonNull(property.getApproverScope())) {
// 审批人所在范围
ExtensionElement approverScopeElement = new ExtensionElement();
approverScopeElement.setName(CONFIG_APPROVER_SCOPE);

View File

@ -27,7 +27,7 @@ public abstract class AbstractCommand<T> implements Command<T> {
throw e;
} catch (Exception e) {
log.warn(e.getMessage(), e);
throw new WorkflowEngineException(ENGINE_EXEC_EXCEPTION);
throw new WorkflowEngineException(ENGINE_EXEC_EXCEPTION, e, e.getMessage());
}
}

View File

@ -1,6 +1,7 @@
package cn.axzo.workflow.core.engine.cmd;
import cn.axzo.workflow.common.exception.WorkflowEngineException;
import cn.axzo.workflow.common.model.dto.AmountFieldDTO;
import cn.axzo.workflow.common.model.dto.UploadFieldDTO;
import cn.axzo.workflow.core.engine.cmd.helper.FormFieldClone;
import cn.axzo.workflow.form.engine.model.CustomSimpleFormModel;
@ -381,6 +382,19 @@ public class CustomGetFormInstanceModelCmd extends GetFormInstanceModelCmd {
throw new WorkflowEngineException(FORM_DATA_PARSE_ERROR_BY_CUSTOM_COMPONENT);
}
}
} else if (FormFieldTypes.AMOUNT.equals(field.getType())) {
if (variables.containsKey(field.getId())) {
String amountValue = (String) variables.get(field.getId());
if (StringUtils.hasText(amountValue)) {
try {
AmountFieldDTO amount = formEngineConfiguration.getObjectMapper().readValue(amountValue, new TypeReference<AmountFieldDTO>() {
});
field.setValue(amount);
} catch (JsonProcessingException e) {
throw new FlowableException("Error parsing amount json value: " + amountValue, e);
}
}
}
} else {
Object variableValue = variables.get(field.getId());
if (variableValue != null) {

View File

@ -2,6 +2,7 @@ package cn.axzo.workflow.core.engine.cmd;
import cn.axzo.workflow.common.enums.VarTypeEnum;
import cn.axzo.workflow.common.exception.WorkflowEngineException;
import cn.axzo.workflow.common.model.dto.ContactsPersonDTO;
import cn.axzo.workflow.common.model.dto.SignatureDTO;
import cn.axzo.workflow.common.model.dto.VariableObjectDTO;
import cn.axzo.workflow.common.model.request.category.CategoryGroupVarSearchDto;
@ -25,18 +26,21 @@ import org.flowable.form.api.FormRepositoryService;
import org.flowable.form.api.FormService;
import org.flowable.form.model.FormContainer;
import org.flowable.form.model.FormField;
import org.flowable.form.model.FormFieldTypes;
import org.flowable.form.model.SimpleFormModel;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import java.io.Serializable;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import static cn.axzo.workflow.common.code.FormModelRespCode.FORM_MODEL_NOT_EXISTS;
import static cn.axzo.workflow.common.constant.BpmnConstants.BPM_MODEL_CATEGORY;
@ -44,10 +48,15 @@ import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_INITIATOR;
import static cn.axzo.workflow.common.constant.BpmnConstants.SIGNATURE_COLLECTION;
import static cn.axzo.workflow.common.constant.BpmnConstants.SIGN_VARIABLE;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_DEFINITION_KEY;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_DEFINITION_KEY_DESC;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_END_TIME;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_END_TIME_DESC;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_INITIATOR;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_INITIATOR_DESC;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_INSTANCE_ID;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_INSTANCE_ID_DESC;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_START_TIME;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_START_TIME_DESC;
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_STARTER;
/**
@ -66,7 +75,7 @@ public class CustomGetProcessInstanceVariablesToObjectCmd extends AbstractComman
private final String processInstanceId;
private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
private static final List<String> SUPPORTED_FORM_TYPES = Lists.newArrayList("input", "textarea", "image");
private static final List<String> SUPPORTED_FORM_TYPES = Lists.newArrayList("input", "date", "textarea", "image", "contacts", "amount");
public CustomGetProcessInstanceVariablesToObjectCmd(String processInstanceId) {
this.processInstanceId = processInstanceId;
@ -87,6 +96,7 @@ public class CustomGetProcessInstanceVariablesToObjectCmd extends AbstractComman
}
returnVariables.add(VariableObjectDTO.builder()
.key(PRINT_VAR_PROCESS_INSTANCE_ID)
.desc(PRINT_VAR_PROCESS_INSTANCE_ID_DESC)
.value(processInstanceId)
.build());
@ -98,10 +108,12 @@ public class CustomGetProcessInstanceVariablesToObjectCmd extends AbstractComman
// 添加流程开始时间
returnVariables.add(VariableObjectDTO.builder()
.key(PRINT_VAR_PROCESS_START_TIME)
.desc(PRINT_VAR_PROCESS_START_TIME_DESC)
.value(sdf.format(historicProcessInstance.getStartTime()))
.build());
returnVariables.add(VariableObjectDTO.builder()
.key(PRINT_VAR_PROCESS_END_TIME)
.desc(PRINT_VAR_PROCESS_END_TIME_DESC)
.value(Objects.nonNull(historicProcessInstance.getEndTime()) ? sdf.format(historicProcessInstance.getEndTime()) : null)
.build());
@ -112,6 +124,7 @@ public class CustomGetProcessInstanceVariablesToObjectCmd extends AbstractComman
// 发起人流程引擎内部模型需要外部调用该命令时再解析 当前命令所在 module 不支持调用二方接口
returnVariables.add(VariableObjectDTO.builder()
.key(PRINT_VAR_PROCESS_INITIATOR)
.desc(PRINT_VAR_PROCESS_INITIATOR_DESC)
.value(processVariables.get(INTERNAL_INITIATOR))
.type(VariableObjectDTO.Type.obj)
.build());
@ -160,11 +173,51 @@ public class CustomGetProcessInstanceVariablesToObjectCmd extends AbstractComman
if (!(field instanceof FormContainer) && SUPPORTED_FORM_TYPES.contains(field.getType())) {
Object fieldValue = formFieldValues.getOrDefault(field.getId(), null);
if (Objects.nonNull(fieldValue)) {
variables.add(VariableObjectDTO.builder()
.key(field.getId())
.value(fieldValue)
.type(convert(field.getType()))
.build());
if (Objects.equals(field.getType(), FormFieldTypes.AMOUNT)) {
if (StringUtils.hasText(fieldValue.toString())) {
JSONObject jsonObject = JSON.parseObject(fieldValue.toString());
BigDecimal standardNumerals = jsonObject.getBigDecimal("standardNumerals");
if (Objects.nonNull(standardNumerals)) {
variables.add(VariableObjectDTO.builder()
.key(field.getId() + "_standardNumerals")
.desc(field.getName() + "小写")
.value(standardNumerals)
.type(convert(field.getType()))
.build());
}
if (Boolean.parseBoolean(field.getParam("toUpper").toString())) {
String uppercaseNumerals = jsonObject.getString("uppercaseNumerals");
if (StringUtils.hasText(uppercaseNumerals)) {
variables.add(VariableObjectDTO.builder()
.key(field.getId() + "_uppercaseNumerals")
.desc(field.getName() + "大写")
.value(uppercaseNumerals)
.type(convert(field.getType()))
.build());
}
}
}
} else if (Objects.equals(field.getType(), "contacts")) {
if (StringUtils.hasText(fieldValue.toString())
&& fieldValue.toString().startsWith("[")
&& fieldValue.toString().endsWith("]")) {
List<String> names = JSON.parseArray((String) fieldValue, ContactsPersonDTO.class)
.stream().map(ContactsPersonDTO::getRealName).collect(Collectors.toList());
variables.add(VariableObjectDTO.builder()
.key(field.getId())
.desc(field.getName())
.value(StringUtils.collectionToCommaDelimitedString(names))
.type(convert(field.getType()))
.build());
}
} else {
variables.add(VariableObjectDTO.builder()
.key(field.getId())
.desc(field.getName())
.value(fieldValue)
.type(convert(field.getType()))
.build());
}
}
}
});
@ -179,6 +232,7 @@ public class CustomGetProcessInstanceVariablesToObjectCmd extends AbstractComman
if (!Objects.equals(NODE_STARTER.getType(), sign.getActivityId())) {
variables.add(VariableObjectDTO.builder()
.key(sign.getActivityId())
.desc(sign.getActivityName())
.value(sign.getSignatures())
.type(VariableObjectDTO.Type.signatureAndAdvice)
.build());
@ -191,6 +245,7 @@ public class CustomGetProcessInstanceVariablesToObjectCmd extends AbstractComman
categoryService.get(BPM_MODEL_CATEGORY, historicProcessInstance.getProcessDefinitionKey()).ifPresent(category -> {
variables.add(VariableObjectDTO.builder()
.key(PRINT_VAR_PROCESS_DEFINITION_KEY)
.desc(PRINT_VAR_PROCESS_DEFINITION_KEY_DESC)
.value(category.getLabel() + "(" + category.getValue() + ")")
.build());
// 添加业务下的变量
@ -215,6 +270,7 @@ public class CustomGetProcessInstanceVariablesToObjectCmd extends AbstractComman
}
variables.add(VariableObjectDTO.builder()
.key(variable.getCode())
.desc(group.getGroupName() + variable.getName())
.value(value)
.type(convert(variable.getType()))
.build());
@ -240,7 +296,10 @@ public class CustomGetProcessInstanceVariablesToObjectCmd extends AbstractComman
switch (type) {
case "input":
case "text":
case "date":
case "textarea":
case "amount":
case "contacts":
return VariableObjectDTO.Type.text;
case "image":
return VariableObjectDTO.Type.img;

View File

@ -467,7 +467,7 @@ public class BpmnProcessInstanceServiceImpl implements BpmnProcessInstanceServic
if (Objects.equals(BusinessTypeEnum.SIGN, itemVO.getBusinessType())) {
// 签署业务
dto.getVariables().put(SIGN_PROCESS_ENABLE_DOC_IDS, dto.getDocIds());
dto.getVariables().put(SIGN_VARIABLE, dto.getSignVariables());
dto.getVariables().put(SIGN_VARIABLE, dto.getBizCustomVariables());
dto.getVariables().put(SIGNATORIES, dto.getSignatories());
}
});

View File

@ -269,6 +269,9 @@ public class ExtAxModelDocServiceImpl implements ExtAxModelDocService {
@Transactional(rollbackFor = Exception.class)
public Boolean deleteDoc(Long docId) {
ExtAxModelDoc origin = extAxModelDocMapper.selectById(docId);
if(Objects.isNull(origin)) {
return false;
}
// 用于发送文档变更事件
List<ExtAxModelDoc> oldSettings = querySetting(origin.getModelKey(), origin.getTenantId());

View File

@ -24,6 +24,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import static cn.axzo.workflow.common.code.FormInstanceRespCode.FORM_DATA_PARSE_ERROR_BY_AMOUNT;
import static cn.axzo.workflow.common.code.FormInstanceRespCode.FORM_DATA_PARSE_ERROR_BY_UPLOAD;
/**
@ -103,6 +104,15 @@ public class CustomCreateFormInstanceCmd extends CreateFormInstanceCmd {
} catch (JsonProcessingException e) {
throw new WorkflowEngineException(FORM_DATA_PARSE_ERROR_BY_UPLOAD);
}
} else if (variableValue instanceof Map) {
if (CollectionUtils.isEmpty((Map<?, ?>) variableValue)) {
variableValue = Collections.emptyMap();
}
try {
valuesNode.put(fieldId, objectMapper.writeValueAsString(variableValue));
} catch (JsonProcessingException e) {
throw new WorkflowEngineException(FORM_DATA_PARSE_ERROR_BY_AMOUNT);
}
} else {
valuesNode.put(fieldId, variableValue.toString());
}

View File

@ -23,8 +23,6 @@ public class ConversionUtils {
} else if (obj instanceof String) {
if (StringUtils.pathEquals(obj.toString(), "[]")) {
return null;
} else if (StringUtils.hasText(obj.toString()) && ((String) obj).startsWith("[") && ((String) obj).endsWith("]")) {
return ((String) obj).replace("[", "").replace("]", "");
}
// 如果输入不是列表类型返回空列表或进行其他处理
return obj;

View File

@ -36,8 +36,11 @@ import java.util.stream.Collectors;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_INITIATOR;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_INITIATOR_NAME;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_INITIATOR_NAME_DESC;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_INITIATOR_PHONE;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_INITIATOR_PHONE_DESC;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_INITIATOR_POSITION;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_INITIATOR_POSITION_DESC;
import static cn.axzo.workflow.common.model.dto.VariableObjectDTO.Type.signatureAndAdvice;
/**
@ -67,8 +70,11 @@ public class WpsUtil {
String fileCode, String fileKey, String fileName) {
List<FileReplaceContent> fileReplaceContents = BeanMapper.copyList(wpsVariables.stream()
.filter(i -> Objects.nonNull(i.getValue()))
.filter(i -> !(Objects.equals(i.getType().name(), "img") && !StringUtils.hasText(i.getValue().toString())))
.filter(i -> Objects.equals(i.getType().name(), "img") || Objects.equals(i.getType().name(), "text"))
.collect(Collectors.toList()), FileReplaceContent.class, (s, t) -> {
t.setKey(s.getDesc());
if (Objects.equals(s.getType().name(), "img")) {
if (isJson(s.getValue().toString())) {
t.setContent(JSON.parseArray(s.getValue().toString(), UploadFieldDTO.class).get(0).getFileUrl());
@ -79,6 +85,8 @@ public class WpsUtil {
t.setContent(Objects.nonNull(s.getValue()) ? s.getValue().toString() : "");
}
t.setType(s.getType().name());
t.setPrefix("[");
t.setSuffix("]");
});
if (StringUtils.hasText(fileCode)) {
FileTemplateReplaceRequest request = new FileTemplateReplaceRequest();
@ -110,11 +118,13 @@ public class WpsUtil {
List<ApiSignUrlDownloadResponse> signUrl = RpcExternalUtil.rpcProcessor(() -> serverFileServiceApi.signUrlFetchDownload(request), "获取手写签图片地址", request);
signatureAndAdvices.add(VariableObjectDTO.builder()
.key(variableObjectDTO.getKey() + "_signature")
.desc(variableObjectDTO.getDesc() + "电子签名")
.value(Lists.newArrayList(UploadFieldDTO.builder().fileKey(signDetail.getSignature()).fileUrl(signUrl.get(0).getSignUrl()).build()))
.type(VariableObjectDTO.Type.img)
.build());
signatureAndAdvices.add(VariableObjectDTO.builder()
.key(variableObjectDTO.getKey() + "_advice")
.desc(variableObjectDTO.getDesc() + "审批意见")
.value(signDetail.getAdvice())
.type(VariableObjectDTO.Type.text)
.build());
@ -127,14 +137,17 @@ public class WpsUtil {
Optional<OrgNodeUserBriefInfoResp> user = getUserInfo(initiator);
wpsVariables.add(VariableObjectDTO.builder()
.key(PRINT_VAR_PROCESS_INITIATOR_NAME)
.desc(PRINT_VAR_PROCESS_INITIATOR_NAME_DESC)
.value(user.isPresent() ? user.get().getRealName() : "")
.build());
wpsVariables.add(VariableObjectDTO.builder()
.key(PRINT_VAR_PROCESS_INITIATOR_POSITION)
.desc(PRINT_VAR_PROCESS_INITIATOR_POSITION_DESC)
.value(user.isPresent() && Objects.nonNull(user.get().getJob()) ? user.get().getJob().getName() : "")
.build());
wpsVariables.add(VariableObjectDTO.builder()
.key(PRINT_VAR_PROCESS_INITIATOR_PHONE)
.desc(PRINT_VAR_PROCESS_INITIATOR_PHONE_DESC)
.value(user.isPresent() ? user.get().getProfile().getPhone() : "")
.build());

View File

@ -63,6 +63,11 @@ public abstract class AbstractBpmnTaskAssigneeSelector implements BpmnTaskAssign
protected SupportRefreshProperties refreshProperties;
private ApplicationContext applicationContext;
@Override
public boolean support(String param) {
return getType().equals(param);
}
@Override
public List<BpmnTaskDelegateAssigner> select(FlowElement flowElement, DelegateExecution execution,
Boolean throwException) {
@ -244,7 +249,7 @@ public abstract class AbstractBpmnTaskAssigneeSelector implements BpmnTaskAssign
}
long personId = Long.parseLong(Optional.ofNullable(assigner.getPersonId()).orElse("-1"));
if (personProfileMap.containsKey(personId)) {
log.warn("查询到的人员信息:{}", JSON.toJSONString(personProfileMap.getOrDefault(personId, null)));
log.info("查询到的人员信息:{}", JSON.toJSONString(personProfileMap.getOrDefault(personId, null)));
assigner.setAvatar(personProfileMap.getOrDefault(personId, new PersonProfileResp()).getAvatarUrl());
assigner.setAssignerName(personProfileMap.getOrDefault(personId, new PersonProfileResp()).getRealName());

View File

@ -18,7 +18,11 @@ import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import static cn.axzo.workflow.common.code.FlowableEngineRespCode.ENGINE_USER_TASK_CALC_ERROR;
@ -39,11 +43,6 @@ public class BasedFixedPersonTaskAssigneeSelector extends AbstractBpmnTaskAssign
return ApproverSpecifyEnum.fixedPerson.getType();
}
@Override
public boolean support(String param) {
return getType().equals(param);
}
@Override
public List<BpmnTaskDelegateAssigner> select(FlowElement flowElement, DelegateExecution execution,
Boolean throwException) {

View File

@ -31,11 +31,6 @@ public class BasedIdentityTaskAssigneeSelector extends AbstractBpmnTaskAssigneeS
return ApproverSpecifyEnum.identity.getType();
}
@Override
public boolean support(String param) {
return getType().equals(param);
}
@Override
public List<BpmnTaskDelegateAssigner> select(FlowElement flowElement, DelegateExecution execution,
Boolean throwException) {

View File

@ -1,8 +1,8 @@
package cn.axzo.workflow.server.controller.delegate;
import cn.axzo.workflow.common.enums.ApproverSpecifyEnum;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import cn.axzo.workflow.common.exception.WorkflowEngineException;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.engine.delegate.DelegateExecution;
import org.springframework.stereotype.Component;
@ -27,11 +27,6 @@ public class BasedInitiatorLeaderRecursionTaskAssigneeSelector extends AbstractB
return ApproverSpecifyEnum.initiatorLeaderRecursion.getType();
}
@Override
public boolean support(String param) {
return getType().equals(param);
}
@Override
public List<BpmnTaskDelegateAssigner> select(FlowElement flowElement, DelegateExecution execution,
Boolean throwException) {

View File

@ -40,11 +40,6 @@ public class BasedInitiatorLeaderTaskAssigneeSelector extends AbstractBpmnTaskAs
return ApproverSpecifyEnum.initiatorLeader.getType();
}
@Override
public boolean support(String param) {
return getType().equals(param);
}
@Override
public List<BpmnTaskDelegateAssigner> select(FlowElement flowElement, DelegateExecution execution,
Boolean throwException) {

View File

@ -41,7 +41,7 @@ public class BasedInitiatorSpecifiedTaskAssigneeSelector extends AbstractBpmnTas
@Override
public boolean support(String param) {
return getType().equals(param);
return getType().equals(param) || ApproverSpecifyEnum.signerRelated.getType().equals(param);
}
@Override

View File

@ -36,11 +36,6 @@ public class BasedPositionTaskAssigneeSelector extends AbstractBpmnTaskAssigneeS
return ApproverSpecifyEnum.position.getType();
}
@Override
public boolean support(String param) {
return getType().equals(param);
}
@Override
public List<BpmnTaskDelegateAssigner> select(FlowElement flowElement, DelegateExecution execution,
Boolean throwException) {

View File

@ -47,11 +47,6 @@ public class BasedRoleTaskAssigneeSelector extends AbstractBpmnTaskAssigneeSelec
return ApproverSpecifyEnum.role.getType();
}
@Override
public boolean support(String param) {
return getType().equals(param);
}
@Override
public List<BpmnTaskDelegateAssigner> select(FlowElement flowElement, DelegateExecution execution,
Boolean throwException) {

View File

@ -32,11 +32,6 @@ public class PreNodeSpecifiedTaskAssigneeSelector extends AbstractBpmnTaskAssign
return ApproverSpecifyEnum.preNodeSpecified.getType();
}
@Override
public boolean support(String param) {
return getType().equals(param);
}
@Override
public List<BpmnTaskDelegateAssigner> select(FlowElement flowElement, DelegateExecution execution,
Boolean throwException) {

View File

@ -53,11 +53,6 @@ public class TransferToAdminTaskAssigneeSelector extends AbstractBpmnTaskAssigne
return ApproverEmptyHandleTypeEnum.transferToAdmin.getType();
}
@Override
public boolean support(String param) {
return getType().equals(param);
}
@Override
public List<BpmnTaskDelegateAssigner> select(FlowElement flowElement, DelegateExecution execution,
Boolean throwException) {

View File

@ -19,7 +19,11 @@ import org.flowable.engine.delegate.DelegateExecution;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import static cn.axzo.workflow.common.code.FlowableEngineRespCode.ENGINE_USER_TASK_CALC_ERROR;
@ -39,11 +43,6 @@ public class TransferToSpecifyTaskAssigneeSelector extends AbstractBpmnTaskAssig
return ApproverEmptyHandleTypeEnum.specifyAssignee.getType();
}
@Override
public boolean support(String param) {
return getType().equals(param);
}
@Override
public List<BpmnTaskDelegateAssigner> select(FlowElement flowElement, DelegateExecution execution, Boolean throwException) {
if (!(flowElement instanceof UserTask)) {

View File

@ -1,160 +1,165 @@
package cn.axzo.workflow.server.controller.listener.activity;
import cn.axzo.nanopart.doc.api.anonymous.DocAnonymousDatabaseApi;
import cn.axzo.nanopart.doc.api.index.request.CopyNodeRequest;
import cn.axzo.workflow.common.enums.FileTypeEnum;
import cn.axzo.workflow.common.model.dto.SignFileDTO;
import cn.axzo.workflow.common.model.dto.VariableObjectDTO;
import cn.axzo.workflow.common.model.request.bpmn.BpmnSignConf;
import cn.axzo.workflow.common.model.request.bpmn.model.doc.DocCloneDTO;
import cn.axzo.workflow.common.model.response.bpmn.model.doc.DocBaseVO;
import cn.axzo.workflow.core.common.context.ActivityOperationContext;
import cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper;
import cn.axzo.workflow.core.engine.cmd.CustomGetModelDocsCmd;
import cn.axzo.workflow.core.listener.AbstractBpmnEventListener;
import cn.axzo.workflow.core.listener.BpmnActivityEventListener;
import cn.axzo.workflow.core.repository.entity.ExtAxProcessSign;
import cn.axzo.workflow.core.repository.mapper.ExtAxModelDocMapper;
import cn.axzo.workflow.core.service.ExtAxModelDocService;
import cn.axzo.workflow.core.service.ExtAxProcessSignService;
import cn.axzo.workflow.core.service.ExtAxReModelService;
import cn.axzo.workflow.server.common.util.RpcExternalUtil;
import cn.axzo.workflow.server.common.util.WpsUtil;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.Process;
import org.flowable.common.engine.impl.interceptor.CommandExecutor;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
import org.springframework.context.annotation.Scope;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
/**
* 签署业务才会执行
* <p>
* 流程实例启用成功后:
* 1将模型关联的且实例勾选使用过的文档进行原始模板复制
* 2进行初始数据的模板变量替换
* <p>
* 并存至 ext_ax_process_sign 中的 doc_template 字段
*
* @author wangli
* @since 2025-04-23 14:32
*/
@Slf4j
@Component
@Scope("prototype")
public class FirstCopyTemplateFileActivityEvent_101_Listener extends AbstractBpmnEventListener<ActivityOperationContext> implements BpmnActivityEventListener, Ordered {
@Resource
private ExtAxProcessSignService extAxProcessSignService;
@Resource
private ExtAxModelDocMapper extAxModelDocMapper;
@Resource
private ExtAxReModelService extAxReModelService;
@Resource
private ExtAxModelDocService extAxModelDocService;
@Resource
private DocAnonymousDatabaseApi docAnonymousApi;
@Resource
private WpsUtil wpsUtil;
@Override
public int getOrder() {
return Integer.MIN_VALUE + 101;
}
@Override
public void onStart(DelegateExecution execution) {
String processInstanceId = execution.getProcessInstanceId();
Process mainProcess = ProcessDefinitionUtil.getBpmnModel(execution.getProcessDefinitionId()).getMainProcess();
Optional<BpmnSignConf> signConfig = BpmnMetaParserHelper.getSignConfig(mainProcess);
if (!signConfig.isPresent() || Objects.isNull(signConfig.get().getSignType())) {
return;
}
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();
CommandExecutor commandExecutor = processEngineConfiguration.getCommandExecutor();
List<DocBaseVO> docs = commandExecutor.execute(new CustomGetModelDocsCmd(processInstanceId, true, extAxModelDocMapper, extAxReModelService));
ExtAxProcessSign processSign = new ExtAxProcessSign();
processSign.setProcessInstanceId(processInstanceId);
processSign.setSignType(signConfig.get().getSignType().getType());
processSign.setPendingMessageId(signConfig.get().getSignPendingProperty().getPendingMessageId());
if (CollectionUtils.isEmpty(docs)) {
processSign.setDocTemplate(Collections.emptyList());
processSign.setFileArchive(Collections.emptyList());
} else {
// 复制基础模板
List<SignFileDTO> docTemplates = copyTempTemplate(docs);
processSign.setDocTemplate(docTemplates);
List<SignFileDTO> archives = replaceTemplateVariable(docTemplates, processEngineConfiguration, processInstanceId);
processSign.setFileArchive(archives);
}
// 没有可用的文档但仍然记录库表
extAxProcessSignService.save(processSign);
}
private List<SignFileDTO> replaceTemplateVariable(List<SignFileDTO> docTemplates, ProcessEngineConfigurationImpl processEngineConfiguration, String processInstanceId) {
List<SignFileDTO> archives = new ArrayList<>();
List<VariableObjectDTO> wpsReplaceVariables = wpsUtil.getWpsReplaceVariables(processEngineConfiguration, processInstanceId);
docTemplates.forEach(template -> {
SignFileDTO signFileDTO = new SignFileDTO();
signFileDTO.setId(template.getId());
signFileDTO.setFileName(template.getFileName());
signFileDTO.setTemplateName(template.getTemplateName());
signFileDTO.setFileTag(template.getFileTag());
signFileDTO.setFileType(template.getFileType());
signFileDTO.setFileCode(template.getFileCode());
if (Objects.equals(template.getFileType(), FileTypeEnum.WORD) || Objects.equals(template.getFileType(), FileTypeEnum.EXCEL)) {
String fileKey = wpsUtil.wpsFileVariableReplace(wpsReplaceVariables, template.getFileCode(), null, template.getTemplateName() + template.getFileType().getSuffix());
signFileDTO.setFileKey(fileKey);
}
archives.add(signFileDTO);
});
return archives;
}
private List<SignFileDTO> copyTempTemplate(List<DocBaseVO> docs) {
List<SignFileDTO> files = new ArrayList<>();
docs.forEach(doc -> {
SignFileDTO signFileDTO = new SignFileDTO();
// 原始文档 ID
signFileDTO.setId(doc.getId());
signFileDTO.setFileName(doc.getFileName());
signFileDTO.setTemplateName(doc.getTemplateName());
signFileDTO.setFileTag(doc.getTag());
signFileDTO.setFileType(doc.getFileType());
switch (doc.getFileType()) {
case WORD:
case EXCEL:
CopyNodeRequest copy = new CopyNodeRequest();
copy.setCode(doc.getFileRelationId());
String fileCode = RpcExternalUtil.rpcProcessor(() -> docAnonymousApi.copy(copy), "复制文档", copy);
signFileDTO.setFileCode(fileCode);
break;
case HIPRINT:
Long newDocId = extAxModelDocService.cloneDoc(DocCloneDTO.builder().docId(doc.getId()).build(), true);
signFileDTO.setFileCode(String.valueOf(newDocId));
break;
case PDF:
break;
default:
break;
}
files.add(signFileDTO);
});
return files;
}
}
//package cn.axzo.workflow.server.controller.listener.activity;
//
//import cn.axzo.nanopart.doc.api.anonymous.DocAnonymousDatabaseApi;
//import cn.axzo.nanopart.doc.api.index.request.CopyNodeRequest;
//import cn.axzo.workflow.common.enums.FileTypeEnum;
//import cn.axzo.workflow.common.model.dto.SignFileDTO;
//import cn.axzo.workflow.common.model.dto.VariableObjectDTO;
//import cn.axzo.workflow.common.model.request.bpmn.BpmnSignConf;
//import cn.axzo.workflow.common.model.request.bpmn.model.doc.DocCloneDTO;
//import cn.axzo.workflow.common.model.response.bpmn.model.doc.DocBaseVO;
//import cn.axzo.workflow.core.common.context.ActivityOperationContext;
//import cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper;
//import cn.axzo.workflow.core.engine.cmd.CustomGetModelDocsCmd;
//import cn.axzo.workflow.core.listener.AbstractBpmnEventListener;
//import cn.axzo.workflow.core.listener.BpmnActivityEventListener;
//import cn.axzo.workflow.core.repository.entity.ExtAxProcessSign;
//import cn.axzo.workflow.core.repository.mapper.ExtAxModelDocMapper;
//import cn.axzo.workflow.core.service.ExtAxModelDocService;
//import cn.axzo.workflow.core.service.ExtAxProcessSignService;
//import cn.axzo.workflow.core.service.ExtAxReModelService;
//import cn.axzo.workflow.server.common.util.RpcExternalUtil;
//import cn.axzo.workflow.server.common.util.WpsUtil;
//import lombok.extern.slf4j.Slf4j;
//import org.flowable.bpmn.model.Process;
//import org.flowable.common.engine.impl.interceptor.CommandExecutor;
//import org.flowable.engine.delegate.DelegateExecution;
//import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
//import org.flowable.engine.impl.util.CommandContextUtil;
//import org.flowable.engine.impl.util.ProcessDefinitionUtil;
//import org.springframework.context.annotation.Scope;
//import org.springframework.core.Ordered;
//import org.springframework.stereotype.Component;
//import org.springframework.util.CollectionUtils;
//
//import javax.annotation.Resource;
//import java.util.ArrayList;
//import java.util.Collections;
//import java.util.List;
//import java.util.Objects;
//import java.util.Optional;
//
//import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_STARTER;
//
/// **
// * 签署业务才会执行
// * <p>
// * 流程实例启用成功后:
// * 1将模型关联的且实例勾选使用过的文档进行原始模板复制
// * 2进行初始数据的模板变量替换
// * <p>
// * 并存至 ext_ax_process_sign 中的 doc_template 字段
// *
// * @author wangli
// * @since 2025-04-23 14:32
// */
//@Slf4j
////@Component
//@Scope("prototype")
//public class FirstCopyTemplateFileActivityEvent_101_Listener extends AbstractBpmnEventListener<ActivityOperationContext> implements BpmnActivityEventListener, Ordered {
//
// @Resource
// private ExtAxProcessSignService extAxProcessSignService;
// @Resource
// private ExtAxModelDocMapper extAxModelDocMapper;
// @Resource
// private ExtAxReModelService extAxReModelService;
// @Resource
// private ExtAxModelDocService extAxModelDocService;
// @Resource
// private DocAnonymousDatabaseApi docAnonymousApi;
// @Resource
// private WpsUtil wpsUtil;
//
// @Override
// public int getOrder() {
// return Integer.MIN_VALUE + 101;
// }
//
// @Override
// public void onStart(DelegateExecution execution) {
// if (!Objects.equals(NODE_STARTER.getType(), execution.getCurrentActivityId())) {
// return;
// }
// String processInstanceId = execution.getProcessInstanceId();
//
// Process mainProcess = ProcessDefinitionUtil.getBpmnModel(execution.getProcessDefinitionId()).getMainProcess();
// Optional<BpmnSignConf> signConfig = BpmnMetaParserHelper.getSignConfig(mainProcess);
// if (!signConfig.isPresent() || Objects.isNull(signConfig.get().getSignType())) {
// return;
// }
//
// ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();
// CommandExecutor commandExecutor = processEngineConfiguration.getCommandExecutor();
// List<DocBaseVO> docs = commandExecutor.execute(new CustomGetModelDocsCmd(processInstanceId, true, extAxModelDocMapper, extAxReModelService));
// ExtAxProcessSign processSign = new ExtAxProcessSign();
// processSign.setProcessInstanceId(processInstanceId);
// processSign.setSignType(signConfig.get().getSignType().getType());
// processSign.setPendingMessageId(signConfig.get().getSignPendingProperty().getPendingMessageId());
// if (CollectionUtils.isEmpty(docs)) {
// processSign.setDocTemplate(Collections.emptyList());
// processSign.setFileArchive(Collections.emptyList());
// } else {
// // 复制基础模板
// List<SignFileDTO> docTemplates = copyTempTemplate(docs);
// processSign.setDocTemplate(docTemplates);
//
// List<SignFileDTO> archives = replaceTemplateVariable(docTemplates, processEngineConfiguration, processInstanceId);
// processSign.setFileArchive(archives);
// }
// // 没有可用的文档但仍然记录库表
// extAxProcessSignService.save(processSign);
// }
//
// private List<SignFileDTO> replaceTemplateVariable(List<SignFileDTO> docTemplates, ProcessEngineConfigurationImpl processEngineConfiguration, String processInstanceId) {
// List<SignFileDTO> archives = new ArrayList<>();
// List<VariableObjectDTO> wpsReplaceVariables = wpsUtil.getWpsReplaceVariables(processEngineConfiguration, processInstanceId);
// docTemplates.forEach(template -> {
// SignFileDTO signFileDTO = new SignFileDTO();
// signFileDTO.setId(template.getId());
// signFileDTO.setFileName(template.getFileName());
// signFileDTO.setTemplateName(template.getTemplateName());
// signFileDTO.setFileTag(template.getFileTag());
// signFileDTO.setFileType(template.getFileType());
// signFileDTO.setFileCode(template.getFileCode());
// if (Objects.equals(template.getFileType(), FileTypeEnum.WORD) || Objects.equals(template.getFileType(), FileTypeEnum.EXCEL)) {
// String fileKey = wpsUtil.wpsFileVariableReplace(wpsReplaceVariables, template.getFileCode(), null, template.getTemplateName() + template.getFileType().getSuffix());
// signFileDTO.setFileKey(fileKey);
// }
// archives.add(signFileDTO);
// });
// return archives;
// }
//
// private List<SignFileDTO> copyTempTemplate(List<DocBaseVO> docs) {
// List<SignFileDTO> files = new ArrayList<>();
// docs.forEach(doc -> {
// SignFileDTO signFileDTO = new SignFileDTO();
// // 原始文档 ID
// signFileDTO.setId(doc.getId());
// signFileDTO.setFileName(doc.getFileName());
// signFileDTO.setTemplateName(doc.getTemplateName());
// signFileDTO.setFileTag(doc.getTag());
// signFileDTO.setFileType(doc.getFileType());
// switch (doc.getFileType()) {
// case WORD:
// case EXCEL:
// CopyNodeRequest copy = new CopyNodeRequest();
// copy.setCode(doc.getFileRelationId());
// String fileCode = RpcExternalUtil.rpcProcessor(() -> docAnonymousApi.copy(copy), "复制文档", copy);
// signFileDTO.setFileCode(fileCode);
// break;
// case HIPRINT:
// Long newDocId = extAxModelDocService.cloneDoc(DocCloneDTO.builder().docId(doc.getId()).build(), true);
// signFileDTO.setFileCode(String.valueOf(newDocId));
// break;
// case PDF:
// break;
// default:
// break;
// }
// files.add(signFileDTO);
// });
// return files;
// }
//}

View File

@ -1,6 +1,7 @@
package cn.axzo.workflow.server.controller.listener.activity;
import cn.axzo.workflow.common.enums.FileTypeEnum;
import cn.axzo.workflow.common.exception.WorkflowEngineException;
import cn.axzo.workflow.common.model.dto.VariableObjectDTO;
import cn.axzo.workflow.common.model.request.bpmn.BpmnSignConf;
import cn.axzo.workflow.core.common.context.ActivityOperationContext;
@ -25,6 +26,8 @@ import java.util.List;
import java.util.Objects;
import java.util.Optional;
import static cn.axzo.workflow.common.code.BpmnInstanceRespCode.PROCESS_SIGN_DATA_NOT_EXISTS;
/**
* 每个审批节点运行结束后临时替换一次变量并更新至 ext_ax_process_sign file_archive 字段
*
@ -34,7 +37,7 @@ import java.util.Optional;
@Slf4j
@Component
@Scope("prototype")
public class OperationFileArchiveActivityEvent_102_Listener extends AbstractBpmnEventListener<ActivityOperationContext> implements BpmnActivityEventListener, Ordered {
public class OperationFileArchiveActivityEvent_101_Listener extends AbstractBpmnEventListener<ActivityOperationContext> implements BpmnActivityEventListener, Ordered {
@Resource
private ExtAxProcessSignService extAxProcessSignService;
@Resource
@ -54,6 +57,9 @@ public class OperationFileArchiveActivityEvent_102_Listener extends AbstractBpmn
}
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();
ExtAxProcessSign processSign = extAxProcessSignService.findByProcessInstanceId(execution.getProcessInstanceId());
if (Objects.isNull(processSign)) {
throw new WorkflowEngineException(PROCESS_SIGN_DATA_NOT_EXISTS);
}
List<VariableObjectDTO> wpsReplaceVariables = wpsUtil.getWpsReplaceVariables(processEngineConfiguration, execution.getProcessInstanceId());
processSign.getFileArchive().stream().filter(i -> Objects.equals(i.getFileType(), FileTypeEnum.WORD)
|| Objects.equals(i.getFileType(), FileTypeEnum.EXCEL))

View File

@ -217,13 +217,13 @@ public class RocketMqBpmActivityEvent_100_Listener extends AbstractBpmnEventList
}
Map<String, String> header = new HashMap<>();
if (StringUtils.hasText(dto.getProcessDefinitionKey())) {
log.warn("record process definition key: {}", dto.getProcessDefinitionKey());
log.info("record process definition key: {}", dto.getProcessDefinitionKey());
header.put(MQ_OWNERSHIP_PROCESS_DEFINITION_KEY, dto.getProcessDefinitionKey());
}
if (dto.getVariables().containsKey(PROCESS_OWNERSHIP_APPLICATION)) {
Object orDefault = dto.getVariables().getOrDefault(PROCESS_OWNERSHIP_APPLICATION, "");
if (Objects.nonNull(orDefault)) {
log.warn("record process ownership app name: {}", orDefault);
log.info("record process ownership app name: {}", orDefault);
header.put(MQ_OWNERSHIP_APPLICATION, orDefault.toString());
}
}

View File

@ -410,6 +410,7 @@ public class RocketMqMessagePushEventListener extends AbstractBpmnEventListener<
Object> variables, Boolean activitySignature) {
return new MessagePushDTO()
.setProcessInstanceId(event.getProcessInstanceId())
.setAdscriptionTenantId(event.getTenantId())
.setProcessDefinitionKey(event.getProcessDefinitionKey())
.setType(type)
.setTemplateId(templateId)
@ -427,13 +428,13 @@ public class RocketMqMessagePushEventListener extends AbstractBpmnEventListener<
}
Map<String, String> header = new HashMap<>();
if (StringUtils.hasText(dto.getProcessDefinitionKey())) {
log.warn("record process definition key: {}", dto.getProcessDefinitionKey());
log.info("record process definition key: {}", dto.getProcessDefinitionKey());
header.put(MQ_OWNERSHIP_PROCESS_DEFINITION_KEY, dto.getProcessDefinitionKey());
}
if (dto.getVariables().containsKey(PROCESS_OWNERSHIP_APPLICATION)) {
Object orDefault = dto.getVariables().getOrDefault(PROCESS_OWNERSHIP_APPLICATION, "");
if (Objects.nonNull(orDefault)) {
log.warn("record process ownership app name: {}", orDefault);
log.info("record process ownership app name: {}", orDefault);
header.put(MQ_OWNERSHIP_APPLICATION, orDefault.toString());
}
}

View File

@ -298,13 +298,13 @@ public class RocketMqBpmnProcessEventListener extends AbstractBpmnEventListener<
}
Map<String, String> header = new HashMap<>();
if (StringUtils.hasText(dto.getProcessDefinitionKey())) {
log.warn("record process definition key: {}", dto.getProcessDefinitionKey());
log.info("record process definition key: {}", dto.getProcessDefinitionKey());
header.put(MQ_OWNERSHIP_PROCESS_DEFINITION_KEY, dto.getProcessDefinitionKey());
}
if (dto.getVariables().containsKey(PROCESS_OWNERSHIP_APPLICATION)) {
Object orDefault = dto.getVariables().getOrDefault(PROCESS_OWNERSHIP_APPLICATION, "");
if (Objects.nonNull(orDefault)) {
log.warn("record process ownership app name: {}", orDefault);
log.info("record process ownership app name: {}", orDefault);
header.put(MQ_OWNERSHIP_APPLICATION, orDefault.toString());
}
}

View File

@ -0,0 +1,164 @@
package cn.axzo.workflow.server.controller.listener.task;
import cn.axzo.nanopart.doc.api.anonymous.DocAnonymousDatabaseApi;
import cn.axzo.nanopart.doc.api.index.request.CopyNodeRequest;
import cn.axzo.workflow.common.enums.FileTypeEnum;
import cn.axzo.workflow.common.model.dto.SignFileDTO;
import cn.axzo.workflow.common.model.dto.VariableObjectDTO;
import cn.axzo.workflow.common.model.request.bpmn.BpmnSignConf;
import cn.axzo.workflow.common.model.request.bpmn.model.doc.DocCloneDTO;
import cn.axzo.workflow.common.model.response.bpmn.model.doc.DocBaseVO;
import cn.axzo.workflow.core.common.context.TaskOperationContext;
import cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper;
import cn.axzo.workflow.core.engine.cmd.CustomGetModelDocsCmd;
import cn.axzo.workflow.core.listener.AbstractBpmnEventListener;
import cn.axzo.workflow.core.listener.BpmnTaskEventListener;
import cn.axzo.workflow.core.repository.entity.ExtAxProcessSign;
import cn.axzo.workflow.core.repository.mapper.ExtAxModelDocMapper;
import cn.axzo.workflow.core.service.ExtAxModelDocService;
import cn.axzo.workflow.core.service.ExtAxProcessSignService;
import cn.axzo.workflow.core.service.ExtAxReModelService;
import cn.axzo.workflow.server.common.util.RpcExternalUtil;
import cn.axzo.workflow.server.common.util.WpsUtil;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.Process;
import org.flowable.common.engine.impl.interceptor.CommandExecutor;
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
import org.flowable.task.service.delegate.DelegateTask;
import org.springframework.context.annotation.Scope;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_STARTER;
/**
* 签署业务才会执行
* <p>
* 流程实例启用成功后:
* 1将模型关联的且实例勾选使用过的文档进行原始模板复制
* 2进行初始数据的模板变量替换
* <p>
* 并存至 ext_ax_process_sign 中的 doc_template 字段
*
* @author wangli
* @since 2025-05-16 15:12
*/
@Slf4j
@Component
@Scope("prototype")
public class FirstCopyTemplateFileTaskEvent_105_Listener extends AbstractBpmnEventListener<TaskOperationContext> implements BpmnTaskEventListener, Ordered {
@Resource
private ExtAxProcessSignService extAxProcessSignService;
@Resource
private ExtAxModelDocMapper extAxModelDocMapper;
@Resource
private ExtAxReModelService extAxReModelService;
@Resource
private ExtAxModelDocService extAxModelDocService;
@Resource
private DocAnonymousDatabaseApi docAnonymousApi;
@Resource
private WpsUtil wpsUtil;
@Override
public void onCompleted(DelegateTask delegateTask) {
if (!Objects.equals(NODE_STARTER.getType(), delegateTask.getTaskDefinitionKey())) {
return;
}
String processInstanceId = delegateTask.getProcessInstanceId();
Process mainProcess = ProcessDefinitionUtil.getBpmnModel(delegateTask.getProcessDefinitionId()).getMainProcess();
Optional<BpmnSignConf> signConfig = BpmnMetaParserHelper.getSignConfig(mainProcess);
if (!signConfig.isPresent() || Objects.isNull(signConfig.get().getSignType())) {
return;
}
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();
CommandExecutor commandExecutor = processEngineConfiguration.getCommandExecutor();
List<DocBaseVO> docs = commandExecutor.execute(new CustomGetModelDocsCmd(processInstanceId, true, extAxModelDocMapper, extAxReModelService));
ExtAxProcessSign processSign = new ExtAxProcessSign();
processSign.setProcessInstanceId(processInstanceId);
processSign.setSignType(signConfig.get().getSignType().getType());
processSign.setPendingMessageId(signConfig.get().getSignPendingProperty().getPendingMessageId());
if (CollectionUtils.isEmpty(docs)) {
processSign.setDocTemplate(Collections.emptyList());
processSign.setFileArchive(Collections.emptyList());
} else {
// 复制基础模板
List<SignFileDTO> docTemplates = copyTempTemplate(docs);
processSign.setDocTemplate(docTemplates);
List<SignFileDTO> archives = replaceTemplateVariable(docTemplates, processEngineConfiguration, processInstanceId);
processSign.setFileArchive(archives);
}
// 没有可用的文档但仍然记录库表
extAxProcessSignService.save(processSign);
}
private List<SignFileDTO> replaceTemplateVariable(List<SignFileDTO> docTemplates, ProcessEngineConfigurationImpl processEngineConfiguration, String processInstanceId) {
List<SignFileDTO> archives = new ArrayList<>();
List<VariableObjectDTO> wpsReplaceVariables = wpsUtil.getWpsReplaceVariables(processEngineConfiguration, processInstanceId);
docTemplates.forEach(template -> {
SignFileDTO signFileDTO = new SignFileDTO();
signFileDTO.setId(template.getId());
signFileDTO.setFileName(template.getFileName());
signFileDTO.setTemplateName(template.getTemplateName());
signFileDTO.setFileTag(template.getFileTag());
signFileDTO.setFileType(template.getFileType());
signFileDTO.setFileCode(template.getFileCode());
if (Objects.equals(template.getFileType(), FileTypeEnum.WORD) || Objects.equals(template.getFileType(), FileTypeEnum.EXCEL)) {
String fileKey = wpsUtil.wpsFileVariableReplace(wpsReplaceVariables, template.getFileCode(), null, template.getTemplateName() + template.getFileType().getSuffix());
signFileDTO.setFileKey(fileKey);
}
archives.add(signFileDTO);
});
return archives;
}
private List<SignFileDTO> copyTempTemplate(List<DocBaseVO> docs) {
List<SignFileDTO> files = new ArrayList<>();
docs.forEach(doc -> {
SignFileDTO signFileDTO = new SignFileDTO();
// 原始文档 ID
signFileDTO.setId(doc.getId());
signFileDTO.setFileName(doc.getFileName());
signFileDTO.setTemplateName(doc.getTemplateName());
signFileDTO.setFileTag(doc.getTag());
signFileDTO.setFileType(doc.getFileType());
switch (doc.getFileType()) {
case WORD:
case EXCEL:
CopyNodeRequest copy = new CopyNodeRequest();
copy.setCode(doc.getFileRelationId());
String fileCode = RpcExternalUtil.rpcProcessor(() -> docAnonymousApi.copy(copy), "复制文档", copy);
signFileDTO.setFileCode(fileCode);
break;
case HIPRINT:
Long newDocId = extAxModelDocService.cloneDoc(DocCloneDTO.builder().docId(doc.getId()).build(), true);
signFileDTO.setFileCode(String.valueOf(newDocId));
break;
case PDF:
break;
default:
break;
}
files.add(signFileDTO);
});
return files;
}
@Override
public int getOrder() {
return Integer.MIN_VALUE + 105;
}
}

View File

@ -38,7 +38,6 @@ import java.util.Optional;
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_ACTIVITY_RELATION_ASSIGNEE_LIST_INFO_SNAPSHOT;
import static cn.axzo.workflow.common.constant.BpmnConstants.NO_ASSIGNEE;
import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_ASSIGNEE_SKIP_FLAT;
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_STARTER;
import static cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper.getActivitySignature;
import static cn.axzo.workflow.core.engine.event.BizSpecifyAssigneeEventType.ADD_ASSIGNEE;
@ -66,9 +65,9 @@ public class MessagePushTaskEvent_103_Listener extends AbstractBpmnEventListener
public void onAssigned(DelegateTask delegateTask) {
log.info("MessagePushTaskEventListener#onAssigned...{}, assignee: {}, taskId: {}, processInstanceId:{}",
delegateTask.getTaskDefinitionKey(), delegateTask.getAssignee(), delegateTask.getId(), delegateTask.getProcessInstanceId());
if (Objects.equals(NODE_STARTER.getType(), delegateTask.getTaskDefinitionKey())) {
return;
}
// if (Objects.equals(NODE_STARTER.getType(), delegateTask.getTaskDefinitionKey())) {
// return;
// }
if (StringUtils.hasLength(delegateTask.getAssignee()) && delegateTask.getAssignee().contains(TASK_ASSIGNEE_SKIP_FLAT)) {
// 转交功能原审批人完成待办, 由于在流程引擎侧, 任务是不会在转交时立即结束, 但待办消息需要立即完成,
// 下面的 onDelete 事件根据测试情况,看是否需要过滤掉这种任务的"完成待办"事件的推送
@ -96,9 +95,9 @@ public class MessagePushTaskEvent_103_Listener extends AbstractBpmnEventListener
@Override
public void onDeleted(DelegateTask delegateTask) {
log.info("MessagePushTaskEventListener#onDeleted...{}, processInstanceId:{}", delegateTask.getTaskDefinitionKey(), delegateTask.getProcessInstanceId());
if (Objects.equals(NODE_STARTER.getType(), delegateTask.getTaskDefinitionKey())) {
return;
}
// if (Objects.equals(NODE_STARTER.getType(), delegateTask.getTaskDefinitionKey())) {
// return;
// }
pendingCompleteEvent(delegateTask);
log.info("MessagePushTaskEventListener#onDeleted...end: {}, processInstanceId:{}", delegateTask.getTaskDefinitionKey(), delegateTask.getProcessInstanceId());
}

View File

@ -180,14 +180,14 @@ public class RocketMqBpmnTaskEvent_102_Listener extends AbstractBpmnEventListene
Map<String, String> header = new HashMap<>();
if (StringUtils.hasText(dto.getProcessDefinitionKey())) {
if (log.isDebugEnabled()) {
log.debug("record process definition key: {}", dto.getProcessDefinitionKey());
log.info("record process definition key: {}", dto.getProcessDefinitionKey());
}
header.put(MQ_OWNERSHIP_PROCESS_DEFINITION_KEY, dto.getProcessDefinitionKey());
}
if (dto.getVariables().containsKey(PROCESS_OWNERSHIP_APPLICATION)) {
Object orDefault = dto.getVariables().getOrDefault(PROCESS_OWNERSHIP_APPLICATION, "");
if (Objects.nonNull(orDefault)) {
log.warn("record process ownership app name: {}", orDefault);
log.info("record process ownership app name: {}", orDefault);
header.put(MQ_OWNERSHIP_APPLICATION, orDefault.toString());
}
}

View File

@ -15,6 +15,8 @@ import cn.axzo.workflow.core.service.support.FlowNodeForecastService;
import cn.axzo.workflow.form.service.FormDefinitionService;
import cn.axzo.workflow.server.common.annotation.RepeatSubmit;
import cn.axzo.workflow.server.common.util.ShellUtil;
import cn.axzo.workflow.server.xxljob.EsIndexOperationJobHandler;
import cn.axzo.workflow.server.xxljob.SpecifyProcessInstanceSyncEsJobHandler;
import cn.azxo.framework.common.model.CommonResponse;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.FlowElement;
@ -96,6 +98,10 @@ public class TestController {
// private WorkflowManageService workflowManageService;
@Resource
private SpringProcessEngineConfiguration processEngineConfiguration;
@Resource
private EsIndexOperationJobHandler esIndexOperationJobHandler;
@Resource
private SpecifyProcessInstanceSyncEsJobHandler specifyProcessInstanceSyncEsJobHandler;
@RepeatSubmit
@GetMapping("/test")
@ -350,5 +356,17 @@ public class TestController {
String value = propertyPlaceholderHelper.replacePlaceholders(expression, resolver);
return CommonResponse.success(value);
}
@GetMapping("/es/index")
public CommonResponse<String> esIndex(@RequestParam String str) {
esIndexOperationJobHandler.execute(str);
return CommonResponse.success();
}
@GetMapping("/es/sync")
public CommonResponse<String> syncProcessInstanceToEs(@RequestParam String processInstanceId) {
specifyProcessInstanceSyncEsJobHandler.execute(processInstanceId);
return CommonResponse.success();
}
}

View File

@ -37,6 +37,7 @@ import org.flowable.form.api.FormInfo;
import org.flowable.form.api.FormRepositoryService;
import org.flowable.form.model.FormContainer;
import org.flowable.form.model.FormField;
import org.flowable.form.model.FormFieldTypes;
import org.flowable.form.model.SimpleFormModel;
import org.flowable.spring.SpringProcessEngineConfiguration;
import org.springframework.util.CollectionUtils;
@ -65,18 +66,37 @@ import java.util.stream.Collectors;
import static cn.axzo.workflow.common.code.FormModelRespCode.FORM_MODEL_NOT_EXISTS;
import static cn.axzo.workflow.common.constant.FormConstants.FORM_FIELD_TYPE_IMAGE;
import static cn.axzo.workflow.common.constant.FormConstants.FORM_FIELD_TYPE_INPUT;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_DEFINITION_KEY;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_DEFINITION_KEY_DESC;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_END_TIME;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_END_TIME_DESC;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_INITIATOR;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_INITIATOR_NAME;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_INITIATOR_NAME_DESC;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_INITIATOR_PHONE;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_INITIATOR_PHONE_DESC;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_INITIATOR_POSITION;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_INITIATOR_POSITION_DESC;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_INSTANCE_ID;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_INSTANCE_ID_DESC;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_LOGS;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_LOGS_DESC;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_LOG_ACTIVITY_NAME;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_LOG_ACTIVITY_NAME_DESC;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_LOG_ADVICE;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_LOG_ADVICE_DESC;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_LOG_APPROVER_NAME;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_LOG_APPROVER_NAME_DESC;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_LOG_OPERATION_TIME;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_LOG_OPERATION_TIME_DESC;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_LOG_POSITION;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_LOG_POSITION_DESC;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_LOG_SIGNATURE;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_LOG_SIGNATURE_DESC;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_LOG_UNIT;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_LOG_UNIT_DESC;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_START_TIME;
import static cn.axzo.workflow.common.constant.VariableConstants.PRINT_VAR_PROCESS_START_TIME_DESC;
import static cn.axzo.workflow.common.enums.PrintFieldCategoryEnum.form;
import static cn.axzo.workflow.common.enums.PrintFieldCategoryEnum.sign;
import static cn.axzo.workflow.common.enums.PrintFieldCategoryEnum.signature;
@ -126,6 +146,7 @@ public class PrintAdminController implements PrintAdminApi {
/**
* 获取打印模板中可打印的字段, 或者是 WPS 模板中可配置的变量字段
*
* @param dto
* @return
*/
@ -147,15 +168,8 @@ public class PrintAdminController implements PrintAdminApi {
.setCode(field.getId())
.setFieldCategoryType(form)
.setFieldFormType(field.getType());
if (field instanceof FormContainer) {
FormContainer container = (FormContainer) field;
printFieldDTO.setAttributes(container.getFields().get(0)
.stream().map(subField -> new FieldAttributeDTO()
.setCode(subField.getId())
.setFieldFormType(subField.getType())
.setName(subField.getName()))
.collect(Collectors.toList()));
}
switchAmount(field, printFieldDTO);
switchFormContainer(field, printFieldDTO);
return printFieldDTO;
}
).collect(Collectors.toList()));
@ -176,6 +190,38 @@ public class PrintAdminController implements PrintAdminApi {
return success(printFields);
}
// 自定义组件类型的额外处理
private static void switchFormContainer(FormField field, PrintFieldDTO printFieldDTO) {
if (field instanceof FormContainer) {
FormContainer container = (FormContainer) field;
printFieldDTO.setAttributes(container.getFields().get(0)
.stream().map(subField -> new FieldAttributeDTO()
.setCode(subField.getId())
.setFieldFormType(subField.getType())
.setName(subField.getName()))
.collect(Collectors.toList()));
}
}
// 金额组件类型的额外处理
private static void switchAmount(FormField field, PrintFieldDTO printFieldDTO) {
if (Objects.equals(field.getType(), FormFieldTypes.AMOUNT)) {
List<FieldAttributeDTO> attributes = new ArrayList<>();
attributes.add(new FieldAttributeDTO()
.setCode("standardNumerals")
.setName("小写")
.setFieldFormType(FORM_FIELD_TYPE_INPUT)
);
if (Boolean.parseBoolean(field.getParam("toUpper").toString())) {
attributes.add(new FieldAttributeDTO()
.setCode("uppercaseNumerals")
.setName("大写")
.setFieldFormType(FORM_FIELD_TYPE_INPUT));
}
printFieldDTO.setAttributes(attributes);
}
}
private List<PrintFieldDTO> generateDictVariables(List<PrintFieldDTO> printFields, String processDefinitionKey) {
if (CollectionUtils.isEmpty(printFields)) {
printFields = new ArrayList<>();
@ -213,22 +259,22 @@ public class PrintAdminController implements PrintAdminApi {
private List<PrintFieldDTO> generateSystemFields(String processDefinitionKey, String tenantId) {
List<PrintFieldDTO> printFields = new ArrayList<>();
printFields.add(new PrintFieldDTO().setName("业务名称").setCode("processDefinitionKey").setFieldCategoryType(system).setFieldFormType("input"));
printFields.add(new PrintFieldDTO().setName("审批编号").setCode("processInstanceId").setFieldCategoryType(system).setFieldFormType("input"));
printFields.add(new PrintFieldDTO().setName("发起时间").setCode("startTime").setFieldCategoryType(system).setFieldFormType("input"));
printFields.add(new PrintFieldDTO().setName("审批结束时间").setCode("endTime").setFieldCategoryType(system).setFieldFormType("input"));
printFields.add(new PrintFieldDTO().setName("发起人姓名").setCode("initiatorName").setFieldCategoryType(system).setFieldFormType("input"));
printFields.add(new PrintFieldDTO().setName("发起人岗位").setCode("initiatorPosition").setFieldCategoryType(system).setFieldFormType("input"));
printFields.add(new PrintFieldDTO().setName("发起人联系方式").setCode("initiatorPhone").setFieldCategoryType(system).setFieldFormType("input"));
printFields.add(new PrintFieldDTO().setName("审批日志").setCode("processLogs").setFieldCategoryType(system).setFieldFormType("table")
printFields.add(new PrintFieldDTO().setName(PRINT_VAR_PROCESS_DEFINITION_KEY_DESC).setCode(PRINT_VAR_PROCESS_DEFINITION_KEY).setFieldCategoryType(system).setFieldFormType("input"));
printFields.add(new PrintFieldDTO().setName(PRINT_VAR_PROCESS_INSTANCE_ID_DESC).setCode(PRINT_VAR_PROCESS_INSTANCE_ID).setFieldCategoryType(system).setFieldFormType("input"));
printFields.add(new PrintFieldDTO().setName(PRINT_VAR_PROCESS_START_TIME_DESC).setCode(PRINT_VAR_PROCESS_START_TIME).setFieldCategoryType(system).setFieldFormType("input"));
printFields.add(new PrintFieldDTO().setName(PRINT_VAR_PROCESS_END_TIME_DESC).setCode(PRINT_VAR_PROCESS_END_TIME).setFieldCategoryType(system).setFieldFormType("input"));
printFields.add(new PrintFieldDTO().setName(PRINT_VAR_PROCESS_INITIATOR_NAME_DESC).setCode(PRINT_VAR_PROCESS_INITIATOR_NAME).setFieldCategoryType(system).setFieldFormType("input"));
printFields.add(new PrintFieldDTO().setName(PRINT_VAR_PROCESS_INITIATOR_POSITION_DESC).setCode(PRINT_VAR_PROCESS_INITIATOR_POSITION).setFieldCategoryType(system).setFieldFormType("input"));
printFields.add(new PrintFieldDTO().setName(PRINT_VAR_PROCESS_INITIATOR_PHONE_DESC).setCode(PRINT_VAR_PROCESS_INITIATOR_PHONE).setFieldCategoryType(system).setFieldFormType("input"));
printFields.add(new PrintFieldDTO().setName(PRINT_VAR_PROCESS_LOGS_DESC).setCode(PRINT_VAR_PROCESS_LOGS).setFieldCategoryType(system).setFieldFormType("table")
.setAttributes(Lists.newArrayList(
new FieldAttributeDTO().setCode("activityName").setName("节点名称"),
new FieldAttributeDTO().setCode("approverName").setName("审批人"),
new FieldAttributeDTO().setCode("unit").setName("单位"),
new FieldAttributeDTO().setCode("position").setName("岗位"),
new FieldAttributeDTO().setCode("advice").setName("审批意见"),
new FieldAttributeDTO().setCode("operationTime").setName("审批时间"),
new FieldAttributeDTO().setCode("signature").setName("签名")
new FieldAttributeDTO().setCode(PRINT_VAR_PROCESS_LOG_ACTIVITY_NAME).setName(PRINT_VAR_PROCESS_LOG_ACTIVITY_NAME_DESC),
new FieldAttributeDTO().setCode(PRINT_VAR_PROCESS_LOG_APPROVER_NAME).setName(PRINT_VAR_PROCESS_LOG_APPROVER_NAME_DESC),
new FieldAttributeDTO().setCode(PRINT_VAR_PROCESS_LOG_UNIT).setName(PRINT_VAR_PROCESS_LOG_UNIT_DESC),
new FieldAttributeDTO().setCode(PRINT_VAR_PROCESS_LOG_POSITION).setName(PRINT_VAR_PROCESS_LOG_POSITION_DESC),
new FieldAttributeDTO().setCode(PRINT_VAR_PROCESS_LOG_ADVICE).setName(PRINT_VAR_PROCESS_LOG_ADVICE_DESC),
new FieldAttributeDTO().setCode(PRINT_VAR_PROCESS_LOG_OPERATION_TIME).setName(PRINT_VAR_PROCESS_LOG_OPERATION_TIME_DESC),
new FieldAttributeDTO().setCode(PRINT_VAR_PROCESS_LOG_SIGNATURE).setName(PRINT_VAR_PROCESS_LOG_SIGNATURE_DESC)
)));
// 电子签名
@ -241,8 +287,8 @@ public class PrintAdminController implements PrintAdminApi {
.setCode(activity.getId())
.setFieldCategoryType(signature)
.setFieldFormType("signature")
.setAttributes(Lists.newArrayList(new FieldAttributeDTO().setCode("signature").setName("电子签名"),
new FieldAttributeDTO().setCode("advice").setName("审批意见"))))
.setAttributes(Lists.newArrayList(new FieldAttributeDTO().setCode(PRINT_VAR_PROCESS_LOG_SIGNATURE).setName(PRINT_VAR_PROCESS_LOG_SIGNATURE_DESC).setFieldFormType(FORM_FIELD_TYPE_INPUT),
new FieldAttributeDTO().setCode(PRINT_VAR_PROCESS_LOG_ADVICE).setName(PRINT_VAR_PROCESS_LOG_ADVICE_DESC).setFieldFormType(FORM_FIELD_TYPE_INPUT))))
.collect(Collectors.toList())
);
@ -251,6 +297,7 @@ public class PrintAdminController implements PrintAdminApi {
/**
* 获取指定流程下用于替换打印的相关变量
*
* @param processInstanceId
* @return
*/

View File

@ -46,6 +46,9 @@ public class ProcessConfigController implements ProcessConfigApi {
.setBtnKey(buttonEnum.getBtnKey())
.setBtnName(buttonEnum.getBtnName())
.setChecked(false)
.setDisabled(false)).collect(Collectors.toList()));
.setDisabled(false)
.setSupportBizType(buttonEnum.getSupportBizType())
)
.collect(Collectors.toList()));
}
}

View File

@ -63,7 +63,7 @@ public class ElasticSearchBatchSyncListener {
// consumer.setConsumeThreadMax(1);
// consumer.setConsumeThreadMin(1);
consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
log.warn("batch get msg size: {}", msgs.size());
log.info("batch get msg size: {}", msgs.size());
if(CollectionUtils.isEmpty(msgs)) {
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
@ -77,7 +77,7 @@ public class ElasticSearchBatchSyncListener {
idSet.add(processInstanceId);
}
}
log.warn("deduplication ids size: {}", idSet.size());
log.info("deduplication ids size: {}", idSet.size());
idSet.forEach(this::sync);
} catch (Exception e) {
return ConsumeConcurrentlyStatus.RECONSUME_LATER;

View File

@ -30,7 +30,7 @@ spring:
nacos:
config:
# server-addr: ${NACOS_HOST:nacos.mybiwin.top}:${NACOS_PORT:9090}
server-addr: ${NACOS_HOST:https://dev-nacos.axzo.cn}:${NACOS_PORT:443}
server-addr: ${NACOS_HOST:https://dev-nacos-hs.axzo.cn}:${NACOS_PORT:443}
file-extension: yaml
# namespace: ${NACOS_NAMESPACE_ID:1b5d2a22-b340-4503-8464-7d7fc2059d39}
namespace: ${NACOS_NAMESPACE_ID:f82179f1-81a9-41a1-a489-4f9ab5660a6e}
@ -44,7 +44,7 @@ spring:
cloud:
nacos:
config:
server-addr: ${NACOS_HOST:https://dev-nacos.axzo.cn}:${NACOS_PORT:443}
server-addr: ${NACOS_HOST:https://dev-nacos-hs.axzo.cn}:${NACOS_PORT:443}
file-extension: yaml
namespace: ${NACOS_NAMESPACE_ID:35eada10-9574-4db8-9fea-bc6a4960b6c7}

View File

@ -1,54 +1,58 @@
package cn.axzo.workflow.starter.api;
import cn.axzo.workflow.common.annotation.InvokeMode;
import cn.axzo.workflow.common.model.dto.SimpleDocDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BeforeProcessInstanceCreateDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceAbortDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCancelDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCarbonCopyDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCreateDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceLogQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.doc.ApproverReadStatusDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.doc.ChangeApproverReadStatusDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.doc.ProcessDocQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivitySetAssigneeDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivityTriggerDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnNodeBackSystemOperateDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnOptionalNodeDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnRobotTaskCompleteDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnRobotTaskCreateDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAuditDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAuditWithFormDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskBackAuditDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskButtonSearchDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskCommentDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskCountersignDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskTransferDTO;
import cn.axzo.workflow.common.model.request.form.instance.FormVariablesUpdateDTO;
import cn.axzo.workflow.common.model.response.bpmn.BatchOperationResultVO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceLogVO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceVO;
import cn.axzo.workflow.common.model.response.bpmn.process.NodesByModelVO;
import cn.axzo.workflow.common.model.response.bpmn.process.doc.DocPendingVO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskButtonVo;
import cn.axzo.workflow.common.util.ThreadUtil;
import cn.axzo.workflow.starter.feign.ext.WorkflowEngineStarterFeignConfiguration;
import cn.axzo.workflow.common.util.ThreadUtil;
import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.ASYNC;
import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.SYNC;
import cn.axzo.workflow.client.annotation.WorkflowEngineFeignClient;
import cn.axzo.workflow.common.annotation.InvokeMode;
import cn.axzo.workflow.common.annotation.Manageable;
import cn.axzo.workflow.common.model.request.bpmn.activity.BpmnActivityTimeoutCallbackDTO;
import cn.axzo.workflow.common.model.request.bpmn.activity.BpmnActivityTimeoutTriggerDTO;
import cn.azxo.framework.common.model.CommonResponse;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import javax.annotation.Nullable;
import javax.validation.constraints.NotBlank;
import cn.axzo.workflow.common.model.dto.SignFileDTO;
import cn.axzo.workflow.common.model.dto.SimpleDocDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BeforeProcessInstanceCreateDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceAbortDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceAdminPageReqVO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCancelDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCarbonCopyDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCheckApproverDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCreateDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceLogQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceMyPageReqVO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.SuperBpmnProcessInstanceCancelDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.doc.ApproverReadStatusDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.doc.ChangeApproverReadStatusDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.doc.ProcessDocQueryDTO;
import cn.axzo.workflow.common.model.request.form.instance.FormVariablesUpdateDTO;
import cn.axzo.workflow.common.model.response.BpmPageResult;
import cn.axzo.workflow.common.model.response.bpmn.BatchOperationResultVO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceAdminPageItemVO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceLogVO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstancePageItemVO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceVO;
import cn.axzo.workflow.common.model.response.bpmn.process.NodesByModelVO;
import cn.axzo.workflow.common.model.response.bpmn.process.ProcessNodeDetailVO;
import cn.axzo.workflow.common.model.response.bpmn.process.doc.DocPendingVO;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PutMapping;
import javax.annotation.Nullable;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Map;
import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.ASYNC;
import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.SYNC;
import cn.axzo.workflow.common.model.request.bpmn.task.*;
import cn.axzo.workflow.common.model.response.bpmn.task.*;
import javax.validation.constraints.NotEmpty;
/**
* Workflow Engine Starter Core Service
@ -93,152 +97,6 @@ public interface WorkflowCoreService {
@Operation(summary = "业务节点设置审批人,不支持重复调用设置审批人,需一次性传入所有审批人")
Boolean setAssignee(@Validated @RequestBody BpmnActivitySetAssigneeDTO dto);
/**
* 同意
*
* <pre>
* MQ 触发规则:
* 1. 当前审批任务会依次触发 process-task-completed process-task-deleted 事件(如果有下一级审批,则会触发第 2.1 点中的事件,
* 如果当前审核任务最后一级审批,则会触发第 2.2 点中的事件)
* 2.1. 下一级审批任务会依次触发 process-task-assigned process-task-created 事件
* 2.2. 流程实例正常结束会触发 process-instance-completed 事件
* </pre>
*/
@Operation(summary = "同意MQ 触发规则:1. 当前审批任务会依次触发 process-task-completed 和 process-task-deleted 事件(如果有下一级审批,则会触发第 2.1 点中的事件,如果当前审核任务最后一级审批,则会触发第 2.2 点中的事件)2.1. 下一级审批任务会依次触发 process-task-assigned 和 process-task-created 事件2.2. 流程实例正常结束会触发 process-instance-completed 事件")
@PostMapping("/api/process/task/approve")
Boolean approveTask(@Validated @RequestBody BpmnTaskAuditDTO dto);
/**
* 同意时并提交表单数据
*
* @param dto
* @return
*/
@Operation(summary = "同意时并提交表单")
@PostMapping("/api/process/task/form/approve")
Boolean approveTaskWithForm(@Validated @RequestBody BpmnTaskAuditWithFormDTO dto);
/**
* 批量同意
*
* @param dtos
* @return
*/
@Operation(summary = "批量同意")
@PostMapping("/api/process/task/batch/approve")
BatchOperationResultVO batchApproveTask(@Validated @RequestBody List<BpmnTaskAuditDTO> dtos);
/**
* 获取当前节点可回退节点选项列表
*
* @param taskId 当前任务id
* @return 可以回退节点列表
*/
@Operation(summary = "获取当前节点可回退节点选项列表")
@GetMapping("/api/process/task/back/optional/nodes")
List<BpmnOptionalNodeDTO> getBackOptionalNodes(@RequestParam @NotBlank(message = "任务id不能为空") String taskId);
/**
* 回退到指定节点
*
* @param dto
* @return
*/
@Operation(summary = "回退")
@PostMapping("/api/process/task/back")
Boolean backTask(@Validated @RequestBody BpmnTaskBackAuditDTO dto);
/**
* 用于系统内部操作跳转到指定节点
* @param dto 请求参数
* @return 是否成功
*/
@Operation(summary = "系统操作回退任务到指定节点")
@PostMapping("/api/process/task/system/back")
Boolean systemBackTask(@Validated @RequestBody BpmnNodeBackSystemOperateDTO dto);
/**
* 驳回
*
* <pre>
* MQ 触发规则:
* 1. 当前审批任务会触发 process-task-deleted 事件
* 2. 当前流程实例会触发 process-instance-rejected 事件
* </pre>
*/
@Operation(summary = "驳回MQ 触发规则1. 当前审批任务会触发 process-task-deleted 事件, 2. 当前流程实例会触发 process-instance-rejected 事件")
@PostMapping("/api/process/task/reject")
Boolean rejectTask(@Validated @RequestBody BpmnTaskAuditDTO dto);
/**
* 批量驳回
*
* @param dtos 批量请求参数
* @return
*/
@PostMapping("/api/process/task/batch/reject")
BatchOperationResultVO batchRejectTask(@Validated @RequestBody List<BpmnTaskAuditDTO> dtos);
/**
* 转交
*
* @param dto
* @return
*/
@Operation(summary = "直接修改审批任务的审批人")
@PostMapping("/api/process/task/transfer")
Boolean transferTask(@Validated @RequestBody BpmnTaskTransferDTO dto);
/**
* 批量转交
*
* @param dtos
* @return
*/
@Operation(summary = "批量修改审批任务的审批人")
@PostMapping("/api/process/task/batch/transfer")
BatchOperationResultVO batchTransferTask(@Validated @RequestBody List<BpmnTaskTransferDTO> dtos);
/**
* 评论
*
* @param dto 评论请求参数
* @return
*/
@Operation(summary = "审批流程评论")
@PostMapping("/api/process/task/comment")
Boolean commentTask(@Validated @RequestBody BpmnTaskCommentDTO dto);
/**
* 加签
*
* @param dto 加签请求参数
* @return
*/
@Operation(summary = "审批流程加签")
@PostMapping("/api/process/task/countersign")
Boolean countersignTask(@Validated @RequestBody BpmnTaskCountersignDTO dto);
/**
* 暂停流程任务,并创建机器人节点,等待业务推动
*
* @param dto
* @return 返回机器人节点任务 ID
*/
@Operation(summary = "创建机器人节点, 暂停流程任务")
@PostMapping("/api/process/task/robot/create")
String createRobotTask(@Validated @RequestBody BpmnRobotTaskCreateDTO dto);
/**
* 完成机器人节点
*
* @param dto
* @return
*/
@Operation(summary = "完成机器人节点, 继续流程任务")
@PostMapping("/api/process/task/robot/complete")
Boolean completeRobotTask(@Validated @RequestBody BpmnRobotTaskCompleteDTO dto);
/**
* 创建流程前的节点列表
* 用于发起人自选
@ -397,6 +255,162 @@ public interface WorkflowCoreService {
@InvokeMode(SYNC)
Boolean approveReadStatusChange(@Validated @RequestBody ChangeApproverReadStatusDTO dto);
/**
* 获取签署业务流程最后替换的文档 fileKey 集合
*
* @return
*/
@Operation(summary = "获取签署业务流程最后替换的文档 fileKey 集合")
@GetMapping("/api/process/instance/final/docs")
@InvokeMode(SYNC)
List<SignFileDTO> getProcessInstanceFinalDocs(@NotBlank(message = "流程实例 ID 不能为空") @RequestParam(required = false) String processInstanceId);
/**
* 同意
*
* <pre>
* MQ 触发规则:
* 1. 当前审批任务会依次触发 process-task-completed process-task-deleted 事件(如果有下一级审批,则会触发第 2.1 点中的事件,
* 如果当前审核任务最后一级审批,则会触发第 2.2 点中的事件)
* 2.1. 下一级审批任务会依次触发 process-task-assigned process-task-created 事件
* 2.2. 流程实例正常结束会触发 process-instance-completed 事件
* </pre>
*/
@Operation(summary = "同意MQ 触发规则:1. 当前审批任务会依次触发 process-task-completed 和 process-task-deleted 事件(如果有下一级审批,则会触发第 2.1 点中的事件,如果当前审核任务最后一级审批,则会触发第 2.2 点中的事件)2.1. 下一级审批任务会依次触发 process-task-assigned 和 process-task-created 事件2.2. 流程实例正常结束会触发 process-instance-completed 事件")
@PostMapping("/api/process/task/approve")
Boolean approveTask(@Validated @RequestBody BpmnTaskAuditDTO dto);
/**
* 同意时并提交表单数据
*
* @param dto
* @return
*/
@Operation(summary = "同意时并提交表单")
@PostMapping("/api/process/task/form/approve")
Boolean approveTaskWithForm(@Validated @RequestBody BpmnTaskAuditWithFormDTO dto);
/**
* 批量同意
*
* @param dtos
* @return
*/
@Operation(summary = "批量同意")
@PostMapping("/api/process/task/batch/approve")
BatchOperationResultVO batchApproveTask(@Validated @RequestBody List<BpmnTaskAuditDTO> dtos);
/**
* 获取当前节点可回退节点选项列表
*
* @param taskId 当前任务id
* @return 可以回退节点列表
*/
@Operation(summary = "获取当前节点可回退节点选项列表")
@GetMapping("/api/process/task/back/optional/nodes")
List<BpmnOptionalNodeDTO> getBackOptionalNodes(@RequestParam @NotBlank(message = "任务id不能为空") String taskId);
/**
* 回退到指定节点
*
* @param dto
* @return
*/
@Operation(summary = "回退")
@PostMapping("/api/process/task/back")
Boolean backTask(@Validated @RequestBody BpmnTaskBackAuditDTO dto);
/**
* 用于系统内部操作跳转到指定节点
* @param dto 请求参数
* @return 是否成功
*/
@Operation(summary = "系统操作回退任务到指定节点")
@PostMapping("/api/process/task/system/back")
Boolean systemBackTask(@Validated @RequestBody BpmnNodeBackSystemOperateDTO dto);
/**
* 驳回
*
* <pre>
* MQ 触发规则:
* 1. 当前审批任务会触发 process-task-deleted 事件
* 2. 当前流程实例会触发 process-instance-rejected 事件
* </pre>
*/
@Operation(summary = "驳回MQ 触发规则1. 当前审批任务会触发 process-task-deleted 事件, 2. 当前流程实例会触发 process-instance-rejected 事件")
@PostMapping("/api/process/task/reject")
Boolean rejectTask(@Validated @RequestBody BpmnTaskAuditDTO dto);
/**
* 批量驳回
*
* @param dtos 批量请求参数
* @return
*/
@PostMapping("/api/process/task/batch/reject")
BatchOperationResultVO batchRejectTask(@Validated @RequestBody List<BpmnTaskAuditDTO> dtos);
/**
* 转交
*
* @param dto
* @return
*/
@Operation(summary = "直接修改审批任务的审批人")
@PostMapping("/api/process/task/transfer")
Boolean transferTask(@Validated @RequestBody BpmnTaskTransferDTO dto);
/**
* 批量转交
*
* @param dtos
* @return
*/
@Operation(summary = "批量修改审批任务的审批人")
@PostMapping("/api/process/task/batch/transfer")
BatchOperationResultVO batchTransferTask(@Validated @RequestBody List<BpmnTaskTransferDTO> dtos);
/**
* 评论
*
* @param dto 评论请求参数
* @return
*/
@Operation(summary = "审批流程评论")
@PostMapping("/api/process/task/comment")
Boolean commentTask(@Validated @RequestBody BpmnTaskCommentDTO dto);
/**
* 加签
*
* @param dto 加签请求参数
* @return
*/
@Operation(summary = "审批流程加签")
@PostMapping("/api/process/task/countersign")
Boolean countersignTask(@Validated @RequestBody BpmnTaskCountersignDTO dto);
/**
* 暂停流程任务,并创建机器人节点,等待业务推动
*
* @param dto
* @return 返回机器人节点任务 ID
*/
@Operation(summary = "创建机器人节点, 暂停流程任务")
@PostMapping("/api/process/task/robot/create")
String createRobotTask(@Validated @RequestBody BpmnRobotTaskCreateDTO dto);
/**
* 完成机器人节点
*
* @param dto
* @return
*/
@Operation(summary = "完成机器人节点, 继续流程任务")
@PostMapping("/api/process/task/robot/complete")
Boolean completeRobotTask(@Validated @RequestBody BpmnRobotTaskCompleteDTO dto);
/**
* 强制使用异步模式调用该方法请在调用真实方法前调用该方法
* <pre>

View File

@ -83,6 +83,10 @@ public class ComplexInvokeClient implements Client {
@Override
public Response execute(Request request, Request.Options options) throws IOException {
log.debug("ComplexInvokeClient execute... Url: {}", request.url());
if (useMetaFeign(request)) {
log.debug("use meta feign client: {}", request.url());
return feignClient.execute(request, options);
}
RpcInvokeModeEnum currentInvokeModeEnum = getInvokeMode(request);
log.debug("[{}] invoke url: {}", currentInvokeModeEnum, request.url());
if (Objects.equals(SYNC, currentInvokeModeEnum)) {
@ -91,6 +95,10 @@ public class ComplexInvokeClient implements Client {
return asyncInvoke(request, options);
}
private boolean useMetaFeign(Request request) {
return starterProperties.getMetaFeign() && request.requestTemplate().feignTarget().type().getName().contains("cn.axzo.workflow.client.feign");
}
/**
* 发送 RPC 调用动作的 MQ 事件
*
@ -117,12 +125,12 @@ public class ComplexInvokeClient implements Client {
Map<String, Collection<String>> headers = request.headers();
headers.forEach((k, v) -> log.debug("ComplexInvokeClient Header: {} = {}", k, v));
return Response.builder()
.status(HttpStatus.OK.value())
.reason(HttpStatus.OK.getReasonPhrase())
.headers(headers)
.request(request)
.body(body)
.build();
.status(HttpStatus.OK.value())
.reason(HttpStatus.OK.getReasonPhrase())
.headers(headers)
.request(request)
.body(body)
.build();
} catch (BeansException e) {
return feignClient.execute(request, options);
}
@ -218,7 +226,7 @@ public class ComplexInvokeClient implements Client {
private RpcInvokeModeEnum getInvokeMode(Request request) {
Collection<String> invokeModel = request.headers().getOrDefault(STARTER_INVOKE_MODE,
Collections.singletonList(starterProperties.getInvokeMode().name()));
Collections.singletonList(starterProperties.getInvokeMode().name()));
if (CollectionUtils.isEmpty(invokeModel)) {
return starterProperties.getInvokeMode();
} else if (invokeModel.size() > 1) {