fix(流程模型和部署): 修改流程模型设计方案,模型信息和流程图分开操作,表单在开始节点设置。

This commit is contained in:
konbai
2022-07-19 20:59:32 +08:00
parent 0ae300919d
commit 8acdf651a9
20 changed files with 609 additions and 571 deletions

View File

@@ -16,6 +16,11 @@ import lombok.Data;
public class WfDeployForm {
private static final long serialVersionUID = 1L;
/**
* 表单主键
*/
private String formKey;
/**
* 流程定义主键
*/

View File

@@ -1,5 +1,7 @@
package com.ruoyi.workflow.domain.bo;
import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -16,33 +18,31 @@ import javax.validation.constraints.NotNull;
public class WfModelBo {
@ApiModelProperty(value = "模型主键")
@NotNull(message = "模型主键不能为空", groups = { EditGroup.class })
private String modelId;
@ApiModelProperty(value = "模型名称", required = true)
@NotNull(message = "模型名称不能为空")
@NotNull(message = "模型名称不能为空", groups = { AddGroup.class, EditGroup.class })
private String modelName;
@ApiModelProperty(value = "模型Key", required = true)
@NotNull(message = "模型Key不能为空")
@NotNull(message = "模型Key不能为空", groups = { AddGroup.class, EditGroup.class })
private String modelKey;
@ApiModelProperty(value = "流程分类", required = true)
@NotBlank(message = "流程分类不能为空")
@NotBlank(message = "流程分类不能为空", groups = { AddGroup.class, EditGroup.class })
private String category;
@ApiModelProperty(value = "描述")
private String description;
@ApiModelProperty(value = "表单类型", required = true)
@NotBlank(message = "表单类型不能为空")
private Integer formType;
@ApiModelProperty(value = "表单主键", required = true)
@NotBlank(message = "表单不能为空")
private Long formId;
@ApiModelProperty(value = "流程xml", required = true)
@NotBlank(message = "流程xml不能为空")
private String bpmnXml;
@ApiModelProperty(value = "是否保存为新版本", required = true)

View File

@@ -9,6 +9,11 @@ import lombok.Data;
@Data
public class WfMetaInfoDto {
/**
* 创建者username
*/
private String createUser;
/**
* 流程描述
*/

View File

@@ -22,10 +22,10 @@ public interface IWfDeployFormService {
/**
* 保存流程实例关联表单
* @param deployId
* @param formId
* @param formKey
* @return
*/
int saveInternalDeployForm(String deployId, Long formId);
int saveInternalDeployForm(String deployId, String formKey);
/**
* 查询流程挂着的表单

View File

@@ -13,19 +13,53 @@ import java.util.Collection;
*/
public interface IWfModelService {
/**
* 查询流程模型列表
*/
TableDataInfo<WfModelVo> list(WfModelBo modelBo, PageQuery pageQuery);
/**
* 查询流程模型列表
*/
TableDataInfo<WfModelVo> historyList(WfModelBo modelBo, PageQuery pageQuery);
/**
* 查询流程模型详情信息
*/
WfModelVo getModel(String modelId);
/**
* 查询流程表单详细信息
*/
String queryBpmnXmlById(String modelId);
/**
* 新增模型信息
*/
void insertModel(WfModelBo modelBo);
/**
* 修改模型信息
*/
void updateModel(WfModelBo modelBo);
/**
* 保存流程模型信息
*/
void saveModel(WfModelBo modelBo);
/**
* 设为最新流程模型
*/
void latestModel(String modelId);
/**
* 删除流程模型
*/
void deleteByIds(Collection<String> ids);
/**
* 部署流程模型
*/
void deployModel(String modelId);
}

View File

@@ -21,6 +21,13 @@ public interface IWfProcessService {
*/
TableDataInfo<WfDefinitionVo> processList(PageQuery pageQuery);
/**
* 查询流程部署关联表单信息
* @param definitionId 流程定义ID
* @param deployId 部署ID
*/
String selectFormContent(String definitionId, String deployId);
/**
* 启动流程实例
* @param procDefId 流程定义ID

View File

@@ -1,10 +1,12 @@
package com.ruoyi.workflow.service.impl;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.workflow.domain.WfDeployForm;
import com.ruoyi.workflow.domain.WfForm;
import com.ruoyi.workflow.domain.vo.WfFormVo;
@@ -48,10 +50,11 @@ public class WfDeployFormServiceImpl implements IWfDeployFormService {
@Override
@Transactional(rollbackFor = Exception.class)
public int saveInternalDeployForm(String deployId, Long formId) {
public int saveInternalDeployForm(String deployId, String formKey) {
WfDeployForm deployForm = new WfDeployForm();
deployForm.setDeployId(deployId);
deployForm.setFormId(formId);
deployForm.setFormKey(formKey);
Long formId = Convert.toLong(StringUtils.substringAfter(formKey, "key_"));
WfForm wfForm = formMapper.selectById(formId);
if (ObjectUtil.isNotNull(wfForm)) {
deployForm.setContent(wfForm.getContent());

View File

@@ -5,6 +5,7 @@ import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.flowable.common.constant.ProcessConstants;
@@ -21,6 +22,7 @@ import com.ruoyi.workflow.service.IWfModelService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.StartEvent;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.Model;
import org.flowable.engine.repository.ModelQuery;
@@ -156,36 +158,75 @@ public class WfModelServiceImpl extends FlowServiceFactory implements IWfModelSe
@Override
public String queryBpmnXmlById(String modelId) {
byte[] bpmnBytes = repositoryService.getModelEditorSource(modelId);
if (ObjectUtil.isNull(bpmnBytes)) {
throw new RuntimeException("流程图不存在!");
}
return StrUtil.utf8Str(bpmnBytes);
}
@Override
public void insertModel(WfModelBo modelBo) {
Model model = repositoryService.newModel();
model.setName(modelBo.getModelName());
model.setKey(modelBo.getModelKey());
model.setCategory(modelBo.getCategory());
String metaInfo = buildMetaInfo(new WfMetaInfoDto(), modelBo.getDescription());
model.setMetaInfo(metaInfo);
// 保存流程模型
repositoryService.saveModel(model);
}
@Override
public void updateModel(WfModelBo modelBo) {
// 根据模型Key查询模型信息
Model model = repositoryService.getModel(modelBo.getModelId());
if (ObjectUtil.isNull(model)) {
throw new RuntimeException("流程模型不存在!");
}
model.setCategory(modelBo.getCategory());
WfMetaInfoDto metaInfoDto = JsonUtils.parseObject(model.getMetaInfo(), WfMetaInfoDto.class);
String metaInfo = buildMetaInfo(metaInfoDto, modelBo.getDescription());
model.setMetaInfo(metaInfo);
// 保存流程模型
repositoryService.saveModel(model);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void saveModel(WfModelBo modelBo) {
// 根据模型Key查询模型信息
Model model = repositoryService.createModelQuery().modelKey(modelBo.getModelKey()).singleResult();
Model newModel;
// 查询模型信息
Model model = repositoryService.getModel(modelBo.getModelId());
if (ObjectUtil.isNull(model)) {
newModel = repositoryService.newModel();
} else {
if (modelBo.getNewVersion() != null && modelBo.getNewVersion()) {
newModel = repositoryService.newModel();
newModel.setVersion(model.getVersion() + 1);
} else {
newModel = model;
}
throw new RuntimeException("流程模型不存在!");
}
BpmnModel bpmnModel = ModelUtils.getBpmnModel(modelBo.getBpmnXml());
if (ObjectUtil.isEmpty(bpmnModel)) {
throw new RuntimeException("获取模型设计失败!");
}
String processName = bpmnModel.getMainProcess().getName();
// 获取开始节点
StartEvent startEvent = ModelUtils.getStartEvent(bpmnModel);
if (ObjectUtil.isNull(startEvent)) {
throw new RuntimeException("开始节点不存在,请检查流程设计是否有误!");
}
// 获取开始节点配置的表单Key
if (StrUtil.isBlank(startEvent.getFormKey())) {
throw new RuntimeException("请配置流程表单");
}
Model newModel;
if (Boolean.TRUE.equals(modelBo.getNewVersion())) {
newModel = repositoryService.newModel();
newModel.setName(processName);
newModel.setKey(model.getKey());
newModel.setCategory(model.getCategory());
newModel.setMetaInfo(model.getMetaInfo());
newModel.setVersion(model.getVersion() + 1);
} else {
newModel = model;
// 设置流程名称
newModel.setName(processName);
}
newModel.setName(modelBo.getModelName());
newModel.setKey(modelBo.getModelKey());
newModel.setCategory(modelBo.getCategory());
newModel.setMetaInfo(buildMetaInfo(modelBo));
// 保存流程模型
repositoryService.saveModel(newModel);
// 保存 BPMN XML
saveModelBpmnXml(newModel.getId(), modelBo.getBpmnXml());
repositoryService.addModelEditorSource(newModel.getId(), ModelUtils.getBpmnXml(bpmnModel));
}
@Override
@@ -214,7 +255,7 @@ public class WfModelServiceImpl extends FlowServiceFactory implements IWfModelSe
// 保存流程模型
repositoryService.saveModel(newModel);
// 保存 BPMN XML
saveModelBpmnXml(newModel.getId(), bpmnXml);
repositoryService.addModelEditorSource(newModel.getId(), StrUtil.utf8Bytes(bpmnXml));
}
@Override
@@ -237,10 +278,18 @@ public class WfModelServiceImpl extends FlowServiceFactory implements IWfModelSe
if (ObjectUtil.isNull(model)) {
throw new RuntimeException("流程模型不存在!");
}
WfMetaInfoDto metaInfo = getMetaInfo(model.getMetaInfo());
// 获取流程图
String bpmnXml = queryBpmnXmlById(modelId);
BpmnModel bpmnModel = ModelUtils.getBpmnModel(bpmnXml);
// 获取开始节点
StartEvent startEvent = ModelUtils.getStartEvent(bpmnModel);
if (ObjectUtil.isNull(startEvent)) {
throw new RuntimeException("开始节点不存在,请检查流程设计是否有误!");
}
String formKey = startEvent.getFormKey();
if (StringUtils.isEmpty(formKey)) {
throw new RuntimeException("请配置流程表单");
}
String processName = model.getName() + ProcessConstants.SUFFIX;
Deployment deployment = repositoryService.createDeployment()
.name(model.getName())
@@ -249,38 +298,22 @@ public class WfModelServiceImpl extends FlowServiceFactory implements IWfModelSe
.category(model.getCategory())
.deploy();
// 保存部署表单
if (FormType.PROCESS.getType().equals(metaInfo.getFormType())) {
deployFormService.saveInternalDeployForm(deployment.getId(), metaInfo.getFormId());
}
deployFormService.saveInternalDeployForm(deployment.getId(), formKey);
}
private String buildMetaInfo(WfModelBo modelBo) {
WfMetaInfoDto metaInfo = new WfMetaInfoDto();
/**
* 构建模型扩展信息
* @return
*/
private String buildMetaInfo(WfMetaInfoDto metaInfo, String description) {
// 只有非空,才进行设置,避免更新时的覆盖
if (StringUtils.isNotEmpty(modelBo.getDescription())) {
metaInfo.setDescription(modelBo.getDescription());
if (StringUtils.isNotEmpty(description)) {
metaInfo.setDescription(description);
}
if (ObjectUtil.isNotNull(modelBo.getFormType())) {
metaInfo.setFormType(modelBo.getFormType());
metaInfo.setFormId(modelBo.getFormId());
if (StringUtils.isNotEmpty(metaInfo.getCreateUser())) {
metaInfo.setCreateUser(LoginHelper.getUsername());
}
return JsonUtils.toJsonString(metaInfo);
}
private WfMetaInfoDto getMetaInfo(String metaInfoJson) {
WfMetaInfoDto metaInfo = JsonUtils.parseObject(metaInfoJson, WfMetaInfoDto.class);
if (ObjectUtil.isNull(metaInfo) || ObjectUtil.hasNull(metaInfo.getFormType(), metaInfo.getFormId())) {
throw new RuntimeException("未配置表单信息!");
}
return metaInfo;
}
private void saveModelBpmnXml(String modelId, String bpmnXml) {
if (StringUtils.isBlank(modelId)) {
throw new RuntimeException("模板主键不能为空!");
}
if (StringUtils.isNotEmpty(bpmnXml)) {
repositoryService.addModelEditorSource(modelId, StrUtil.utf8Bytes(bpmnXml));
}
}
}

View File

@@ -3,6 +3,9 @@ package com.ruoyi.workflow.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.BetweenFormatter;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.ruoyi.common.core.domain.PageQuery;
@@ -14,14 +17,19 @@ import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.flowable.common.constant.TaskConstants;
import com.ruoyi.flowable.factory.FlowServiceFactory;
import com.ruoyi.flowable.utils.ModelUtils;
import com.ruoyi.flowable.utils.TaskUtils;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.workflow.domain.WfDeployForm;
import com.ruoyi.workflow.domain.bo.WfProcessBo;
import com.ruoyi.workflow.domain.vo.WfDefinitionVo;
import com.ruoyi.workflow.domain.vo.WfTaskVo;
import com.ruoyi.workflow.mapper.WfDeployFormMapper;
import com.ruoyi.workflow.service.IWfProcessService;
import com.ruoyi.workflow.service.IWfTaskService;
import lombok.RequiredArgsConstructor;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.StartEvent;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.history.HistoricProcessInstanceQuery;
import org.flowable.engine.repository.Deployment;
@@ -35,6 +43,7 @@ import org.flowable.task.api.history.HistoricTaskInstanceQuery;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -50,6 +59,7 @@ public class WfProcessServiceImpl extends FlowServiceFactory implements IWfProce
private final IWfTaskService wfTaskService;
private final ISysUserService userService;
private final WfDeployFormMapper deployFormMapper;
/**
* 流程定义列表
@@ -82,7 +92,6 @@ public class WfProcessServiceImpl extends FlowServiceFactory implements IWfProce
vo.setProcessKey(processDefinition.getKey());
vo.setProcessName(processDefinition.getName());
vo.setVersion(processDefinition.getVersion());
vo.setCategory(processDefinition.getCategory());
vo.setDeploymentId(processDefinition.getDeploymentId());
vo.setSuspended(processDefinition.isSuspended());
// 流程定义时间
@@ -95,6 +104,23 @@ public class WfProcessServiceImpl extends FlowServiceFactory implements IWfProce
return TableDataInfo.build(page);
}
@Override
public String selectFormContent(String definitionId, String deployId) {
InputStream inputStream = repositoryService.getProcessModel(definitionId);
String bpmnString;
try {
bpmnString = IoUtil.readUtf8(inputStream);
} catch (IORuntimeException exception) {
throw new RuntimeException("获取流程设计失败!");
}
BpmnModel bpmnModel = ModelUtils.getBpmnModel(bpmnString);
StartEvent startEvent = ModelUtils.getStartEvent(bpmnModel);
WfDeployForm deployForm = deployFormMapper.selectVoOne(new LambdaQueryWrapper<WfDeployForm>()
.eq(WfDeployForm::getDeployId, deployId)
.eq(WfDeployForm::getFormKey, startEvent.getFormKey()));
return deployForm.getContent();
}
/**
* 根据流程定义ID启动流程实例
*