工作流模块提交

This commit is contained in:
2024-05-09 14:23:18 +08:00
parent bedd70136b
commit 4936d22884
98 changed files with 6780 additions and 108 deletions

View File

@@ -0,0 +1,70 @@
package com.njcn.bpm.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.njcn.bpm.pojo.param.BpmCategoryParam;
import com.njcn.bpm.pojo.po.BpmCategory;
import com.njcn.bpm.pojo.vo.BpmCategoryVO;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import static com.njcn.bpm.utils.CollectionUtils.convertMap;
/**
* BPM 流程分类 Service 接口
*
* @author 芋道源码
*/
public interface IBpmCategoryService extends IService<BpmCategory> {
/**
* 创建流程分类
*
* @return 编号
*/
String createCategory( BpmCategoryParam bpmCategoryParam);
/**
* 更新流程分类
*
*/
void updateCategory( BpmCategoryParam.BpmCategoryUpdateParam updateParam);
/**
* 删除流程分类
*/
void deleteCategory(List<String> ids);
/**
* 获得流程分类分页
*
* @return 流程分类分页
*/
Page<BpmCategoryVO> getCategoryPage(BpmCategoryParam.BpmCategoryQueryParam bpmCategoryQueryParam);
/**
* 获得流程分类 Map基于指定编码
*
* @param codes 编号数组
* @return 流程分类 Map
*/
default Map<String, BpmCategory> getCategoryMap(Collection<String> codes) {
return convertMap(getCategoryListByCode(codes), BpmCategory::getCode);
}
/**
* 获得流程分类列表,基于指定编码
*
* @return 流程分类列表
*/
List<BpmCategory> getCategoryListByCode(Collection<String> codes);
List<BpmCategory> getCategoryList();
}

View File

@@ -0,0 +1,77 @@
package com.njcn.bpm.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.njcn.bpm.pojo.param.BpmFormParam;
import com.njcn.bpm.pojo.po.BpmForm;
import com.njcn.bpm.pojo.vo.BpmFormVO;
import com.njcn.bpm.utils.CollectionUtils;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 动态表单 Service 接口
*
* @author @风里雾里
*/
public interface IBpmFormService extends IService<BpmForm> {
/**
* 创建动态表单
*
* @return 编号
*/
String createForm(BpmFormParam bpmFormParam);
/**
* 更新动态表单
*
*/
void updateForm(BpmFormParam.BpmFormUpdateParam updateParam);
/**
* 删除动态表单
*
* @param id 编号
*/
void deleteForm(List<String> id);
/**
* 获得动态表单列表
*
* @return 动态表单列表
*/
List<BpmForm> getFormList();
/**
* 获得动态表单列表
*
* @param ids 编号
* @return 动态表单列表
*/
List<BpmForm> getFormList(Collection<String> ids);
/**
* 获得动态表单 Map
*
* @param ids 编号
* @return 动态表单 Map
*/
default Map<String, BpmForm> getFormMap(Collection<String> ids) {
return CollectionUtils.convertMap(this.getFormList(ids), BpmForm::getId);
}
/**
* 获得动态表单分页
*
* @return 动态表单分页
*/
Page<BpmFormVO> getFormPage(BpmFormParam.BpmFormQueryParam bpmFormQueryParam);
}

View File

@@ -0,0 +1,84 @@
package com.njcn.bpm.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.njcn.bpm.pojo.param.BpmModelParam;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.repository.Model;
import javax.validation.Valid;
/**
* Flowable流程模型接口
*
* @author yunlongn
*/
public interface IBpmModelService {
/**
* 获得流程模型分页
*
* @return 流程模型分页
*/
Page<Model> getModelPage(BpmModelParam.BpmModelQueryParam bpmModelQueryParam);
/**
* 创建流程模型
*
* @param bpmnXml BPMN XML
* @return 创建的流程模型的编号
*/
String createModel(BpmModelParam bpmModelParam, String bpmnXml);
/**
* 获得流程模块
*
* @param id 编号
* @return 流程模型
*/
Model getModel(String id);
/**
* 获得流程模型的 BPMN XML
*
* @param id 编号
* @return BPMN XML
*/
byte[] getModelBpmnXML(String id);
/**
* 修改流程模型
*
*/
void updateModel(BpmModelParam.BpmModelUpdateParam updateParam);
/**
* 将流程模型,部署成一个流程定义
*
* @param id 编号
*/
void deployModel(String id);
/**
* 删除模型
*
* @param id 编号
*/
void deleteModel(String id);
/**
* 修改模型的状态,实际更新的部署的流程定义的状态
*
* @param id 编号
* @param state 状态
*/
void updateModelState(String id, Integer state);
/**
* 获得流程定义编号对应的 BPMN Model
*
* @param processDefinitionId 流程定义编号
* @return BPMN Model
*/
BpmnModel getBpmnModelByDefinitionId(String processDefinitionId);
}

View File

