# 流程操作权限扩展
# 背景&需求
支持客户对流程操作权限的特殊需求,可实现BPM暴露的扩展接口,实现自定义逻辑。
# 操作步骤&解决方案
BPM提供权限扩展接口BpmOperationSpi,三方SPI工程依赖bpm-facade工程,实现此接口方法,对流程节点权限的校验做扩展处理。BPM服务加载运行时,会执行此工程实现类的逻辑,对流程节点权限进行定制化的校验。
BPM SPI扩展方案 : https://docs.qq.com/doc/DYkZHZFVtdHpNRVd6 V8平台SPI扩展机制和开发文档: https://www.yuque.com/teamdocs/v8-client-kb/nizgyacv5x4oh0wh
# 接口信息:
/**
* 流程操作权限扩展接口SPI
**/
public interface BpmOperationSpi {
/**
* 节点权限操作校验
* @param requestDto 校验参数
* @return 校验结果
*/
BpmCheckNodePermissionResp checkNodePermission(BpmCheckNodePermissionReq requestDto);
}
###参数说明: ####入参:
@DtoInfo("节点权限操作校验请求")
public class BpmCheckNodePermissionReq {
@DtoAttribute("流程实例ID")
private Long caseId;
@DtoAttribute("事项ID")
private Long affairId;
@DtoAttribute("节点权限ID")
private Long permissionId;
@DtoAttribute("意见实体")
private BpmCommentDto commentDto;
@DtoAttribute("操作编码")
private String operationCode;
####出参:
@DtoInfo("节点权限操作校验响应")
public class BpmCheckNodePermissionResp {
@DtoAttribute("是否通过操作合法校验")
private boolean passOperationVerify = false;
@DtoAttribute("是否通过操作意见必填校验")
private boolean passCommentRequiredVerify = false;
@DtoAttribute("是否通过操作意见长度校验")
private boolean passCommentLengthVerify = false;
###操作步骤:
# 第一步:
创建工程:依赖bpm-facade
<dependency>
<groupId>com.seeyon</groupId>
<artifactId>bpm-facade</artifactId>
<version>3.15.0-DEV-SNAPSHOT</version>
</dependency>
# 第二步:
实现接口BpmOperationSpi 重写方法checkNodePermission
public class BpmOperationSpiImpl implements BpmOperationSpi {
@Override
public BpmCheckNodePermissionResp checkNodePermission(BpmCheckNodePermissionReq bpmCheckNodePermissionReq) {
}
}
# DEMO:
####业务需求: 客户将节点权限做了合并处理,一个节点权限下拥有了除本身流程操作外,还自定义添加了其他操作,那么当执行绑定了此节点权限的事项时,节点权限校验需要自定义实现,校验自定义后的全量操作。 ####实现代码:
@Slf4j
public class BpmOperationSpiImpl implements BpmOperationSpi {
@Override
public BpmCheckNodePermissionResp checkNodePermission(BpmCheckNodePermissionReq bpmCheckNodePermissionReq) {
log.info("BpmOperationSpiImpl checkNodePermission req : {}", JsonUtils.toJson(bpmCheckNodePermissionReq));
BpmCheckNodePermissionResp resp = new BpmCheckNodePermissionResp();
Long caseId = bpmCheckNodePermissionReq.getCaseId();
String operationCode = bpmCheckNodePermissionReq.getOperationCode();
BpmCommentDto commentDto = bpmCheckNodePermissionReq.getCommentDto();
List<BpmNodePermissionOperationSimpleDto> operationList;
// 根据流程实例ID和用户ID获取事项列表
List<AffairDto> affairDtoList = CommonUtil.selectAffairList(RequestContext.get().getUserId(), caseId);
// 根据事项ID获取合并后的节点权限操作列表
List<Long> affairIds = affairDtoList.stream().map(AffairDto::getId).collect(Collectors.toList());
operationList = CommonUtil.selectOperationList(affairIds, new ArrayList<>());
if (CollectionUtils.isNotEmpty(operationList)){
Map<String, BpmNodePermissionOperationSimpleDto> code2SimpleDtoMap = operationList.stream().collect(Collectors.toMap(BpmNodePermissionOperationSimpleDto::getCode, Function.identity()));
// 操作合法校验
if (code2SimpleDtoMap.containsKey(operationCode)){
resp.setPassOperationVerify(true);
}
// 意见必填校验
BpmNodePermissionOperationSimpleDto simpleDto = code2SimpleDtoMap.get(operationCode);
Boolean commentRequired = simpleDto.getCommentRequired();
if (!commentRequired){
resp.setPassCommentRequiredVerify(true);
}
if (commentRequired && commentDto != null && (StringUtils.isNotBlank(commentDto.getContent()) || StringUtils.isBlank(commentDto.getRichContent()))){
resp.setPassCommentRequiredVerify(true);
}
// 意见长度校验
if (Objects.isNull(simpleDto.getMinOpinionLength())){
resp.setPassCommentLengthVerify(true);
}
int minLength = simpleDto.getMinOpinionLength();
if (Objects.nonNull(commentDto) && Boolean.TRUE.equals(commentRequired) && minLength > 0){
if (commentDto.getContent().length() < minLength && commentDto.getRichContent().length() < minLength){
resp.setPassCommentLengthVerify(true);
}
}
}
log.info("BpmOperationSpiImpl checkNodePermission resp : {}", JsonUtils.toJson(resp));
return resp;
}
}
编撰人:wensl、liuhf、shugang