feat(REQ-3004) - 集成表单引擎测试
This commit is contained in:
parent
7edfd1e0a0
commit
d4e1b97a8a
@ -4,9 +4,13 @@ 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.form.definition.FormDefinitionSearchDTO;
|
||||
import cn.axzo.workflow.common.model.request.form.definition.StartFormSearchDTO;
|
||||
import cn.axzo.workflow.common.model.request.form.instance.FormDetailDTO;
|
||||
import cn.axzo.workflow.common.model.request.form.instance.FormInstanceSearchDTO;
|
||||
import cn.axzo.workflow.common.model.request.form.instance.FormSearchDTO;
|
||||
import cn.axzo.workflow.common.model.response.form.FormVO;
|
||||
import cn.axzo.workflow.common.model.response.form.definition.FormDefinitionVO;
|
||||
import cn.axzo.workflow.common.model.response.form.instance.FormInstanceVO;
|
||||
import cn.azxo.framework.common.model.CommonResponse;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -30,7 +34,11 @@ public interface FormInstanceApi {
|
||||
@InvokeMode(SYNC)
|
||||
CommonResponse<List<FormVO>> formPage(@Validated @RequestBody FormSearchDTO dto);
|
||||
|
||||
@PostMapping("/api/form/instance/init")
|
||||
@PostMapping("/api/form/instance/start/form")
|
||||
@InvokeMode(SYNC)
|
||||
CommonResponse<FormDefinitionVO> getFormDefinition(@Validated @RequestBody FormDefinitionSearchDTO dto);
|
||||
CommonResponse<FormDefinitionVO> getFormDefinition(@Validated @RequestBody StartFormSearchDTO dto);
|
||||
|
||||
@PostMapping("/api/form/instance/get")
|
||||
@InvokeMode(SYNC)
|
||||
CommonResponse<FormInstanceVO> getFormInstance(@Validated @RequestBody FormDetailDTO dto);
|
||||
}
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
package cn.axzo.workflow.common.code;
|
||||
|
||||
import cn.axzo.framework.domain.web.code.IModuleRespCode;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 表单实例相关响应码
|
||||
*
|
||||
* @author wangli
|
||||
* @since 2024-11-13 14:34
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum FormInstanceRespCode implements IModuleRespCode {
|
||||
FORM_PARAM_ERROR("001", "流程实例 ID 和任务 ID 不能都为空"),
|
||||
FORM_FIELD_NOT_FOUND("002", "无法获取全量表单字段权限配置信息"),
|
||||
|
||||
;
|
||||
|
||||
private final String code;
|
||||
private final String message;
|
||||
|
||||
@Override
|
||||
public String getModuleCode() {
|
||||
return "13";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProjectCode() {
|
||||
return "998";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -7,5 +7,14 @@ package cn.axzo.workflow.common.constant;
|
||||
* @since 2024-11-05 10:20
|
||||
*/
|
||||
public interface FormConstants {
|
||||
String DRAFT_CATEGORY = "draft";
|
||||
|
||||
String FIELD_PROPERTY_REQUIRED = "required";
|
||||
|
||||
String FIELD_PROPERTY_EDITABLE = "editable";
|
||||
|
||||
String FIELD_PROPERTY_READONLY = "readonly";
|
||||
|
||||
String FIELD_PROPERTY_HIDDEN = "hidden";
|
||||
|
||||
String FIELD_PROPERTY_DEFAULT_VALUE= "defaultValue";
|
||||
}
|
||||
|
||||
@ -1,60 +1,60 @@
|
||||
package cn.axzo.workflow.common.model.request.form;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 表单字段权限配置
|
||||
* <p>
|
||||
* 发起人
|
||||
* 只读 可编辑必填 可编辑非必填 隐藏
|
||||
* 1 1 1 1 字段 1
|
||||
* 1 0 0 1 字段 2
|
||||
*
|
||||
* @author wangli
|
||||
* @since 2024-11-06 18:19
|
||||
*/
|
||||
@ApiModel("JSON 版本的 BPMN 协议模型中的表单字段权限")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
public class FormFieldPermissionConf implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 发起人的表单字段权限
|
||||
*/
|
||||
@ApiModelProperty(value = "发起人的表单字段权限")
|
||||
private List<FormPermissionMetaInfo> initiator;
|
||||
|
||||
/**
|
||||
* 审批人的表单字段权限
|
||||
*/
|
||||
@ApiModelProperty(value = "审批人的表单字段权限")
|
||||
private List<FormPermissionMetaInfo> current;
|
||||
|
||||
/**
|
||||
* 历史审批人的表单字段权限
|
||||
*/
|
||||
@ApiModelProperty(value = "历史审批人的表单字段权限")
|
||||
private List<FormPermissionMetaInfo> history;
|
||||
|
||||
/**
|
||||
* 抄送人的表单字段权限
|
||||
*/
|
||||
@ApiModelProperty(value = "抄送人的表单字段权限")
|
||||
private List<FormPermissionMetaInfo> carbonCopy;
|
||||
|
||||
/**
|
||||
* 管理员的字段权限
|
||||
*/
|
||||
@ApiModelProperty(value = "管理员的字段权限")
|
||||
private List<FormPermissionMetaInfo> admin;
|
||||
|
||||
}
|
||||
//package cn.axzo.workflow.common.model.request.form;
|
||||
//
|
||||
//import io.swagger.annotations.ApiModel;
|
||||
//import io.swagger.annotations.ApiModelProperty;
|
||||
//import lombok.Data;
|
||||
//import lombok.NoArgsConstructor;
|
||||
//import lombok.experimental.Accessors;
|
||||
//
|
||||
//import java.io.Serializable;
|
||||
//import java.util.List;
|
||||
//
|
||||
///**
|
||||
// * 表单字段权限配置
|
||||
// * <p>
|
||||
// * 发起人
|
||||
// * 只读 可编辑必填 可编辑非必填 隐藏
|
||||
// * 1 1 1 1 字段 1
|
||||
// * 1 0 0 1 字段 2
|
||||
// *
|
||||
// * @author wangli
|
||||
// * @since 2024-11-06 18:19
|
||||
// */
|
||||
//@ApiModel("JSON 版本的 BPMN 协议模型中的表单字段权限")
|
||||
//@Data
|
||||
//@NoArgsConstructor
|
||||
//@Accessors(chain = true)
|
||||
//public class FormFieldPermissionConf implements Serializable {
|
||||
// private static final long serialVersionUID = 1L;
|
||||
//
|
||||
// /**
|
||||
// * 发起人的表单字段权限
|
||||
// */
|
||||
// @ApiModelProperty(value = "发起人的表单字段权限")
|
||||
// private List<FormPermissionMetaInfo> initiator;
|
||||
//
|
||||
// /**
|
||||
// * 审批人的表单字段权限
|
||||
// */
|
||||
// @ApiModelProperty(value = "审批人的表单字段权限")
|
||||
// private List<FormPermissionMetaInfo> current;
|
||||
//
|
||||
// /**
|
||||
// * 历史审批人的表单字段权限
|
||||
// */
|
||||
// @ApiModelProperty(value = "历史审批人的表单字段权限")
|
||||
// private List<FormPermissionMetaInfo> history;
|
||||
//
|
||||
// /**
|
||||
// * 抄送人的表单字段权限
|
||||
// */
|
||||
// @ApiModelProperty(value = "抄送人的表单字段权限")
|
||||
// private List<FormPermissionMetaInfo> carbonCopy;
|
||||
//
|
||||
// /**
|
||||
// * 管理员的字段权限
|
||||
// */
|
||||
// @ApiModelProperty(value = "管理员的字段权限")
|
||||
// private List<FormPermissionMetaInfo> admin;
|
||||
//
|
||||
//}
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
package cn.axzo.workflow.common.model.request.form;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
@ -12,7 +15,9 @@ import java.io.Serializable;
|
||||
* @since 2024-11-07 11:09
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class FormPermissionMetaInfo implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ -29,7 +34,7 @@ public class FormPermissionMetaInfo implements Serializable {
|
||||
/**
|
||||
* 可编辑非必填
|
||||
*/
|
||||
private Boolean editable = true;
|
||||
private Boolean editable = false;
|
||||
|
||||
/**
|
||||
* 只读
|
||||
@ -39,5 +44,28 @@ public class FormPermissionMetaInfo implements Serializable {
|
||||
/**
|
||||
* 隐藏
|
||||
*/
|
||||
private Boolean hidden = false;
|
||||
private Boolean hidden = true;
|
||||
|
||||
// 将对象的属性转换为对应的整数表示
|
||||
public int toBinary() {
|
||||
int binaryValue = 0;
|
||||
binaryValue |= (editable? 1 : 0) << 3;
|
||||
binaryValue |= (required? 1 : 0) << 2;
|
||||
binaryValue |= (readonly? 1 : 0) << 1;
|
||||
binaryValue |= (hidden? 1 : 0);
|
||||
return binaryValue;
|
||||
}
|
||||
|
||||
// 从整数表示还原出对象
|
||||
public static FormPermissionMetaInfo fromBinary(String fieldId, int binaryValue) {
|
||||
boolean editable = ((binaryValue >> 3) & 1) == 1;
|
||||
boolean required = ((binaryValue >> 2) & 1) == 1;
|
||||
boolean readonly = ((binaryValue >> 1) & 1) == 1;
|
||||
boolean hidden = (binaryValue & 1) == 1;
|
||||
return new FormPermissionMetaInfo(fieldId, editable, required, readonly, hidden);
|
||||
}
|
||||
|
||||
public String toBinaryString() {
|
||||
return String.format("%04d", Integer.parseInt(Integer.toBinaryString(toBinary()), 10));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,42 +0,0 @@
|
||||
package cn.axzo.workflow.common.model.request.form.definition;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
import static cn.axzo.workflow.common.constant.BpmnConstants.NO_TENANT_ID;
|
||||
|
||||
/**
|
||||
* 表单定义的草稿模型
|
||||
*
|
||||
* @author wangli
|
||||
* @since 2024-11-05 10:11
|
||||
*/
|
||||
@Data
|
||||
public class FormDraftDefinitionDTO {
|
||||
/**
|
||||
* 模型的 KEY
|
||||
*/
|
||||
@ApiModelProperty(value = "模型的 KEY")
|
||||
private String key;
|
||||
|
||||
/**
|
||||
* 模型的分类
|
||||
*/
|
||||
@ApiModelProperty(value = "模型的分类")
|
||||
private String category;
|
||||
|
||||
/**
|
||||
* 租户 ID
|
||||
*/
|
||||
@ApiModelProperty(value = "租户 ID")
|
||||
private String tenantId = NO_TENANT_ID;
|
||||
|
||||
/**
|
||||
* 表单定义
|
||||
*/
|
||||
@ApiModelProperty(value = "表单定义内容")
|
||||
@Valid
|
||||
private FormDefinitionDTO formDefinition;
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package cn.axzo.workflow.common.model.request.form.definition;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
import static cn.axzo.workflow.common.constant.BpmnConstants.NO_TENANT_ID;
|
||||
|
||||
/**
|
||||
* 获取开始表单的模型入参
|
||||
*
|
||||
* @author wangli
|
||||
* @since 2024-11-14 16:27
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("获取开始表单的模型入参")
|
||||
public class StartFormSearchDTO {
|
||||
/**
|
||||
* 业务标识
|
||||
*/
|
||||
@ApiModelProperty(value = "业务标识", notes = "也等于表单唯一标识,目前新建一个审批模型,表单和审批的标识都是一样的")
|
||||
@NotBlank(message = "业务标识不能为空")
|
||||
private String key;
|
||||
|
||||
/**
|
||||
* 租户 ID
|
||||
*/
|
||||
private String tenantId = NO_TENANT_ID;
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
package cn.axzo.workflow.common.model.request.form.instance;
|
||||
|
||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 表单详情响应模型
|
||||
*
|
||||
* @author wangli
|
||||
* @since 2024-11-14 14:22
|
||||
*/
|
||||
@ApiModel("表单详情响应模型")
|
||||
@Data
|
||||
public class FormDetailDTO {
|
||||
|
||||
/**
|
||||
* 流程实例 ID
|
||||
*/
|
||||
@ApiModelProperty(value = "流程实例ID")
|
||||
@NotBlank(message = "流程实例 ID 不能为空")
|
||||
private String processInstanceId;
|
||||
|
||||
/**
|
||||
* 任务 ID
|
||||
*/
|
||||
@ApiModelProperty(value = "任务 ID")
|
||||
private String taskId;
|
||||
|
||||
/**
|
||||
* 访问表单的人
|
||||
*/
|
||||
@ApiModelProperty(value = "访问表单的人")
|
||||
private BpmnTaskDelegateAssigner assigner;
|
||||
}
|
||||
@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
|
||||
@ -29,6 +30,7 @@ public class FormInstanceSearchDTO implements Serializable {
|
||||
* 实例 ID
|
||||
*/
|
||||
@ApiModelProperty(value = "实例 ID")
|
||||
@NotBlank(message = "流程实例不能为空")
|
||||
private String processInstanceId;
|
||||
|
||||
/**
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
package cn.axzo.workflow.common.model.response.form.instance;
|
||||
|
||||
import cn.axzo.workflow.common.model.response.form.definition.FormDefinitionVO;
|
||||
import cn.axzo.workflow.common.model.response.form.model.FormModelVO;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 表单实例的响应模型
|
||||
*
|
||||
* @author wangli
|
||||
* @since 2024-11-14 10:05
|
||||
*/
|
||||
@ApiModel("表单实例的响应模型")
|
||||
@Data
|
||||
public class FormInstanceVO {
|
||||
private String id;
|
||||
private String name;
|
||||
private String key;
|
||||
private Integer version;
|
||||
private FormModelVO formModel;
|
||||
private String formInstanceId;
|
||||
private String submittedBy;
|
||||
private Date submittedDate;
|
||||
private String taskId;
|
||||
private String processInstanceId;
|
||||
private String processDefinitionId;
|
||||
private String tenantId;
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package cn.axzo.workflow.common.model.response.form.model;
|
||||
|
||||
import cn.axzo.workflow.common.model.request.form.definition.FormFieldDTO;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 表单模型响应模型
|
||||
*
|
||||
* @author wangli
|
||||
* @since 2024-11-14 10:10
|
||||
*/
|
||||
@ApiModel("表单模型响应模型")
|
||||
@Data
|
||||
public class FormModelVO {
|
||||
private String id;
|
||||
private String name;
|
||||
private String key;
|
||||
private Integer version;
|
||||
private List<FormFieldDTO> fields;
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
package cn.axzo.workflow.core.common.utils;
|
||||
|
||||
import cn.axzo.workflow.common.enums.ApprovalMethodEnum;
|
||||
import cn.axzo.workflow.common.exception.WorkflowEngineException;
|
||||
import cn.axzo.workflow.common.model.request.BpmnApproveConf;
|
||||
import cn.axzo.workflow.common.model.request.bpmn.BpmnButtonConf;
|
||||
import cn.axzo.workflow.common.model.request.bpmn.BpmnButtonMetaInfo;
|
||||
@ -9,8 +10,7 @@ import cn.axzo.workflow.common.model.request.bpmn.BpmnJsonModel;
|
||||
import cn.axzo.workflow.common.model.request.bpmn.BpmnJsonNode;
|
||||
import cn.axzo.workflow.common.model.request.bpmn.BpmnNoticeConf;
|
||||
import cn.axzo.workflow.common.model.request.bpmn.model.BpmnModelCreateDTO;
|
||||
import cn.axzo.workflow.common.exception.WorkflowEngineException;
|
||||
import cn.axzo.workflow.common.model.request.form.FormFieldPermissionConf;
|
||||
import cn.axzo.workflow.common.model.request.form.FormPermissionMetaInfo;
|
||||
import cn.axzo.workflow.core.converter.json.AbstractBpmnJsonConverter;
|
||||
import cn.axzo.workflow.core.converter.json.BoundaryEventJsonConverter;
|
||||
import cn.axzo.workflow.core.converter.json.EndEventJsonConverter;
|
||||
@ -71,6 +71,7 @@ import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import static cn.axzo.workflow.common.code.ConvertorRespCode.CONVERTOR_COMMON_ERROR;
|
||||
import static cn.axzo.workflow.common.constant.BpmnConstants.APPROVE_SUPPORT_BATCH_OPERATION;
|
||||
import static cn.axzo.workflow.common.constant.BpmnConstants.APPROVE_USER_AGREE_SIGNATURE;
|
||||
import static cn.axzo.workflow.common.constant.BpmnConstants.AUTO_APPROVAL_TYPE;
|
||||
@ -112,7 +113,6 @@ import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_SMS_MESSAG
|
||||
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_CONDITION;
|
||||
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_EMPTY;
|
||||
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_EXCLUSIVE_GATEWAY;
|
||||
import static cn.axzo.workflow.common.code.ConvertorRespCode.CONVERTOR_COMMON_ERROR;
|
||||
import static cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper.getButtonConfig;
|
||||
import static cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper.getFieldConfig;
|
||||
import static cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper.getNoticeConfig;
|
||||
@ -765,8 +765,8 @@ public final class BpmnJsonConverterUtil {
|
||||
|
||||
// FlowElement flowElement = bpmnModel.getFlowElement("node_350687681316");
|
||||
FlowElement flowElement = bpmnModel.getFlowElement("node_429076682717");
|
||||
Optional<FormFieldPermissionConf> formFieldPermissionConf =
|
||||
BpmnMetaParserHelper.getFormFieldPermissionConf(flowElement);
|
||||
Optional<List<FormPermissionMetaInfo>> formFieldPermissionConf
|
||||
= BpmnMetaParserHelper.getFormFieldPermissionConf(flowElement);
|
||||
// ServiceTask serviceTask = (ServiceTask) bpmnModel.getFlowElement("node_946990365785");
|
||||
// Optional<List<BpmnCarbonCopyConf>> carbonCopyConfigs = BpmnMetaParserHelper.getCarbonCopyConfigs
|
||||
// (serviceTask);
|
||||
|
||||
@ -20,9 +20,9 @@ import cn.axzo.workflow.common.model.request.bpmn.BpmnNoticeProperty;
|
||||
import cn.axzo.workflow.common.model.request.bpmn.BpmnNoticeReceiver;
|
||||
import cn.axzo.workflow.common.model.request.bpmn.BpmnPendingProperty;
|
||||
import cn.axzo.workflow.common.model.request.bpmn.BpmnSmsProperty;
|
||||
import cn.axzo.workflow.common.model.request.form.FormFieldPermissionConf;
|
||||
import cn.axzo.workflow.common.model.request.form.FormPermissionMetaInfo;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.bpmn.model.ExtensionElement;
|
||||
import org.flowable.bpmn.model.FlowElement;
|
||||
@ -38,10 +38,13 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.axzo.workflow.common.constant.BpmnConstants.APPROVE_SUPPORT_BATCH_OPERATION;
|
||||
import static cn.axzo.workflow.common.constant.BpmnConstants.APPROVE_USER_AGREE_SIGNATURE;
|
||||
@ -427,17 +430,90 @@ public final class BpmnMetaParserHelper {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public static Optional<FormFieldPermissionConf> getFormFieldPermissionConf(FlowElement flowElement) {
|
||||
return defaultValid(flowElement, CONFIG_FIELD_PERMISSION).map(element-> JSON.parseObject(element.getElementText(), FormFieldPermissionConf.class));
|
||||
public static Optional<List<FormPermissionMetaInfo>> getFormFieldPermissionConf(FlowElement flowElement) {
|
||||
return defaultValid(flowElement, CONFIG_FIELD_PERMISSION).map(element -> JSON.parseObject(element.getElementText(), new TypeReference<List<FormPermissionMetaInfo>>() {
|
||||
}.getType()));
|
||||
}
|
||||
|
||||
public static Optional<Map<String, Integer>> getFormFieldPermissionForCalc(FlowElement flowElement) {
|
||||
FormFieldPermissionConf formFieldPermissionConf = getFormFieldPermissionConf(flowElement).orElse(null);
|
||||
if(Objects.nonNull(formFieldPermissionConf)) {
|
||||
// formFieldPermissionConf.getCurrent()
|
||||
return Optional.of(null);
|
||||
List<FormPermissionMetaInfo> fieldMetaInfos = getFormFieldPermissionConf(flowElement).orElse(new ArrayList<>());
|
||||
return getFormFieldPermissionForModel(fieldMetaInfos);
|
||||
}
|
||||
|
||||
public static Optional<Map<String, Integer>> getFormFieldPermissionForModel(List<FormPermissionMetaInfo> fieldMetaInfos) {
|
||||
if (CollectionUtils.isEmpty(fieldMetaInfos)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.empty();
|
||||
Map<String, Integer> result = fieldMetaInfos.stream()
|
||||
.collect(Collectors.toMap(FormPermissionMetaInfo::getFieldId,
|
||||
FormPermissionMetaInfo::toBinary,
|
||||
(s, t) -> s));
|
||||
return Optional.of(result);
|
||||
}
|
||||
|
||||
public static List<FormPermissionMetaInfo> mergeAllPermission(List<FormPermissionMetaInfo>... permissions) {
|
||||
if (permissions.length == 0) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<Map<String, Integer>> combinedMap = new ArrayList<>();
|
||||
for (List<FormPermissionMetaInfo> permission : permissions) {
|
||||
combinedMap.add(getFormFieldPermissionForModel(permission).orElse(new HashMap<>()));
|
||||
}
|
||||
|
||||
Map<String, List<Integer>> mergeMap = new HashMap<>();
|
||||
for (Map<String, Integer> map : combinedMap) {
|
||||
for (Map.Entry<String, Integer> entry : map.entrySet()) {
|
||||
mergeMap.putIfAbsent(entry.getKey(), new ArrayList<>());
|
||||
mergeMap.get(entry.getKey()).add(entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
List<FormPermissionMetaInfo> permissionResult = new ArrayList<>();
|
||||
for (Map.Entry<String, List<Integer>> entry : mergeMap.entrySet()) {
|
||||
int[] array = entry.getValue().stream().mapToInt(Integer::intValue).toArray();
|
||||
int result = performBitwiseOr(array);
|
||||
permissionResult.add(FormPermissionMetaInfo.fromBinary(entry.getKey(), result));
|
||||
}
|
||||
return permissionResult;
|
||||
}
|
||||
|
||||
|
||||
private static int performBitwiseOr(int... numbers) {
|
||||
int result = 0;
|
||||
for (int num : numbers) {
|
||||
result |= num;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// just for testing
|
||||
private static List<FormPermissionMetaInfo> genericConf(int num) {
|
||||
List<FormPermissionMetaInfo> fields = new ArrayList<>();
|
||||
Random random = new Random();
|
||||
for (int i = 0; i < num; i++) {
|
||||
String fieldId = "field_" + i;
|
||||
FormPermissionMetaInfo metaInfo = FormPermissionMetaInfo
|
||||
.builder()
|
||||
.fieldId(fieldId)
|
||||
.editable(random.nextBoolean())
|
||||
.required(random.nextBoolean())
|
||||
.readonly(random.nextBoolean())
|
||||
.hidden(random.nextBoolean())
|
||||
.build();
|
||||
fields.add(metaInfo);
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
List<FormPermissionMetaInfo> conf1 = genericConf(5);
|
||||
conf1.forEach(e -> System.out.println("conf1 ---> e.fieldId = " + e.getFieldId() + ",e.toBinary() = " + e.toBinary() + ",e.toBinaryString() = " + e.toBinaryString()));
|
||||
List<FormPermissionMetaInfo> conf2 = genericConf(5);
|
||||
conf2.forEach(e -> System.out.println("conf2 ---> e.fieldId = " + e.getFieldId() + ",e.toBinary() = " + e.toBinary() + ",e.toBinaryString() = " + e.toBinaryString()));
|
||||
|
||||
List<FormPermissionMetaInfo> result = mergeAllPermission(conf1, conf2);
|
||||
result.forEach(e -> System.out.println("result ---> e.fieldId = " + e.getFieldId() + ",e.toBinary() = " + e.toBinary() + ",e.toBinaryString() = " + e.toBinaryString()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,58 @@
|
||||
package cn.axzo.workflow.core.conf.handler;
|
||||
|
||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||
import cn.axzo.workflow.common.model.request.form.FormPermissionMetaInfo;
|
||||
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.ObjectMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import org.apache.ibatis.type.MappedJdbcTypes;
|
||||
import org.apache.ibatis.type.MappedTypes;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* BpmnTaskDelegateAssigner 数据映射转换
|
||||
*
|
||||
* @author wangli
|
||||
* @since 2024-09-07 22:40
|
||||
*/
|
||||
@Slf4j
|
||||
@MappedTypes({List.class})
|
||||
@MappedJdbcTypes({JdbcType.VARCHAR})
|
||||
public class ListFormFieldPermissionTypeHandler extends AbstractJsonTypeHandler<List<FormPermissionMetaInfo>> {
|
||||
private static ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
public ListFormFieldPermissionTypeHandler(Class<?> type) {
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace("JacksonTypeHandler(" + type + ")");
|
||||
}
|
||||
Assert.notNull(type, "Type argument cannot be null", new Object[0]);
|
||||
}
|
||||
|
||||
protected List<FormPermissionMetaInfo> parse(String json) {
|
||||
try {
|
||||
// 这里进行了json解析,同样在这里也可以进行字段查询后的处理,如对象内部的手机号字段的加密展示等
|
||||
return objectMapper.readValue(json, new TypeReference<List<FormPermissionMetaInfo>>() {
|
||||
});
|
||||
} catch (IOException var3) {
|
||||
throw new RuntimeException(var3);
|
||||
}
|
||||
}
|
||||
|
||||
protected String toJson(List<FormPermissionMetaInfo> obj) {
|
||||
try {
|
||||
return objectMapper.writeValueAsString(obj);
|
||||
} catch (JsonProcessingException var3) {
|
||||
throw new RuntimeException(var3);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setObjectMapper(ObjectMapper om) {
|
||||
objectMapper = om;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,252 @@
|
||||
package cn.axzo.workflow.core.engine.cmd;
|
||||
|
||||
import cn.axzo.workflow.common.exception.WorkflowEngineException;
|
||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||
import cn.axzo.workflow.common.model.request.form.FormPermissionMetaInfo;
|
||||
import cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper;
|
||||
import cn.axzo.workflow.core.repository.entity.ExtAxBpmnFormRelation;
|
||||
import cn.axzo.workflow.core.repository.entity.ExtAxProcessLog;
|
||||
import cn.axzo.workflow.core.service.BpmnProcessTaskForEsService;
|
||||
import cn.axzo.workflow.core.service.ExtAxBpmnFormRelationService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.common.engine.api.delegate.Expression;
|
||||
import org.flowable.common.engine.impl.el.ExpressionManager;
|
||||
import org.flowable.common.engine.impl.el.VariableContainerWrapper;
|
||||
import org.flowable.common.engine.impl.interceptor.Command;
|
||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||
import org.flowable.engine.HistoryService;
|
||||
import org.flowable.engine.history.HistoricProcessInstance;
|
||||
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
|
||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||
import org.flowable.form.api.FormDefinition;
|
||||
import org.flowable.form.api.FormEngineConfigurationApi;
|
||||
import org.flowable.form.api.FormInstanceInfo;
|
||||
import org.flowable.form.api.FormRepositoryService;
|
||||
import org.flowable.form.api.FormService;
|
||||
import org.flowable.form.model.FormField;
|
||||
import org.flowable.form.model.SimpleFormModel;
|
||||
import org.flowable.task.api.history.HistoricTaskInstance;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.axzo.workflow.common.code.BpmnInstanceRespCode.PROCESS_INSTANCE_ID_NOT_EXISTS;
|
||||
import static cn.axzo.workflow.common.code.BpmnTaskRespCode.TASK_COMPLETE_FAIL_NOT_EXISTS;
|
||||
import static cn.axzo.workflow.common.code.FormInstanceRespCode.FORM_FIELD_NOT_FOUND;
|
||||
import static cn.axzo.workflow.common.code.FormInstanceRespCode.FORM_PARAM_ERROR;
|
||||
import static cn.axzo.workflow.common.constant.FormConstants.FIELD_PROPERTY_DEFAULT_VALUE;
|
||||
import static cn.axzo.workflow.common.constant.FormConstants.FIELD_PROPERTY_EDITABLE;
|
||||
import static cn.axzo.workflow.common.constant.FormConstants.FIELD_PROPERTY_HIDDEN;
|
||||
import static cn.axzo.workflow.common.constant.FormConstants.FIELD_PROPERTY_READONLY;
|
||||
import static cn.axzo.workflow.common.constant.FormConstants.FIELD_PROPERTY_REQUIRED;
|
||||
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_STARTER;
|
||||
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.PROCESSING;
|
||||
|
||||
/**
|
||||
* 获取指定审批实例的表单内容以及字段权限
|
||||
*
|
||||
* @author wangli
|
||||
* @since 2024-11-13 14:24
|
||||
*/
|
||||
@Slf4j
|
||||
public class GetFormInstanceAndPermissionCmd implements Command<FormInstanceInfo> {
|
||||
private final ExtAxBpmnFormRelationService bpmnFormRelationService;
|
||||
private final BpmnProcessTaskForEsService bpmnProcessTaskForEsService;
|
||||
private final BpmnTaskDelegateAssigner assigner;
|
||||
private String processInstanceId;
|
||||
private String taskId;
|
||||
|
||||
/**
|
||||
* 全权通过实例查询一切
|
||||
*
|
||||
* @param processInstanceId
|
||||
*/
|
||||
public GetFormInstanceAndPermissionCmd(ExtAxBpmnFormRelationService bpmnFormRelationService,
|
||||
BpmnProcessTaskForEsService bpmnProcessTaskForEsService,
|
||||
BpmnTaskDelegateAssigner assigner,
|
||||
String processInstanceId) {
|
||||
this.bpmnFormRelationService = bpmnFormRelationService;
|
||||
this.bpmnProcessTaskForEsService = bpmnProcessTaskForEsService;
|
||||
this.assigner = assigner;
|
||||
this.processInstanceId = processInstanceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过实例和任务查询
|
||||
*
|
||||
* @param processInstanceId 可为空,则用 taskId 反查实例相关
|
||||
* @param taskId
|
||||
*/
|
||||
public GetFormInstanceAndPermissionCmd(ExtAxBpmnFormRelationService bpmnFormRelationService,
|
||||
BpmnProcessTaskForEsService bpmnProcessTaskForEsService,
|
||||
BpmnTaskDelegateAssigner assigner,
|
||||
String processInstanceId,
|
||||
String taskId) {
|
||||
this.bpmnFormRelationService = bpmnFormRelationService;
|
||||
this.bpmnProcessTaskForEsService = bpmnProcessTaskForEsService;
|
||||
this.assigner = assigner;
|
||||
this.processInstanceId = processInstanceId;
|
||||
this.taskId = taskId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FormInstanceInfo execute(CommandContext commandContext) {
|
||||
preCheckParam();
|
||||
|
||||
// 获取表单定义+字段内容
|
||||
FormInstanceInfo formInstanceInfo = getFormInstanceInfo(commandContext);
|
||||
if (Objects.isNull(formInstanceInfo)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 获取字段权限
|
||||
List<FormPermissionMetaInfo> fieldPermission = getFieldPermission(commandContext);
|
||||
Map<String, FormPermissionMetaInfo> fieldMap = fieldPermission.stream()
|
||||
.collect(Collectors.toMap(FormPermissionMetaInfo::getFieldId, Function.identity(), (s, t) -> s));
|
||||
|
||||
SimpleFormModel formModel = (SimpleFormModel) formInstanceInfo.getFormModel();
|
||||
Map<String, FormField> flatField = formModel.allFieldsAsMap();
|
||||
|
||||
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||
HistoryService historyService = processEngineConfiguration.getHistoryService();
|
||||
ExpressionManager expressionManager = processEngineConfiguration.getExpressionManager();
|
||||
HistoricProcessInstance instance = historyService.createHistoricProcessInstanceQuery()
|
||||
.processInstanceId(processInstanceId)
|
||||
.includeProcessVariables()
|
||||
.singleResult();
|
||||
Map<String, Object> processVariables = instance.getProcessVariables();
|
||||
VariableContainerWrapper variableContainerWrapper = new VariableContainerWrapper(processVariables);
|
||||
|
||||
flatField.forEach((fieldId, formField) -> {
|
||||
Map<String, Object> oldParams = CollectionUtils.isEmpty(formField.getParams()) ? new HashMap<>() : formField.getParams();
|
||||
FormPermissionMetaInfo defaultPermission = fieldMap.getOrDefault(fieldId, new FormPermissionMetaInfo());
|
||||
oldParams.put(FIELD_PROPERTY_REQUIRED, defaultPermission.getRequired());
|
||||
oldParams.put(FIELD_PROPERTY_EDITABLE, defaultPermission.getEditable());
|
||||
oldParams.put(FIELD_PROPERTY_READONLY, defaultPermission.getReadonly());
|
||||
oldParams.put(FIELD_PROPERTY_HIDDEN, defaultPermission.getHidden());
|
||||
if (oldParams.containsKey(FIELD_PROPERTY_DEFAULT_VALUE)) {
|
||||
Expression expression = expressionManager.createExpression(String.valueOf(oldParams.getOrDefault(FIELD_PROPERTY_DEFAULT_VALUE, "")));
|
||||
Object value = expression.getValue(variableContainerWrapper);
|
||||
oldParams.put(FIELD_PROPERTY_DEFAULT_VALUE, Objects.nonNull(value) ? String.valueOf(value) : null);
|
||||
}
|
||||
});
|
||||
return formInstanceInfo;
|
||||
}
|
||||
|
||||
private List<FormPermissionMetaInfo> getFieldPermission(CommandContext commandContext) {
|
||||
List<ExtAxProcessLog> logs = bpmnProcessTaskForEsService.queryProcessLogByProcessInstanceId(processInstanceId);
|
||||
|
||||
Map<String, ExtAxProcessLog> activityMap = logs.stream()
|
||||
.collect(Collectors.toMap(ExtAxProcessLog::getActivityId, Function.identity(), (s, t) -> s));
|
||||
|
||||
// 待审批的节点
|
||||
List<ExtAxProcessLog> processingLogs = logs.stream()
|
||||
.filter(e -> Objects.equals(PROCESSING.getStatus(), e.getStatus()) && Objects.isNull(e.getEndTime()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<FormPermissionMetaInfo> list = binaryMerge(processingLogs, activityMap);
|
||||
if (!CollectionUtils.isEmpty(list)) {
|
||||
return list;
|
||||
}
|
||||
|
||||
// 已结束的审批节点
|
||||
List<ExtAxProcessLog> finishLogs = logs.stream()
|
||||
.filter(e -> !Objects.equals(PROCESSING.getStatus(), e.getStatus()) && Objects.nonNull(e.getEndTime()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
list = binaryMerge(finishLogs, activityMap);
|
||||
if (!CollectionUtils.isEmpty(list)) {
|
||||
return list;
|
||||
}
|
||||
|
||||
// 默认全字段都是隐藏
|
||||
ExtAxProcessLog starterLog = logs.stream().filter(e -> Objects.equals(NODE_STARTER.getType(), e.getActivityId()))
|
||||
.findFirst().orElseThrow(() -> new WorkflowEngineException(FORM_FIELD_NOT_FOUND));
|
||||
return CollectionUtils.isEmpty(starterLog.getFormFieldPermissionConf()) ? new ArrayList<>() : starterLog.getFormFieldPermissionConf();
|
||||
}
|
||||
|
||||
private List<FormPermissionMetaInfo> binaryMerge(List<ExtAxProcessLog> logs, Map<String, ExtAxProcessLog> activityMap) {
|
||||
List<List<FormPermissionMetaInfo>> permissions = new ArrayList<>();
|
||||
collectActivityIds(logs).forEach(id -> {
|
||||
ExtAxProcessLog log = activityMap.getOrDefault(id, null);
|
||||
if (Objects.nonNull(log)) {
|
||||
permissions.add(log.getFormFieldPermissionConf());
|
||||
}
|
||||
});
|
||||
return BpmnMetaParserHelper.mergeAllPermission(permissions.toArray(new List[0]));
|
||||
}
|
||||
|
||||
private List<String> collectActivityIds(List<ExtAxProcessLog> logs) {
|
||||
List<String> activityIds = new ArrayList<>();
|
||||
if (!CollectionUtils.isEmpty(logs)) {
|
||||
Map<String, List<BpmnTaskDelegateAssigner>> nodeUserMap = rebuildToNodeUserMap(logs);
|
||||
|
||||
nodeUserMap.forEach((activityId, assigners) -> {
|
||||
assigners.forEach(u -> {
|
||||
if (Objects.equals(u.getPersonId(), assigner.getPersonId())) {
|
||||
activityIds.add(activityId);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
return activityIds;
|
||||
}
|
||||
|
||||
private static Map<String, List<BpmnTaskDelegateAssigner>> rebuildToNodeUserMap(List<ExtAxProcessLog> logs) {
|
||||
Map<String, List<BpmnTaskDelegateAssigner>> assignerMap = new HashMap<>();
|
||||
logs.forEach(e -> {
|
||||
if (assignerMap.containsKey(e.getActivityId())) {
|
||||
assignerMap.get(e.getActivityId()).addAll(e.getAssigneeFull());
|
||||
} else {
|
||||
assignerMap.put(e.getActivityId(), new ArrayList<>());
|
||||
}
|
||||
});
|
||||
return assignerMap;
|
||||
}
|
||||
|
||||
private FormInstanceInfo getFormInstanceInfo(CommandContext commandContext) {
|
||||
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||
HistoryService historyService = processEngineConfiguration.getHistoryService();
|
||||
|
||||
HistoricProcessInstance instance;
|
||||
if (StringUtils.hasText(processInstanceId)) {
|
||||
instance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
|
||||
} else {
|
||||
HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
|
||||
if (Objects.isNull(task)) {
|
||||
throw new WorkflowEngineException(TASK_COMPLETE_FAIL_NOT_EXISTS);
|
||||
}
|
||||
instance = historyService.createHistoricProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
|
||||
}
|
||||
if (Objects.isNull(instance)) {
|
||||
throw new WorkflowEngineException(PROCESS_INSTANCE_ID_NOT_EXISTS, processInstanceId);
|
||||
}
|
||||
processInstanceId = instance.getId();
|
||||
ExtAxBpmnFormRelation relation = bpmnFormRelationService.queryByBpmnDefinitionId(instance.getProcessDefinitionId());
|
||||
if (Objects.isNull(relation)) {
|
||||
// 没有配置表单
|
||||
return null;
|
||||
}
|
||||
|
||||
FormEngineConfigurationApi formEngineConfiguration = CommandContextUtil.getFormEngineConfiguration(commandContext);
|
||||
FormRepositoryService formRepositoryService = formEngineConfiguration.getFormRepositoryService();
|
||||
FormDefinition formDefinition = formRepositoryService.createFormDefinitionQuery().deploymentId(relation.getFormDeploymentId()).singleResult();
|
||||
|
||||
FormService formService = formEngineConfiguration.getFormService();
|
||||
// 获取表单定义+字段内容
|
||||
return formService.getFormInstanceModelById(formDefinition.getId(), taskId, processInstanceId, null, instance.getTenantId(), false);
|
||||
}
|
||||
|
||||
private void preCheckParam() {
|
||||
if (!StringUtils.hasText(processInstanceId) && !StringUtils.hasText(taskId)) {
|
||||
throw new WorkflowEngineException(FORM_PARAM_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -13,6 +13,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.ListUtils;
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.bpmn.model.FlowElement;
|
||||
import org.flowable.bpmn.model.Process;
|
||||
import org.flowable.bpmn.model.UserTask;
|
||||
import org.flowable.engine.RuntimeService;
|
||||
import org.flowable.engine.impl.bpmn.behavior.MultiInstanceActivityBehavior;
|
||||
@ -98,16 +99,16 @@ public class TaskEntityEventHandle implements EntityEventHandle<TaskEntity> {
|
||||
|
||||
@Override
|
||||
public void onInitialized(TaskEntity taskEntity) {
|
||||
BpmnMetaParserHelper.getButtonConfig(ProcessDefinitionUtil.getProcess(taskEntity.getProcessDefinitionId()), taskEntity.getTaskDefinitionKey())
|
||||
.ifPresent(buttons -> {
|
||||
ExtAxProcessLog queryLog = new ExtAxProcessLog();
|
||||
queryLog.setProcessInstanceId(taskEntity.getProcessInstanceId());
|
||||
queryLog.setTaskId(taskEntity.getId());
|
||||
|
||||
ExtAxProcessLog updateLog = new ExtAxProcessLog();
|
||||
updateLog.setButtonConf(buttons);
|
||||
processLogService.update(queryLog, updateLog);
|
||||
});
|
||||
Process process = ProcessDefinitionUtil.getProcess(taskEntity.getProcessDefinitionId());
|
||||
ExtAxProcessLog queryLog = new ExtAxProcessLog();
|
||||
queryLog.setProcessInstanceId(taskEntity.getProcessInstanceId());
|
||||
queryLog.setTaskId(taskEntity.getId());
|
||||
ExtAxProcessLog updateLog = new ExtAxProcessLog();
|
||||
BpmnMetaParserHelper.getButtonConfig(process, taskEntity.getTaskDefinitionKey())
|
||||
.ifPresent(updateLog::setButtonConf);
|
||||
BpmnMetaParserHelper.getFormFieldPermissionConf(process.getFlowElement(taskEntity.getTaskDefinitionKey()))
|
||||
.ifPresent(updateLog::setFormFieldPermissionConf);
|
||||
processLogService.update(queryLog, updateLog);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -162,9 +163,13 @@ public class TaskEntityEventHandle implements EntityEventHandle<TaskEntity> {
|
||||
}
|
||||
Object operationDesc = taskEntity.getTransientVariableLocal(COMMENT_TYPE_OPERATION_DESC);
|
||||
if (Objects.nonNull(operationDesc) && StringUtils.hasText(operationDesc.toString())) {
|
||||
update.setOperationDesc(Objects.nonNull(assignee) ? assignee.getAssignerName() + operationDesc : operationDesc.toString());
|
||||
update.setOperationDesc(Objects.nonNull(assignee) ?
|
||||
(StringUtils.hasText(assignee.getAssignerName()) ? assignee.getAssignerName() : "") + operationDesc
|
||||
: operationDesc.toString());
|
||||
} else {
|
||||
update.setOperationDesc(Objects.nonNull(assignee) ? assignee.getAssignerName() : "");
|
||||
update.setOperationDesc(Objects.nonNull(assignee) ?
|
||||
(StringUtils.hasText(assignee.getAssignerName()) ? assignee.getAssignerName() : "")
|
||||
: "");
|
||||
}
|
||||
|
||||
|
||||
@ -212,7 +217,7 @@ public class TaskEntityEventHandle implements EntityEventHandle<TaskEntity> {
|
||||
UserTask userTask = (UserTask) flowElement;
|
||||
if (userTask.getBehavior() instanceof MultiInstanceActivityBehavior) {
|
||||
MultiInstanceActivityBehavior behavior =
|
||||
(MultiInstanceActivityBehavior) userTask.getBehavior();
|
||||
(MultiInstanceActivityBehavior) userTask.getBehavior();
|
||||
node = Objects.equals(AND_SIGN_EXPRESSION, behavior.getCompletionCondition()) ? AND : OR;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,8 +3,10 @@ package cn.axzo.workflow.core.repository.entity;
|
||||
import cn.axzo.framework.data.mybatisplus.model.BaseEntity;
|
||||
import cn.axzo.workflow.common.model.request.bpmn.BpmnButtonConf;
|
||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||
import cn.axzo.workflow.common.model.request.form.FormPermissionMetaInfo;
|
||||
import cn.axzo.workflow.core.conf.handler.ButtonConfTypeHandler;
|
||||
import cn.axzo.workflow.core.conf.handler.ListAssigneeTypeHandler;
|
||||
import cn.axzo.workflow.core.conf.handler.ListFormFieldPermissionTypeHandler;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
@ -102,6 +104,11 @@ public class ExtAxProcessLog extends BaseEntity<ExtAxProcessLog> {
|
||||
*/
|
||||
@TableField(typeHandler = ButtonConfTypeHandler.class)
|
||||
private BpmnButtonConf buttonConf;
|
||||
/**
|
||||
* 表单字段权限配置
|
||||
*/
|
||||
@TableField(typeHandler = ListFormFieldPermissionTypeHandler.class)
|
||||
private List<FormPermissionMetaInfo> formFieldPermissionConf;
|
||||
/**
|
||||
* 任务状态:审批中/通过/驳回/转交/加签/回退
|
||||
*/
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
package cn.axzo.workflow.core.service;
|
||||
|
||||
import cn.axzo.workflow.common.model.dto.BpmnFormRelationSearchDTO;
|
||||
import cn.axzo.workflow.common.model.request.form.definition.FormDefinitionSearchDTO;
|
||||
import cn.axzo.workflow.common.model.request.form.definition.StartFormSearchDTO;
|
||||
import cn.axzo.workflow.common.model.request.form.instance.FormDetailDTO;
|
||||
import cn.axzo.workflow.common.model.request.form.instance.FormInstanceSearchDTO;
|
||||
import cn.axzo.workflow.common.model.response.form.FormVO;
|
||||
import cn.axzo.workflow.common.model.response.form.definition.FormDefinitionVO;
|
||||
import cn.axzo.workflow.common.model.response.form.instance.FormInstanceVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 由于 POM 的结构的问题,这个类主要解决循环依赖的问题
|
||||
*
|
||||
* @author wangli
|
||||
* @since 2024-11-14 10:17
|
||||
*/
|
||||
public interface FormCoreService {
|
||||
|
||||
List<FormVO> pageForm(BpmnFormRelationSearchDTO dto);
|
||||
|
||||
FormDefinitionVO getStartForm(StartFormSearchDTO dto);
|
||||
|
||||
FormInstanceVO getFormInstance(FormDetailDTO dto);
|
||||
}
|
||||
@ -16,6 +16,7 @@ import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceAdm
|
||||
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.BpmnProcessInstanceCreateWithFormDTO;
|
||||
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceLogQueryDTO;
|
||||
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceMyPageReqVO;
|
||||
@ -375,7 +376,7 @@ public class BpmnProcessInstanceServiceImpl implements BpmnProcessInstanceServic
|
||||
if (Objects.isNull(relation)) {
|
||||
// 如果模型没有绑定表单,则强制情况表单相关属性,避免报错
|
||||
instanceBuilder.startFormVariables(null).outcome(null);
|
||||
}else {
|
||||
} else {
|
||||
instanceBuilder.startFormVariables(dto.getStartFormVariables())
|
||||
.outcome(dto.getOutcome());
|
||||
}
|
||||
|
||||
@ -348,6 +348,7 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService {
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void approveTaskWithForm(BpmnTaskAuditWithFormDTO dto) {
|
||||
// 表单级别暂时只允许同步
|
||||
CommandExecutor commandExecutor = processEngineConfiguration.getCommandExecutor();
|
||||
commandExecutor.execute(new CustomApproveTaskWithFormCmd(dto));
|
||||
}
|
||||
|
||||
@ -79,6 +79,7 @@ public class ExtAxBpmnFormRelationServiceImpl implements ExtAxBpmnFormRelationSe
|
||||
.eq(StringUtils.hasText(dto.getFormDeploymentId()), ExtAxBpmnFormRelation::getFormDeploymentId, dto.getFormDeploymentId())
|
||||
.eq(!StringUtils.hasText(dto.getTenantId()), ExtAxBpmnFormRelation::getTenantId, NO_TENANT_ID)
|
||||
.eq(StringUtils.hasText(dto.getTenantId()), ExtAxBpmnFormRelation::getTenantId, dto.getTenantId())
|
||||
.eq(ExtAxBpmnFormRelation::getIsDelete, 0)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,134 @@
|
||||
package cn.axzo.workflow.core.service.impl;
|
||||
|
||||
import cn.axzo.workflow.common.exception.WorkflowEngineException;
|
||||
import cn.axzo.workflow.common.model.dto.BpmnFormRelationSearchDTO;
|
||||
import cn.axzo.workflow.common.model.request.form.FormPermissionMetaInfo;
|
||||
import cn.axzo.workflow.common.model.request.form.definition.StartFormSearchDTO;
|
||||
import cn.axzo.workflow.common.model.request.form.instance.FormDetailDTO;
|
||||
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessDefinitionVO;
|
||||
import cn.axzo.workflow.common.model.response.form.FormVO;
|
||||
import cn.axzo.workflow.common.model.response.form.definition.FormDefinitionVO;
|
||||
import cn.axzo.workflow.common.model.response.form.instance.FormInstanceVO;
|
||||
import cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper;
|
||||
import cn.axzo.workflow.core.engine.cmd.GetFormInstanceAndPermissionCmd;
|
||||
import cn.axzo.workflow.core.repository.entity.ExtAxBpmnFormRelation;
|
||||
import cn.axzo.workflow.core.service.BpmnProcessDefinitionService;
|
||||
import cn.axzo.workflow.core.service.BpmnProcessTaskForEsService;
|
||||
import cn.axzo.workflow.core.service.ExtAxBpmnFormRelationService;
|
||||
import cn.axzo.workflow.core.service.FormCoreService;
|
||||
import cn.axzo.workflow.form.service.converter.FormFieldConverter;
|
||||
import cn.axzo.workflow.form.service.converter.FormInstanceConverter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.common.engine.api.FlowableObjectNotFoundException;
|
||||
import org.flowable.common.engine.impl.interceptor.CommandExecutor;
|
||||
import org.flowable.engine.impl.cmd.GetBpmnModelCmd;
|
||||
import org.flowable.form.api.FormInfo;
|
||||
import org.flowable.form.api.FormInstanceInfo;
|
||||
import org.flowable.form.api.FormRepositoryService;
|
||||
import org.flowable.form.model.FormField;
|
||||
import org.flowable.form.model.SimpleFormModel;
|
||||
import org.flowable.spring.SpringProcessEngineConfiguration;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
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.FIELD_PROPERTY_EDITABLE;
|
||||
import static cn.axzo.workflow.common.constant.FormConstants.FIELD_PROPERTY_HIDDEN;
|
||||
import static cn.axzo.workflow.common.constant.FormConstants.FIELD_PROPERTY_READONLY;
|
||||
import static cn.axzo.workflow.common.constant.FormConstants.FIELD_PROPERTY_REQUIRED;
|
||||
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_STARTER;
|
||||
|
||||
/**
|
||||
* @author wangli
|
||||
* @since 2024-11-14 10:18
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class FormCoreServiceImpl implements FormCoreService {
|
||||
@Resource
|
||||
private SpringProcessEngineConfiguration springProcessEngineConfiguration;
|
||||
@Resource
|
||||
private ExtAxBpmnFormRelationService bpmnFormRelationService;
|
||||
@Resource
|
||||
private BpmnProcessTaskForEsService bpmnProcessTaskForEsService;
|
||||
@Resource
|
||||
private FormInstanceConverter formInstanceConverter;
|
||||
@Resource
|
||||
private FormRepositoryService formRepositoryService;
|
||||
@Resource
|
||||
private BpmnProcessDefinitionService bpmnProcessDefinitionService;
|
||||
@Resource
|
||||
private FormFieldConverter formFieldConverter;
|
||||
|
||||
@Override
|
||||
public List<FormVO> pageForm(BpmnFormRelationSearchDTO searchDTO) {
|
||||
List<ExtAxBpmnFormRelation> list = bpmnFormRelationService.keyQuery(searchDTO);
|
||||
|
||||
return list.stream()
|
||||
.collect(Collectors.collectingAndThen(Collectors.toMap(ExtAxBpmnFormRelation::getKey, Function.identity(), (s, t) -> s), x -> new ArrayList<>(x.values())))
|
||||
.stream()
|
||||
.map(e -> FormVO.builder()
|
||||
.key(e.getKey())
|
||||
.tenantId(e.getTenantId())
|
||||
.build())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FormDefinitionVO getStartForm(StartFormSearchDTO dto) {
|
||||
FormInfo formModel;
|
||||
try {
|
||||
formModel = formRepositoryService.getFormModelByKey(dto.getKey(), dto.getTenantId(), true);
|
||||
} catch (FlowableObjectNotFoundException e) {
|
||||
log.warn("can't found form model");
|
||||
throw new WorkflowEngineException(FORM_MODEL_NOT_EXISTS);
|
||||
}
|
||||
BpmnProcessDefinitionVO definitionVO = bpmnProcessDefinitionService.getActiveProcessDefinitionByKey(dto.getKey(), dto.getTenantId());
|
||||
CommandExecutor commandExecutor = springProcessEngineConfiguration.getCommandExecutor();
|
||||
BpmnModel bpmnModel = commandExecutor.execute(new GetBpmnModelCmd(definitionVO.getId()));
|
||||
BpmnMetaParserHelper.getFormFieldPermissionConf(bpmnModel.getFlowElement(NODE_STARTER.getType())).ifPresent(permission -> {
|
||||
|
||||
Map<String, FormPermissionMetaInfo> permissionMap = permission.stream()
|
||||
.collect(Collectors.toMap(FormPermissionMetaInfo::getFieldId, Function.identity(), (s, t) -> s));
|
||||
|
||||
if (formModel.getFormModel() instanceof SimpleFormModel) {
|
||||
SimpleFormModel simpleFormModel = (SimpleFormModel) formModel.getFormModel();
|
||||
simpleFormModel.listAllFields().forEach(field -> {
|
||||
Map<String, Object> params = CollectionUtils.isEmpty(field.getParams()) ? new HashMap<>() : field.getParams();
|
||||
FormPermissionMetaInfo meta = permissionMap.getOrDefault(field.getId(), new FormPermissionMetaInfo());
|
||||
params.put(FIELD_PROPERTY_REQUIRED, meta.getRequired());
|
||||
params.put(FIELD_PROPERTY_EDITABLE, meta.getEditable());
|
||||
params.put(FIELD_PROPERTY_READONLY, meta.getReadonly());
|
||||
params.put(FIELD_PROPERTY_HIDDEN, meta.getHidden());
|
||||
field.setParams(params);
|
||||
});
|
||||
}
|
||||
});
|
||||
FormDefinitionVO formDefinitionVO = new FormDefinitionVO();
|
||||
formDefinitionVO.setFormDefinitionId(formModel.getId());
|
||||
formDefinitionVO.setName(formModel.getName());
|
||||
formDefinitionVO.setKey(formModel.getKey());
|
||||
formDefinitionVO.setVersion(formModel.getVersion());
|
||||
formDefinitionVO.setTenantId(dto.getTenantId());
|
||||
List<FormField> fields = ((SimpleFormModel) formModel.getFormModel()).getFields();
|
||||
formDefinitionVO.setFields(formFieldConverter.toVos(fields));
|
||||
return formDefinitionVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FormInstanceVO getFormInstance(FormDetailDTO dto) {
|
||||
CommandExecutor commandExecutor = springProcessEngineConfiguration.getCommandExecutor();
|
||||
FormInstanceInfo formInstanceInfo = commandExecutor.execute(new GetFormInstanceAndPermissionCmd(bpmnFormRelationService,
|
||||
bpmnProcessTaskForEsService, dto.getAssigner(), dto.getProcessInstanceId(), dto.getTaskId()));
|
||||
return formInstanceConverter.toVo(formInstanceInfo);
|
||||
}
|
||||
}
|
||||
@ -10,4 +10,9 @@ create table ext_ax_bpmn_form_relation
|
||||
create_at datetime default CURRENT_TIMESTAMP not null comment '创建时间',
|
||||
create_by bigint default 0 not null comment '创建人',
|
||||
is_delete bigint default 0 not null comment '是否删除:0否,1是'
|
||||
);
|
||||
);
|
||||
|
||||
|
||||
-- 流程日志表增加字段权限配置
|
||||
alter table ext_ax_process_log
|
||||
add form_field_permission_conf json null comment '表单字段权限' after button_conf;
|
||||
@ -3,6 +3,7 @@ package cn.axzo.workflow.form.service;
|
||||
|
||||
import cn.axzo.workflow.common.model.request.form.instance.FormContentUpdateDTO;
|
||||
import cn.axzo.workflow.common.model.request.form.instance.FormInstanceSearchDTO;
|
||||
import cn.axzo.workflow.common.model.response.form.instance.FormInstanceVO;
|
||||
import org.flowable.form.api.FormInstanceInfo;
|
||||
|
||||
/**
|
||||
@ -25,5 +26,5 @@ public interface FormInstanceService {
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
FormInstanceInfo getFormInstanceInfo(FormInstanceSearchDTO dto);
|
||||
FormInstanceVO getFormInstanceInfo(FormInstanceSearchDTO dto);
|
||||
}
|
||||
|
||||
@ -0,0 +1,107 @@
|
||||
package cn.axzo.workflow.form.service.converter;
|
||||
|
||||
import cn.axzo.workflow.common.model.request.form.definition.FormFieldDTO;
|
||||
import cn.axzo.workflow.common.model.response.form.instance.FormInstanceVO;
|
||||
import cn.axzo.workflow.common.model.response.form.model.FormModelVO;
|
||||
import org.flowable.form.api.FormInstanceInfo;
|
||||
import org.flowable.form.api.FormModel;
|
||||
import org.flowable.form.model.FormContainer;
|
||||
import org.flowable.form.model.FormField;
|
||||
import org.flowable.form.model.SimpleFormModel;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.mapstruct.NullValueCheckStrategy.ALWAYS;
|
||||
|
||||
/**
|
||||
* 表单实例模型的 MapStruts 转换器
|
||||
*
|
||||
* @author wangli
|
||||
* @since 2024-11-14 10:31
|
||||
*/
|
||||
@Mapper(
|
||||
componentModel = "spring",
|
||||
nullValueCheckStrategy = ALWAYS,
|
||||
imports = Arrays.class
|
||||
)
|
||||
public interface FormInstanceConverter extends EntityConverter<FormInstanceVO, FormInstanceInfo> {
|
||||
|
||||
@Mapping(target = "id", source = "entity.id")
|
||||
@Mapping(target = "name", source = "entity.name")
|
||||
@Mapping(target = "key", source = "entity.key")
|
||||
@Mapping(target = "version", source = "entity.version")
|
||||
@Mapping(target = "formModel", expression = "java(formModelConverter(entity.getFormModel()))")
|
||||
@Mapping(target = "formInstanceId", source = "entity.formInstanceId")
|
||||
@Mapping(target = "submittedBy", source = "entity.submittedBy")
|
||||
@Mapping(target = "submittedDate", source = "entity.submittedDate")
|
||||
@Mapping(target = "taskId", source = "entity.taskId")
|
||||
@Mapping(target = "processInstanceId", source = "entity.processInstanceId")
|
||||
@Mapping(target = "processDefinitionId", source = "entity.processDefinitionId")
|
||||
@Mapping(target = "tenantId", source = "entity.tenantId")
|
||||
FormInstanceVO toVo(FormInstanceInfo entity);
|
||||
|
||||
default FormModelVO formModelConverter(FormModel formModel) {
|
||||
FormModelVO formModelVO = new FormModelVO();
|
||||
if (formModel instanceof SimpleFormModel) {
|
||||
SimpleFormModel simpleFormModel = (SimpleFormModel) formModel;
|
||||
formModelVO.setName(simpleFormModel.getName());
|
||||
formModelVO.setKey(simpleFormModel.getKey());
|
||||
formModelVO.setVersion(simpleFormModel.getVersion());
|
||||
formModelVO.setFields(formContainersToFormFieldDTOs(simpleFormModel.getFields()));
|
||||
}
|
||||
return formModelVO;
|
||||
}
|
||||
|
||||
default FormFieldDTO formFieldConverter(FormField formField) {
|
||||
FormFieldDTO formFieldDTO = new FormFieldDTO();
|
||||
formFieldDTO.setType(formField.getType());
|
||||
formFieldDTO.setId(formField.getId());
|
||||
formFieldDTO.setName(formField.getName());
|
||||
formFieldDTO.setValue(castList(formField.getValue()));
|
||||
formFieldDTO.setPlaceholder(formField.getPlaceholder());
|
||||
formFieldDTO.setParams(formField.getParams());
|
||||
if (formField instanceof FormContainer) {
|
||||
FormContainer formContainer = (FormContainer) formField;
|
||||
formFieldDTO.setFields(formContainerListsToFormFieldDTOLists(formContainer.getFields()));
|
||||
|
||||
}
|
||||
return formFieldDTO;
|
||||
}
|
||||
|
||||
default List<String> castList(Object value) {
|
||||
if (Objects.isNull(value)) {
|
||||
return (List<String>) value;
|
||||
}
|
||||
List<String> values = new ArrayList<>();
|
||||
if (value instanceof String) {
|
||||
values.add((String) value);
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
// 辅助方法,用于处理List<FormContainer>到List<FormFieldDTO>的转换,调用上面自定义的转换方法
|
||||
default List<FormFieldDTO> formContainersToFormFieldDTOs(List<FormField> formContainers) {
|
||||
if (formContainers == null) {
|
||||
return null;
|
||||
}
|
||||
return formContainers.stream()
|
||||
.map(e -> formFieldConverter(e))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// 辅助方法,用于处理List<List<FormContainer>>到List<List<FormFieldDTO>>的转换,调用上面的辅助方法
|
||||
default List<List<FormFieldDTO>> formContainerListsToFormFieldDTOLists(List<List<FormField>> formContainerLists) {
|
||||
if (formContainerLists == null) {
|
||||
return null;
|
||||
}
|
||||
return formContainerLists.stream()
|
||||
.map(this::formContainersToFormFieldDTOs)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@ -4,12 +4,14 @@ import cn.axzo.workflow.common.code.BpmnTaskRespCode;
|
||||
import cn.axzo.workflow.common.exception.WorkflowEngineException;
|
||||
import cn.axzo.workflow.common.model.request.form.instance.FormContentUpdateDTO;
|
||||
import cn.axzo.workflow.common.model.request.form.instance.FormInstanceSearchDTO;
|
||||
import cn.axzo.workflow.common.model.response.form.instance.FormInstanceVO;
|
||||
import cn.axzo.workflow.form.service.FormInstanceService;
|
||||
import cn.axzo.workflow.form.service.converter.FormInstanceConverter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.engine.HistoryService;
|
||||
import org.flowable.engine.TaskService;
|
||||
import org.flowable.form.api.FormInfo;
|
||||
import org.flowable.engine.history.HistoricProcessInstance;
|
||||
import org.flowable.form.api.FormInstanceInfo;
|
||||
import org.flowable.form.api.FormRepositoryService;
|
||||
import org.flowable.form.api.FormService;
|
||||
@ -20,6 +22,8 @@ import org.springframework.stereotype.Service;
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Objects;
|
||||
|
||||
import static cn.axzo.workflow.common.code.BpmnInstanceRespCode.PROCESS_INSTANCE_ID_NOT_EXISTS;
|
||||
|
||||
|
||||
/**
|
||||
* 表单实例 Service 实现
|
||||
@ -32,14 +36,16 @@ import java.util.Objects;
|
||||
@RequiredArgsConstructor
|
||||
public class FormInstanceServiceImpl implements FormInstanceService {
|
||||
|
||||
@Resource
|
||||
private FormRepositoryService formRepositoryService;
|
||||
@Resource
|
||||
private FormService formService;
|
||||
@Resource
|
||||
private TaskService taskService;
|
||||
@Resource
|
||||
private FormInstanceConverter formInstanceConverter;
|
||||
@Resource
|
||||
private HistoryService historyService;
|
||||
@Resource
|
||||
private FormRepositoryService formRepositoryService;
|
||||
|
||||
@Override
|
||||
public void updateFormContent(FormContentUpdateDTO dto) {
|
||||
@ -55,7 +61,6 @@ public class FormInstanceServiceImpl implements FormInstanceService {
|
||||
throw new WorkflowEngineException(BpmnTaskRespCode.TASK_COMPLETE_FAIL_ASSIGN_NOT_SELF);
|
||||
}
|
||||
|
||||
FormInfo formInfo = formRepositoryService.getFormModelById(dto.getFormDefinitionId());
|
||||
if (Objects.nonNull(task.getProcessInstanceId())) {
|
||||
formService.saveFormInstanceByFormDefinitionId(dto.getFormVariables(), dto.getFormDefinitionId(),
|
||||
dto.getTaskId(),
|
||||
@ -68,8 +73,15 @@ public class FormInstanceServiceImpl implements FormInstanceService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public FormInstanceInfo getFormInstanceInfo(FormInstanceSearchDTO dto) {
|
||||
public FormInstanceVO getFormInstanceInfo(FormInstanceSearchDTO dto) {
|
||||
HistoricProcessInstance instance = historyService.createHistoricProcessInstanceQuery().processInstanceId(dto.getProcessInstanceId()).singleResult();
|
||||
if (Objects.isNull(instance)) {
|
||||
throw new WorkflowEngineException(PROCESS_INSTANCE_ID_NOT_EXISTS, dto.getProcessInstanceId());
|
||||
}
|
||||
|
||||
return formService.getFormInstanceModelById(dto.getFormDefinitionId(), dto.getTaskId(), dto.getProcessInstanceId(), dto.getVariables(), dto.getTenantId(), true);
|
||||
String processDefinitionKey = instance.getProcessDefinitionKey();
|
||||
|
||||
FormInstanceInfo formInstanceInfo = formService.getFormInstanceModelByKey(processDefinitionKey, dto.getTaskId(), dto.getProcessInstanceId(), dto.getVariables(), instance.getTenantId(), true);
|
||||
return formInstanceConverter.toVo(formInstanceInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,10 +29,15 @@ import org.flowable.form.api.FormInfo;
|
||||
import org.flowable.form.api.FormInstanceInfo;
|
||||
import org.flowable.form.api.FormRepositoryService;
|
||||
import org.flowable.form.api.FormService;
|
||||
import org.flowable.spring.SpringProcessEngineConfiguration;
|
||||
import org.flowable.task.api.history.HistoricTaskInstance;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.util.PropertyPlaceholderHelper;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -45,7 +50,9 @@ import javax.annotation.Resource;
|
||||
import java.io.InputStream;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
@ -86,10 +93,12 @@ public class TestController {
|
||||
private FormDefinitionService formDefinitionService;
|
||||
@Resource
|
||||
private ExtAxBpmnFormRelationService bpmnFormRelationService;
|
||||
// @Autowired
|
||||
// @Autowired
|
||||
// private WorkflowCoreService workflowCoreService;
|
||||
// @Autowired
|
||||
// private WorkflowManageService workflowManageService;
|
||||
@Resource
|
||||
private SpringProcessEngineConfiguration processEngineConfiguration;
|
||||
|
||||
@RepeatSubmit
|
||||
@GetMapping("/test")
|
||||
@ -319,4 +328,30 @@ public class TestController {
|
||||
FormInstanceInfo formInstance = formService.getFormInstanceModelById(formDefinition.getId(), dto.getTaskId(), dto.getProcessInstanceId(), dto.getVariables(), relation.getTenantId(), false);
|
||||
return CommonResponse.success(formInstance);
|
||||
}
|
||||
|
||||
/**
|
||||
* 表达式测试
|
||||
*
|
||||
* @param expression
|
||||
* @param variables
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/expression/testing")
|
||||
public CommonResponse<String> parseExpression(@RequestParam String expression, @RequestBody Map<String, String> variables) {
|
||||
// ExpressionManager expressionManager = processEngineConfiguration.getExpressionManager();
|
||||
// Expression exp = expressionManager.createExpression(expression);
|
||||
// VariableContainerWrapper variableContainer = new VariableContainerWrapper(variables);
|
||||
// String stringFromField = ExpressionUtils.getStringFromField(exp, variableContainer);
|
||||
// Object value = exp.getValue(variableContainer);
|
||||
|
||||
PropertyPlaceholderHelper propertyPlaceholderHelper = new PropertyPlaceholderHelper("${", "}");
|
||||
Properties properties = new Properties();
|
||||
variables.forEach(properties::setProperty);
|
||||
|
||||
// 自定义PlaceholderResolver实现类,用于处理占位符找不到对应值时返回空字符串
|
||||
PropertyPlaceholderHelper.PlaceholderResolver resolver = placeholder -> properties.getProperty(placeholder, "");
|
||||
String value = propertyPlaceholderHelper.replacePlaceholders(expression, resolver);
|
||||
return CommonResponse.success(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -112,7 +112,10 @@ public class BpmnProcessTaskController extends BasicPopulateAvatarController imp
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PostMapping("/approveWithForm")
|
||||
@Operation(summary = "通过任务")
|
||||
@Override
|
||||
@PostMapping("/form/approve")
|
||||
@RepeatSubmit
|
||||
public CommonResponse<Boolean> approveTaskWithForm(@Validated @RequestBody BpmnTaskAuditWithFormDTO dto) {
|
||||
log.info("同意 approveTask===>>>参数:{}", JSON.toJSONString(dto));
|
||||
List<AttachmentDTO> tempAttachments = ListUtils.defaultIfNull(dto.getAttachmentList(), new ArrayList<>());
|
||||
|
||||
@ -3,14 +3,18 @@ package cn.axzo.workflow.server.controller.web.form;
|
||||
import cn.axzo.workflow.client.feign.manage.FormInstanceApi;
|
||||
import cn.axzo.workflow.common.model.dto.BpmnFormRelationSearchDTO;
|
||||
import cn.axzo.workflow.common.model.request.form.definition.FormDefinitionSearchDTO;
|
||||
import cn.axzo.workflow.common.model.request.form.definition.StartFormSearchDTO;
|
||||
import cn.axzo.workflow.common.model.request.form.instance.FormContentUpdateDTO;
|
||||
import cn.axzo.workflow.common.model.request.form.instance.FormDetailDTO;
|
||||
import cn.axzo.workflow.common.model.request.form.instance.FormInstanceSearchDTO;
|
||||
import cn.axzo.workflow.common.model.request.form.instance.FormSearchDTO;
|
||||
import cn.axzo.workflow.common.model.response.BpmPageResult;
|
||||
import cn.axzo.workflow.common.model.response.form.FormVO;
|
||||
import cn.axzo.workflow.common.model.response.form.definition.FormDefinitionVO;
|
||||
import cn.axzo.workflow.common.model.response.form.instance.FormInstanceVO;
|
||||
import cn.axzo.workflow.core.repository.entity.ExtAxBpmnFormRelation;
|
||||
import cn.axzo.workflow.core.service.ExtAxBpmnFormRelationService;
|
||||
import cn.axzo.workflow.core.service.FormCoreService;
|
||||
import cn.axzo.workflow.form.service.FormDefinitionService;
|
||||
import cn.axzo.workflow.form.service.FormInstanceService;
|
||||
import cn.axzo.workflow.server.common.annotation.ErrorReporter;
|
||||
@ -33,7 +37,7 @@ import java.util.stream.Collectors;
|
||||
import static cn.azxo.framework.common.model.CommonResponse.success;
|
||||
|
||||
/**
|
||||
* 表单模型相关控制器
|
||||
* 表单实例相关控制器
|
||||
*
|
||||
* @author wangli
|
||||
* @since 2023/7/21 15:23
|
||||
@ -46,11 +50,7 @@ import static cn.azxo.framework.common.model.CommonResponse.success;
|
||||
public class FormInstanceController implements FormInstanceApi {
|
||||
|
||||
@Resource
|
||||
private FormInstanceService formInstanceService;
|
||||
@Resource
|
||||
private FormDefinitionService formDefinitionService;
|
||||
@Resource
|
||||
private ExtAxBpmnFormRelationService bpmnFormRelationService;
|
||||
private FormCoreService formCoreService;
|
||||
|
||||
@Operation(summary = "表单列表")
|
||||
@PostMapping("/form/page")
|
||||
@ -58,29 +58,18 @@ public class FormInstanceController implements FormInstanceApi {
|
||||
BpmnFormRelationSearchDTO searchDTO = new BpmnFormRelationSearchDTO();
|
||||
searchDTO.setKey(dto.getKey());
|
||||
searchDTO.setTenantId(dto.getTenantId());
|
||||
List<ExtAxBpmnFormRelation> list = bpmnFormRelationService.keyQuery(searchDTO);
|
||||
|
||||
List<FormVO> result = list
|
||||
.stream()
|
||||
.collect(Collectors.collectingAndThen(Collectors.toMap(ExtAxBpmnFormRelation::getKey,Function.identity(),(s,t)->s), x->new ArrayList<>(x.values())))
|
||||
.stream()
|
||||
.map(e -> FormVO.builder()
|
||||
.key(e.getKey())
|
||||
.tenantId(e.getTenantId())
|
||||
.build())
|
||||
.collect(Collectors.toList());
|
||||
return success(result);
|
||||
return success(formCoreService.pageForm(searchDTO));
|
||||
}
|
||||
|
||||
@Operation(summary = "获取指定业务含有表单的定义内容")
|
||||
@PostMapping("/init")
|
||||
public CommonResponse<FormDefinitionVO> getFormDefinition(@Validated @RequestBody FormDefinitionSearchDTO dto) {
|
||||
return success(formDefinitionService.get(dto));
|
||||
@Operation(summary = "获取指定业务含有表单的定义内容和权限")
|
||||
@PostMapping("/start/form")
|
||||
public CommonResponse<FormDefinitionVO> getFormDefinition(@Validated @RequestBody StartFormSearchDTO dto) {
|
||||
return success(formCoreService.getStartForm(dto));
|
||||
}
|
||||
|
||||
@Operation(summary = "获取指定表单审批的实例信息")
|
||||
@PostMapping("/render")
|
||||
public CommonResponse<FormInstanceInfo> getFormInstance(@Validated @RequestBody FormInstanceSearchDTO dto) {
|
||||
return success(formInstanceService.getFormInstanceInfo(dto));
|
||||
public CommonResponse<FormInstanceVO> getFormInstance(@Validated @RequestBody FormDetailDTO dto) {
|
||||
return success(formCoreService.getFormInstance(dto));
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,9 +60,11 @@ import cn.axzo.workflow.common.model.response.category.CategoryItemVO;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import cn.axzo.workflow.common.model.request.form.definition.FormDefinitionSearchDTO;
|
||||
import cn.axzo.workflow.common.model.request.form.instance.FormInstanceSearchDTO;
|
||||
import cn.axzo.workflow.common.model.request.form.instance.FormSearchDTO;
|
||||
import cn.axzo.workflow.common.model.response.form.FormVO;
|
||||
import cn.axzo.workflow.common.model.response.form.definition.FormDefinitionVO;
|
||||
import cn.axzo.workflow.common.model.response.form.instance.FormInstanceVO;
|
||||
import cn.axzo.workflow.common.model.request.bpmn.BpmnButtonMetaInfo;
|
||||
import cn.axzo.workflow.common.model.request.bpmn.model.BpmnModelCreateDTO;
|
||||
import cn.axzo.workflow.common.model.request.bpmn.model.BpmnModelSearchDTO;
|
||||
@ -463,6 +465,10 @@ public interface WorkflowManageService {
|
||||
@InvokeMode(SYNC)
|
||||
FormDefinitionVO getFormDefinition(@Validated @RequestBody FormDefinitionSearchDTO dto);
|
||||
|
||||
@PostMapping("/api/form/instance/get")
|
||||
@InvokeMode(SYNC)
|
||||
FormInstanceVO getFormInstance(@Validated @RequestBody FormInstanceSearchDTO dto);
|
||||
|
||||
/**
|
||||
* 获取流程操作按钮列表
|
||||
*
|
||||
|
||||
Loading…
Reference in New Issue
Block a user