@@ -0,0 +1,163 @@
package com.njcn.bpm.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.njcn.bpm.pojo.dto.BpmModelMetaInfoRespDTO;
import com.njcn.bpm.pojo.param.BpmProcessDefinitionInfoParam;
import com.njcn.bpm.pojo.po.BpmForm;
import com.njcn.bpm.pojo.po.BpmProcessDefinitionInfo;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.Model;
import org.flowable.engine.repository.ProcessDefinition;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static com.njcn.bpm.utils.CollectionUtils.convertMap;
/**
* Flowable流程定义接口
*
* @author yunlong.li
* @author ZJQ
* @author 芋道源码
*/
public interface IBpmProcessDefinitionService extends IService<BpmProcessDefinitionInfo> {
/**
* 获得流程定义分页
*
* @return 流程定义 Page
*/
Page<ProcessDefinition> getProcessDefinitionPage(BpmProcessDefinitionInfoParam.BpmProcessDefinitionInfoQueryParam bpmProcessDefinitionInfoQueryParam);
/**
* 获得流程定义列表
*
* @param suspensionState 中断状态
* @return 流程定义列表
*/
List<ProcessDefinition> getProcessDefinitionListBySuspensionState(Integer suspensionState);
/**
* 基于流程模型,创建流程定义
*
* @param model 流程模型
* @param modelMetaInfo 流程模型元信息
* @param bpmnBytes BPMN XML 字节数组
* @param form 表单
* @return 流程编号
*/
String createProcessDefinition(Model model, BpmModelMetaInfoRespDTO modelMetaInfo, byte[] bpmnBytes, BpmForm form);
/**
* 更新流程定义状态
*
* @param id 流程定义的编号
* @param state 状态
*/
void updateProcessDefinitionState(String id, Integer state);
/**
* 获得流程定义对应的 BPMN
*
* @param id 流程定义编号
* @return BPMN
*/
BpmnModel getProcessDefinitionBpmnModel(String id);
/**
* 获得流程定义的信息
*
* @param id 流程定义编号
* @return 流程定义信息
*/
BpmProcessDefinitionInfo getProcessDefinitionInfo(String id);
/**
* 获得流程定义的信息 List
*
* @param ids 流程定义编号数组
* @return 流程额定义信息数组
*/
List<BpmProcessDefinitionInfo> getProcessDefinitionInfoList(Collection<String> ids);
default Map<String, BpmProcessDefinitionInfo> getProcessDefinitionInfoMap(Set<String> ids) {
return convertMap(getProcessDefinitionInfoList(ids), BpmProcessDefinitionInfo::getProcessDefinitionId);
}
/**
* 获得流程定义编号对应的 ProcessDefinition
*
* @param id 流程定义编号
* @return 流程定义
*/
ProcessDefinition getProcessDefinition(String id);
/**
* 获得 ids 对应的 ProcessDefinition 数组
*
* @param ids 编号的数组
* @return 流程定义的数组
*/
List<ProcessDefinition> getProcessDefinitionList(Set<String> ids);
default Map<String, ProcessDefinition> getProcessDefinitionMap(Set<String> ids) {
return convertMap(getProcessDefinitionList(ids), ProcessDefinition::getId);
}
/**
* 获得 deploymentId 对应的 ProcessDefinition
*
* @param deploymentId 部署编号
* @return 流程定义
*/
ProcessDefinition getProcessDefinitionByDeploymentId(String deploymentId);
/**
* 获得 deploymentIds 对应的 ProcessDefinition 数组
*
* @param deploymentIds 部署编号的数组
* @return 流程定义的数组
*/
List<ProcessDefinition> getProcessDefinitionListByDeploymentIds(Set<String> deploymentIds);
/**
* 获得流程定义标识对应的激活的流程定义
*
* @param key 流程定义的标识
* @return 流程定义
*/
ProcessDefinition getActiveProcessDefinition(String key);
/**
* 获得 ids 对应的 Deployment Map
*
* @param ids 部署编号的数组
* @return 流程部署 Map
*/
default Map<String, Deployment> getDeploymentMap(Set<String> ids) {
return convertMap(getDeploymentList(ids), Deployment::getId);
}
/**
* 获得 ids 对应的 Deployment 数组
*
* @param ids 部署编号的数组
* @return 流程部署的数组
*/
List<Deployment> getDeploymentList(Set<String> ids);
/**
* 获得 id 对应的 Deployment
*
* @param id 部署编号
* @return 流程部署
*/
Deployment getDeployment(String id);
}

View File

@@ -0,0 +1,143 @@
package com.njcn.bpm.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.bpm.enums.BpmResponseEnum;
import com.njcn.bpm.mapper.BpmCategoryMapper;
import com.njcn.bpm.pojo.param.BpmCategoryParam;
import com.njcn.bpm.pojo.po.BpmCategory;
import com.njcn.bpm.pojo.po.BpmForm;
import com.njcn.bpm.pojo.vo.BpmCategoryVO;
import com.njcn.bpm.pojo.vo.BpmFormVO;
import com.njcn.bpm.service.IBpmCategoryService;
import com.njcn.bpm.utils.BeanUtils;
import com.njcn.common.pojo.enums.common.DataStateEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.web.factory.PageFactory;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* BPM 流程分类 Service 实现类
*
* @author 芋道源码
*/
@Service
@Validated
public class BpmCategoryServiceImpl extends ServiceImpl<BpmCategoryMapper, BpmCategory> implements IBpmCategoryService {
@Override
public String createCategory(BpmCategoryParam bpmCategoryParam) {
// 校验唯一
checkCategoryName(bpmCategoryParam, false);
checkCategoryCode(bpmCategoryParam, false);
// 插入
BpmCategory category = BeanUtils.toBean(bpmCategoryParam, BpmCategory.class);
this.baseMapper.insert(category);
return category.getId();
}
@Override
public void updateCategory(BpmCategoryParam.BpmCategoryUpdateParam updateParam) {
// 校验唯一
checkCategoryName(updateParam, true);
checkCategoryCode(updateParam, true);
// 更新
BpmCategory updateObj = BeanUtils.toBean(updateParam, BpmCategory.class);
this.baseMapper.updateById(updateObj);
}
@Override
public void deleteCategory(List<String> ids) {
this.lambdaUpdate().set(BpmCategory::getState, DataStateEnum.DELETED.getCode())
.in(BpmCategory::getId, ids)
.update();
}
@Override
public Page<BpmCategoryVO> getCategoryPage(BpmCategoryParam.BpmCategoryQueryParam bpmCategoryQueryParam) {
QueryWrapper<BpmCategoryVO> categoryVOQueryWrapper = new QueryWrapper<>();
if (StrUtil.isNotBlank(bpmCategoryQueryParam.getName())) {
categoryVOQueryWrapper.like("bpm_category.name", bpmCategoryQueryParam.getName());
}
if (StrUtil.isNotBlank(bpmCategoryQueryParam.getCode())) {
categoryVOQueryWrapper.like("bpm_category.name", bpmCategoryQueryParam.getCode());
}
categoryVOQueryWrapper.eq("bpm_category.state", DataStateEnum.ENABLE.getCode());
categoryVOQueryWrapper.orderByDesc("bpm_category.update_time");
return this.baseMapper.page(new Page<>(PageFactory.getPageNum(bpmCategoryQueryParam), PageFactory.getPageSize(bpmCategoryQueryParam)), categoryVOQueryWrapper);
}
@Override
public List<BpmCategory> getCategoryListByCode(Collection<String> codes) {
if (CollUtil.isEmpty(codes)) {
return Collections.emptyList();
}
LambdaQueryWrapper<BpmCategory> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.in(BpmCategory::getCode,codes);
return this.baseMapper.selectList(lambdaQueryWrapper);
}
@Override
public List<BpmCategory> getCategoryList() {
LambdaQueryWrapper<BpmCategory> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.select(BpmCategory::getId,BpmCategory::getName)
.eq(BpmCategory::getState,DataStateEnum.ENABLE.getCode());
return this.baseMapper.selectList(lambdaQueryWrapper);
}
private void checkCategoryName(BpmCategoryParam bpmCategoryParam, boolean isExcludeSelf) {
LambdaQueryWrapper<BpmCategory> categoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
//判断流程表单的名称
categoryLambdaQueryWrapper
.eq(BpmCategory::getName, bpmCategoryParam.getName())
.eq(BpmCategory::getState, DataStateEnum.ENABLE.getCode());
//更新的时候,需排除当前记录
if (isExcludeSelf) {
if (bpmCategoryParam instanceof BpmCategoryParam.BpmCategoryUpdateParam) {
categoryLambdaQueryWrapper.ne(BpmCategory::getId, ((BpmCategoryParam.BpmCategoryUpdateParam) bpmCategoryParam).getId());
}
}
int nameCountByAccount = this.count(categoryLambdaQueryWrapper);
//大于等于1个则表示重复
if (nameCountByAccount >= 1) {
throw new BusinessException(BpmResponseEnum.REPEAT_CATEGORY_NAME_FORM);
}
}
private void checkCategoryCode(BpmCategoryParam bpmCategoryParam, boolean isExcludeSelf) {
LambdaQueryWrapper<BpmCategory> categoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
//判断流程表单的名称
categoryLambdaQueryWrapper
.eq(BpmCategory::getCode, bpmCategoryParam.getCode())
.eq(BpmCategory::getState, DataStateEnum.ENABLE.getCode());
//更新的时候,需排除当前记录
if (isExcludeSelf) {
if (bpmCategoryParam instanceof BpmCategoryParam.BpmCategoryUpdateParam) {
categoryLambdaQueryWrapper.ne(BpmCategory::getId, ((BpmCategoryParam.BpmCategoryUpdateParam) bpmCategoryParam).getId());
}
}
int nameCountByAccount = this.count(categoryLambdaQueryWrapper);
//大于等于1个则表示重复
if (nameCountByAccount >= 1) {
throw new BusinessException(BpmResponseEnum.REPEAT_CATEGORY_NAME_FORM);
}
}
}

