14 changed files with 755 additions and 1 deletions
@ -0,0 +1,46 @@ |
|||||
|
package org.dromara.system.api.domain.vo; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
|
||||
|
import java.io.Serial; |
||||
|
import java.io.Serializable; |
||||
|
import java.util.Date; |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 字典类型视图对象 sys_dict_type |
||||
|
* |
||||
|
* @author Michelle.Chung |
||||
|
*/ |
||||
|
@Data |
||||
|
public class RemoteDictTypeVo implements Serializable { |
||||
|
|
||||
|
@Serial |
||||
|
private static final long serialVersionUID = 1L; |
||||
|
|
||||
|
/** |
||||
|
* 字典主键 |
||||
|
*/ |
||||
|
private Long dictId; |
||||
|
|
||||
|
/** |
||||
|
* 字典名称 |
||||
|
*/ |
||||
|
private String dictName; |
||||
|
|
||||
|
/** |
||||
|
* 字典类型 |
||||
|
*/ |
||||
|
private String dictType; |
||||
|
|
||||
|
/** |
||||
|
* 备注 |
||||
|
*/ |
||||
|
private String remark; |
||||
|
|
||||
|
/** |
||||
|
* 创建时间 |
||||
|
*/ |
||||
|
private Date createTime; |
||||
|
|
||||
|
} |
@ -0,0 +1,15 @@ |
|||||
|
package org.dromara.sample.feign; |
||||
|
|
||||
|
import org.springframework.cloud.openfeign.FeignClient; |
||||
|
import org.springframework.web.bind.annotation.PostMapping; |
||||
|
import org.springframework.web.bind.annotation.RequestParam; |
||||
|
|
||||
|
@FeignClient(name = "gateway",path = "business") |
||||
|
public interface BusinessTaskFeign { |
||||
|
|
||||
|
@PostMapping("/update/status") |
||||
|
void updateTaskStatus(@RequestParam String waylineId, |
||||
|
@RequestParam String status, |
||||
|
@RequestParam(required = false) String jobId, |
||||
|
@RequestParam(required = false) String jobName); |
||||
|
} |
@ -0,0 +1,80 @@ |
|||||
|
package org.dromara.workflow.common.enums; |
||||
|
|
||||
|
import lombok.AllArgsConstructor; |
||||
|
import lombok.Getter; |
||||
|
|
||||
|
/** |
||||
|
* 按钮权限枚举 |
||||
|
* |
||||
|
* @author AprilWind |
||||
|
*/ |
||||
|
@Getter |
||||
|
@AllArgsConstructor |
||||
|
public enum ButtonPermissionEnum implements NodeExtEnum { |
||||
|
|
||||
|
/** |
||||
|
* 是否弹窗选人 |
||||
|
*/ |
||||
|
POP("是否弹窗选人", "pop", false), |
||||
|
|
||||
|
/** |
||||
|
* 是否能委托 |
||||
|
*/ |
||||
|
TRUST("是否能委托", "trust", false), |
||||
|
|
||||
|
/** |
||||
|
* 是否能转办 |
||||
|
*/ |
||||
|
TRANSFER("是否能转办", "transfer", false), |
||||
|
|
||||
|
/** |
||||
|
* 是否能抄送 |
||||
|
*/ |
||||
|
COPY("是否能抄送", "copy", false), |
||||
|
|
||||
|
/** |
||||
|
* 是否显示退回 |
||||
|
*/ |
||||
|
BACK("是否显示退回", "back", true), |
||||
|
|
||||
|
/** |
||||
|
* 是否能加签 |
||||
|
*/ |
||||
|
ADD_SIGN("是否能加签", "addSign", false), |
||||
|
|
||||
|
/** |
||||
|
* 是否能减签 |
||||
|
*/ |
||||
|
SUB_SIGN("是否能减签", "subSign", false), |
||||
|
|
||||
|
/** |
||||
|
* 是否能终止 |
||||
|
*/ |
||||
|
TERMINATION("是否能终止", "termination", false), |
||||
|
|
||||
|
/** |
||||
|
* 任务指派 |
||||
|
*/ |
||||
|
TASK_ASSIGN("任务指派","taskAssign",true), |
||||
|
|
||||
|
/** |
||||
|
* 完结提交 |
||||
|
*/ |
||||
|
COM_SUB("完结提交","comSub",false), |
||||
|
|
||||
|
/** |
||||
|
* 提交 |
||||
|
*/ |
||||
|
SUBMIT("提交","submit",false), |
||||
|
|
||||
|
/** |
||||
|
* 违法用地认证 |
||||
|
*/ |
||||
|
ILLEGAL_AUTH("违法用地认证","illegalAuth",false); |
||||
|
|
||||
|
private final String label; |
||||
|
private final String value; |
||||
|
private final boolean selected; |
||||
|
|
||||
|
} |
||||
|
|
@ -0,0 +1,32 @@ |
|||||
|
package org.dromara.workflow.common.enums; |
||||
|
|
||||
|
/** |
||||
|
* 节点扩展属性枚举 |
||||
|
* |
||||
|
* @author AprilWind |
||||
|
*/ |
||||
|
public interface NodeExtEnum { |
||||
|
|
||||
|
/** |
||||
|
* 选项label |
||||
|
* |
||||
|
* @return 选项label |
||||
|
*/ |
||||
|
String getLabel(); |
||||
|
|
||||
|
/** |
||||
|
* 选项值 |
||||
|
* |
||||
|
* @return 选项值 |
||||
|
*/ |
||||
|
String getValue(); |
||||
|
|
||||
|
/** |
||||
|
* 是否默认选中 |
||||
|
* |
||||
|
* @return 是否默认选中 |
||||
|
*/ |
||||
|
boolean isSelected(); |
||||
|
|
||||
|
} |
||||
|
|
@ -0,0 +1,38 @@ |
|||||
|
package org.dromara.workflow.domain.bo; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
|
||||
|
import java.io.Serial; |
||||
|
import java.io.Serializable; |
||||
|
import java.util.HashMap; |
||||
|
import java.util.Map; |
||||
|
import java.util.Objects; |
||||
|
|
||||
|
/** |
||||
|
* 下一节点信息 |
||||
|
* |
||||
|
* @author may |
||||
|
*/ |
||||
|
@Data |
||||
|
public class FlowNextNodeBo implements Serializable { |
||||
|
|
||||
|
@Serial |
||||
|
private static final long serialVersionUID = 1L; |
||||
|
/** |
||||
|
* 任务id |
||||
|
*/ |
||||
|
private Long taskId; |
||||
|
|
||||
|
/** |
||||
|
* 流程变量 |
||||
|
*/ |
||||
|
private Map<String, Object> variables; |
||||
|
|
||||
|
public Map<String, Object> getVariables() { |
||||
|
if (variables == null) { |
||||
|
return new HashMap<>(16); |
||||
|
} |
||||
|
variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue())); |
||||
|
return variables; |
||||
|
} |
||||
|
} |
@ -0,0 +1,34 @@ |
|||||
|
package org.dromara.workflow.domain.vo; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
|
||||
|
import java.io.Serial; |
||||
|
import java.io.Serializable; |
||||
|
|
||||
|
/** |
||||
|
* 按钮权限 |
||||
|
* |
||||
|
* @author may |
||||
|
* @date 2025-02-28 |
||||
|
*/ |
||||
|
@Data |
||||
|
public class ButtonPermission implements Serializable { |
||||
|
|
||||
|
@Serial |
||||
|
private static final long serialVersionUID = 1L; |
||||
|
|
||||
|
/** |
||||
|
* 枚举路径 |
||||
|
*/ |
||||
|
private String code; |
||||
|
|
||||
|
/** |
||||
|
* 按钮编码 |
||||
|
*/ |
||||
|
private String value; |
||||
|
|
||||
|
/** |
||||
|
* 是否显示 |
||||
|
*/ |
||||
|
private boolean show; |
||||
|
} |
@ -0,0 +1,73 @@ |
|||||
|
package org.dromara.workflow.service; |
||||
|
|
||||
|
import org.dromara.warm.flow.core.entity.User; |
||||
|
import org.dromara.warm.flow.core.service.UserService; |
||||
|
|
||||
|
import java.util.List; |
||||
|
import java.util.Set; |
||||
|
|
||||
|
/** |
||||
|
* 通用 工作流服务 |
||||
|
* |
||||
|
* @author LionLi |
||||
|
*/ |
||||
|
public interface IFlwCommonService { |
||||
|
|
||||
|
/** |
||||
|
* 获取工作流用户service |
||||
|
*/ |
||||
|
UserService getFlowUserService(); |
||||
|
|
||||
|
/** |
||||
|
* 构建工作流用户 |
||||
|
* |
||||
|
* @param userList 办理用户 |
||||
|
* @param taskId 任务ID |
||||
|
* @return 用户 |
||||
|
*/ |
||||
|
Set<User> buildUser(List<User> userList, Long taskId); |
||||
|
|
||||
|
/** |
||||
|
* 构建工作流用户 |
||||
|
* |
||||
|
* @param userIdList 办理用户 |
||||
|
* @param taskId 任务ID |
||||
|
* @return 用户 |
||||
|
*/ |
||||
|
Set<User> buildFlowUser(List<String> userIdList, Long taskId); |
||||
|
|
||||
|
/** |
||||
|
* 发送消息 |
||||
|
* |
||||
|
* @param flowName 流程定义名称 |
||||
|
* @param messageType 消息类型 |
||||
|
* @param message 消息内容,为空则发送默认配置的消息内容 |
||||
|
*/ |
||||
|
void sendMessage(String flowName, Long instId, List<String> messageType, String message); |
||||
|
|
||||
|
/** |
||||
|
* 驳回 |
||||
|
* |
||||
|
* @param message 审批意见 |
||||
|
* @param instanceId 流程实例id |
||||
|
* @param targetNodeCode 目标节点 |
||||
|
* @param flowStatus 流程状态 |
||||
|
* @param flowHisStatus 节点操作状态 |
||||
|
*/ |
||||
|
void backTask(String message, Long instanceId, String targetNodeCode, String flowStatus, String flowHisStatus); |
||||
|
|
||||
|
/** |
||||
|
* 申请人节点编码 |
||||
|
* |
||||
|
* @param definitionId 流程定义id |
||||
|
* @return 申请人节点编码 |
||||
|
*/ |
||||
|
String applyNodeCode(Long definitionId); |
||||
|
|
||||
|
/** |
||||
|
* 删除运行中的任务 |
||||
|
* |
||||
|
* @param taskIds 任务id |
||||
|
*/ |
||||
|
void deleteRunTask(List<Long> taskIds); |
||||
|
} |
@ -0,0 +1,250 @@ |
|||||
|
package org.dromara.workflow.service.impl; |
||||
|
|
||||
|
import cn.hutool.core.collection.CollUtil; |
||||
|
import cn.hutool.core.util.ObjectUtil; |
||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.apache.dubbo.config.annotation.DubboReference; |
||||
|
import org.dromara.common.core.utils.SpringUtils; |
||||
|
import org.dromara.common.core.utils.StreamUtils; |
||||
|
import org.dromara.common.core.utils.StringUtils; |
||||
|
import org.dromara.resource.api.RemoteMailService; |
||||
|
import org.dromara.resource.api.RemoteMessageService; |
||||
|
import org.dromara.system.api.domain.vo.RemoteUserVo; |
||||
|
import org.dromara.warm.flow.core.constant.ExceptionCons; |
||||
|
import org.dromara.warm.flow.core.dto.FlowParams; |
||||
|
import org.dromara.warm.flow.core.entity.Node; |
||||
|
import org.dromara.warm.flow.core.entity.Task; |
||||
|
import org.dromara.warm.flow.core.entity.User; |
||||
|
import org.dromara.warm.flow.core.enums.NodeType; |
||||
|
import org.dromara.warm.flow.core.enums.SkipType; |
||||
|
import org.dromara.warm.flow.core.service.NodeService; |
||||
|
import org.dromara.warm.flow.core.service.TaskService; |
||||
|
import org.dromara.warm.flow.core.service.UserService; |
||||
|
import org.dromara.warm.flow.core.utils.AssertUtil; |
||||
|
import org.dromara.warm.flow.orm.entity.FlowNode; |
||||
|
import org.dromara.warm.flow.orm.entity.FlowTask; |
||||
|
import org.dromara.warm.flow.orm.entity.FlowUser; |
||||
|
import org.dromara.warm.flow.orm.mapper.FlowNodeMapper; |
||||
|
import org.dromara.warm.flow.orm.mapper.FlowTaskMapper; |
||||
|
import org.dromara.workflow.common.ConditionalOnEnable; |
||||
|
import org.dromara.workflow.common.enums.MessageTypeEnum; |
||||
|
import org.dromara.workflow.common.enums.TaskAssigneeType; |
||||
|
import org.dromara.workflow.service.IFlwCommonService; |
||||
|
import org.dromara.workflow.service.IFlwTaskAssigneeService; |
||||
|
import org.dromara.workflow.service.IFlwTaskService; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
|
||||
|
import java.util.ArrayList; |
||||
|
import java.util.HashSet; |
||||
|
import java.util.List; |
||||
|
import java.util.Set; |
||||
|
import java.util.stream.Collectors; |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 工作流工具 |
||||
|
* |
||||
|
* @author LionLi |
||||
|
*/ |
||||
|
@ConditionalOnEnable |
||||
|
@Slf4j |
||||
|
@RequiredArgsConstructor |
||||
|
@Service |
||||
|
public class FlwCommonServiceImpl implements IFlwCommonService { |
||||
|
|
||||
|
private final FlowNodeMapper flowNodeMapper; |
||||
|
private final FlowTaskMapper flowTaskMapper; |
||||
|
private final UserService userService; |
||||
|
private final TaskService taskService; |
||||
|
private final NodeService nodeService; |
||||
|
|
||||
|
@DubboReference |
||||
|
private RemoteMessageService remoteMessageService; |
||||
|
@DubboReference |
||||
|
private RemoteMailService remoteMailService; |
||||
|
|
||||
|
/** |
||||
|
* 获取工作流用户service |
||||
|
*/ |
||||
|
@Override |
||||
|
public UserService getFlowUserService() { |
||||
|
return userService; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 构建工作流用户 |
||||
|
* |
||||
|
* @param userList 办理用户 |
||||
|
* @param taskId 任务ID |
||||
|
* @return 用户 |
||||
|
*/ |
||||
|
@Override |
||||
|
public Set<User> buildUser(List<User> userList, Long taskId) { |
||||
|
if (CollUtil.isEmpty(userList)) { |
||||
|
return Set.of(); |
||||
|
} |
||||
|
Set<User> list = new HashSet<>(); |
||||
|
Set<String> processedBySet = new HashSet<>(); |
||||
|
IFlwTaskAssigneeService taskAssigneeService = SpringUtils.getBean(IFlwTaskAssigneeService.class); |
||||
|
for (User user : userList) { |
||||
|
// 根据 processedBy 前缀判断处理人类型,分别获取用户列表
|
||||
|
List<RemoteUserVo> users = taskAssigneeService.fetchUsersByStorageId(user.getProcessedBy()); |
||||
|
// 转换为 FlowUser 并添加到结果集合
|
||||
|
if (CollUtil.isNotEmpty(users)) { |
||||
|
users.forEach(dto -> { |
||||
|
String processedBy = String.valueOf(dto.getUserId()); |
||||
|
if (!processedBySet.contains(processedBy)) { |
||||
|
FlowUser flowUser = new FlowUser(); |
||||
|
flowUser.setType(user.getType()); |
||||
|
flowUser.setProcessedBy(processedBy); |
||||
|
flowUser.setAssociated(taskId); |
||||
|
list.add(flowUser); |
||||
|
processedBySet.add(processedBy); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 构建工作流用户 |
||||
|
* |
||||
|
* @param userIdList 办理用户 |
||||
|
* @param taskId 任务ID |
||||
|
* @return 用户 |
||||
|
*/ |
||||
|
@Override |
||||
|
public Set<User> buildFlowUser(List<String> userIdList, Long taskId) { |
||||
|
if (CollUtil.isEmpty(userIdList)) { |
||||
|
return Set.of(); |
||||
|
} |
||||
|
Set<User> list = new HashSet<>(); |
||||
|
Set<String> processedBySet = new HashSet<>(); |
||||
|
for (String userId : userIdList) { |
||||
|
if (!processedBySet.contains(userId)) { |
||||
|
FlowUser flowUser = new FlowUser(); |
||||
|
flowUser.setType(TaskAssigneeType.APPROVER.getCode()); |
||||
|
flowUser.setProcessedBy(String.valueOf(userId)); |
||||
|
flowUser.setAssociated(taskId); |
||||
|
list.add(flowUser); |
||||
|
processedBySet.add(String.valueOf(userId)); |
||||
|
} |
||||
|
} |
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 发送消息 |
||||
|
* |
||||
|
* @param flowName 流程定义名称 |
||||
|
* @param messageType 消息类型 |
||||
|
* @param message 消息内容,为空则发送默认配置的消息内容 |
||||
|
*/ |
||||
|
@Override |
||||
|
public void sendMessage(String flowName, Long instId, List<String> messageType, String message) { |
||||
|
IFlwTaskService flwTaskService = SpringUtils.getBean(IFlwTaskService.class); |
||||
|
List<RemoteUserVo> userList = new ArrayList<>(); |
||||
|
List<FlowTask> list = flwTaskService.selectByInstId(instId); |
||||
|
if (StringUtils.isBlank(message)) { |
||||
|
message = "有新的【" + flowName + "】单据已经提交至您,请您及时处理。"; |
||||
|
} |
||||
|
for (Task task : list) { |
||||
|
List<RemoteUserVo> users = flwTaskService.currentTaskAllUser(task.getId()); |
||||
|
if (CollUtil.isNotEmpty(users)) { |
||||
|
userList.addAll(users); |
||||
|
} |
||||
|
} |
||||
|
if (CollUtil.isNotEmpty(userList)) { |
||||
|
for (String code : messageType) { |
||||
|
MessageTypeEnum messageTypeEnum = MessageTypeEnum.getByCode(code); |
||||
|
if (ObjectUtil.isNotEmpty(messageTypeEnum)) { |
||||
|
switch (messageTypeEnum) { |
||||
|
case SYSTEM_MESSAGE: |
||||
|
List<Long> userIds = StreamUtils.toList(userList, RemoteUserVo::getUserId).stream().distinct().collect(Collectors.toList()); |
||||
|
remoteMessageService.publishMessage(userIds, message); |
||||
|
break; |
||||
|
case EMAIL_MESSAGE: |
||||
|
remoteMailService.send(StreamUtils.join(userList, RemoteUserVo::getEmail), "单据审批提醒", message); |
||||
|
break; |
||||
|
case SMS_MESSAGE: |
||||
|
//todo 短信发送
|
||||
|
break; |
||||
|
default: |
||||
|
throw new IllegalStateException("Unexpected value: " + messageTypeEnum); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 驳回 |
||||
|
* |
||||
|
* @param message 审批意见 |
||||
|
* @param instanceId 流程实例id |
||||
|
* @param targetNodeCode 目标节点 |
||||
|
* @param flowStatus 流程状态 |
||||
|
* @param flowHisStatus 节点操作状态 |
||||
|
*/ |
||||
|
@Override |
||||
|
public void backTask(String message, Long instanceId, String targetNodeCode, String flowStatus, String flowHisStatus) { |
||||
|
IFlwTaskService flwTaskService = SpringUtils.getBean(IFlwTaskService.class); |
||||
|
List<FlowTask> list = flwTaskService.selectByInstId(instanceId); |
||||
|
if (CollUtil.isNotEmpty(list)) { |
||||
|
List<FlowTask> tasks = StreamUtils.filter(list, e -> e.getNodeCode().equals(targetNodeCode)); |
||||
|
if (list.size() == tasks.size()) { |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
for (FlowTask task : list) { |
||||
|
List<RemoteUserVo> userList = flwTaskService.currentTaskAllUser(task.getId()); |
||||
|
FlowParams flowParams = FlowParams.build(); |
||||
|
flowParams.nodeCode(targetNodeCode); |
||||
|
flowParams.message(message); |
||||
|
flowParams.skipType(SkipType.PASS.getKey()); |
||||
|
flowParams.flowStatus(flowStatus).hisStatus(flowHisStatus); |
||||
|
flowParams.ignore(true); |
||||
|
//解决会签没权限问题
|
||||
|
if (CollUtil.isNotEmpty(userList)) { |
||||
|
flowParams.handler(userList.get(0).getUserId().toString()); |
||||
|
} |
||||
|
taskService.skip(task.getId(), flowParams); |
||||
|
} |
||||
|
//解决会签多人审批问题
|
||||
|
backTask(message, instanceId, targetNodeCode, flowStatus, flowHisStatus); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 申请人节点编码 |
||||
|
* |
||||
|
* @param definitionId 流程定义id |
||||
|
* @return 申请人节点编码 |
||||
|
*/ |
||||
|
@Override |
||||
|
public String applyNodeCode(Long definitionId) { |
||||
|
//获取已发布的流程节点
|
||||
|
List<FlowNode> flowNodes = flowNodeMapper.selectList(new LambdaQueryWrapper<FlowNode>().eq(FlowNode::getDefinitionId, definitionId)); |
||||
|
AssertUtil.isTrue(CollUtil.isEmpty(flowNodes), ExceptionCons.NOT_PUBLISH_NODE); |
||||
|
Node startNode = flowNodes.stream().filter(t -> NodeType.isStart(t.getNodeType())).findFirst().orElse(null); |
||||
|
AssertUtil.isNull(startNode, ExceptionCons.LOST_START_NODE); |
||||
|
Node nextNode = nodeService.getNextNode(definitionId, startNode.getNodeCode(), null, SkipType.PASS.getKey()); |
||||
|
return nextNode.getNodeCode(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 删除运行中的任务 |
||||
|
* |
||||
|
* @param taskIds 任务id |
||||
|
*/ |
||||
|
@Override |
||||
|
public void deleteRunTask(List<Long> taskIds) { |
||||
|
if (CollUtil.isEmpty(taskIds)) { |
||||
|
return; |
||||
|
} |
||||
|
userService.deleteByTaskIds(taskIds); |
||||
|
flowTaskMapper.deleteByIds(taskIds); |
||||
|
} |
||||
|
} |
@ -0,0 +1,177 @@ |
|||||
|
package org.dromara.workflow.service.impl; |
||||
|
|
||||
|
import cn.hutool.core.convert.Convert; |
||||
|
import cn.hutool.core.util.ObjectUtil; |
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.apache.dubbo.config.annotation.DubboReference; |
||||
|
import org.dromara.system.api.RemoteDictService; |
||||
|
import org.dromara.system.api.domain.vo.RemoteDictTypeVo; |
||||
|
import org.dromara.warm.flow.ui.service.NodeExtService; |
||||
|
import org.dromara.warm.flow.ui.vo.NodeExt; |
||||
|
import org.dromara.workflow.common.ConditionalOnEnable; |
||||
|
import org.dromara.workflow.common.enums.ButtonPermissionEnum; |
||||
|
import org.dromara.workflow.common.enums.NodeExtEnum; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
|
||||
|
import java.util.*; |
||||
|
|
||||
|
/** |
||||
|
* 流程设计器-节点扩展属性 |
||||
|
* |
||||
|
* @author AprilWind |
||||
|
*/ |
||||
|
@ConditionalOnEnable |
||||
|
@Slf4j |
||||
|
@RequiredArgsConstructor |
||||
|
@Service |
||||
|
public class FlwNodeExtServiceImpl implements NodeExtService { |
||||
|
|
||||
|
/** |
||||
|
* 权限页code |
||||
|
*/ |
||||
|
private static final String PERMISSION_TAB = "wf_button_tab"; |
||||
|
|
||||
|
/** |
||||
|
* 权限页名称 |
||||
|
*/ |
||||
|
private static final String PERMISSION_TAB_NAME = "权限"; |
||||
|
|
||||
|
/** |
||||
|
* 基础设置 |
||||
|
*/ |
||||
|
private static final int TYPE_BASE_SETTING = 1; |
||||
|
|
||||
|
/** |
||||
|
* 新页签 |
||||
|
*/ |
||||
|
private static final int TYPE_NEW_TAB = 2; |
||||
|
|
||||
|
/** |
||||
|
* 存储不同 dictType 对应的配置信息 |
||||
|
*/ |
||||
|
private static final Map<String, Map<String, Object>> CHILD_NODE_MAP = new HashMap<>(); |
||||
|
|
||||
|
static { |
||||
|
CHILD_NODE_MAP.put(ButtonPermissionEnum.class.getSimpleName(), |
||||
|
Map.of("label", "权限按钮", "type", 4, "must", false, "multiple", true)); |
||||
|
} |
||||
|
|
||||
|
@DubboReference |
||||
|
private RemoteDictService remoteDictService; |
||||
|
|
||||
|
/** |
||||
|
* 获取节点扩展属性 |
||||
|
* |
||||
|
* @return 节点扩展属性列表 |
||||
|
*/ |
||||
|
@Override |
||||
|
public List<NodeExt> getNodeExt() { |
||||
|
List<NodeExt> nodeExtList = new ArrayList<>(); |
||||
|
// 构建按钮权限页面
|
||||
|
nodeExtList.add(buildNodeExt(PERMISSION_TAB, PERMISSION_TAB_NAME, TYPE_NEW_TAB, |
||||
|
List.of(ButtonPermissionEnum.class))); |
||||
|
return nodeExtList; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 构建一个 `NodeExt` 对象 |
||||
|
* |
||||
|
* @param code 唯一编码 |
||||
|
* @param name 名称(新页签时,作为页签名称) |
||||
|
* @param type 节点类型(1: 基础设置,2: 新页签) |
||||
|
* @param sources 数据来源(枚举类或字典类型) |
||||
|
* @return 构建的 `NodeExt` 对象 |
||||
|
*/ |
||||
|
@SuppressWarnings("unchecked cast") |
||||
|
private NodeExt buildNodeExt(String code, String name, int type, List<Object> sources) { |
||||
|
NodeExt nodeExt = new NodeExt(); |
||||
|
nodeExt.setCode(code); |
||||
|
nodeExt.setType(type); |
||||
|
nodeExt.setName(name); |
||||
|
nodeExt.setChilds(sources.stream() |
||||
|
.map(source -> { |
||||
|
if (source instanceof Class<?> clazz && NodeExtEnum.class.isAssignableFrom(clazz)) { |
||||
|
return buildChildNode((Class<? extends NodeExtEnum>) clazz); |
||||
|
} else if (source instanceof String dictType) { |
||||
|
return buildChildNode(dictType); |
||||
|
} |
||||
|
return null; |
||||
|
}) |
||||
|
.filter(ObjectUtil::isNotNull) |
||||
|
.toList() |
||||
|
); |
||||
|
return nodeExt; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 根据枚举类型构建一个 `ChildNode` 对象 |
||||
|
* |
||||
|
* @param enumClass 枚举类,必须实现 `NodeExtEnum` 接口 |
||||
|
* @return 构建的 `ChildNode` 对象 |
||||
|
*/ |
||||
|
private NodeExt.ChildNode buildChildNode(Class<? extends NodeExtEnum> enumClass) { |
||||
|
if (!enumClass.isEnum()) { |
||||
|
return null; |
||||
|
} |
||||
|
String simpleName = enumClass.getSimpleName(); |
||||
|
NodeExt.ChildNode childNode = buildChildNodeMap(simpleName); |
||||
|
// 编码,此json中唯
|
||||
|
childNode.setCode(simpleName); |
||||
|
// 字典,下拉框和复选框时用到
|
||||
|
childNode.setDict(Arrays.stream(enumClass.getEnumConstants()) |
||||
|
.map(NodeExtEnum.class::cast) |
||||
|
.map(x -> |
||||
|
new NodeExt.DictItem(x.getLabel(), x.getValue(), x.isSelected()) |
||||
|
).toList()); |
||||
|
return childNode; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 根据字典类型构建 `ChildNode` 对象 |
||||
|
* |
||||
|
* @param dictType 字典类型 |
||||
|
* @return 构建的 `ChildNode` 对象 |
||||
|
*/ |
||||
|
private NodeExt.ChildNode buildChildNode(String dictType) { |
||||
|
RemoteDictTypeVo dictTypeDTO = remoteDictService.selectDictTypeByType(dictType); |
||||
|
if (ObjectUtil.isNull(dictTypeDTO)) { |
||||
|
return null; |
||||
|
} |
||||
|
NodeExt.ChildNode childNode = buildChildNodeMap(dictType); |
||||
|
// 编码,此json中唯一
|
||||
|
childNode.setCode(dictType); |
||||
|
// label名称
|
||||
|
childNode.setLabel(dictTypeDTO.getDictName()); |
||||
|
// 描述
|
||||
|
childNode.setDesc(dictTypeDTO.getRemark()); |
||||
|
// 字典,下拉框和复选框时用到
|
||||
|
childNode.setDict(remoteDictService.selectDictDataByType(dictType) |
||||
|
.stream().map(x -> |
||||
|
new NodeExt.DictItem(x.getDictLabel(), x.getDictValue(), Convert.toBool(x.getIsDefault(), false)) |
||||
|
).toList()); |
||||
|
return childNode; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 根据 CHILD_NODE_MAP 中的配置信息,构建一个基本的 ChildNode 对象 |
||||
|
* 该方法用于设置 ChildNode 的常规属性,例如 label、type、是否必填、是否多选等 |
||||
|
* |
||||
|
* @param key CHILD_NODE_MAP 的 key |
||||
|
* @return 返回构建好的 ChildNode 对象 |
||||
|
*/ |
||||
|
private NodeExt.ChildNode buildChildNodeMap(String key) { |
||||
|
NodeExt.ChildNode childNode = new NodeExt.ChildNode(); |
||||
|
Map<String, Object> map = CHILD_NODE_MAP.get(key); |
||||
|
// label名称
|
||||
|
childNode.setLabel((String) map.get("label")); |
||||
|
// 1:输入框 2:输入框 3:下拉框 4:选择框
|
||||
|
childNode.setType(Convert.toInt(map.get("type"), 1)); |
||||
|
// 是否必填
|
||||
|
childNode.setMust(Convert.toBool(map.get("must"), false)); |
||||
|
// 是否多选
|
||||
|
childNode.setMultiple(Convert.toBool(map.get("multiple"), true)); |
||||
|
return childNode; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1 @@ |
|||||
|
3f2ee348-0303-40ca-bf03-03f48d2d2141 |
Binary file not shown.
@ -0,0 +1,4 @@ |
|||||
|
3 |
||||
|
SIMSUN.TTC -misc-simsun-medium-r-normal--0-0-0-0-p-0-iso10646-1 |
||||
|
SIMSUN.TTC -misc-simsun-medium-r-normal--0-0-0-0-p-0-iso8859-1 |
||||
|
SIMSUN.TTC -misc-simsun-medium-r-normal--0-0-0-0-p-0-koi8-r |
@ -0,0 +1,4 @@ |
|||||
|
3 |
||||
|
SIMSUN.TTC -misc-simsun-medium-r-normal--0-0-0-0-p-0-iso10646-1 |
||||
|
SIMSUN.TTC -misc-simsun-medium-r-normal--0-0-0-0-p-0-iso8859-1 |
||||
|
SIMSUN.TTC -misc-simsun-medium-r-normal--0-0-0-0-p-0-koi8-r |
Loading…
Reference in new issue