update 优化工作流权限按钮获取,若需要扩展更多按钮权限,只需在 sources 中新增对应的枚举类或字典类型
This commit is contained in:
parent
31502dccc7
commit
5c9721cfac
@ -12,18 +12,18 @@ import java.io.Serializable;
|
|||||||
* @date 2025-02-28
|
* @date 2025-02-28
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class ButtonPermission implements Serializable {
|
public class ButtonPermissionVo implements Serializable {
|
||||||
|
|
||||||
@Serial
|
@Serial
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 枚举路径
|
* 唯一编码
|
||||||
*/
|
*/
|
||||||
private String code;
|
private String code;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按钮编码
|
* 选项值
|
||||||
*/
|
*/
|
||||||
private String value;
|
private String value;
|
||||||
|
|
||||||
@ -31,4 +31,13 @@ public class ButtonPermission implements Serializable {
|
|||||||
* 是否显示
|
* 是否显示
|
||||||
*/
|
*/
|
||||||
private boolean show;
|
private boolean show;
|
||||||
|
|
||||||
|
public ButtonPermissionVo() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ButtonPermissionVo(String code, boolean show) {
|
||||||
|
this.code = code;
|
||||||
|
this.show = show;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,20 +1,16 @@
|
|||||||
package org.dromara.workflow.domain.vo;
|
package org.dromara.workflow.domain.vo;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
|
||||||
import cn.hutool.json.JSONUtil;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.dromara.common.core.utils.StringUtils;
|
|
||||||
import org.dromara.common.translation.annotation.Translation;
|
import org.dromara.common.translation.annotation.Translation;
|
||||||
import org.dromara.common.translation.constant.TransConstant;
|
import org.dromara.common.translation.constant.TransConstant;
|
||||||
import org.dromara.warm.flow.core.entity.User;
|
import org.dromara.warm.flow.core.entity.User;
|
||||||
import org.dromara.workflow.common.constant.FlowConstant;
|
import org.dromara.workflow.common.constant.FlowConstant;
|
||||||
import org.dromara.workflow.common.enums.ButtonPermissionEnum;
|
|
||||||
|
|
||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.*;
|
import java.util.Date;
|
||||||
import java.util.stream.Collectors;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 任务视图
|
* 任务视图
|
||||||
@ -186,30 +182,6 @@ public class FlowTaskVo implements Serializable {
|
|||||||
/**
|
/**
|
||||||
* 按钮权限
|
* 按钮权限
|
||||||
*/
|
*/
|
||||||
private List<ButtonPermission> buttonList;
|
private List<ButtonPermissionVo> buttonList;
|
||||||
|
|
||||||
public List<ButtonPermission> getButtonList(String ext) {
|
|
||||||
List<ButtonPermission> buttonPermissions = Arrays.stream(ButtonPermissionEnum.values())
|
|
||||||
.map(value -> {
|
|
||||||
ButtonPermission buttonPermission = new ButtonPermission();
|
|
||||||
buttonPermission.setCode(value.getValue());
|
|
||||||
buttonPermission.setShow(false);
|
|
||||||
return buttonPermission;
|
|
||||||
})
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
if (StringUtils.isNotBlank(ext)) {
|
|
||||||
List<ButtonPermission> buttonCodeList = JSONUtil.toList(JSONUtil.parseArray(ext), ButtonPermission.class);
|
|
||||||
if (CollUtil.isNotEmpty(buttonCodeList)) {
|
|
||||||
Optional<ButtonPermission> firstPermission = buttonCodeList.stream().findFirst();
|
|
||||||
firstPermission.ifPresent(permission -> {
|
|
||||||
Set<String> codeSet = Arrays.stream(permission.getValue().split(","))
|
|
||||||
.map(String::trim)
|
|
||||||
.filter(code -> !code.isEmpty())
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
buttonPermissions.forEach(bp -> bp.setShow(codeSet.contains(bp.getCode())));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return buttonPermissions;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
package org.dromara.workflow.service;
|
||||||
|
|
||||||
|
import org.dromara.workflow.domain.vo.ButtonPermissionVo;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程节点扩展属性 服务层
|
||||||
|
*
|
||||||
|
* @author AprilWind
|
||||||
|
*/
|
||||||
|
public interface IFlwNodeExtService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从扩展属性构建按钮权限列表:根据 ext 中记录的权限值,标记每个按钮是否勾选
|
||||||
|
*
|
||||||
|
* @param ext 扩展属性 JSON 字符串
|
||||||
|
* @return 按钮权限 VO 列表
|
||||||
|
*/
|
||||||
|
List<ButtonPermissionVo> buildButtonPermissionsFromExt(String ext);
|
||||||
|
|
||||||
|
}
|
@ -191,7 +191,7 @@ public class FlwDefinitionServiceImpl implements IFlwDefinitionService {
|
|||||||
List<FlowDefinition> flowDefinitions = flowDefinitionMapper.selectByIds(StreamUtils.toList(flowHisTasks, FlowHisTask::getDefinitionId));
|
List<FlowDefinition> flowDefinitions = flowDefinitionMapper.selectByIds(StreamUtils.toList(flowHisTasks, FlowHisTask::getDefinitionId));
|
||||||
if (CollUtil.isNotEmpty(flowDefinitions)) {
|
if (CollUtil.isNotEmpty(flowDefinitions)) {
|
||||||
String join = StreamUtils.join(flowDefinitions, FlowDefinition::getFlowCode);
|
String join = StreamUtils.join(flowDefinitions, FlowDefinition::getFlowCode);
|
||||||
log.error("流程定义【{}】已被使用不可被删除!", join);
|
log.info("流程定义【{}】已被使用不可被删除!", join);
|
||||||
throw new ServiceException("流程定义【" + join + "】已被使用不可被删除!");
|
throw new ServiceException("流程定义【" + join + "】已被使用不可被删除!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,18 +2,25 @@ package org.dromara.workflow.service.impl;
|
|||||||
|
|
||||||
import cn.hutool.core.convert.Convert;
|
import cn.hutool.core.convert.Convert;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.dromara.common.core.domain.dto.DictTypeDTO;
|
import org.dromara.common.core.domain.dto.DictTypeDTO;
|
||||||
import org.dromara.common.core.service.DictService;
|
import org.dromara.common.core.service.DictService;
|
||||||
|
import org.dromara.common.core.utils.StringUtils;
|
||||||
|
import org.dromara.common.json.utils.JsonUtils;
|
||||||
import org.dromara.warm.flow.ui.service.NodeExtService;
|
import org.dromara.warm.flow.ui.service.NodeExtService;
|
||||||
import org.dromara.warm.flow.ui.vo.NodeExt;
|
import org.dromara.warm.flow.ui.vo.NodeExt;
|
||||||
import org.dromara.workflow.common.ConditionalOnEnable;
|
import org.dromara.workflow.common.ConditionalOnEnable;
|
||||||
import org.dromara.workflow.common.enums.ButtonPermissionEnum;
|
import org.dromara.workflow.common.enums.ButtonPermissionEnum;
|
||||||
import org.dromara.workflow.common.enums.NodeExtEnum;
|
import org.dromara.workflow.common.enums.NodeExtEnum;
|
||||||
|
import org.dromara.workflow.domain.vo.ButtonPermissionVo;
|
||||||
|
import org.dromara.workflow.service.IFlwNodeExtService;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 流程设计器-节点扩展属性
|
* 流程设计器-节点扩展属性
|
||||||
@ -24,14 +31,15 @@ import java.util.*;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@Service
|
@Service
|
||||||
public class FlwNodeExtServiceImpl implements NodeExtService {
|
public class FlwNodeExtServiceImpl implements NodeExtService, IFlwNodeExtService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 存储不同 dictType 对应的配置信息
|
* 存储不同 dictType 对应的配置信息
|
||||||
*/
|
*/
|
||||||
private static final Map<String, ButtonPermission> CHILD_NODE_MAP = new HashMap<>();
|
private static final Map<String, ButtonPermission> CHILD_NODE_MAP = new HashMap<>();
|
||||||
|
|
||||||
record ButtonPermission(String label, Integer type, Boolean must, Boolean multiple) {}
|
record ButtonPermission(String label, Integer type, Boolean must, Boolean multiple) {
|
||||||
|
}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
CHILD_NODE_MAP.put(ButtonPermissionEnum.class.getSimpleName(),
|
CHILD_NODE_MAP.put(ButtonPermissionEnum.class.getSimpleName(),
|
||||||
@ -162,4 +170,74 @@ public class FlwNodeExtServiceImpl implements NodeExtService {
|
|||||||
return childNode;
|
return childNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从扩展属性构建按钮权限列表:根据 ext 中记录的权限值,标记每个按钮是否勾选
|
||||||
|
*
|
||||||
|
* @param ext 扩展属性 JSON 字符串
|
||||||
|
* @return 按钮权限 VO 列表
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<ButtonPermissionVo> buildButtonPermissionsFromExt(String ext) {
|
||||||
|
// 解析 ext 为 Map<code, Set<value>>,用于标记权限
|
||||||
|
Map<String, Set<String>> permissionMap = JsonUtils.parseArray(ext, ButtonPermissionVo.class)
|
||||||
|
.stream()
|
||||||
|
.collect(Collectors.toMap(
|
||||||
|
ButtonPermissionVo::getCode,
|
||||||
|
item -> StringUtils.splitList(item.getValue()).stream()
|
||||||
|
.map(String::trim)
|
||||||
|
.filter(StrUtil::isNotBlank)
|
||||||
|
.collect(Collectors.toSet()),
|
||||||
|
(a, b) -> b,
|
||||||
|
HashMap::new
|
||||||
|
));
|
||||||
|
|
||||||
|
// 构建按钮权限列表,标记哪些按钮在 permissionMap 中出现(表示已勾选)
|
||||||
|
return buildPermissionsFromSources(permissionMap, List.of(ButtonPermissionEnum.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将权限映射与按钮权限来源(枚举类或字典类型)进行匹配,生成权限视图列表
|
||||||
|
* <p>
|
||||||
|
* 使用说明:
|
||||||
|
* - sources 支持传入多个来源类型,支持 NodeExtEnum 枚举类 或 字典类型字符串(dictType)
|
||||||
|
* - 若需要扩展更多按钮权限,只需在 sources 中新增对应的枚举类或字典类型
|
||||||
|
* <p>
|
||||||
|
* 示例:
|
||||||
|
* buildPermissionsFromSources(permissionMap, List.of(ButtonPermissionEnum.class, "custom_button_dict"));
|
||||||
|
*
|
||||||
|
* @param permissionMap 权限映射
|
||||||
|
* @param sources 枚举类或字典类型列表
|
||||||
|
* @return 按钮权限视图对象列表
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked cast")
|
||||||
|
private List<ButtonPermissionVo> buildPermissionsFromSources(Map<String, Set<String>> permissionMap, List<Object> sources) {
|
||||||
|
return sources.stream()
|
||||||
|
.flatMap(source -> {
|
||||||
|
if (source instanceof Class<?> clazz && NodeExtEnum.class.isAssignableFrom(clazz)) {
|
||||||
|
Set<String> selectedSet = permissionMap.getOrDefault(clazz.getSimpleName(), Collections.emptySet());
|
||||||
|
return extractDictItems(this.buildChildNode((Class<? extends NodeExtEnum>) clazz), selectedSet).stream();
|
||||||
|
} else if (source instanceof String dictType) {
|
||||||
|
Set<String> selectedSet = permissionMap.getOrDefault(dictType, Collections.emptySet());
|
||||||
|
return extractDictItems(this.buildChildNode(dictType), selectedSet).stream();
|
||||||
|
}
|
||||||
|
return Stream.empty();
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从节点子项中提取字典项,并构建按钮权限视图对象列表
|
||||||
|
*
|
||||||
|
* @param childNode 子节点
|
||||||
|
* @param selectedSet 已选中的值集
|
||||||
|
* @return 按钮权限视图对象列表
|
||||||
|
*/
|
||||||
|
private List<ButtonPermissionVo> extractDictItems(NodeExt.ChildNode childNode, Set<String> selectedSet) {
|
||||||
|
return Optional.ofNullable(childNode)
|
||||||
|
.map(NodeExt.ChildNode::getDict)
|
||||||
|
.orElse(List.of())
|
||||||
|
.stream()
|
||||||
|
.map(dict -> new ButtonPermissionVo(dict.getValue(), selectedSet.contains(dict.getValue())))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,7 @@ import org.dromara.workflow.handler.WorkflowPermissionHandler;
|
|||||||
import org.dromara.workflow.mapper.FlwCategoryMapper;
|
import org.dromara.workflow.mapper.FlwCategoryMapper;
|
||||||
import org.dromara.workflow.mapper.FlwTaskMapper;
|
import org.dromara.workflow.mapper.FlwTaskMapper;
|
||||||
import org.dromara.workflow.service.IFlwCommonService;
|
import org.dromara.workflow.service.IFlwCommonService;
|
||||||
|
import org.dromara.workflow.service.IFlwNodeExtService;
|
||||||
import org.dromara.workflow.service.IFlwTaskAssigneeService;
|
import org.dromara.workflow.service.IFlwTaskAssigneeService;
|
||||||
import org.dromara.workflow.service.IFlwTaskService;
|
import org.dromara.workflow.service.IFlwTaskService;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@ -86,6 +87,7 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
|
|||||||
private final FlowNodeMapper flowNodeMapper;
|
private final FlowNodeMapper flowNodeMapper;
|
||||||
private final IFlwTaskAssigneeService flwTaskAssigneeService;
|
private final IFlwTaskAssigneeService flwTaskAssigneeService;
|
||||||
private final IFlwCommonService flwCommonService;
|
private final IFlwCommonService flwCommonService;
|
||||||
|
private final IFlwNodeExtService flwNodeExtService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 启动任务
|
* 启动任务
|
||||||
@ -561,12 +563,12 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
|
|||||||
flowTaskVo.setFlowCode(definition.getFlowCode());
|
flowTaskVo.setFlowCode(definition.getFlowCode());
|
||||||
flowTaskVo.setFlowName(definition.getFlowName());
|
flowTaskVo.setFlowName(definition.getFlowName());
|
||||||
flowTaskVo.setBusinessId(instance.getBusinessId());
|
flowTaskVo.setBusinessId(instance.getBusinessId());
|
||||||
//设置按钮权限
|
FlowNode flowNode = this.getByNodeCode(flowTaskVo.getNodeCode(), instance.getDefinitionId());
|
||||||
FlowNode flowNode = getByNodeCode(flowTaskVo.getNodeCode(), instance.getDefinitionId());
|
|
||||||
if (ObjectUtil.isNull(flowNode)) {
|
if (ObjectUtil.isNull(flowNode)) {
|
||||||
throw new NullPointerException("当前【" + flowTaskVo.getNodeCode() + "】节点编码不存在");
|
throw new NullPointerException("当前【" + flowTaskVo.getNodeCode() + "】节点编码不存在");
|
||||||
}
|
}
|
||||||
flowTaskVo.setButtonList(flowTaskVo.getButtonList(flowNode.getExt()));
|
//设置按钮权限
|
||||||
|
flowTaskVo.setButtonList(flwNodeExtService.buildButtonPermissionsFromExt(flowNode.getExt()));
|
||||||
flowTaskVo.setNodeRatio(flowNode.getNodeRatio());
|
flowTaskVo.setNodeRatio(flowNode.getNodeRatio());
|
||||||
flowTaskVo.setApplyNode(flowNode.getNodeCode().equals(flwCommonService.applyNodeCode(task.getDefinitionId())));
|
flowTaskVo.setApplyNode(flowNode.getNodeCode().equals(flwCommonService.applyNodeCode(task.getDefinitionId())));
|
||||||
return flowTaskVo;
|
return flowTaskVo;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user