View File

@@ -0,0 +1,139 @@
package com.njcn.bpm.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.bpm.enums.BpmResponseEnum;
import com.njcn.bpm.mapper.BpmFormMapper;
import com.njcn.bpm.pojo.param.BpmFormParam;
import com.njcn.bpm.pojo.po.BpmForm;
import com.njcn.bpm.pojo.vo.BpmFormVO;
import com.njcn.bpm.service.IBpmFormService;
import com.njcn.bpm.utils.BeanUtils;
import com.njcn.common.pojo.enums.common.DataStateEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.web.factory.PageFactory;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.util.*;
/**
* 动态表单 Service 实现类
*
* @author 风里雾里
*/
@Service
@Validated
public class BpmFormServiceImpl extends ServiceImpl<BpmFormMapper, BpmForm> implements IBpmFormService {
@Override
public Page<BpmFormVO> getFormPage(BpmFormParam.BpmFormQueryParam bpmFormQueryParam) {
QueryWrapper<BpmFormVO> bpmFormVOQueryWrapper = new QueryWrapper<>();
if (StrUtil.isNotBlank(bpmFormQueryParam.getName())) {
bpmFormVOQueryWrapper.like("bpm_form.name", bpmFormQueryParam.getName());
}
bpmFormVOQueryWrapper.eq("bpm_form.state", DataStateEnum.ENABLE.getCode());
bpmFormVOQueryWrapper.orderByDesc("bpm_form.update_time");
return this.baseMapper.page(new Page<>(PageFactory.getPageNum(bpmFormQueryParam), PageFactory.getPageSize(bpmFormQueryParam)), bpmFormVOQueryWrapper);
}
@Override
public String createForm(BpmFormParam bpmFormParam) {
// this.validateFields(createReqVO.getFields());
checkFormName(bpmFormParam, false);
// 插入
BpmForm form = BeanUtils.toBean(bpmFormParam, BpmForm.class);
this.baseMapper.insert(form);
// 返回
return form.getId();
}
private void checkFormName(BpmFormParam bpmFormParam, boolean isExcludeSelf) {
LambdaQueryWrapper<BpmForm> categoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
//判断流程表单的名称
categoryLambdaQueryWrapper
.eq(BpmForm::getName, bpmFormParam.getName())
.eq(BpmForm::getState, DataStateEnum.ENABLE.getCode());
//更新的时候,需排除当前记录
if (isExcludeSelf) {
if (bpmFormParam instanceof BpmFormParam.BpmFormUpdateParam) {
categoryLambdaQueryWrapper.ne(BpmForm::getId, ((BpmFormParam.BpmFormUpdateParam) bpmFormParam).getId());
}
}
int nameCountByAccount = this.count(categoryLambdaQueryWrapper);
//大于等于1个则表示重复
if (nameCountByAccount >= 1) {
throw new BusinessException(BpmResponseEnum.REPEAT_NAME_FORM);
}
}
@Override
public void updateForm(BpmFormParam.BpmFormUpdateParam updateParam) {
checkFormName(updateParam, true);
BpmForm updateObj = BeanUtils.toBean(updateParam, BpmForm.class);
this.updateById(updateObj);
}
@Override
public void deleteForm(List<String> ids) {
this.lambdaUpdate().set(BpmForm::getState, DataStateEnum.DELETED.getCode())
.in(BpmForm::getId, ids)
.update();
}
// private void validateFormExists(Long id) {
// if (this.baseMapper.selectById(id) == null) {
// throw exception(ErrorCodeConstants.FORM_NOT_EXISTS);
// }
// }
@Override
public List<BpmForm> getFormList() {
LambdaQueryWrapper<BpmForm> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.select(BpmForm::getId,BpmForm::getName)
.eq(BpmForm::getState,DataStateEnum.ENABLE.getCode());
return this.baseMapper.selectList(lambdaQueryWrapper);
}
@Override
public List<BpmForm> getFormList(Collection<String> ids) {
if (CollUtil.isEmpty(ids)) {
return Collections.emptyList();
}
return this.baseMapper.selectBatchIds(ids);
}
/**
* 校验 Field避免 field 重复
*
* @param fields field 数组
*/
private void validateFields(List<String> fields) {
if (true) { // TODO 芋艿:兼容 Vue3 工作流:因为采用了新的表单设计器,所以暂时不校验
return;
}
// Map<String, String> fieldMap = new HashMap<>(); // key 是 vModelvalue 是 label
// for (String field : fields) {
// BpmFormFieldRespDTO fieldDTO = JsonUtils.parseObject(field, BpmFormFieldRespDTO.class);
// Assert.notNull(fieldDTO);
// String oldLabel = fieldMap.put(fieldDTO.getVModel(), fieldDTO.getLabel());
// // 如果不存在,则直接返回
// if (oldLabel == null) {
// continue;
// }
// // 如果存在,则报错
// throw exception(ErrorCodeConstants.FORM_FIELD_REPEAT, oldLabel, fieldDTO.getLabel(), fieldDTO.getVModel());
// }
}
}

