diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/DeptService.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/DeptService.java index f93d1778a..725718ae8 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/DeptService.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/DeptService.java @@ -3,6 +3,7 @@ package org.dromara.common.core.service; import org.dromara.common.core.domain.dto.DeptDTO; import java.util.List; +import java.util.Map; /** * 通用 部门服务 @@ -34,4 +35,12 @@ public interface DeptService { */ List selectDeptsByList(); + /** + * 根据部门 ID 列表查询部门名称映射关系 + * + * @param deptIds 部门 ID 列表 + * @return Map,其中 key 为部门 ID,value 为对应的部门名称 + */ + Map selectDeptNamesByIds(List deptIds); + } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/PostService.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/PostService.java index 41d4e8308..58c68d676 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/PostService.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/PostService.java @@ -1,5 +1,8 @@ package org.dromara.common.core.service; +import java.util.List; +import java.util.Map; + /** * 通用 岗位服务 * @@ -7,4 +10,12 @@ package org.dromara.common.core.service; */ public interface PostService { + /** + * 根据岗位 ID 列表查询岗位名称映射关系 + * + * @param postIds 岗位 ID 列表 + * @return Map,其中 key 为岗位 ID,value 为对应的岗位名称 + */ + Map selectPostNamesByIds(List postIds); + } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/RoleService.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/RoleService.java index ba62c82ae..d2805b7e0 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/RoleService.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/RoleService.java @@ -1,5 +1,8 @@ package org.dromara.common.core.service; +import java.util.List; +import java.util.Map; + /** * 通用 角色服务 * @@ -7,4 +10,12 @@ package org.dromara.common.core.service; */ public interface RoleService { + /** + * 根据角色 ID 列表查询角色名称映射关系 + * + * @param roleIds 角色 ID 列表 + * @return Map,其中 key 为角色 ID,value 为对应的角色名称 + */ + Map selectRoleNamesByIds(List roleIds); + } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/UserService.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/UserService.java index 4903c3860..eefeef011 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/UserService.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/UserService.java @@ -100,28 +100,4 @@ public interface UserService { */ Map selectUserNamesByIds(List userIds); - /** - * 根据角色 ID 列表查询角色名称映射关系 - * - * @param roleIds 角色 ID 列表 - * @return Map,其中 key 为角色 ID,value 为对应的角色名称 - */ - Map selectRoleNamesByIds(List roleIds); - - /** - * 根据部门 ID 列表查询部门名称映射关系 - * - * @param deptIds 部门 ID 列表 - * @return Map,其中 key 为部门 ID,value 为对应的部门名称 - */ - Map selectDeptNamesByIds(List deptIds); - - /** - * 根据岗位 ID 列表查询岗位名称映射关系 - * - * @param postIds 岗位 ID 列表 - * @return Map,其中 key 为岗位 ID,value 为对应的岗位名称 - */ - Map selectPostNamesByIds(List postIds); - } diff --git a/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/controller/SseController.java b/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/controller/SseController.java index 412834cfb..addd01d17 100644 --- a/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/controller/SseController.java +++ b/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/controller/SseController.java @@ -6,7 +6,6 @@ import lombok.RequiredArgsConstructor; import org.dromara.common.core.domain.R; import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.sse.core.SseEmitterManager; -import org.dromara.common.sse.dto.SseMessageDto; import org.springframework.beans.factory.DisposableBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.http.MediaType; @@ -14,8 +13,6 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; -import java.util.List; - /** * SSE 控制器 * @@ -51,31 +48,32 @@ public class SseController implements DisposableBean { return R.ok(); } - /** - * 向特定用户发送消息 - * - * @param userId 目标用户的 ID - * @param msg 要发送的消息内容 - */ - @GetMapping(value = "${sse.path}/send") - public R send(Long userId, String msg) { - SseMessageDto dto = new SseMessageDto(); - dto.setUserIds(List.of(userId)); - dto.setMessage(msg); - sseEmitterManager.publishMessage(dto); - return R.ok(); - } - - /** - * 向所有用户发送消息 - * - * @param msg 要发送的消息内容 - */ - @GetMapping(value = "${sse.path}/sendAll") - public R send(String msg) { - sseEmitterManager.publishAll(msg); - return R.ok(); - } + // 以下为demo仅供参考 禁止使用 请在业务逻辑中使用工具发送而不是用接口发送 +// /** +// * 向特定用户发送消息 +// * +// * @param userId 目标用户的 ID +// * @param msg 要发送的消息内容 +// */ +// @GetMapping(value = "${sse.path}/send") +// public R send(Long userId, String msg) { +// SseMessageDto dto = new SseMessageDto(); +// dto.setUserIds(List.of(userId)); +// dto.setMessage(msg); +// sseEmitterManager.publishMessage(dto); +// return R.ok(); +// } +// +// /** +// * 向所有用户发送消息 +// * +// * @param msg 要发送的消息内容 +// */ +// @GetMapping(value = "${sse.path}/sendAll") +// public R send(String msg) { +// sseEmitterManager.publishAll(msg); +// return R.ok(); +// } /** * 清理资源。此方法目前不执行任何操作,但避免因未实现而导致错误 diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/MailController.java b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/MailSendController.java similarity index 98% rename from ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/MailController.java rename to ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/MailSendController.java index 6fc5a17ba..48365a350 100644 --- a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/MailController.java +++ b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/MailSendController.java @@ -21,7 +21,7 @@ import java.util.Arrays; @RequiredArgsConstructor @RestController @RequestMapping("/demo/mail") -public class MailController { +public class MailSendController { /** * 发送邮件 diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysPostController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysPostController.java index 5333a4aef..387b1c6f3 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysPostController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysPostController.java @@ -19,6 +19,7 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -107,7 +108,7 @@ public class SysPostController extends BaseController { @Log(title = "岗位管理", businessType = BusinessType.DELETE) @DeleteMapping("/{postIds}") public R remove(@PathVariable Long[] postIds) { - return toAjax(postService.deletePostByIds(postIds)); + return toAjax(postService.deletePostByIds(Arrays.asList(postIds))); } /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysOssExt.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysOssExt.java new file mode 100644 index 000000000..15a95e760 --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysOssExt.java @@ -0,0 +1,75 @@ +package org.dromara.system.domain; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.List; + +/** + * 附件扩展字段对象(存储在 SysOss.ext1 的 JSON 字符串中) + * + * @author AprilWind + */ +@Data +public class SysOssExt implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 所属业务类型(如 avatar、report、contract) + */ + private String bizType; + + /** + * 文件大小(单位:字节) + */ + private Long fileSize; + + /** + * 文件类型(MIME类型,如 image/png) + */ + private String contentType; + + /** + * 来源标识(如 userUpload、systemImport) + */ + private String source; + + /** + * 上传 IP 地址,便于审计和追踪 + */ + private String uploadIp; + + /** + * 附件说明或备注 + */ + private String remark; + + /** + * 附件标签,如 ["图片", "证件"] + */ + private List tags; + + /** + * 业务绑定ID(如某业务记录ID) + */ + private String refId; + + /** + * 绑定业务类型 + */ + private String refType; + + /** + * 是否为临时文件,用于区分正式或待清理 + */ + private Boolean isTemp; + + /** + * 文件MD5值(可用于去重或校验) + */ + private String md5; + +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java index e29942058..15096f8a8 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java @@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.apache.ibatis.annotations.Param; +import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.mybatis.annotation.DataColumn; import org.dromara.common.mybatis.annotation.DataPermission; import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; @@ -72,6 +73,19 @@ public interface SysDeptMapper extends BaseMapperPlus { .apply(DataBaseHelper.findInSet(parentId, "ancestors"))); } + /** + * 查询某个部门及其所有子部门ID(含自身) + * + * @param parentId 父部门ID + * @return 部门ID集合 + */ + default List selectDeptAndChildById(Long parentId) { + List deptList = this.selectListByParentId(parentId); + List deptIds = StreamUtils.toList(deptList, SysDept::getDeptId); + deptIds.add(parentId); + return deptIds; + } + /** * 根据角色ID查询部门树信息 * diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysPostService.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysPostService.java index a760d497e..511d842ee 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysPostService.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysPostService.java @@ -110,7 +110,7 @@ public interface ISysPostService { * @param postIds 需要删除的岗位ID * @return 结果 */ - int deletePostByIds(Long[] postIds); + int deletePostByIds(List postIds); /** * 新增保存岗位信息 diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java index 12a507203..e30080212 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java @@ -7,7 +7,6 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.RequiredArgsConstructor; import org.dromara.common.core.constant.CacheNames; import org.dromara.common.core.utils.StreamUtils; -import org.dromara.system.domain.SysDept; import org.dromara.system.domain.SysRoleDept; import org.dromara.system.mapper.SysDeptMapper; import org.dromara.system.mapper.SysRoleDeptMapper; @@ -66,13 +65,8 @@ public class SysDataScopeServiceImpl implements ISysDataScopeService { if (ObjectUtil.isNull(deptId)) { return "-1"; } - List deptList = deptMapper.selectListByParentId(deptId); - List ids = StreamUtils.toList(deptList, SysDept::getDeptId); - ids.add(deptId); - if (CollUtil.isNotEmpty(ids)) { - return StreamUtils.join(ids, Convert::toStr); - } - return "-1"; + List deptIds = deptMapper.selectDeptAndChildById(deptId); + return CollUtil.isNotEmpty(deptIds) ? StreamUtils.join(deptIds, Convert::toStr) : "-1"; } } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java index fde4b875b..7e4e24210 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java @@ -36,10 +36,7 @@ import org.springframework.cache.annotation.Caching; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; +import java.util.*; /** * 部门管理 服务实现 @@ -110,10 +107,7 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { if (ObjectUtil.isNotNull(bo.getBelongDeptId())) { //部门树搜索 lqw.and(x -> { - Long parentId = bo.getBelongDeptId(); - List deptList = baseMapper.selectListByParentId(parentId); - List deptIds = StreamUtils.toList(deptList, SysDept::getDeptId); - deptIds.add(parentId); + List deptIds = baseMapper.selectDeptAndChildById(bo.getBelongDeptId()); x.in(SysDept::getDeptId, deptIds); }); } @@ -409,4 +403,24 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { return baseMapper.deleteById(deptId); } + + /** + * 根据部门 ID 列表查询部门名称映射关系 + * + * @param deptIds 部门 ID 列表 + * @return Map,其中 key 为部门 ID,value 为对应的部门名称 + */ + @Override + public Map selectDeptNamesByIds(List deptIds) { + if (CollUtil.isEmpty(deptIds)) { + return Collections.emptyMap(); + } + List list = baseMapper.selectList( + new LambdaQueryWrapper() + .select(SysDept::getDeptId, SysDept::getDeptName) + .in(SysDept::getDeptId, deptIds) + ); + return StreamUtils.toMap(list, SysDept::getDeptId, SysDept::getDeptName); + } + } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java index 1f2bf80db..e60b21ea7 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java @@ -17,6 +17,7 @@ import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.file.FileUtils; +import org.dromara.common.json.utils.JsonUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.oss.core.OssClient; @@ -24,6 +25,7 @@ import org.dromara.common.oss.entity.UploadResult; import org.dromara.common.oss.enums.AccessPolicyType; import org.dromara.common.oss.factory.OssFactory; import org.dromara.system.domain.SysOss; +import org.dromara.system.domain.SysOssExt; import org.dromara.system.domain.bo.SysOssBo; import org.dromara.system.domain.vo.SysOssVo; import org.dromara.system.mapper.SysOssMapper; @@ -199,8 +201,11 @@ public class SysOssServiceImpl implements ISysOssService, OssService { } catch (IOException e) { throw new ServiceException(e.getMessage()); } + SysOssExt ext1 = new SysOssExt(); + ext1.setFileSize(file.getSize()); + ext1.setContentType(file.getContentType()); // 保存文件信息 - return buildResultEntity(originalfileName, suffix, storage.getConfigKey(), uploadResult); + return buildResultEntity(originalfileName, suffix, storage.getConfigKey(), uploadResult, ext1); } /** @@ -215,18 +220,21 @@ public class SysOssServiceImpl implements ISysOssService, OssService { String suffix = StringUtils.substring(originalfileName, originalfileName.lastIndexOf("."), originalfileName.length()); OssClient storage = OssFactory.instance(); UploadResult uploadResult = storage.uploadSuffix(file, suffix); + SysOssExt ext1 = new SysOssExt(); + ext1.setFileSize(file.length()); // 保存文件信息 - return buildResultEntity(originalfileName, suffix, storage.getConfigKey(), uploadResult); + return buildResultEntity(originalfileName, suffix, storage.getConfigKey(), uploadResult, ext1); } @NotNull - private SysOssVo buildResultEntity(String originalfileName, String suffix, String configKey, UploadResult uploadResult) { + private SysOssVo buildResultEntity(String originalfileName, String suffix, String configKey, UploadResult uploadResult, SysOssExt ext1) { SysOss oss = new SysOss(); oss.setUrl(uploadResult.getUrl()); oss.setFileSuffix(suffix); oss.setFileName(uploadResult.getFilename()); oss.setOriginalName(originalfileName); oss.setService(configKey); + oss.setExt1(JsonUtils.toJsonString(ext1)); baseMapper.insert(oss); SysOssVo sysOssVo = MapstructUtils.convert(oss, SysOssVo.class); return this.matchingUrl(sysOssVo); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPostServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPostServiceImpl.java index 122492e0c..ad1055ac0 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPostServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPostServiceImpl.java @@ -14,7 +14,6 @@ import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.system.domain.SysDept; import org.dromara.system.domain.SysPost; import org.dromara.system.domain.SysUserPost; import org.dromara.system.domain.bo.SysPostBo; @@ -25,7 +24,7 @@ import org.dromara.system.mapper.SysUserPostMapper; import org.dromara.system.service.ISysPostService; import org.springframework.stereotype.Service; -import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map; @@ -92,9 +91,7 @@ public class SysPostServiceImpl implements ISysPostService, PostService { } else if (ObjectUtil.isNotNull(bo.getBelongDeptId())) { //部门树搜索 wrapper.and(x -> { - List deptList = deptMapper.selectListByParentId(bo.getBelongDeptId()); - List deptIds = StreamUtils.toList(deptList, SysDept::getDeptId); - deptIds.add(bo.getBelongDeptId()); + List deptIds = deptMapper.selectDeptAndChildById(bo.getBelongDeptId()); x.in(SysPost::getDeptId, deptIds); }); } @@ -217,14 +214,14 @@ public class SysPostServiceImpl implements ISysPostService, PostService { * @return 结果 */ @Override - public int deletePostByIds(Long[] postIds) { - for (Long postId : postIds) { - SysPost post = baseMapper.selectById(postId); - if (countUserPostById(postId) > 0) { + public int deletePostByIds(List postIds) { + List list = baseMapper.selectByIds(postIds); + for (SysPost post : list) { + if (this.countUserPostById(post.getPostId()) > 0) { throw new ServiceException(String.format("%1$s已分配,不能删除!", post.getPostName())); } } - return baseMapper.deleteByIds(Arrays.asList(postIds)); + return baseMapper.deleteByIds(postIds); } /** @@ -251,4 +248,23 @@ public class SysPostServiceImpl implements ISysPostService, PostService { return baseMapper.updateById(post); } + /** + * 根据岗位 ID 列表查询岗位名称映射关系 + * + * @param postIds 岗位 ID 列表 + * @return Map,其中 key 为岗位 ID,value 为对应的岗位名称 + */ + @Override + public Map selectPostNamesByIds(List postIds) { + if (CollUtil.isEmpty(postIds)) { + return Collections.emptyMap(); + } + List list = baseMapper.selectList( + new LambdaQueryWrapper() + .select(SysPost::getPostId, SysPost::getPostName) + .in(SysPost::getPostId, postIds) + ); + return StreamUtils.toMap(list, SysPost::getPostId, SysPost::getPostName); + } + } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java index 0a2e485f6..f6d106854 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java @@ -549,4 +549,23 @@ public class SysRoleServiceImpl implements ISysRoleService, RoleService { }); } + /** + * 根据角色 ID 列表查询角色名称映射关系 + * + * @param roleIds 角色 ID 列表 + * @return Map,其中 key 为角色 ID,value 为对应的角色名称 + */ + @Override + public Map selectRoleNamesByIds(List roleIds) { + if (CollUtil.isEmpty(roleIds)) { + return Collections.emptyMap(); + } + List list = baseMapper.selectList( + new LambdaQueryWrapper() + .select(SysRole::getRoleId, SysRole::getRoleName) + .in(SysRole::getRoleId, roleIds) + ); + return StreamUtils.toMap(list, SysRole::getRoleId, SysRole::getRoleName); + } + } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java index d673a2159..70197a36c 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java @@ -22,7 +22,10 @@ import org.dromara.common.core.utils.*; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.satoken.utils.LoginHelper; -import org.dromara.system.domain.*; +import org.dromara.system.domain.SysRole; +import org.dromara.system.domain.SysUser; +import org.dromara.system.domain.SysUserPost; +import org.dromara.system.domain.SysUserRole; import org.dromara.system.domain.bo.SysUserBo; import org.dromara.system.domain.vo.SysPostVo; import org.dromara.system.domain.vo.SysRoleVo; @@ -36,7 +39,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.*; -import java.util.stream.Collectors; /** * 用户 业务层处理 @@ -79,10 +81,8 @@ public class SysUserServiceImpl implements ISysUserService, UserService { .between(params.get("beginTime") != null && params.get("endTime") != null, "u.create_time", params.get("beginTime"), params.get("endTime")) .and(ObjectUtil.isNotNull(user.getDeptId()), w -> { - List deptList = deptMapper.selectListByParentId(user.getDeptId()); - List ids = StreamUtils.toList(deptList, SysDept::getDeptId); - ids.add(user.getDeptId()); - w.in("u.dept_id", ids); + List deptIds = deptMapper.selectDeptAndChildById(user.getDeptId()); + w.in("u.dept_id", deptIds); }).orderByAsc("u.user_id"); return baseMapper.selectUserExportList(wrapper); } @@ -100,9 +100,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { .between(params.get("beginTime") != null && params.get("endTime") != null, SysUser::getCreateTime, params.get("beginTime"), params.get("endTime")) .and(ObjectUtil.isNotNull(user.getDeptId()), w -> { - List deptList = deptMapper.selectListByParentId(user.getDeptId()); - List ids = StreamUtils.toList(deptList, SysDept::getDeptId); - ids.add(user.getDeptId()); + List ids = deptMapper.selectDeptAndChildById(user.getDeptId()); w.in(SysUser::getDeptId, ids); }).orderByAsc(SysUser::getUserId); if (StringUtils.isNotBlank(user.getExcludeUserIds())) { @@ -748,69 +746,12 @@ public class SysUserServiceImpl implements ISysUserService, UserService { if (CollUtil.isEmpty(userIds)) { return Collections.emptyMap(); } - return baseMapper.selectList( - new LambdaQueryWrapper() - .select(SysUser::getUserId, SysUser::getNickName) - .in(SysUser::getUserId, userIds) - ).stream() - .collect(Collectors.toMap(SysUser::getUserId, SysUser::getNickName)); - } - - /** - * 根据角色 ID 列表查询角色名称映射关系 - * - * @param roleIds 角色 ID 列表 - * @return Map,其中 key 为角色 ID,value 为对应的角色名称 - */ - @Override - public Map selectRoleNamesByIds(List roleIds) { - if (CollUtil.isEmpty(roleIds)) { - return Collections.emptyMap(); - } - return roleMapper.selectList( - new LambdaQueryWrapper() - .select(SysRole::getRoleId, SysRole::getRoleName) - .in(SysRole::getRoleId, roleIds) - ).stream() - .collect(Collectors.toMap(SysRole::getRoleId, SysRole::getRoleName)); - } - - /** - * 根据部门 ID 列表查询部门名称映射关系 - * - * @param deptIds 部门 ID 列表 - * @return Map,其中 key 为部门 ID,value 为对应的部门名称 - */ - @Override - public Map selectDeptNamesByIds(List deptIds) { - if (CollUtil.isEmpty(deptIds)) { - return Collections.emptyMap(); - } - return deptMapper.selectList( - new LambdaQueryWrapper() - .select(SysDept::getDeptId, SysDept::getDeptName) - .in(SysDept::getDeptId, deptIds) - ).stream() - .collect(Collectors.toMap(SysDept::getDeptId, SysDept::getDeptName)); - } - - /** - * 根据岗位 ID 列表查询岗位名称映射关系 - * - * @param postIds 岗位 ID 列表 - * @return Map,其中 key 为岗位 ID,value 为对应的岗位名称 - */ - @Override - public Map selectPostNamesByIds(List postIds) { - if (CollUtil.isEmpty(postIds)) { - return Collections.emptyMap(); - } - return postMapper.selectList( - new LambdaQueryWrapper() - .select(SysPost::getPostId, SysPost::getPostName) - .in(SysPost::getPostId, postIds) - ).stream() - .collect(Collectors.toMap(SysPost::getPostId, SysPost::getPostName)); + List list = baseMapper.selectList( + new LambdaQueryWrapper() + .select(SysUser::getUserId, SysUser::getNickName) + .in(SysUser::getUserId, userIds) + ); + return StreamUtils.toMap(list, SysUser::getUserId, SysUser::getNickName); } } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwTaskController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwTaskController.java index 5534b6732..b765340bb 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwTaskController.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwTaskController.java @@ -206,7 +206,7 @@ public class FlwTaskController extends BaseController { */ @GetMapping("/currentTaskAllUser/{taskId}") public R> currentTaskAllUser(@PathVariable Long taskId) { - return R.ok(flwTaskService.currentTaskAllUser(taskId)); + return R.ok(flwTaskService.currentTaskAllUser(List.of(taskId))); } } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowTaskVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowTaskVo.java index 07a22c4f3..28753be28 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowTaskVo.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowTaskVo.java @@ -145,6 +145,7 @@ public class FlowTaskVo implements Serializable { /** * 办理人名称 */ + @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "assigneeIds") private String assigneeNames; /** diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/WorkflowPermissionHandler.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/WorkflowPermissionHandler.java index f9ede15ce..43af0105e 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/WorkflowPermissionHandler.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/WorkflowPermissionHandler.java @@ -3,11 +3,14 @@ package org.dromara.workflow.handler; import cn.hutool.core.collection.CollUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.domain.dto.UserDTO; +import org.dromara.common.core.utils.StreamUtils; +import org.dromara.common.core.utils.StringUtils; import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.warm.flow.core.dto.FlowParams; import org.dromara.warm.flow.core.handler.PermissionHandler; import org.dromara.workflow.common.ConditionalOnEnable; -import org.dromara.workflow.service.IFlwCommonService; +import org.dromara.workflow.service.IFlwTaskAssigneeService; import org.springframework.stereotype.Component; import java.util.Collections; @@ -24,7 +27,7 @@ import java.util.List; @Slf4j public class WorkflowPermissionHandler implements PermissionHandler { - private final IFlwCommonService flwCommonService; + private final IFlwTaskAssigneeService flwTaskAssigneeService; /** * 办理人权限标识,比如用户,角色,部门等,用于校验是否有权限办理任务 @@ -51,9 +54,11 @@ public class WorkflowPermissionHandler implements PermissionHandler { */ @Override public List convertPermissions(List permissions) { - if (CollUtil.isNotEmpty(permissions)) { - permissions = flwCommonService.buildUser(permissions); + if (CollUtil.isEmpty(permissions)) { + return permissions; } - return permissions; + String storageIds = CollUtil.join(permissions, StringUtils.SEPARATOR); + List users = flwTaskAssigneeService.fetchUsersByStorageIds(storageIds); + return StreamUtils.toList(users, userDTO -> String.valueOf(userDTO.getUserId())); } } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/listener/WorkflowGlobalListener.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/listener/WorkflowGlobalListener.java index c1ef2622a..2d23f772c 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/listener/WorkflowGlobalListener.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/listener/WorkflowGlobalListener.java @@ -1,6 +1,7 @@ package org.dromara.workflow.listener; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.TypeReference; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjectUtil; import lombok.RequiredArgsConstructor; @@ -136,33 +137,36 @@ public class WorkflowGlobalListener implements GlobalListener { return; } // 只有办理或者退回的时候才执行消息通知和抄送 - if (TaskStatusEnum.PASS.getStatus().equals(flowParams.getHisStatus()) - || TaskStatusEnum.BACK.getStatus().equals(flowParams.getHisStatus())) { - if (variable != null) { - if (variable.containsKey(FlowConstant.FLOW_COPY_LIST)) { - List flowCopyList = (List) variable.get(FlowConstant.FLOW_COPY_LIST); - // 添加抄送人 - flwTaskService.setCopy(task, flowCopyList); - } - if (variable.containsKey(FlowConstant.MESSAGE_TYPE)) { - List messageType = (List) variable.get(FlowConstant.MESSAGE_TYPE); - String notice = (String) variable.get(FlowConstant.MESSAGE_NOTICE); - // 消息通知 - if (CollUtil.isNotEmpty(messageType)) { - flwCommonService.sendMessage(definition.getFlowName(), instance.getId(), messageType, notice); - } - } - FlowInstance ins = new FlowInstance(); - Map variableMap = instance.getVariableMap(); - variableMap.remove(FlowConstant.FLOW_COPY_LIST); - variableMap.remove(FlowConstant.MESSAGE_TYPE); - variableMap.remove(FlowConstant.MESSAGE_NOTICE); - variableMap.remove(FlowConstant.SUBMIT); - ins.setId(instance.getId()); - ins.setVariable(FlowEngine.jsonConvert.objToStr(variableMap)); - insService.updateById(ins); + if (!StringUtils.equalsAny(flowParams.getHisStatus(), + TaskStatusEnum.PASS.getStatus(), TaskStatusEnum.BACK.getStatus())) { + return; + } + if (ObjectUtil.isNull(variable)) { + return; + } + + if (variable.containsKey(FlowConstant.FLOW_COPY_LIST)) { + List flowCopyList = MapUtil.get(variable, FlowConstant.FLOW_COPY_LIST, new TypeReference<>() {}); + // 添加抄送人 + flwTaskService.setCopy(task, flowCopyList); + } + if (variable.containsKey(FlowConstant.MESSAGE_TYPE)) { + List messageType = MapUtil.get(variable, FlowConstant.FLOW_COPY_LIST, new TypeReference<>() {}); + String notice = MapUtil.getStr(variable, FlowConstant.MESSAGE_NOTICE); + // 消息通知 + if (CollUtil.isNotEmpty(messageType)) { + flwCommonService.sendMessage(definition.getFlowName(), instance.getId(), messageType, notice); } } + FlowInstance ins = new FlowInstance(); + Map variableMap = instance.getVariableMap(); + variableMap.remove(FlowConstant.FLOW_COPY_LIST); + variableMap.remove(FlowConstant.MESSAGE_TYPE); + variableMap.remove(FlowConstant.MESSAGE_NOTICE); + variableMap.remove(FlowConstant.SUBMIT); + ins.setId(instance.getId()); + ins.setVariable(FlowEngine.jsonConvert.objToStr(variableMap)); + insService.updateById(ins); } /** diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwTaskMapper.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwTaskMapper.java index fd86c82de..0d0422d5a 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwTaskMapper.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwTaskMapper.java @@ -9,8 +9,6 @@ import org.dromara.workflow.domain.bo.FlowTaskBo; import org.dromara.workflow.domain.vo.FlowHisTaskVo; import org.dromara.workflow.domain.vo.FlowTaskVo; -import java.util.List; - /** * 任务信息Mapper接口 @@ -29,14 +27,6 @@ public interface FlwTaskMapper { */ Page getListRunTask(@Param("page") Page page, @Param(Constants.WRAPPER) Wrapper queryWrapper); - /** - * 获取待办信息 - * - * @param queryWrapper 条件 - * @return 结果 - */ - List getListRunTask(@Param(Constants.WRAPPER) Wrapper queryWrapper); - /** * 获取已办 * diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwCommonService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwCommonService.java index 662d599eb..652853599 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwCommonService.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwCommonService.java @@ -9,14 +9,6 @@ import java.util.List; */ public interface IFlwCommonService { - /** - * 构建工作流用户 - * - * @param permissionList 办理用户 - * @return 用户 - */ - List buildUser(List permissionList); - /** * 发送消息 * diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwInstanceService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwInstanceService.java index 01e5124b4..7852c2485 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwInstanceService.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwInstanceService.java @@ -141,14 +141,6 @@ public interface IFlwInstanceService { */ FlowInstance selectByTaskId(Long taskId); - /** - * 按任务id查询实例 - * - * @param taskIdList 任务id - * @return 结果 - */ - List selectByTaskIdList(List taskIdList); - /** * 作废流程 * diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskService.java index e172c001a..8bd399c59 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskService.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskService.java @@ -14,7 +14,6 @@ import org.dromara.workflow.domain.vo.FlowHisTaskVo; import org.dromara.workflow.domain.vo.FlowTaskVo; import java.util.List; -import java.util.Map; /** * 任务 服务层 @@ -150,14 +149,6 @@ public interface IFlwTaskService { */ List getNextNodeList(FlowNextNodeBo bo); - /** - * 按照任务id查询任务 - * - * @param taskIdList 任务id - * @return 结果 - */ - List selectHisTaskByIdList(List taskIdList); - /** * 按照任务id查询任务 * @@ -166,14 +157,6 @@ public interface IFlwTaskService { */ FlowHisTask selectHisTaskById(Long taskId); - /** - * 按照实例id查询任务 - * - * @param instanceIdList 流程实例id - * @return 结果 - */ - List selectByInstIdList(List instanceIdList); - /** * 按照实例id查询任务 * @@ -191,21 +174,13 @@ public interface IFlwTaskService { */ boolean taskOperation(TaskOperationBo bo, String taskOperation); - /** - * 获取任务所有办理人 - * - * @param taskIdList 任务id - * @return 结果 - */ - Map> currentTaskAllUser(List taskIdList); - /** * 获取当前任务的所有办理人 * - * @param taskId 任务id + * @param taskIds 任务id * @return 结果 */ - List currentTaskAllUser(Long taskId); + List currentTaskAllUser(List taskIds); /** * 按照节点编码查询节点 diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwChartExtServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwChartExtServiceImpl.java index d7c6f77eb..dba24e419 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwChartExtServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwChartExtServiceImpl.java @@ -27,8 +27,12 @@ import org.dromara.workflow.common.ConditionalOnEnable; import org.dromara.workflow.common.constant.FlowConstant; import org.springframework.stereotype.Service; +import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; /** * 流程图提示信息 @@ -74,15 +78,26 @@ public class FlwChartExtServiceImpl implements ChartExtService { Map dictType = dictService.getAllDictByDictType(FlowConstant.WF_TASK_STATUS); - // 遍历流程定义中的每个节点,调用处理方法,将对应节点的任务列表及用户信息传入,生成扩展提示内容 for (NodeJson nodeJson : defJson.getNodeList()) { - // 获取当前节点对应的历史任务列表,如果没有则返回空列表避免空指针 List taskList = groupedByNode.get(nodeJson.getNodeCode()); if (CollUtil.isEmpty(taskList)) { continue; } - // 处理当前节点的扩展信息,包括构建审批人提示内容等 - this.processNodeExtInfo(nodeJson, taskList, userMap, dictType); + + // 按审批人分组去重,保留最新处理记录,最终转换成 List + List latestPerApprover = taskList.stream() + .collect(Collectors.collectingAndThen( + Collectors.toMap( + FlowHisTask::getApprover, + Function.identity(), + (oldTask, newTask) -> newTask.getUpdateTime().after(oldTask.getUpdateTime()) ? newTask : oldTask, + LinkedHashMap::new + ), + map -> new ArrayList<>(map.values()) + )); + + // 处理当前节点的扩展信息 + this.processNodeExtInfo(nodeJson, latestPerApprover, userMap, dictType); } } @@ -240,7 +255,7 @@ public class FlwChartExtServiceImpl implements ChartExtService { LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); wrapper.eq(FlowHisTask::getInstanceId, instanceId) .eq(FlowHisTask::getNodeType, NodeType.BETWEEN.getKey()) - .orderByDesc(FlowHisTask::getCreateTime, FlowHisTask::getUpdateTime); + .orderByDesc(FlowHisTask::getUpdateTime); return flowHisTaskMapper.selectList(wrapper); } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCommonServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCommonServiceImpl.java index e6dc8155d..7285b17b1 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCommonServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCommonServiceImpl.java @@ -19,7 +19,6 @@ import org.dromara.warm.flow.orm.entity.FlowTask; import org.dromara.workflow.common.ConditionalOnEnable; import org.dromara.workflow.common.enums.MessageTypeEnum; import org.dromara.workflow.service.IFlwCommonService; -import org.dromara.workflow.service.IFlwTaskAssigneeService; import org.dromara.workflow.service.IFlwTaskService; import org.springframework.stereotype.Service; @@ -40,26 +39,6 @@ import java.util.stream.Collectors; public class FlwCommonServiceImpl implements IFlwCommonService { private final NodeService nodeService; - /** - * 构建工作流用户 - * - * @param permissionList 办理用户 - * @return 用户 - */ - @Override - public List buildUser(List permissionList) { - if (CollUtil.isEmpty(permissionList)) { - return List.of(); - } - IFlwTaskAssigneeService taskAssigneeService = SpringUtils.getBean(IFlwTaskAssigneeService.class); - String processedBys = CollUtil.join(permissionList, StringUtils.SEPARATOR); - // 根据 processedBy 前缀判断处理人类型,分别获取用户列表 - List users = taskAssigneeService.fetchUsersByStorageIds(processedBys); - - return StreamUtils.toList(users, userDTO -> String.valueOf(userDTO.getUserId())); - } - - /** * 发送消息 * @@ -70,40 +49,36 @@ public class FlwCommonServiceImpl implements IFlwCommonService { @Override public void sendMessage(String flowName, Long instId, List messageType, String message) { IFlwTaskService flwTaskService = SpringUtils.getBean(IFlwTaskService.class); - List userList = new ArrayList<>(); List list = flwTaskService.selectByInstId(instId); if (StringUtils.isBlank(message)) { message = "有新的【" + flowName + "】单据已经提交至您,请您及时处理。"; } - for (Task task : list) { - List users = flwTaskService.currentTaskAllUser(task.getId()); - if (CollUtil.isNotEmpty(users)) { - userList.addAll(users); - } + List userList = flwTaskService.currentTaskAllUser(StreamUtils.toList(list, FlowTask::getId)); + if (CollUtil.isEmpty(userList)) { + return; } - if (CollUtil.isNotEmpty(userList)) { - for (String code : messageType) { - MessageTypeEnum messageTypeEnum = MessageTypeEnum.getByCode(code); - if (ObjectUtil.isNotEmpty(messageTypeEnum)) { - switch (messageTypeEnum) { - case SYSTEM_MESSAGE: - SseMessageDto dto = new SseMessageDto(); - dto.setUserIds(StreamUtils.toList(userList, UserDTO::getUserId).stream().distinct().collect(Collectors.toList())); - dto.setMessage(message); - SseMessageUtils.publishMessage(dto); - break; - case EMAIL_MESSAGE: - MailUtils.sendText(StreamUtils.join(userList, UserDTO::getEmail), "单据审批提醒", message); - break; - case SMS_MESSAGE: - //todo 短信发送 - break; - default: - throw new IllegalStateException("Unexpected value: " + messageTypeEnum); - } + for (String code : messageType) { + MessageTypeEnum messageTypeEnum = MessageTypeEnum.getByCode(code); + if (ObjectUtil.isEmpty(messageTypeEnum)) { + continue; + } + switch (messageTypeEnum) { + case SYSTEM_MESSAGE -> { + SseMessageDto dto = new SseMessageDto(); + dto.setUserIds(StreamUtils.toList(userList, UserDTO::getUserId).stream().distinct().collect(Collectors.toList())); + dto.setMessage(message); + SseMessageUtils.publishMessage(dto); } + case EMAIL_MESSAGE -> { + MailUtils.sendText(StreamUtils.join(userList, UserDTO::getEmail), "单据审批提醒", message); + } + case SMS_MESSAGE -> { + //todo 短信发送 + } + default -> throw new IllegalStateException("Unexpected value: " + messageTypeEnum); } } + } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwDefinitionServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwDefinitionServiceImpl.java index 026f9ae8e..d19c7313d 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwDefinitionServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwDefinitionServiceImpl.java @@ -121,8 +121,8 @@ public class FlwDefinitionServiceImpl implements IFlwDefinitionService { List flowNodes = flowNodeMapper.selectList(new LambdaQueryWrapper().eq(FlowNode::getDefinitionId, id)); List errorMsg = new ArrayList<>(); if (CollUtil.isNotEmpty(flowNodes)) { + String applyNodeCode = flwCommonService.applyNodeCode(id); for (FlowNode flowNode : flowNodes) { - String applyNodeCode = flwCommonService.applyNodeCode(id); if (StringUtils.isBlank(flowNode.getPermissionFlag()) && !applyNodeCode.equals(flowNode.getNodeCode()) && NodeType.BETWEEN.getKey().equals(flowNode.getNodeType())) { errorMsg.add(flowNode.getNodeName()); } @@ -213,7 +213,8 @@ public class FlwDefinitionServiceImpl implements IFlwDefinitionService { return; } FlowCategory flowCategory = flwCategoryMapper.selectOne(new LambdaQueryWrapper() - .eq(FlowCategory::getTenantId, DEFAULT_TENANT_ID).eq(FlowCategory::getCategoryId, FlowConstant.FLOW_CATEGORY_ID)); + .eq(FlowCategory::getTenantId, DEFAULT_TENANT_ID) + .eq(FlowCategory::getCategoryId, FlowConstant.FLOW_CATEGORY_ID)); flowCategory.setCategoryId(null); flowCategory.setTenantId(tenantId); flowCategory.setCreateDept(null); diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java index a3e272f7e..e9775af9a 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java @@ -11,7 +11,6 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.dromara.common.core.domain.dto.UserDTO; import org.dromara.common.core.enums.BusinessStatusEnum; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.StreamUtils; @@ -19,11 +18,13 @@ import org.dromara.common.core.utils.StringUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.warm.flow.core.FlowEngine; import org.dromara.warm.flow.core.constant.ExceptionCons; import org.dromara.warm.flow.core.dto.FlowParams; import org.dromara.warm.flow.core.entity.Definition; import org.dromara.warm.flow.core.entity.Instance; 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.service.DefService; import org.dromara.warm.flow.core.service.InsService; @@ -49,7 +50,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.*; -import java.util.stream.Collectors; +import java.util.function.Function; /** * 流程实例 服务层实现 @@ -203,9 +204,11 @@ public class FlwInstanceServiceImpl implements IFlwInstanceService { return false; } // 获取定义信息 - Map definitionMap = defService.getByIds( - StreamUtils.toList(instances, Instance::getDefinitionId) - ).stream().collect(Collectors.toMap(Definition::getId, definition -> definition)); + Map definitionMap = StreamUtils.toMap( + defService.getByIds(StreamUtils.toList(instances, Instance::getDefinitionId)), + Definition::getId, + Function.identity() + ); // 逐一触发删除事件 instances.forEach(instance -> { @@ -281,37 +284,50 @@ public class FlwInstanceServiceImpl implements IFlwInstanceService { throw new ServiceException(ExceptionCons.NOT_FOUNT_INSTANCE); } Long instanceId = flowInstance.getId(); - //运行中的任务 - List list = new ArrayList<>(); - List flowTaskList = flwTaskService.selectByInstId(instanceId); - if (CollUtil.isNotEmpty(flowTaskList)) { - List flowHisTaskVos = BeanUtil.copyToList(flowTaskList, FlowHisTaskVo.class); - for (FlowHisTaskVo flowHisTaskVo : flowHisTaskVos) { - flowHisTaskVo.setFlowStatus(TaskStatusEnum.WAITING.getStatus()); - flowHisTaskVo.setUpdateTime(null); - flowHisTaskVo.setRunDuration(null); - List allUser = flwTaskService.currentTaskAllUser(flowHisTaskVo.getId()); - if (CollUtil.isNotEmpty(allUser)) { - String join = StreamUtils.join(allUser, e -> String.valueOf(e.getUserId())); - flowHisTaskVo.setApprover(join); + + // 先组装待审批任务(运行中的任务) + List runningTaskVos = new ArrayList<>(); + List runningTasks = flwTaskService.selectByInstId(instanceId); + if (CollUtil.isNotEmpty(runningTasks)) { + runningTaskVos = BeanUtil.copyToList(runningTasks, FlowHisTaskVo.class); + + List associatedUsers = FlowEngine.userService() + .getByAssociateds(StreamUtils.toList(runningTasks, FlowTask::getId)); + Map> taskUserMap = StreamUtils.groupByKey(associatedUsers, User::getAssociated); + + for (FlowHisTaskVo vo : runningTaskVos) { + vo.setFlowStatus(TaskStatusEnum.WAITING.getStatus()); + vo.setUpdateTime(null); + vo.setRunDuration(null); + + List users = taskUserMap.get(vo.getId()); + if (CollUtil.isNotEmpty(users)) { + vo.setApprover(StreamUtils.join(users, User::getProcessedBy)); } if (BusinessStatusEnum.isDraftOrCancelOrBack(flowInstance.getFlowStatus())) { - flowHisTaskVo.setApprover(LoginHelper.getUserIdStr()); - flowHisTaskVo.setApproveName(LoginHelper.getLoginUser().getNickname()); + vo.setApprover(LoginHelper.getUserIdStr()); } } - list.addAll(flowHisTaskVos); } - //历史任务 - LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); - wrapper.eq(FlowHisTask::getInstanceId, instanceId) - .eq(FlowHisTask::getNodeType, NodeType.BETWEEN.getKey()) - .orderByDesc(FlowHisTask::getCreateTime, FlowHisTask::getUpdateTime); - List flowHisTasks = flowHisTaskMapper.selectList(wrapper); - if (CollUtil.isNotEmpty(flowHisTasks)) { - list.addAll(BeanUtil.copyToList(flowHisTasks, FlowHisTaskVo.class)); + + // 再组装历史任务(已处理任务) + List hisTaskVos = new ArrayList<>(); + List hisTasks = flowHisTaskMapper.selectList( + new LambdaQueryWrapper() + .eq(FlowHisTask::getInstanceId, instanceId) + .eq(FlowHisTask::getNodeType, NodeType.BETWEEN.getKey()) + .orderByDesc(FlowHisTask::getUpdateTime) + ); + if (CollUtil.isNotEmpty(hisTasks)) { + hisTaskVos = BeanUtil.copyToList(hisTasks, FlowHisTaskVo.class); } - return Map.of("list", list, "instanceId", instanceId); + + // 结果列表,待审批任务在前,历史任务在后 + List combinedList = new ArrayList<>(); + combinedList.addAll(runningTaskVos); + combinedList.addAll(hisTaskVos); + + return Map.of("list", combinedList, "instanceId", instanceId); } /** @@ -377,31 +393,6 @@ public class FlwInstanceServiceImpl implements IFlwInstanceService { return null; } - /** - * 按任务id查询实例 - * - * @param taskIdList 任务id - */ - @Override - public List selectByTaskIdList(List taskIdList) { - if (CollUtil.isEmpty(taskIdList)) { - return Collections.emptyList(); - } - Set instanceIds = new HashSet<>(); - List flowTaskList = flwTaskService.selectByIdList(taskIdList); - for (FlowTask flowTask : flowTaskList) { - instanceIds.add(flowTask.getInstanceId()); - } - List flowHisTaskList = flwTaskService.selectHisTaskByIdList(taskIdList); - for (FlowHisTask flowHisTask : flowHisTaskList) { - instanceIds.add(flowHisTask.getInstanceId()); - } - if (!instanceIds.isEmpty()) { - return this.selectInstListByIdList(new ArrayList<>(instanceIds)); - } - return Collections.emptyList(); - } - /** * 作废流程 * diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java index ceefa8032..ff720a9e4 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java @@ -12,9 +12,7 @@ import org.dromara.common.core.domain.dto.TaskAssigneeDTO; import org.dromara.common.core.domain.dto.UserDTO; import org.dromara.common.core.domain.model.TaskAssigneeBody; import org.dromara.common.core.enums.FormatsType; -import org.dromara.common.core.service.DeptService; -import org.dromara.common.core.service.TaskAssigneeService; -import org.dromara.common.core.service.UserService; +import org.dromara.common.core.service.*; import org.dromara.common.core.utils.DateUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.warm.flow.ui.dto.HandlerFunDto; @@ -45,6 +43,8 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand private final TaskAssigneeService taskAssigneeService; private final UserService userService; private final DeptService deptService; + private final RoleService roleService; + private final PostService postService; /** * 获取办理人权限设置列表tabs页签 @@ -216,9 +216,9 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand private Map getNamesByType(TaskAssigneeEnum type, List ids) { return switch (type) { case USER -> userService.selectUserNamesByIds(ids); - case ROLE -> userService.selectRoleNamesByIds(ids); - case DEPT -> userService.selectDeptNamesByIds(ids); - case POST -> userService.selectPostNamesByIds(ids); + case ROLE -> roleService.selectRoleNamesByIds(ids); + case DEPT -> deptService.selectDeptNamesByIds(ids); + case POST -> postService.selectPostNamesByIds(ids); }; } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java index f96a75732..ab5f1c34f 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java @@ -55,7 +55,6 @@ import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.util.*; -import java.util.stream.Collectors; import static org.dromara.workflow.common.constant.FlowConstant.*; @@ -252,14 +251,12 @@ public class FlwTaskServiceImpl implements IFlwTaskService { hisTask.setCreateTime(updateTime); hisTask.setUpdateTime(updateTime); hisTaskService.save(hisTask); - List userList = flowCopyList.stream() - .map(flowCopy -> { - FlowUser flowUser = new FlowUser(); - flowUser.setType(TaskAssigneeType.COPY.getCode()); - flowUser.setProcessedBy(String.valueOf(flowCopy.getUserId())); - flowUser.setAssociated(taskId); - return flowUser; - }).collect(Collectors.toList()); + List userList = StreamUtils.toList(flowCopyList, x -> + new FlowUser() + .setType(TaskAssigneeType.COPY.getCode()) + .setProcessedBy(String.valueOf(x.getUserId())) + .setAssociated(taskId) + ); // 批量保存抄送人员 FlowEngine.userService().saveBatch(userList); } @@ -276,7 +273,8 @@ public class FlwTaskServiceImpl implements IFlwTaskService { queryWrapper.eq("t.node_type", NodeType.BETWEEN.getKey()); queryWrapper.in("t.processed_by", LoginHelper.getUserIdStr()); queryWrapper.in("t.flow_status", BusinessStatusEnum.WAITING.getStatus()); - Page page = this.getFlowTaskVoPage(pageQuery, queryWrapper); + Page page = flwTaskMapper.getListRunTask(pageQuery.build(), queryWrapper); + this.wrapAssigneeInfo(page.getRecords()); return TableDataInfo.build(page); } @@ -306,25 +304,28 @@ public class FlwTaskServiceImpl implements IFlwTaskService { public TableDataInfo pageByAllTaskWait(FlowTaskBo flowTaskBo, PageQuery pageQuery) { QueryWrapper queryWrapper = buildQueryWrapper(flowTaskBo); queryWrapper.eq("t.node_type", NodeType.BETWEEN.getKey()); - Page page = getFlowTaskVoPage(pageQuery, queryWrapper); + Page page = flwTaskMapper.getListRunTask(pageQuery.build(), queryWrapper); + this.wrapAssigneeInfo(page.getRecords()); return TableDataInfo.build(page); } - private Page getFlowTaskVoPage(PageQuery pageQuery, QueryWrapper queryWrapper) { - Page page = flwTaskMapper.getListRunTask(pageQuery.build(), queryWrapper); - List records = page.getRecords(); - if (CollUtil.isNotEmpty(records)) { - List taskIds = StreamUtils.toList(records, FlowTaskVo::getId); - Map> listMap = currentTaskAllUser(taskIds); - records.forEach(t -> { - List userList = listMap.getOrDefault(t.getId(), Collections.emptyList()); - if (CollUtil.isNotEmpty(userList)) { - t.setAssigneeIds(StreamUtils.join(userList, e -> String.valueOf(e.getUserId()))); - t.setAssigneeNames(StreamUtils.join(userList, UserDTO::getNickName)); - } - }); + /** + * 为流程任务列表封装处理人 ID(assigneeIds) + * + * @param taskList 流程任务列表 + */ + private void wrapAssigneeInfo(List taskList) { + if (CollUtil.isEmpty(taskList)) { + return; + } + List associatedUsers = FlowEngine.userService() + .getByAssociateds(StreamUtils.toList(taskList, FlowTaskVo::getId)); + Map> taskUserMap = StreamUtils.groupByKey(associatedUsers, User::getAssociated); + // 组装用户数据回任务列表 + for (FlowTaskVo task : taskList) { + List users = taskUserMap.get(task.getId()); + task.setAssigneeIds(StreamUtils.join(users, User::getProcessedBy)); } - return page; } /** @@ -527,15 +528,15 @@ public class FlwTaskServiceImpl implements IFlwTaskService { // 只获取中间节点 nextFlowNodes = StreamUtils.filter(nextFlowNodes, node -> NodeType.BETWEEN.getKey().equals(node.getNodeType())); if (CollUtil.isNotEmpty(nextNodeList)) { - // 构建以下节点数据 + //构建以下节点数据 List buildNextTaskList = StreamUtils.toList(nextNodeList, node -> taskService.addTask(node, instance, definition, FlowParams.build())); - // 办理人变量替换 - ExpressionUtil.evalVariable(buildNextTaskList, - FlowParams.build() - .variable(mergeVariable) - ); + //办理人变量替换 + ExpressionUtil.evalVariable(buildNextTaskList, FlowParams.build().variable(mergeVariable)); for (FlowNode flowNode : nextFlowNodes) { - buildNextTaskList.stream().filter(t -> t.getNodeCode().equals(flowNode.getNodeCode())).findFirst().ifPresent(t -> { + Optional first = buildNextTaskList.stream() + .filter(t -> t.getNodeCode().equals(flowNode.getNodeCode())) + .findFirst(); + first.ifPresent(t -> { if (CollUtil.isNotEmpty(t.getPermissionList())) { List users = flwTaskAssigneeService.fetchUsersByStorageIds(String.join(StringUtils.SEPARATOR, t.getPermissionList())); if (CollUtil.isNotEmpty(users)) { @@ -548,18 +549,6 @@ public class FlwTaskServiceImpl implements IFlwTaskService { return nextFlowNodes; } - /** - * 按照任务id查询任务 - * - * @param taskIdList 任务id - * @return 结果 - */ - @Override - public List selectHisTaskByIdList(List taskIdList) { - return flowHisTaskMapper.selectList(new LambdaQueryWrapper<>(FlowHisTask.class) - .in(FlowHisTask::getId, taskIdList)); - } - /** * 按照任务id查询任务 * @@ -572,17 +561,6 @@ public class FlwTaskServiceImpl implements IFlwTaskService { .eq(FlowHisTask::getId, taskId)); } - /** - * 按照实例id查询任务 - * - * @param instanceIdList 流程实例id - */ - @Override - public List selectByInstIdList(List instanceIdList) { - return flowTaskMapper.selectList(new LambdaQueryWrapper<>(FlowTask.class) - .in(FlowTask::getInstanceId, instanceIdList)); - } - /** * 按照实例id查询任务 * @@ -683,15 +661,12 @@ public class FlwTaskServiceImpl implements IFlwTaskService { // 批量删除现有任务的办理人记录 if (CollUtil.isNotEmpty(flowTasks)) { FlowEngine.userService().deleteByTaskIds(StreamUtils.toList(flowTasks, FlowTask::getId)); - List userList = flowTasks.stream() - .map(flowTask -> { - FlowUser flowUser = new FlowUser(); - flowUser.setType(TaskAssigneeType.APPROVER.getCode()); - flowUser.setProcessedBy(userId); - flowUser.setAssociated(flowTask.getId()); - return flowUser; - }) - .collect(Collectors.toList()); + List userList = StreamUtils.toList(flowTasks, flowTask -> + new FlowUser() + .setType(TaskAssigneeType.APPROVER.getCode()) + .setProcessedBy(userId) + .setAssociated(flowTask.getId()) + ); if (CollUtil.isNotEmpty(userList)) { FlowEngine.userService().saveBatch(userList); } @@ -703,36 +678,15 @@ public class FlwTaskServiceImpl implements IFlwTaskService { return true; } - /** - * 获取任务所有办理人 - * - * @param taskIdList 任务id - */ - @Override - public Map> currentTaskAllUser(List taskIdList) { - Map> map = new HashMap<>(); - // 获取与当前任务关联的用户列表 - List associatedUsers = FlowEngine.userService().getByAssociateds(taskIdList); - Map> listMap = StreamUtils.groupByKey(associatedUsers, User::getAssociated); - for (Map.Entry> entry : listMap.entrySet()) { - List value = entry.getValue(); - if (CollUtil.isNotEmpty(value)) { - List userDtoList = userService.selectListByIds(StreamUtils.toList(value, e -> Convert.toLong(e.getProcessedBy()))); - map.put(entry.getKey(), userDtoList); - } - } - return map; - } - /** * 获取当前任务的所有办理人 * - * @param taskId 任务id + * @param taskIds 任务id */ @Override - public List currentTaskAllUser(Long taskId) { + public List currentTaskAllUser(List taskIds) { // 获取与当前任务关联的用户列表 - List userList = FlowEngine.userService().getByAssociateds(Collections.singletonList(taskId)); + List userList = FlowEngine.userService().getByAssociateds(taskIds); if (CollUtil.isEmpty(userList)) { return Collections.emptyList(); }