[add] 工作流

This commit is contained in:
lcj
2025-07-02 11:18:59 +08:00
parent bb9d654d57
commit 7f49b7882c
64 changed files with 2250 additions and 602 deletions

View File

@ -0,0 +1,41 @@
package org.dromara.common.core.domain.dto;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
/**
* 字典数据DTO
*
* @author AprilWind
*/
@Data
@NoArgsConstructor
public class DictDataDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 字典标签
*/
private String dictLabel;
/**
* 字典键值
*/
private String dictValue;
/**
* 是否默认Y是 N否
*/
private String isDefault;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,41 @@
package org.dromara.common.core.domain.dto;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
/**
* 字典类型DTO
*
* @author AprilWind
*/
@Data
@NoArgsConstructor
public class DictTypeDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 字典主键
*/
private Long dictId;
/**
* 字典名称
*/
private String dictName;
/**
* 字典类型
*/
private String dictType;
/**
* 备注
*/
private String remark;
}

View File

@ -33,7 +33,22 @@ public class ProcessEvent implements Serializable {
private String businessId;
/**
* 状态
* 节点类型0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关
*/
private Integer nodeType;
/**
* 流程节点编码
*/
private String nodeCode;
/**
* 流程节点名称
*/
private String nodeName;
/**
* 流程状态
*/
private String status;
@ -45,6 +60,6 @@ public class ProcessEvent implements Serializable {
/**
* 当为true时为申请人节点办理
*/
private boolean submit;
private Boolean submit;
}

View File

@ -27,10 +27,20 @@ public class ProcessTaskEvent implements Serializable {
private String flowCode;
/**
* 审批节点编码
* 节点类型0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关
*/
private Integer nodeType;
/**
* 流程节点编码
*/
private String nodeCode;
/**
* 流程节点名称
*/
private String nodeName;
/**
* 任务id
*/
@ -41,4 +51,9 @@ public class ProcessTaskEvent implements Serializable {
*/
private String businessId;
/**
* 流程状态
*/
private String status;
}

View File

@ -0,0 +1,21 @@
package org.dromara.common.core.exception.file;
import org.dromara.common.core.exception.base.BaseException;
import java.io.Serial;
/**
* 文件信息异常类
*
* @author ruoyi
*/
public class FileException extends BaseException {
@Serial
private static final long serialVersionUID = 1L;
public FileException(String code, Object[] args) {
super("file", code, args, null);
}
}

View File

@ -0,0 +1,18 @@
package org.dromara.common.core.exception.file;
import java.io.Serial;
/**
* 文件名称超长限制异常类
*
* @author ruoyi
*/
public class FileNameLengthLimitExceededException extends FileException {
@Serial
private static final long serialVersionUID = 1L;
public FileNameLengthLimitExceededException(int defaultFileNameLength) {
super("upload.filename.exceed.length", new Object[]{defaultFileNameLength});
}
}

View File

@ -0,0 +1,18 @@
package org.dromara.common.core.exception.file;
import java.io.Serial;
/**
* 文件名大小限制异常类
*
* @author ruoyi
*/
public class FileSizeLimitExceededException extends FileException {
@Serial
private static final long serialVersionUID = 1L;
public FileSizeLimitExceededException(long defaultMaxSize) {
super("upload.exceed.maxSize", new Object[]{defaultMaxSize});
}
}

View File

@ -1,5 +1,9 @@
package org.dromara.common.core.service;
import org.dromara.common.core.domain.dto.DictDataDTO;
import org.dromara.common.core.domain.dto.DictTypeDTO;
import java.util.List;
import java.util.Map;
/**
@ -64,4 +68,20 @@ public interface DictService {
*/
Map<String, String> getAllDictByDictType(String dictType);
/**
* 根据字典类型查询详细信息
*
* @param dictType 字典类型
* @return 字典类型详细信息
*/
DictTypeDTO getDictType(String dictType);
/**
* 根据字典类型查询字典数据列表
*
* @param dictType 字典类型
* @return 字典数据列表
*/
List<DictDataDTO> getDictData(String dictType);
}

View File

@ -3,6 +3,7 @@ package org.dromara.common.core.service;
import org.dromara.common.core.domain.dto.UserDTO;
import java.util.List;
import java.util.Map;
/**
* 通用 用户服务
@ -91,4 +92,36 @@ public interface UserService {
*/
List<UserDTO> selectUsersByPostIds(List<Long> postIds);
/**
* 根据用户 ID 列表查询用户名称映射关系
*
* @param userIds 用户 ID 列表
* @return Map其中 key 为用户 IDvalue 为对应的用户名称
*/
Map<Long, String> selectUserNamesByIds(List<Long> userIds);
/**
* 根据角色 ID 列表查询角色名称映射关系
*
* @param roleIds 角色 ID 列表
* @return Map其中 key 为角色 IDvalue 为对应的角色名称
*/
Map<Long, String> selectRoleNamesByIds(List<Long> roleIds);
/**
* 根据部门 ID 列表查询部门名称映射关系
*
* @param deptIds 部门 ID 列表
* @return Map其中 key 为部门 IDvalue 为对应的部门名称
*/
Map<Long, String> selectDeptNamesByIds(List<Long> deptIds);
/**
* 根据岗位 ID 列表查询岗位名称映射关系
*
* @param postIds 岗位 ID 列表
* @return Map其中 key 为岗位 IDvalue 为对应的岗位名称
*/
Map<Long, String> selectPostNamesByIds(List<Long> postIds);
}