View File

@@ -0,0 +1,283 @@
package com.njcn.bpm.service.impl;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.njcn.bpm.enums.BpmModelFormTypeEnum;
import com.njcn.bpm.enums.BpmResponseEnum;
import com.njcn.bpm.pojo.dto.BpmModelMetaInfoRespDTO;
import com.njcn.bpm.pojo.param.BpmModelParam;
import com.njcn.bpm.pojo.po.BpmForm;
import com.njcn.bpm.service.IBpmFormService;
import com.njcn.bpm.service.IBpmModelService;
import com.njcn.bpm.service.IBpmProcessDefinitionService;
import com.njcn.bpm.strategy.BpmTaskCandidateInvoker;
import com.njcn.bpm.utils.*;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.web.factory.PageFactory;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.StartEvent;
import org.flowable.bpmn.model.UserTask;
import org.flowable.common.engine.impl.db.SuspensionState;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Model;
import org.flowable.engine.repository.ModelQuery;
import org.flowable.engine.repository.ProcessDefinition;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
import java.util.Objects;
/**
* Flowable流程模型实现
* 主要进行 Flowable {@link Model} 的维护
*
* @author yunlongn
* @author 芋道源码
* @author jason
*/
@Service
@Validated
@Slf4j
public class BpmModelServiceImpl implements IBpmModelService {
@Resource
private RepositoryService repositoryService;
@Resource
private IBpmProcessDefinitionService processDefinitionService;
@Resource
private IBpmFormService bpmFormService;
@Resource
private BpmTaskCandidateInvoker taskCandidateInvoker;
@Override
public Page<Model> getModelPage(BpmModelParam.BpmModelQueryParam bpmModelQueryParam) {
ModelQuery modelQuery = repositoryService.createModelQuery();
if (StrUtil.isNotBlank(bpmModelQueryParam.getKey())) {
modelQuery.modelKey(bpmModelQueryParam.getKey());
}
if (StrUtil.isNotBlank(bpmModelQueryParam.getName())) {
modelQuery.modelNameLike("%" + bpmModelQueryParam.getName() + "%"); // 模糊匹配
}
if (StrUtil.isNotBlank(bpmModelQueryParam.getCategory())) {
modelQuery.modelCategory(bpmModelQueryParam.getCategory());
}
// 执行查询
long count = modelQuery.count();
if (count == 0) {
return new Page<>();
}
int offset = PageFactory.getPageSize(bpmModelQueryParam) * (PageFactory.getPageNum(bpmModelQueryParam) - 1);
List<Model> models = modelQuery
.modelTenantId(ProcessEngineConfiguration.NO_TENANT_ID)
.orderByCreateTime().desc()
.listPage(offset, PageFactory.getPageSize(bpmModelQueryParam));
Page<Model> page = new Page<>();
page.setRecords(models);
page.setTotal(count);
page.setSize(PageFactory.getPageSize(bpmModelQueryParam));
page.setCurrent(PageFactory.getPageNum(bpmModelQueryParam));
return page;
}
@Override
@Transactional(rollbackFor = Exception.class)
public String createModel(BpmModelParam bpmModelParam, String bpmnXml) {
if (!ValidationUtils.isXmlNCName(bpmModelParam.getKey())) {
throw new BusinessException(BpmResponseEnum.BPM_XML_ERROR);
}
// 校验流程标识已经存在
Model keyModel = getModelByKey(bpmModelParam.getKey());
if (keyModel != null) {
throw new BusinessException(BpmResponseEnum.BPM_MODEL_REPEAT);
}
// 创建流程定义
Model model = repositoryService.newModel();
BpmModelConvert.INSTANCE.copyToCreateModel(model, bpmModelParam);
model.setTenantId(FlowableUtils.getTenantId());
// 保存流程定义
repositoryService.saveModel(model);
// 保存 BPMN XML
saveModelBpmnXml(model, bpmnXml);
return model.getId();
}
@Override
@Transactional(rollbackFor = Exception.class) // 因为进行多个操作,所以开启事务
public void updateModel(BpmModelParam.BpmModelUpdateParam updateParam) {
// 校验流程模型存在
Model model = getModel(updateParam.getId());
if (model == null) {
throw new BusinessException(BpmResponseEnum.BPM_MODEL_NOT_EXIST);
}
// 修改流程定义
BpmModelConvert.INSTANCE.copyToUpdateModel(model, updateParam);
// 更新模型
repositoryService.saveModel(model);
// 更新 BPMN XML
saveModelBpmnXml(model, updateParam.getBpmnXml());
}
@Override
@Transactional(rollbackFor = Exception.class) // 因为进行多个操作,所以开启事务
public void deployModel(String id) {
// 1.1 校验流程模型存在
Model model = getModel(id);
if (ObjectUtils.isEmpty(model)) {
throw new BusinessException(BpmResponseEnum.BPM_MODEL_NOT_EXIST);
}
// 1.2 校验流程图
byte[] bpmnBytes = getModelBpmnXML(model.getId());
validateBpmnXml(bpmnBytes);
// 1.3 校验表单已配
BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class);
BpmForm form = validateFormConfig(metaInfo);
// 1.4 校验任务分配规则已配置
taskCandidateInvoker.validateBpmnConfig(bpmnBytes);
// 2.1 创建流程定义
String definitionId = processDefinitionService.createProcessDefinition(model, metaInfo, bpmnBytes, form);
// 2.2 将老的流程定义进行挂起。也就是说,只有最新部署的流程定义,才可以发起任务。
updateProcessDefinitionSuspended(model.getDeploymentId());
// 2.3 更新 model 的 deploymentId进行关联
ProcessDefinition definition = processDefinitionService.getProcessDefinition(definitionId);
model.setDeploymentId(definition.getDeploymentId());
repositoryService.saveModel(model);
}
private void validateBpmnXml(byte[] bpmnBytes) {
BpmnModel bpmnModel = BpmnModelUtils.getBpmnModel(bpmnBytes);
if (bpmnModel == null) {
throw new BusinessException(BpmResponseEnum.BPM_MODEL_NOT_EXIST);
}
// 1. 没有 StartEvent
StartEvent startEvent = BpmnModelUtils.getStartEvent(bpmnModel);
if (startEvent == null) {
throw new BusinessException(BpmResponseEnum.BPM_START_EVENT_NOT_EXIST);
}
// 2. 校验 UserTask 的 name 都配置了
List<UserTask> userTasks = BpmnModelUtils.getBpmnModelElements(bpmnModel, UserTask.class);
UserTask userTask1 = userTasks.get(0);
userTask1.getName();
userTasks.forEach(userTask -> {
if (StrUtil.isEmpty(userTask.getName())) {
throw new BusinessException(BpmResponseEnum.MODEL_DEPLOY_FAIL_BPMN_USER_TASK_NAME_NOT_EXISTS);
}
});
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteModel(String id) {
// 校验流程模型存在
Model model = getModel(id);
if (model == null) {
throw new BusinessException(BpmResponseEnum.BPM_MODEL_NOT_EXIST);
}
// 执行删除
repositoryService.deleteModel(id);
// 禁用流程定义
updateProcessDefinitionSuspended(model.getDeploymentId());
}
@Override
public void updateModelState(String id, Integer state) {
// 1.1 校验流程模型存在
Model model = getModel(id);
if (model == null) {
throw new BusinessException(BpmResponseEnum.BPM_MODEL_NOT_EXIST);
}
// 1.2 校验流程定义存在
ProcessDefinition definition = processDefinitionService.getProcessDefinitionByDeploymentId(model.getDeploymentId());
if (definition == null) {
throw new BusinessException(BpmResponseEnum.PROCESS_DEFINITION_NOT_EXISTS);
}
// 2. 更新状态
processDefinitionService.updateProcessDefinitionState(definition.getId(), state);
}
@Override
public BpmnModel getBpmnModelByDefinitionId(String processDefinitionId) {
return repositoryService.getBpmnModel(processDefinitionId);
}
/**
* 校验流程表单已配置
*
* @param metaInfo 流程模型元数据
* @return 表单配置
*/
private BpmForm validateFormConfig(BpmModelMetaInfoRespDTO metaInfo) {
if (metaInfo == null || metaInfo.getFormType() == null) {
throw new BusinessException(BpmResponseEnum.MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG);
}
// 校验表单存在
if (Objects.equals(metaInfo.getFormType(), BpmModelFormTypeEnum.NORMAL.getType())) {
if (metaInfo.getFormId() == null) {
throw new BusinessException(BpmResponseEnum.MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG);
}
BpmForm form = bpmFormService.getById(metaInfo.getFormId());
if (form == null) {
throw new BusinessException(BpmResponseEnum.FORM_NOT_EXISTS);
}
return form;
} else {
if (StrUtil.isEmpty(metaInfo.getFormCustomCreatePath()) || StrUtil.isEmpty(metaInfo.getFormCustomViewPath())) {
throw new BusinessException(BpmResponseEnum.MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG);
}
return null;
}
}
private void saveModelBpmnXml(Model model, String bpmnXml) {
if (StrUtil.isEmpty(bpmnXml)) {
return;
}
repositoryService.addModelEditorSource(model.getId(), StrUtil.utf8Bytes(bpmnXml));
}
/**
* 挂起 deploymentId 对应的流程定义
* <p>
* 注意:这里一个 deploymentId 只关联一个流程定义
*
* @param deploymentId 流程发布Id
*/
private void updateProcessDefinitionSuspended(String deploymentId) {
if (StrUtil.isEmpty(deploymentId)) {
return;
}
ProcessDefinition oldDefinition = processDefinitionService.getProcessDefinitionByDeploymentId(deploymentId);
if (oldDefinition == null) {
return;
}
processDefinitionService.updateProcessDefinitionState(oldDefinition.getId(), SuspensionState.SUSPENDED.getStateCode());
}
private Model getModelByKey(String key) {
return repositoryService.createModelQuery().modelKey(key).singleResult();
}
@Override
public Model getModel(String id) {
return repositoryService.getModel(id);
}
@Override
public byte[] getModelBpmnXML(String id) {
return repositoryService.getModelEditorSource(id);
}
}

