feat(流程设计): 流程设计添加是否 节点表单 选项。若为节点表单,则表单信息仅在此节点可用,默认为全局表单,表单信息在整个流程实例中可用。
This commit is contained in:
@@ -62,6 +62,11 @@ public class ProcessConstants {
|
||||
*/
|
||||
public static final String PROCESS_CUSTOM_USER_TYPE = "userType";
|
||||
|
||||
/**
|
||||
* 自定义属性 localScope
|
||||
*/
|
||||
public static final String PROCESS_FORM_LOCAL_SCOPE = "localScope";
|
||||
|
||||
|
||||
/**
|
||||
* 流程跳过
|
||||
|
||||
@@ -130,6 +130,35 @@ public class ModelUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取流程元素信息
|
||||
*
|
||||
* @param model bpmnModel对象
|
||||
* @param flowElementId 元素ID
|
||||
* @return 元素信息
|
||||
*/
|
||||
public static FlowElement getFlowElementById(BpmnModel model, String flowElementId) {
|
||||
Process process = model.getMainProcess();
|
||||
return process.getFlowElement(flowElementId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取元素表单Key(限开始节点和用户节点可用)
|
||||
*
|
||||
* @param flowElement 元素
|
||||
* @return 表单Key
|
||||
*/
|
||||
public static String getFormKey(FlowElement flowElement) {
|
||||
if (flowElement != null) {
|
||||
if (flowElement instanceof StartEvent) {
|
||||
return ((StartEvent) flowElement).getFormKey();
|
||||
} else if (flowElement instanceof UserTask) {
|
||||
return ((UserTask) flowElement).getFormKey();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取开始节点属性值
|
||||
* @param model bpmnModel对象
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.ruoyi.workflow.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.date.BetweenFormatter;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
@@ -17,6 +18,7 @@ import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.common.utils.JsonUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.flowable.common.constant.ProcessConstants;
|
||||
import com.ruoyi.flowable.common.constant.TaskConstants;
|
||||
import com.ruoyi.flowable.core.FormConf;
|
||||
import com.ruoyi.flowable.core.domain.ProcessQuery;
|
||||
@@ -36,10 +38,8 @@ import com.ruoyi.workflow.service.IWfProcessService;
|
||||
import com.ruoyi.workflow.service.IWfTaskService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.flowable.bpmn.constants.BpmnXMLConstants;
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.bpmn.model.Process;
|
||||
import org.flowable.bpmn.model.StartEvent;
|
||||
import org.flowable.bpmn.model.UserTask;
|
||||
import org.flowable.bpmn.model.*;
|
||||
import org.flowable.engine.history.HistoricActivityInstance;
|
||||
import org.flowable.engine.history.HistoricActivityInstanceQuery;
|
||||
import org.flowable.engine.history.HistoricProcessInstance;
|
||||
@@ -638,7 +638,7 @@ public class WfProcessServiceImpl extends FlowServiceFactory implements IWfProce
|
||||
detailVo.setBpmnXml(IoUtil.readUtf8(inputStream));
|
||||
detailVo.setTaskFormData(currTaskFormData(deployId, taskIns));
|
||||
detailVo.setHistoryProcNodeList(historyProcNodeList(procInsId));
|
||||
detailVo.setProcessFormList(processFormList(procInsId, deployId, taskIns));
|
||||
detailVo.setProcessFormList(processFormList(procInsId, deployId));
|
||||
detailVo.setFlowViewer(getFlowViewer(procInsId));
|
||||
return detailVo;
|
||||
}
|
||||
@@ -699,18 +699,64 @@ public class WfProcessServiceImpl extends FlowServiceFactory implements IWfProce
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取流程表单信息(不包括当前任务节点)
|
||||
* 获取历史流程表单信息
|
||||
*/
|
||||
private List<FormConf> processFormList(String procInsId, String deployId, HistoricTaskInstance taskIns) {
|
||||
private List<FormConf> processFormList(String procInsId, String deployId) {
|
||||
List<FormConf> procFormList = new ArrayList<>();
|
||||
HistoricProcessInstance historicProcIns = historyService.createHistoricProcessInstanceQuery().processInstanceId(procInsId).includeProcessVariables().singleResult();
|
||||
Process process = repositoryService.getBpmnModel(historicProcIns.getProcessDefinitionId()).getMainProcess();
|
||||
|
||||
buildStartFormData(historicProcIns, process, deployId, procFormList);
|
||||
buildUserTaskFormData(procInsId, deployId, process, procFormList);
|
||||
BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcIns.getProcessDefinitionId());
|
||||
List<HistoricActivityInstance> activityInstanceList = historyService.createHistoricActivityInstanceQuery()
|
||||
.processInstanceId(procInsId).finished()
|
||||
.activityTypes(CollUtil.newHashSet(BpmnXMLConstants.ELEMENT_EVENT_START, BpmnXMLConstants.ELEMENT_TASK_USER))
|
||||
.orderByHistoricActivityInstanceStartTime().asc()
|
||||
.list();
|
||||
List<String> processFormKeys = new ArrayList<>();
|
||||
for (HistoricActivityInstance activityInstance : activityInstanceList) {
|
||||
// 获取当前节点流程元素信息
|
||||
FlowElement flowElement = ModelUtils.getFlowElementById(bpmnModel, activityInstance.getActivityId());
|
||||
// 获取当前节点表单Key
|
||||
String formKey = ModelUtils.getFormKey(flowElement);
|
||||
if (formKey == null) {
|
||||
continue;
|
||||
}
|
||||
boolean localScope = Convert.toBool(ModelUtils.getElementAttributeValue(flowElement, ProcessConstants.PROCESS_FORM_LOCAL_SCOPE), false);
|
||||
Map<String, Object> variables;
|
||||
if (localScope) {
|
||||
// 查询任务节点参数,并转换成Map
|
||||
variables = historyService.createHistoricVariableInstanceQuery()
|
||||
.processInstanceId(procInsId)
|
||||
.taskId(activityInstance.getTaskId())
|
||||
.list()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(HistoricVariableInstance::getVariableName, HistoricVariableInstance::getValue));
|
||||
} else {
|
||||
if (processFormKeys.contains(formKey)) {
|
||||
continue;
|
||||
}
|
||||
variables = historicProcIns.getProcessVariables();
|
||||
processFormKeys.add(formKey);
|
||||
}
|
||||
// 兼容旧版数据,旧版此处查询可能出现多条
|
||||
List<WfDeployFormVo> formInfoList = deployFormMapper.selectVoList(new LambdaQueryWrapper<WfDeployForm>()
|
||||
.eq(WfDeployForm::getDeployId, deployId)
|
||||
.eq(WfDeployForm::getFormKey, formKey)
|
||||
.eq(localScope, WfDeployForm::getNodeKey, flowElement.getId()));
|
||||
if (CollUtil.isNotEmpty(formInfoList)) {
|
||||
WfDeployFormVo formInfo = formInfoList.get(0);
|
||||
FormConf formConf = JsonUtils.parseObject(formInfo.getContent(), FormConf.class);
|
||||
if (null != formConf) {
|
||||
formConf.setTitle(flowElement.getName());
|
||||
formConf.setDisabled(true);
|
||||
formConf.setFormBtns(false);
|
||||
ProcessFormUtils.fillFormData(formConf, variables);
|
||||
procFormList.add(formConf);
|
||||
}
|
||||
}
|
||||
}
|
||||
return procFormList;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
private void buildStartFormData(HistoricProcessInstance historicProcIns, Process process, String deployId, List<FormConf> procFormList) {
|
||||
procFormList = procFormList == null ? new ArrayList<>() : procFormList;
|
||||
HistoricActivityInstance startInstance = historyService.createHistoricActivityInstanceQuery()
|
||||
@@ -734,6 +780,7 @@ public class WfProcessServiceImpl extends FlowServiceFactory implements IWfProce
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
private void buildUserTaskFormData(String procInsId, String deployId, Process process, List<FormConf> procFormList) {
|
||||
procFormList = procFormList == null ? new ArrayList<>() : procFormList;
|
||||
List<HistoricActivityInstance> activityInstanceList = historyService.createHistoricActivityInstanceQuery()
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package com.ruoyi.workflow.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.common.helper.LoginHelper;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.flowable.common.constant.ProcessConstants;
|
||||
import com.ruoyi.flowable.common.constant.TaskConstants;
|
||||
import com.ruoyi.flowable.common.enums.FlowComment;
|
||||
import com.ruoyi.flowable.factory.FlowServiceFactory;
|
||||
@@ -69,6 +71,8 @@ public class WfTaskServiceImpl extends FlowServiceFactory implements IWfTaskServ
|
||||
if (Objects.isNull(task)) {
|
||||
throw new ServiceException("任务不存在");
|
||||
}
|
||||
// 获取 bpmn 模型
|
||||
BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
|
||||
if (DelegationState.PENDING.equals(task.getDelegationState())) {
|
||||
taskService.addComment(taskBo.getTaskId(), taskBo.getProcInsId(), FlowComment.DELEGATE.getType(), taskBo.getComment());
|
||||
taskService.resolveTask(taskBo.getTaskId());
|
||||
@@ -76,7 +80,10 @@ public class WfTaskServiceImpl extends FlowServiceFactory implements IWfTaskServ
|
||||
taskService.addComment(taskBo.getTaskId(), taskBo.getProcInsId(), FlowComment.NORMAL.getType(), taskBo.getComment());
|
||||
taskService.setAssignee(taskBo.getTaskId(), TaskUtils.getUserId());
|
||||
if (ObjectUtil.isNotEmpty(taskBo.getVariables())) {
|
||||
taskService.complete(taskBo.getTaskId(), taskBo.getVariables(), true);
|
||||
// 获取模型信息
|
||||
String localScopeValue = ModelUtils.getUserTaskAttributeValue(bpmnModel, task.getTaskDefinitionKey(), ProcessConstants.PROCESS_FORM_LOCAL_SCOPE);
|
||||
boolean localScope = Convert.toBool(localScopeValue, false);
|
||||
taskService.complete(taskBo.getTaskId(), taskBo.getVariables(), localScope);
|
||||
} else {
|
||||
taskService.complete(taskBo.getTaskId());
|
||||
}
|
||||
@@ -85,7 +92,7 @@ public class WfTaskServiceImpl extends FlowServiceFactory implements IWfTaskServ
|
||||
taskBo.setTaskName(task.getName());
|
||||
// 处理下一级审批人
|
||||
if (StringUtils.isNotBlank(taskBo.getNextUserIds())) {
|
||||
this.assignNextUsers(task.getProcessDefinitionId(), taskBo.getProcInsId(), taskBo.getNextUserIds());
|
||||
this.assignNextUsers(bpmnModel, taskBo.getProcInsId(), taskBo.getNextUserIds());
|
||||
}
|
||||
// 处理抄送用户
|
||||
if (!copyService.makeCopy(taskBo)) {
|
||||
@@ -578,11 +585,11 @@ public class WfTaskServiceImpl extends FlowServiceFactory implements IWfTaskServ
|
||||
|
||||
/**
|
||||
* 指派下一任务审批人
|
||||
* @param processDefId 流程定义id
|
||||
* @param bpmnModel bpmn模型
|
||||
* @param processInsId 流程实例id
|
||||
* @param userIds 用户ids
|
||||
*/
|
||||
private void assignNextUsers(String processDefId, String processInsId, String userIds) {
|
||||
private void assignNextUsers(BpmnModel bpmnModel, String processInsId, String userIds) {
|
||||
// 获取所有节点信息
|
||||
List<Task> list = taskService.createTaskQuery()
|
||||
.processInstanceId(processInsId)
|
||||
@@ -597,7 +604,6 @@ public class WfTaskServiceImpl extends FlowServiceFactory implements IWfTaskServ
|
||||
}
|
||||
return;
|
||||
}
|
||||
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefId);
|
||||
// 优先处理非多实例任务
|
||||
Iterator<Task> iterator = list.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
|
||||
@@ -196,6 +196,12 @@
|
||||
"name": "formKey",
|
||||
"isAttr": true,
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "localScope",
|
||||
"isAttr": true,
|
||||
"type": "Boolean",
|
||||
"default": false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
<template>
|
||||
<div class="panel-tab__content">
|
||||
<el-form size="mini" label-width="80px" @submit.native.prevent>
|
||||
<el-form size="mini" label-width="90px" @submit.native.prevent>
|
||||
<el-form-item label="表单" prop="formKey">
|
||||
<el-select v-model="formKey" placeholder="请选择表单" @change="updateElementFormKey" clearable>
|
||||
<el-option v-for="item in formOptions" :key="item.formId" :label="item.formName" :value="`key_${item.formId}`" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item prop="localScope">
|
||||
<span slot="label">
|
||||
<el-tooltip content="若为节点表单,则表单信息仅在此节点可用,默认为全局表单,表单信息在整个流程实例中可用" placement="top-start">
|
||||
<i class="header-icon el-icon-info"></i>
|
||||
</el-tooltip>
|
||||
<span>节点表单</span>
|
||||
</span>
|
||||
<el-switch :disabled="type === 'StartEvent'" v-model="localScope" active-text="是" inactive-text="否" @change="updateElementFormScope()" />
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="表单标识">-->
|
||||
<!-- <el-input v-model="formKey" clearable @change="updateElementFormKey" />-->
|
||||
<!-- </el-form-item>-->
|
||||
@@ -169,6 +178,7 @@ export default {
|
||||
return {
|
||||
formOptions: [],
|
||||
formKey: "",
|
||||
localScope: false,
|
||||
businessKey: "",
|
||||
optionModelTitle: "",
|
||||
fieldList: [],
|
||||
@@ -212,6 +222,7 @@ export default {
|
||||
resetFormList() {
|
||||
this.bpmnELement = window.bpmnInstances.bpmnElement;
|
||||
this.formKey = this.bpmnELement.businessObject.formKey;
|
||||
this.localScope = this.bpmnELement.businessObject.localScope;
|
||||
// 获取元素扩展属性 或者 创建扩展属性
|
||||
this.elExtensionElements =
|
||||
this.bpmnELement.businessObject.get("extensionElements") || window.bpmnInstances.moddle.create("bpmn:ExtensionElements", { values: [] });
|
||||
@@ -234,6 +245,9 @@ export default {
|
||||
updateElementFormKey() {
|
||||
window.bpmnInstances.modeling.updateProperties(this.bpmnELement, { formKey: this.formKey });
|
||||
},
|
||||
updateElementFormScope() {
|
||||
window.bpmnInstances.modeling.updateProperties(this.bpmnELement, { localScope: this.localScope });
|
||||
},
|
||||
updateElementBusinessKey() {
|
||||
window.bpmnInstances.modeling.updateModdleProperties(this.bpmnELement, this.formData, { businessKey: this.businessKey });
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user