View File

@ -78,9 +78,18 @@ public interface WorkflowService {
/**
* 办理任务
* 系统后台发起审批 无用户信息 需要忽略权限
* completeTask.getVariables().put("ignore", true);
*
* @param completeTask 参数
* @return 结果
*/
boolean completeTask(CompleteTaskDTO completeTask);
/**
* 办理任务
*
* @param taskId 任务ID
* @param message 办理意见
*/
boolean completeTask(Long taskId, String message);
}

View File

@ -10,6 +10,8 @@ import lombok.NoArgsConstructor;
import org.dromara.common.core.utils.reflect.ReflectUtils;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -60,6 +62,31 @@ public class TreeBuildUtils extends TreeUtil {
return TreeUtil.build(list, parentId, DEFAULT_CONFIG, nodeParser);
}
/**
* 构建多根节点的树结构(支持多个顶级节点)
*
* @param list 原始数据列表
* @param getId 获取节点 ID 的方法引用例如node -> node.getId()
* @param getParentId 获取节点父级 ID 的方法引用例如node -> node.getParentId()
* @param parser 树节点属性映射器,用于将原始节点 T 转为 Tree 节点
* @param <T> 原始数据类型如实体类、DTO 等)
* @param <K> 节点 ID 类型(如 Long、String
* @return 构建完成的树形结构(可能包含多个顶级根节点)
*/
public static <T, K> List<Tree<K>> buildMultiRoot(List<T> list, Function<T, K> getId, Function<T, K> getParentId, NodeParser<T, K> parser) {
if (CollUtil.isEmpty(list)) {
return CollUtil.newArrayList();
}
Set<K> rootParentIds = StreamUtils.toSet(list, getParentId);
rootParentIds.removeAll(StreamUtils.toSet(list, getId));
// 构建每一个根 parentId 下的树,并合并成最终结果列表
return rootParentIds.stream()
.flatMap(rootParentId -> TreeUtil.build(list, rootParentId, parser).stream())
.collect(Collectors.toList());
}
/**
* 获取节点列表中所有节点的叶子节点
*

View File

@ -0,0 +1,74 @@
package org.dromara.common.core.utils.file;
import cn.hutool.core.io.FileUtil;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
/**
* 文件处理工具类
*
* @author Lion Li
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class FileUtils extends FileUtil {
/**
* 下载文件名重新编码
*
* @param response 响应对象
* @param realFileName 真实文件名
*/
public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) {
String percentEncodedFileName = percentEncode(realFileName);
String contentDispositionValue = "attachment; filename=%s;filename*=utf-8''%s".formatted(percentEncodedFileName, percentEncodedFileName);
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
response.setHeader("Content-disposition", contentDispositionValue);
response.setHeader("download-filename", percentEncodedFileName);
}
/**
* 百分号编码工具方法
*
* @param s 需要百分号编码的字符串
* @return 百分号编码后的字符串
*/
public static String percentEncode(String s) {
String encode = URLEncoder.encode(s, StandardCharsets.UTF_8);
return encode.replaceAll("\\+", "%20");
}
/**
* 删除目录
*
* @param path 路径
* @throws IOException I/O异常
*/
public static void deleteDirectory(Path path) throws IOException {
// walkFileTree会递归遍历path下所有文件和文件夹
Files.walkFileTree(path, new SimpleFileVisitor<>() {
// 先删除文件
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}
// 然后删除目录
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
});
}
}

View File

@ -0,0 +1,40 @@
package org.dromara.common.core.utils.file;
/**
* 媒体类型工具类
*
* @author ruoyi
*/
public class MimeTypeUtils {
public static final String IMAGE_PNG = "image/png";
public static final String IMAGE_JPG = "image/jpg";
public static final String IMAGE_JPEG = "image/jpeg";
public static final String IMAGE_BMP = "image/bmp";
public static final String IMAGE_GIF = "image/gif";
public static final String[] IMAGE_EXTENSION = {"bmp", "gif", "jpg", "jpeg", "png"};
public static final String[] FLASH_EXTENSION = {"swf", "flv"};
public static final String[] MEDIA_EXTENSION = {"swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
"asf", "rm", "rmvb"};
public static final String[] VIDEO_EXTENSION = {"mp4", "avi", "rmvb"};
public static final String[] DEFAULT_ALLOWED_EXTENSION = {
// 图片
"bmp", "gif", "jpg", "jpeg", "png",
// word excel powerpoint
"doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
// 压缩文件
"rar", "zip", "gz", "bz2",
// 视频格式
"mp4", "avi", "rmvb",
// pdf
"pdf"};
}