View File

@@ -0,0 +1,218 @@
package com.njcn.bpm.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.bpm.enums.BpmnModelConstants;
import com.njcn.bpm.mapper.BpmCategoryMapper;
import com.njcn.bpm.mapper.BpmProcessDefinitionInfoMapper;
import com.njcn.bpm.pojo.dto.BpmModelMetaInfoRespDTO;
import com.njcn.bpm.pojo.param.BpmProcessDefinitionInfoParam;
import com.njcn.bpm.pojo.po.BpmForm;
import com.njcn.bpm.pojo.po.BpmProcessDefinitionInfo;
import com.njcn.bpm.service.IBpmProcessDefinitionService;
import com.njcn.bpm.utils.BeanUtils;
import com.njcn.bpm.utils.FlowableUtils;
import com.njcn.common.pojo.enums.common.DataStateEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.web.factory.PageFactory;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.common.engine.impl.db.SuspensionState;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.Model;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.repository.ProcessDefinitionQuery;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.*;
import static com.njcn.bpm.utils.CollectionUtils.addIfNotNull;
import static java.util.Collections.emptyList;
/**
* 流程定义实现
* 主要进行 Flowable {@link ProcessDefinition} 和 {@link Deployment} 的维护
*
* @author yunlongn
* @author ZJQ
* @author 芋道源码
*/
@Service
@Validated
@Slf4j
public class BpmProcessDefinitionServiceImpl extends ServiceImpl<BpmProcessDefinitionInfoMapper, BpmProcessDefinitionInfo> implements IBpmProcessDefinitionService {
@Resource
private RepositoryService repositoryService;
@Override
public Page<ProcessDefinition> getProcessDefinitionPage(BpmProcessDefinitionInfoParam.BpmProcessDefinitionInfoQueryParam bpmProcessDefinitionInfoQueryParam) {
ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
if (StrUtil.isNotBlank(bpmProcessDefinitionInfoQueryParam.getKey())) {
query.processDefinitionKey(bpmProcessDefinitionInfoQueryParam.getKey());
}
// 执行查询
long count = query.count();
if (count == 0) {
return new Page<>();
}
int offset = PageFactory.getPageSize(bpmProcessDefinitionInfoQueryParam) * (PageFactory.getPageNum(bpmProcessDefinitionInfoQueryParam) - 1);
List<ProcessDefinition> processDefinitionList = query.orderByProcessDefinitionVersion().desc()
.listPage(offset, PageFactory.getPageSize(bpmProcessDefinitionInfoQueryParam));
Page<ProcessDefinition> page = new Page<>();
page.setRecords(processDefinitionList);
page.setTotal(count);
page.setSize(PageFactory.getPageSize(bpmProcessDefinitionInfoQueryParam));
page.setCurrent(PageFactory.getPageNum(bpmProcessDefinitionInfoQueryParam));
return page;
}
@Override
public ProcessDefinition getProcessDefinition(String id) {
return repositoryService.getProcessDefinition(id);
}
@Override
public List<ProcessDefinition> getProcessDefinitionList(Set<String> ids) {
return repositoryService.createProcessDefinitionQuery().processDefinitionIds(ids).list();
}
@Override
public ProcessDefinition getProcessDefinitionByDeploymentId(String deploymentId) {
if (StrUtil.isEmpty(deploymentId)) {
return null;
}
return repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
}
@Override
public List<ProcessDefinition> getProcessDefinitionListByDeploymentIds(Set<String> deploymentIds) {
if (CollUtil.isEmpty(deploymentIds)) {
return emptyList();
}
return repositoryService.createProcessDefinitionQuery().deploymentIds(deploymentIds).list();
}
@Override
public ProcessDefinition getActiveProcessDefinition(String key) {
return repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).active().singleResult();
}
@Override
public List<Deployment> getDeploymentList(Set<String> ids) {
if (CollUtil.isEmpty(ids)) {
return emptyList();
}
List<Deployment> list = new ArrayList<>(ids.size());
for (String id : ids) {
addIfNotNull(list, getDeployment(id));
}
return list;
}
@Override
public Deployment getDeployment(String id) {
if (StrUtil.isEmpty(id)) {
return null;
}
return repositoryService.createDeploymentQuery().deploymentId(id).singleResult();
}
@Override
public String createProcessDefinition(Model model, BpmModelMetaInfoRespDTO modelMetaInfo,
byte[] bpmnBytes, BpmForm form) {
// 创建 Deployment 部署
Deployment deploy = repositoryService.createDeployment()
.key(model.getKey()).name(model.getName()).category(model.getCategory())
.addBytes(model.getKey() + BpmnModelConstants.BPMN_FILE_SUFFIX, bpmnBytes)
.tenantId(FlowableUtils.getTenantId())
.disableSchemaValidation() // 禁用 XML Schema 验证,因为有自定义的属性
.deploy();
// 设置 ProcessDefinition 的 category 分类
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery()
.deploymentId(deploy.getId()).singleResult();
repositoryService.setProcessDefinitionCategory(definition.getId(), model.getCategory());
// 注意 1ProcessDefinition 的 key 和 name 是通过 BPMN 中的 <bpmn2:process /> 的 id 和 name 决定
// 注意 2目前该项目的设计上需要保证 Model、Deployment、ProcessDefinition 使用相同的 key保证关联性。
// 否则,会导致 ProcessDefinition 的分页无法查询到。
if (!Objects.equals(definition.getKey(), model.getKey())) {
throw new BusinessException("流程定义的标识期望是(" + model.getKey() + "),当前是(" + definition.getKey() + "),请修改 BPMN 流程图");
}
if (!Objects.equals(definition.getName(), model.getName())) {
throw new BusinessException("流程定义的名字期望是(" + model.getName() + "),当前是(" + definition.getName() + "),请修改 BPMN 流程图");
}
// 插入拓展表
BpmProcessDefinitionInfo definitionDO = BeanUtils.toBean(modelMetaInfo, BpmProcessDefinitionInfo.class);
definitionDO.setModelId(model.getId());
definitionDO.setProcessDefinitionId(definition.getId());
if (form != null) {
definitionDO.setFormFields(form.getFields());
definitionDO.setFormConf(form.getConf());
}
this.baseMapper.insert(definitionDO);
return definition.getId();
}
@Override
public void updateProcessDefinitionState(String id, Integer state) {
// 激活
if (Objects.equals(SuspensionState.ACTIVE.getStateCode(), state)) {
repositoryService.activateProcessDefinitionById(id, false, null);
return;
}
// 挂起
if (Objects.equals(SuspensionState.SUSPENDED.getStateCode(), state)) {
// suspendProcessInstances = false进行中的任务不进行挂起。
// 原因:只要新的流程不允许发起即可,老流程继续可以执行。
repositoryService.suspendProcessDefinitionById(id, false, null);
return;
}
log.error("[updateProcessDefinitionState][流程定义({}) 修改未知状态({})]", id, state);
}
@Override
public BpmnModel getProcessDefinitionBpmnModel(String id) {
return repositoryService.getBpmnModel(id);
}
@Override
public BpmProcessDefinitionInfo getProcessDefinitionInfo(String id) {
LambdaQueryWrapper<BpmProcessDefinitionInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(BpmProcessDefinitionInfo::getProcessDefinitionId, id);
return this.baseMapper.selectOne(lambdaQueryWrapper);
}
@Override
public List<BpmProcessDefinitionInfo> getProcessDefinitionInfoList(Collection<String> ids) {
LambdaQueryWrapper<BpmProcessDefinitionInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(BpmProcessDefinitionInfo::getProcessDefinitionId, ids)
.eq(BpmProcessDefinitionInfo::getState, DataStateEnum.ENABLE.getCode());
return this.baseMapper.selectList(lambdaQueryWrapper);
}
@Override
public List<ProcessDefinition> getProcessDefinitionListBySuspensionState(Integer suspensionState) {
// 拼接查询条件
ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
if (Objects.equals(SuspensionState.SUSPENDED.getStateCode(), suspensionState)) {
query.suspended();
} else if (Objects.equals(SuspensionState.ACTIVE.getStateCode(), suspensionState)) {
query.active();
}
// 执行查询
query.processDefinitionTenantId(FlowableUtils.getTenantId());
return query.list();
}
}

View File

@@ -0,0 +1,139 @@
package com.njcn.bpm.service.task;
import org.flowable.engine.delegate.event.FlowableCancelledEvent;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static com.njcn.bpm.utils.CollectionUtils.convertMap;
/**
* 流程实例 Service 接口
*
* @author 芋道源码
*/
public interface IBpmProcessInstanceService {
/**
* 获得流程实例
*
* @param id 流程实例的编号
* @return 流程实例
*/
ProcessInstance getProcessInstance(String id);
//
// /**
// * 获得流程实例列表
// *
// * @param ids 流程实例的编号集合
// * @return 流程实例列表
// */
// List<ProcessInstance> getProcessInstances(Set<String> ids);
//
// /**
// * 获得流程实例 Map
// *
// * @param ids 流程实例的编号集合
// * @return 流程实例列表 Map
// */
// default Map<String, ProcessInstance> getProcessInstanceMap(Set<String> ids) {
// return convertMap(getProcessInstances(ids), ProcessInstance::getProcessInstanceId);
// }
//
// /**
// * 获得历史的流程实例
// *
// * @param id 流程实例的编号
// * @return 历史的流程实例
// */
// HistoricProcessInstance getHistoricProcessInstance(String id);
//
// /**
// * 获得历史的流程实例列表
// *
// * @param ids 流程实例的编号集合
// * @return 历史的流程实例列表
// */
// List<HistoricProcessInstance> getHistoricProcessInstances(Set<String> ids);
//
// /**
// * 获得历史的流程实例 Map
// *
// * @param ids 流程实例的编号集合
// * @return 历史的流程实例列表 Map
// */
// default Map<String, HistoricProcessInstance> getHistoricProcessInstanceMap(Set<String> ids) {
// return convertMap(getHistoricProcessInstances(ids), HistoricProcessInstance::getId);
// }
//
// /**
// * 获得流程实例的分页
// *
// * @param userId 用户编号
// * @param pageReqVO 分页请求
// * @return 流程实例的分页
// */
// PageResult<HistoricProcessInstance> getProcessInstancePage(Long userId, @Valid BpmProcessInstancePageReqVO pageReqVO);
//
// /**
// * 创建流程实例(提供给前端)
// *
// * @param userId 用户编号
// * @param createReqVO 创建信息
// * @return 实例的编号
// */
// String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO);
//
// /**
// * 创建流程实例(提供给内部)
// *
// * @param userId 用户编号
// * @param createReqDTO 创建信息
// * @return 实例的编号
// */
// String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO);
//
// /**
// * 发起人取消流程实例
// *
// * @param userId 用户编号
// * @param cancelReqVO 取消信息
// */
// void cancelProcessInstanceByStartUser(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO);
//
// /**
// * 管理员取消流程实例
// *
// * @param userId 用户编号
// * @param cancelReqVO 取消信息
// */
// void cancelProcessInstanceByAdmin(Long userId, BpmProcessInstanceCancelReqVO cancelReqVO);
//
// /**
// * 更新 ProcessInstance 拓展记录为取消
// *
// * @param event 流程取消事件
// */
// void updateProcessInstanceWhenCancel(FlowableCancelledEvent event);
//
// /**
// * 更新 ProcessInstance 拓展记录为完成
// *
// * @param instance 流程任务
// */
// void updateProcessInstanceWhenApprove(ProcessInstance instance);
//
// /**
// * 更新 ProcessInstance 拓展记录为不通过
// *
// * @param id 流程编号
// * @param reason 理由。例如说,审批不通过时,需要传递该值
// */
// void updateProcessInstanceReject(String id, String reason);
}

View File

@@ -0,0 +1,292 @@
package com.njcn.bpm.service.task.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.njcn.bpm.service.task.IBpmProcessInstanceService;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.UserTask;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.delegate.event.FlowableCancelledEvent;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.history.HistoricProcessInstanceQuery;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.*;
/**
* 流程实例 Service 实现类
*
* ProcessDefinition & ProcessInstance & Execution & Task 的关系:
* 1. <a href="https://blog.csdn.net/bobozai86/article/details/105210414" />
*
* HistoricProcessInstance & ProcessInstance 的关系:
* 1. <a href=" https://my.oschina.net/843294669/blog/71902" />
*
* 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例
*
* @author 芋道源码
*/
@Service
@Validated
@Slf4j
public class BpmProcessInstanceServiceImpl implements IBpmProcessInstanceService {
@Resource
private RuntimeService runtimeService;
@Resource
private HistoryService historyService;
// @Resource
// private BpmProcessDefinitionService processDefinitionService;
// @Resource
// private BpmMessageService messageService;
//
// @Resource
// private AdminUserApi adminUserApi;
//
// @Resource
// private BpmProcessInstanceEventPublisher processInstanceEventPublisher;
@Override
public ProcessInstance getProcessInstance(String id) {
return runtimeService.createProcessInstanceQuery()
.includeProcessVariables()
.processInstanceId(id)
.singleResult();
}
//
// @Override
// public List<ProcessInstance> getProcessInstances(Set<String> ids) {
// return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list();
// }
//
// @Override
// public HistoricProcessInstance getHistoricProcessInstance(String id) {
// return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).includeProcessVariables().singleResult();
// }
//
// @Override
// public List<HistoricProcessInstance> getHistoricProcessInstances(Set<String> ids) {
// return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list();
// }
//
// @Override
// public PageResult<HistoricProcessInstance> getProcessInstancePage(Long userId,
// BpmProcessInstancePageReqVO pageReqVO) {
// // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页
// HistoricProcessInstanceQuery processInstanceQuery = historyService.createHistoricProcessInstanceQuery()
// .includeProcessVariables()
// .processInstanceTenantId(FlowableUtils.getTenantId())
// .orderByProcessInstanceStartTime().desc();
// if (userId != null) { // 【我的流程】菜单时,需要传递该字段
// processInstanceQuery.startedBy(String.valueOf(userId));
// } else if (pageReqVO.getStartUserId() != null) { // 【管理流程】菜单时,才会传递该字段
// processInstanceQuery.startedBy(String.valueOf(pageReqVO.getStartUserId()));
// }
// if (StrUtil.isNotEmpty(pageReqVO.getName())) {
// processInstanceQuery.processInstanceNameLike("%" + pageReqVO.getName() + "%");
// }
// if (StrUtil.isNotEmpty(pageReqVO.getProcessDefinitionId())) {
// processInstanceQuery.processDefinitionId("%" + pageReqVO.getProcessDefinitionId() + "%");
// }
// if (StrUtil.isNotEmpty(pageReqVO.getCategory())) {
// processInstanceQuery.processDefinitionCategory(pageReqVO.getCategory());
// }
// if (pageReqVO.getStatus() != null) {
// processInstanceQuery.variableValueEquals(BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, pageReqVO.getStatus());
// }
// if (ArrayUtil.isNotEmpty(pageReqVO.getCreateTime())) {
// processInstanceQuery.startedAfter(DateUtils.of(pageReqVO.getCreateTime()[0]));
// processInstanceQuery.startedBefore(DateUtils.of(pageReqVO.getCreateTime()[1]));
// }
// // 查询数量
// long processInstanceCount = processInstanceQuery.count();
// if (processInstanceCount == 0) {
// return PageResult.empty(processInstanceCount);
// }
// // 查询列表
// List<HistoricProcessInstance> processInstanceList = processInstanceQuery.listPage(PageUtils.getStart(pageReqVO), pageReqVO.getPageSize());
// return new PageResult<>(processInstanceList, processInstanceCount);
// }
//
// @Override
// @Transactional(rollbackFor = Exception.class)
// public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) {
// // 获得流程定义
// ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId());
// // 发起流程
// return createProcessInstance0(userId, definition, createReqVO.getVariables(), null,
// createReqVO.getStartUserSelectAssignees());
// }
//
// @Override
// public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) {
// // 获得流程定义
// ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey());
// // 发起流程
// return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey(),
// createReqDTO.getStartUserSelectAssignees());
// }
//
// private String createProcessInstance0(Long userId, ProcessDefinition definition,
// Map<String, Object> variables, String businessKey,
// Map<String, List<Long>> startUserSelectAssignees) {
// // 1.1 校验流程定义
// if (definition == null) {
// throw exception(PROCESS_DEFINITION_NOT_EXISTS);
// }
// if (definition.isSuspended()) {
// throw exception(PROCESS_DEFINITION_IS_SUSPENDED);
// }
// // 1.2 校验发起人自选审批人
// validateStartUserSelectAssignees(definition, startUserSelectAssignees);
//
// // 2. 创建流程实例
// if (variables == null) {
// variables = new HashMap<>();
// }
// FlowableUtils.filterProcessInstanceFormVariable(variables); // 过滤一下,避免 ProcessInstance 系统级的变量被占用
// variables.put(BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, // 流程实例状态:审批中
// BpmProcessInstanceStatusEnum.RUNNING.getStatus());
// if (CollUtil.isNotEmpty(startUserSelectAssignees)) {
// variables.put(BpmConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES, startUserSelectAssignees);
// }
// ProcessInstance instance = runtimeService.createProcessInstanceBuilder()
// .processDefinitionId(definition.getId())
// .businessKey(businessKey)
// .name(definition.getName().trim())
// .variables(variables)
// .start();
// return instance.getId();
// }
//
// private void validateStartUserSelectAssignees(ProcessDefinition definition, Map<String, List<Long>> startUserSelectAssignees) {
// // 1. 获得发起人自选审批人的 UserTask 列表
// BpmnModel bpmnModel = processDefinitionService.getProcessDefinitionBpmnModel(definition.getId());
// List<UserTask> userTaskList = BpmTaskCandidateStartUserSelectStrategy.getStartUserSelectUserTaskList(bpmnModel);
// if (CollUtil.isEmpty(userTaskList)) {
// return;
// }
//
// // 2. 校验发起人自选审批人的 UserTask 是否都配置了
// userTaskList.forEach(userTask -> {
// List<Long> assignees = startUserSelectAssignees != null ? startUserSelectAssignees.get(userTask.getId()) : null;
// if (CollUtil.isEmpty(assignees)) {
// throw exception(PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_CONFIG, userTask.getName());
// }
// Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(assignees);
// assignees.forEach(assignee -> {
// if (userMap.get(assignee) == null) {
// throw exception(PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_EXISTS, userTask.getName(), assignee);
// }
// });
// });
// }
//
// @Override
// public void cancelProcessInstanceByStartUser(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) {
// // 1.1 校验流程实例存在
// ProcessInstance instance = getProcessInstance(cancelReqVO.getId());
// if (instance == null) {
// throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS);
// }
// // 1.2 只能取消自己的
// if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) {
// throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF);
// }
//
// // 2. 通过删除流程实例,实现流程实例的取消,
// // 删除流程实例,正则执行任务 ACT_RU_TASK. 任务会被删除。
// deleteProcessInstance(cancelReqVO.getId(),
// BpmDeleteReasonEnum.CANCEL_PROCESS_INSTANCE_BY_START_USER.format(cancelReqVO.getReason()));
//
// // 3. 进一步的处理,交给 updateProcessInstanceCancel 方法
// }
//
// @Override
// public void cancelProcessInstanceByAdmin(Long userId, BpmProcessInstanceCancelReqVO cancelReqVO) {
// // 1.1 校验流程实例存在
// ProcessInstance instance = getProcessInstance(cancelReqVO.getId());
// if (instance == null) {
// throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS);
// }
// // 1.2 管理员取消,不用校验是否为自己的
// AdminUserRespDTO user = adminUserApi.getUser(userId);
//
// // 2. 通过删除流程实例,实现流程实例的取消,
// // 删除流程实例,正则执行任务 ACT_RU_TASK. 任务会被删除。
// deleteProcessInstance(cancelReqVO.getId(),
// BpmDeleteReasonEnum.CANCEL_PROCESS_INSTANCE_BY_ADMIN.format(user.getNickname(), cancelReqVO.getReason()));
//
// // 3. 进一步的处理,交给 updateProcessInstanceCancel 方法
// }
//
// @Override
// public void updateProcessInstanceWhenCancel(FlowableCancelledEvent event) {
// // 1. 判断是否为 Reject 不通过。如果是,则不进行更新.
// // 因为updateProcessInstanceReject 方法(审批不通过),已经进行更新了
// if (BpmDeleteReasonEnum.isRejectReason((String) event.getCause())) {
// return;
// }
//
// // 2. 更新流程实例 status
// runtimeService.setVariable(event.getProcessInstanceId(), BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS,
// BpmProcessInstanceStatusEnum.CANCEL.getStatus());
//
// // 3. 发送流程实例的状态事件
// // 注意:此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance
// HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId());
// // 发送流程实例的状态事件
// processInstanceEventPublisher.sendProcessInstanceResultEvent(
// BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceStatusEvent(this, processInstance, BpmProcessInstanceStatusEnum.CANCEL.getStatus()));
// }
//
// @Override
// public void updateProcessInstanceWhenApprove(ProcessInstance instance) {
// // 1. 更新流程实例 status
// runtimeService.setVariable(instance.getId(), BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS,
// BpmProcessInstanceStatusEnum.APPROVE.getStatus());
//
// // 2. 发送流程被【通过】的消息
// messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceApproveMessage(instance));
//
// // 3. 发送流程实例的状态事件
// // 注意:此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance
// HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId());
// processInstanceEventPublisher.sendProcessInstanceResultEvent(
// BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceStatusEvent(this, processInstance, BpmProcessInstanceStatusEnum.APPROVE.getStatus()));
// }
//
// @Override
// @Transactional(rollbackFor = Exception.class)
// public void updateProcessInstanceReject(String id, String reason) {
// // 1. 更新流程实例 status
// runtimeService.setVariable(id, BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, BpmProcessInstanceStatusEnum.REJECT.getStatus());
//
// // 2. 删除流程实例,以实现驳回任务时,取消整个审批流程
// ProcessInstance processInstance = getProcessInstance(id);
// deleteProcessInstance(id, StrUtil.format(BpmDeleteReasonEnum.REJECT_TASK.format(reason)));
//
// // 3. 发送流程被【不通过】的消息
// messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceRejectMessage(processInstance, reason));
//
// // 4. 发送流程实例的状态事件
// processInstanceEventPublisher.sendProcessInstanceResultEvent(
// BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceStatusEvent(this, processInstance, BpmProcessInstanceStatusEnum.REJECT.getStatus()));
// }
//
// private void deleteProcessInstance(String id, String reason) {
// runtimeService.deleteProcessInstance(id, reason);
// }
}