23 Commits

Author SHA1 Message Date
疯狂的狮子Li
fd5d028e95 fix 修复 有某些无聊人士 对一个demo案例提漏洞 CVE-2025-6925
Signed-off-by: 疯狂的狮子Li <15040126243@163.com>
2025-07-04 01:10:49 +00:00
疯狂的狮子Li
64100cf1ff !712 发布 5.4.1 小步迭代修复问题
Merge pull request !712 from 疯狂的狮子Li/dev
2025-07-01 01:12:39 +00:00
疯狂的狮子Li
7e7d857ba5 Merge remote-tracking branch 'origin/dev' into 5.X 2025-05-29 18:18:20 +08:00
疯狂的狮子Li
d22b2a10df update 优化 PermissionService 无实现类也可以启动服务 2025-05-29 16:28:56 +08:00
疯狂的狮子Li
957a4d1fcd fix 修复 监听器 flowParams 为null报错问题 2025-05-29 16:28:56 +08:00
疯狂的狮子Li
49ef8378fe !691 发布 5.4.0 正式版
Merge pull request !691 from 疯狂的狮子Li/dev
2025-05-29 03:14:59 +00:00
疯狂的狮子Li
57dd6831d3 !664 发布 5.3.1 正式版
Merge pull request !664 from 疯狂的狮子Li/dev
2025-03-27 02:54:00 +00:00
疯狂的狮子Li
8aa60abb1f !663 回退 'Pull Request !662 : 发布 5.3.1 正式版'
* 回退 'Pull Request !662 : 发布 5.3.1 正式版'
2025-03-27 02:53:23 +00:00
疯狂的狮子Li
7a9f51fc7a !662 发布 5.3.1 正式版
* 🐳发布 5.3.1 正式版
* update 优化 删除无用配置
* fix 修复 excel模板导出数据被覆盖的问题
* update 优化 统一用户密码校验长度
* update mybatis-plus 3.5.10.1 => 3.5.11
* fix 修复 跨域未设置请求头问题(cloud版本不需要 vue版本需要)
2025-03-27 02:51:57 +00:00
疯狂的狮子Li
159e30c982 !661 发布 5.3.1-BETA2 公测版本
Merge pull request !661 from 疯狂的狮子Li/dev
2025-03-21 07:25:25 +00:00
疯狂的狮子Li
7334d91d6b !652 发布 5.3.1-BETA 公测版本
Merge pull request !652 from 疯狂的狮子Li/dev
2025-03-13 05:27:36 +00:00
疯狂的狮子Li
95c01301f6 !644 同步修复一些问题
Merge pull request !644 from 疯狂的狮子Li/dev
2025-02-07 06:19:28 +00:00
疯狂的狮子Li
296466fa13 !640 发布 5.3.0 新春版 祝大家新年快乐
Merge pull request !640 from 疯狂的狮子Li/dev
2025-01-24 05:08:28 +00:00
疯狂的狮子Li
3c8d864b5f !639 发布 5.3.0-BETA 公测版本
Merge pull request !639 from 疯狂的狮子Li/dev
2025-01-20 03:35:45 +00:00
疯狂的狮子Li
ea50a57602 update 优化 xss包装器 Parameter 处理 兼容某些容器不允许改参数的情况 2024-11-21 10:17:34 +08:00
疯狂的狮子Li
7e14b98676 reset 回滚错误修改
Signed-off-by: 疯狂的狮子Li <15040126243@163.com>
2024-10-28 09:46:28 +00:00
疯狂的狮子Li
015b406001 !591 发布 5.2.3 正式版
Merge pull request !591 from 疯狂的狮子Li/dev
2024-10-25 03:09:23 +00:00
疯狂的狮子Li
098d3347a0 !577 发布 5.2.2 正式版 安全性提升
Merge pull request !577 from 疯狂的狮子Li/dev
2024-08-26 03:43:59 +00:00
疯狂的狮子Li
08d4493994 update 优化 bug 模板 2024-07-15 15:19:22 +08:00
疯狂的狮子Li
367d739e2d Merge remote-tracking branch 'origin/5.X' into 5.X 2024-07-09 16:38:43 +08:00
疯狂的狮子Li
d6688a367d !562 ♥️发布 5.2.1 正式版本
Merge pull request !562 from 疯狂的狮子Li/dev
2024-07-09 02:42:40 +00:00
疯狂的狮子Li
0b331796e2 !551 ♥️发布 5.2.0 正式版本
Merge pull request !551 from 疯狂的狮子Li/dev
2024-06-20 02:10:15 +00:00
疯狂的狮子Li
456620b638 !549 ♥️发布 5.2.0-BETA2 公测版本
Merge pull request !549 from 疯狂的狮子Li/dev
2024-06-06 03:13:46 +00:00
30 changed files with 447 additions and 429 deletions

View File

@@ -3,7 +3,6 @@ package org.dromara.common.core.service;
import org.dromara.common.core.domain.dto.DeptDTO; import org.dromara.common.core.domain.dto.DeptDTO;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* 通用 部门服务 * 通用 部门服务
@@ -35,12 +34,4 @@ public interface DeptService {
*/ */
List<DeptDTO> selectDeptsByList(); List<DeptDTO> selectDeptsByList();
/**
* 根据部门 ID 列表查询部门名称映射关系
*
* @param deptIds 部门 ID 列表
* @return Map其中 key 为部门 IDvalue 为对应的部门名称
*/
Map<Long, String> selectDeptNamesByIds(List<Long> deptIds);
} }

View File

@@ -1,8 +1,5 @@
package org.dromara.common.core.service; package org.dromara.common.core.service;
import java.util.List;
import java.util.Map;
/** /**
* 通用 岗位服务 * 通用 岗位服务
* *
@@ -10,12 +7,4 @@ import java.util.Map;
*/ */
public interface PostService { public interface PostService {
/**
* 根据岗位 ID 列表查询岗位名称映射关系
*
* @param postIds 岗位 ID 列表
* @return Map其中 key 为岗位 IDvalue 为对应的岗位名称
*/
Map<Long, String> selectPostNamesByIds(List<Long> postIds);
} }

View File

@@ -1,8 +1,5 @@
package org.dromara.common.core.service; package org.dromara.common.core.service;
import java.util.List;
import java.util.Map;
/** /**
* 通用 角色服务 * 通用 角色服务
* *
@@ -10,12 +7,4 @@ import java.util.Map;
*/ */
public interface RoleService { public interface RoleService {
/**
* 根据角色 ID 列表查询角色名称映射关系
*
* @param roleIds 角色 ID 列表
* @return Map其中 key 为角色 IDvalue 为对应的角色名称
*/
Map<Long, String> selectRoleNamesByIds(List<Long> roleIds);
} }

View File

@@ -100,4 +100,28 @@ public interface UserService {
*/ */
Map<Long, String> selectUserNamesByIds(List<Long> userIds); 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

@@ -6,6 +6,7 @@ import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.R;
import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.sse.core.SseEmitterManager; import org.dromara.common.sse.core.SseEmitterManager;
import org.dromara.common.sse.dto.SseMessageDto;
import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.DisposableBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
@@ -13,6 +14,8 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.util.List;
/** /**
* SSE 控制器 * SSE 控制器
* *
@@ -48,32 +51,31 @@ public class SseController implements DisposableBean {
return R.ok(); return R.ok();
} }
// 以下为demo仅供参考 禁止使用 请在业务逻辑中使用工具发送而不是用接口发送 /**
// /** * 向特定用户发送消息
// * 向特定用户发送消息 *
// * * @param userId 目标用户的 ID
// * @param userId 目标用户的 ID * @param msg 要发送的消息内容
// * @param msg 要发送的消息内容 */
// */ @GetMapping(value = "${sse.path}/send")
// @GetMapping(value = "${sse.path}/send") public R<Void> send(Long userId, String msg) {
// public R<Void> send(Long userId, String msg) { SseMessageDto dto = new SseMessageDto();
// SseMessageDto dto = new SseMessageDto(); dto.setUserIds(List.of(userId));
// dto.setUserIds(List.of(userId)); dto.setMessage(msg);
// dto.setMessage(msg); sseEmitterManager.publishMessage(dto);
// sseEmitterManager.publishMessage(dto); return R.ok();
// return R.ok(); }
// }
// /**
// /** * 向所有用户发送消息
// * 向所有用户发送消息 *
// * * @param msg 要发送的消息内容
// * @param msg 要发送的消息内容 */
// */ @GetMapping(value = "${sse.path}/sendAll")
// @GetMapping(value = "${sse.path}/sendAll") public R<Void> send(String msg) {
// public R<Void> send(String msg) { sseEmitterManager.publishAll(msg);
// sseEmitterManager.publishAll(msg); return R.ok();
// return R.ok(); }
// }
/** /**
* 清理资源。此方法目前不执行任何操作,但避免因未实现而导致错误 * 清理资源。此方法目前不执行任何操作,但避免因未实现而导致错误

View File

@@ -21,7 +21,7 @@ import java.util.Arrays;
@RequiredArgsConstructor @RequiredArgsConstructor
@RestController @RestController
@RequestMapping("/demo/mail") @RequestMapping("/demo/mail")
public class MailSendController { public class MailController {
/** /**
* 发送邮件 * 发送邮件

View File

@@ -19,7 +19,6 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
/** /**
@@ -108,7 +107,7 @@ public class SysPostController extends BaseController {
@Log(title = "岗位管理", businessType = BusinessType.DELETE) @Log(title = "岗位管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{postIds}") @DeleteMapping("/{postIds}")
public R<Void> remove(@PathVariable Long[] postIds) { public R<Void> remove(@PathVariable Long[] postIds) {
return toAjax(postService.deletePostByIds(Arrays.asList(postIds))); return toAjax(postService.deletePostByIds(postIds));
} }
/** /**

View File

@@ -1,75 +0,0 @@
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<String> tags;
/**
* 业务绑定ID如某业务记录ID
*/
private String refId;
/**
* 绑定业务类型
*/
private String refType;
/**
* 是否为临时文件,用于区分正式或待清理
*/
private Boolean isTemp;
/**
* 文件MD5值可用于去重或校验
*/
private String md5;
}

View File

@@ -4,7 +4,6 @@ import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param; 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.DataColumn;
import org.dromara.common.mybatis.annotation.DataPermission; import org.dromara.common.mybatis.annotation.DataPermission;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
@@ -73,19 +72,6 @@ public interface SysDeptMapper extends BaseMapperPlus<SysDept, SysDeptVo> {
.apply(DataBaseHelper.findInSet(parentId, "ancestors"))); .apply(DataBaseHelper.findInSet(parentId, "ancestors")));
} }
/**
* 查询某个部门及其所有子部门ID含自身
*
* @param parentId 父部门ID
* @return 部门ID集合
*/
default List<Long> selectDeptAndChildById(Long parentId) {
List<SysDept> deptList = this.selectListByParentId(parentId);
List<Long> deptIds = StreamUtils.toList(deptList, SysDept::getDeptId);
deptIds.add(parentId);
return deptIds;
}
/** /**
* 根据角色ID查询部门树信息 * 根据角色ID查询部门树信息
* *

View File

@@ -110,7 +110,7 @@ public interface ISysPostService {
* @param postIds 需要删除的岗位ID * @param postIds 需要删除的岗位ID
* @return 结果 * @return 结果
*/ */
int deletePostByIds(List<Long> postIds); int deletePostByIds(Long[] postIds);
/** /**
* 新增保存岗位信息 * 新增保存岗位信息

View File

@@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.dromara.common.core.constant.CacheNames; import org.dromara.common.core.constant.CacheNames;
import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StreamUtils;
import org.dromara.system.domain.SysDept;
import org.dromara.system.domain.SysRoleDept; import org.dromara.system.domain.SysRoleDept;
import org.dromara.system.mapper.SysDeptMapper; import org.dromara.system.mapper.SysDeptMapper;
import org.dromara.system.mapper.SysRoleDeptMapper; import org.dromara.system.mapper.SysRoleDeptMapper;
@@ -65,8 +66,13 @@ public class SysDataScopeServiceImpl implements ISysDataScopeService {
if (ObjectUtil.isNull(deptId)) { if (ObjectUtil.isNull(deptId)) {
return "-1"; return "-1";
} }
List<Long> deptIds = deptMapper.selectDeptAndChildById(deptId); List<SysDept> deptList = deptMapper.selectListByParentId(deptId);
return CollUtil.isNotEmpty(deptIds) ? StreamUtils.join(deptIds, Convert::toStr) : "-1"; List<Long> ids = StreamUtils.toList(deptList, SysDept::getDeptId);
ids.add(deptId);
if (CollUtil.isNotEmpty(ids)) {
return StreamUtils.join(ids, Convert::toStr);
}
return "-1";
} }
} }

View File

@@ -36,7 +36,10 @@ import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.*; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/** /**
* 部门管理 服务实现 * 部门管理 服务实现
@@ -107,7 +110,10 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService {
if (ObjectUtil.isNotNull(bo.getBelongDeptId())) { if (ObjectUtil.isNotNull(bo.getBelongDeptId())) {
//部门树搜索 //部门树搜索
lqw.and(x -> { lqw.and(x -> {
List<Long> deptIds = baseMapper.selectDeptAndChildById(bo.getBelongDeptId()); Long parentId = bo.getBelongDeptId();
List<SysDept> deptList = baseMapper.selectListByParentId(parentId);
List<Long> deptIds = StreamUtils.toList(deptList, SysDept::getDeptId);
deptIds.add(parentId);
x.in(SysDept::getDeptId, deptIds); x.in(SysDept::getDeptId, deptIds);
}); });
} }
@@ -403,24 +409,4 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService {
return baseMapper.deleteById(deptId); return baseMapper.deleteById(deptId);
} }
/**
* 根据部门 ID 列表查询部门名称映射关系
*
* @param deptIds 部门 ID 列表
* @return Map其中 key 为部门 IDvalue 为对应的部门名称
*/
@Override
public Map<Long, String> selectDeptNamesByIds(List<Long> deptIds) {
if (CollUtil.isEmpty(deptIds)) {
return Collections.emptyMap();
}
List<SysDept> list = baseMapper.selectList(
new LambdaQueryWrapper<SysDept>()
.select(SysDept::getDeptId, SysDept::getDeptName)
.in(SysDept::getDeptId, deptIds)
);
return StreamUtils.toMap(list, SysDept::getDeptId, SysDept::getDeptName);
}
} }

View File

@@ -17,7 +17,6 @@ import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.utils.file.FileUtils; 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.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.oss.core.OssClient; import org.dromara.common.oss.core.OssClient;
@@ -25,7 +24,6 @@ import org.dromara.common.oss.entity.UploadResult;
import org.dromara.common.oss.enums.AccessPolicyType; import org.dromara.common.oss.enums.AccessPolicyType;
import org.dromara.common.oss.factory.OssFactory; import org.dromara.common.oss.factory.OssFactory;
import org.dromara.system.domain.SysOss; import org.dromara.system.domain.SysOss;
import org.dromara.system.domain.SysOssExt;
import org.dromara.system.domain.bo.SysOssBo; import org.dromara.system.domain.bo.SysOssBo;
import org.dromara.system.domain.vo.SysOssVo; import org.dromara.system.domain.vo.SysOssVo;
import org.dromara.system.mapper.SysOssMapper; import org.dromara.system.mapper.SysOssMapper;
@@ -201,11 +199,8 @@ public class SysOssServiceImpl implements ISysOssService, OssService {
} catch (IOException e) { } catch (IOException e) {
throw new ServiceException(e.getMessage()); throw new ServiceException(e.getMessage());
} }
SysOssExt ext1 = new SysOssExt();
ext1.setFileSize(file.getSize());
ext1.setContentType(file.getContentType());
// 保存文件信息 // 保存文件信息
return buildResultEntity(originalfileName, suffix, storage.getConfigKey(), uploadResult, ext1); return buildResultEntity(originalfileName, suffix, storage.getConfigKey(), uploadResult);
} }
/** /**
@@ -220,21 +215,18 @@ public class SysOssServiceImpl implements ISysOssService, OssService {
String suffix = StringUtils.substring(originalfileName, originalfileName.lastIndexOf("."), originalfileName.length()); String suffix = StringUtils.substring(originalfileName, originalfileName.lastIndexOf("."), originalfileName.length());
OssClient storage = OssFactory.instance(); OssClient storage = OssFactory.instance();
UploadResult uploadResult = storage.uploadSuffix(file, suffix); UploadResult uploadResult = storage.uploadSuffix(file, suffix);
SysOssExt ext1 = new SysOssExt();
ext1.setFileSize(file.length());
// 保存文件信息 // 保存文件信息
return buildResultEntity(originalfileName, suffix, storage.getConfigKey(), uploadResult, ext1); return buildResultEntity(originalfileName, suffix, storage.getConfigKey(), uploadResult);
} }
@NotNull @NotNull
private SysOssVo buildResultEntity(String originalfileName, String suffix, String configKey, UploadResult uploadResult, SysOssExt ext1) { private SysOssVo buildResultEntity(String originalfileName, String suffix, String configKey, UploadResult uploadResult) {
SysOss oss = new SysOss(); SysOss oss = new SysOss();
oss.setUrl(uploadResult.getUrl()); oss.setUrl(uploadResult.getUrl());
oss.setFileSuffix(suffix); oss.setFileSuffix(suffix);
oss.setFileName(uploadResult.getFilename()); oss.setFileName(uploadResult.getFilename());
oss.setOriginalName(originalfileName); oss.setOriginalName(originalfileName);
oss.setService(configKey); oss.setService(configKey);
oss.setExt1(JsonUtils.toJsonString(ext1));
baseMapper.insert(oss); baseMapper.insert(oss);
SysOssVo sysOssVo = MapstructUtils.convert(oss, SysOssVo.class); SysOssVo sysOssVo = MapstructUtils.convert(oss, SysOssVo.class);
return this.matchingUrl(sysOssVo); return this.matchingUrl(sysOssVo);

View File

@@ -14,6 +14,7 @@ import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo; 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.SysPost;
import org.dromara.system.domain.SysUserPost; import org.dromara.system.domain.SysUserPost;
import org.dromara.system.domain.bo.SysPostBo; import org.dromara.system.domain.bo.SysPostBo;
@@ -24,7 +25,7 @@ import org.dromara.system.mapper.SysUserPostMapper;
import org.dromara.system.service.ISysPostService; import org.dromara.system.service.ISysPostService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.Collections; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -91,7 +92,9 @@ public class SysPostServiceImpl implements ISysPostService, PostService {
} else if (ObjectUtil.isNotNull(bo.getBelongDeptId())) { } else if (ObjectUtil.isNotNull(bo.getBelongDeptId())) {
//部门树搜索 //部门树搜索
wrapper.and(x -> { wrapper.and(x -> {
List<Long> deptIds = deptMapper.selectDeptAndChildById(bo.getBelongDeptId()); List<SysDept> deptList = deptMapper.selectListByParentId(bo.getBelongDeptId());
List<Long> deptIds = StreamUtils.toList(deptList, SysDept::getDeptId);
deptIds.add(bo.getBelongDeptId());
x.in(SysPost::getDeptId, deptIds); x.in(SysPost::getDeptId, deptIds);
}); });
} }
@@ -214,14 +217,14 @@ public class SysPostServiceImpl implements ISysPostService, PostService {
* @return 结果 * @return 结果
*/ */
@Override @Override
public int deletePostByIds(List<Long> postIds) { public int deletePostByIds(Long[] postIds) {
List<SysPost> list = baseMapper.selectByIds(postIds); for (Long postId : postIds) {
for (SysPost post : list) { SysPost post = baseMapper.selectById(postId);
if (this.countUserPostById(post.getPostId()) > 0) { if (countUserPostById(postId) > 0) {
throw new ServiceException(String.format("%1$s已分配不能删除!", post.getPostName())); throw new ServiceException(String.format("%1$s已分配不能删除!", post.getPostName()));
} }
} }
return baseMapper.deleteByIds(postIds); return baseMapper.deleteByIds(Arrays.asList(postIds));
} }
/** /**
@@ -248,23 +251,4 @@ public class SysPostServiceImpl implements ISysPostService, PostService {
return baseMapper.updateById(post); return baseMapper.updateById(post);
} }
/**
* 根据岗位 ID 列表查询岗位名称映射关系
*
* @param postIds 岗位 ID 列表
* @return Map其中 key 为岗位 IDvalue 为对应的岗位名称
*/
@Override
public Map<Long, String> selectPostNamesByIds(List<Long> postIds) {
if (CollUtil.isEmpty(postIds)) {
return Collections.emptyMap();
}
List<SysPost> list = baseMapper.selectList(
new LambdaQueryWrapper<SysPost>()
.select(SysPost::getPostId, SysPost::getPostName)
.in(SysPost::getPostId, postIds)
);
return StreamUtils.toMap(list, SysPost::getPostId, SysPost::getPostName);
}
} }

View File

@@ -549,23 +549,4 @@ public class SysRoleServiceImpl implements ISysRoleService, RoleService {
}); });
} }
/**
* 根据角色 ID 列表查询角色名称映射关系
*
* @param roleIds 角色 ID 列表
* @return Map其中 key 为角色 IDvalue 为对应的角色名称
*/
@Override
public Map<Long, String> selectRoleNamesByIds(List<Long> roleIds) {
if (CollUtil.isEmpty(roleIds)) {
return Collections.emptyMap();
}
List<SysRole> list = baseMapper.selectList(
new LambdaQueryWrapper<SysRole>()
.select(SysRole::getRoleId, SysRole::getRoleName)
.in(SysRole::getRoleId, roleIds)
);
return StreamUtils.toMap(list, SysRole::getRoleId, SysRole::getRoleName);
}
} }

View File

@@ -22,10 +22,7 @@ import org.dromara.common.core.utils.*;
import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.domain.SysRole; import org.dromara.system.domain.*;
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.bo.SysUserBo;
import org.dromara.system.domain.vo.SysPostVo; import org.dromara.system.domain.vo.SysPostVo;
import org.dromara.system.domain.vo.SysRoleVo; import org.dromara.system.domain.vo.SysRoleVo;
@@ -39,6 +36,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
/** /**
* 用户 业务层处理 * 用户 业务层处理
@@ -81,8 +79,10 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
.between(params.get("beginTime") != null && params.get("endTime") != null, .between(params.get("beginTime") != null && params.get("endTime") != null,
"u.create_time", params.get("beginTime"), params.get("endTime")) "u.create_time", params.get("beginTime"), params.get("endTime"))
.and(ObjectUtil.isNotNull(user.getDeptId()), w -> { .and(ObjectUtil.isNotNull(user.getDeptId()), w -> {
List<Long> deptIds = deptMapper.selectDeptAndChildById(user.getDeptId()); List<SysDept> deptList = deptMapper.selectListByParentId(user.getDeptId());
w.in("u.dept_id", deptIds); List<Long> ids = StreamUtils.toList(deptList, SysDept::getDeptId);
ids.add(user.getDeptId());
w.in("u.dept_id", ids);
}).orderByAsc("u.user_id"); }).orderByAsc("u.user_id");
return baseMapper.selectUserExportList(wrapper); return baseMapper.selectUserExportList(wrapper);
} }
@@ -100,7 +100,9 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
.between(params.get("beginTime") != null && params.get("endTime") != null, .between(params.get("beginTime") != null && params.get("endTime") != null,
SysUser::getCreateTime, params.get("beginTime"), params.get("endTime")) SysUser::getCreateTime, params.get("beginTime"), params.get("endTime"))
.and(ObjectUtil.isNotNull(user.getDeptId()), w -> { .and(ObjectUtil.isNotNull(user.getDeptId()), w -> {
List<Long> ids = deptMapper.selectDeptAndChildById(user.getDeptId()); List<SysDept> deptList = deptMapper.selectListByParentId(user.getDeptId());
List<Long> ids = StreamUtils.toList(deptList, SysDept::getDeptId);
ids.add(user.getDeptId());
w.in(SysUser::getDeptId, ids); w.in(SysUser::getDeptId, ids);
}).orderByAsc(SysUser::getUserId); }).orderByAsc(SysUser::getUserId);
if (StringUtils.isNotBlank(user.getExcludeUserIds())) { if (StringUtils.isNotBlank(user.getExcludeUserIds())) {
@@ -746,12 +748,69 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
if (CollUtil.isEmpty(userIds)) { if (CollUtil.isEmpty(userIds)) {
return Collections.emptyMap(); return Collections.emptyMap();
} }
List<SysUser> list = baseMapper.selectList( return baseMapper.selectList(
new LambdaQueryWrapper<SysUser>() new LambdaQueryWrapper<SysUser>()
.select(SysUser::getUserId, SysUser::getNickName) .select(SysUser::getUserId, SysUser::getNickName)
.in(SysUser::getUserId, userIds) .in(SysUser::getUserId, userIds)
); ).stream()
return StreamUtils.toMap(list, SysUser::getUserId, SysUser::getNickName); .collect(Collectors.toMap(SysUser::getUserId, SysUser::getNickName));
}
/**
* 根据角色 ID 列表查询角色名称映射关系
*
* @param roleIds 角色 ID 列表
* @return Map其中 key 为角色 IDvalue 为对应的角色名称
*/
@Override
public Map<Long, String> selectRoleNamesByIds(List<Long> roleIds) {
if (CollUtil.isEmpty(roleIds)) {
return Collections.emptyMap();
}
return roleMapper.selectList(
new LambdaQueryWrapper<SysRole>()
.select(SysRole::getRoleId, SysRole::getRoleName)
.in(SysRole::getRoleId, roleIds)
).stream()
.collect(Collectors.toMap(SysRole::getRoleId, SysRole::getRoleName));
}
/**
* 根据部门 ID 列表查询部门名称映射关系
*
* @param deptIds 部门 ID 列表
* @return Map其中 key 为部门 IDvalue 为对应的部门名称
*/
@Override
public Map<Long, String> selectDeptNamesByIds(List<Long> deptIds) {
if (CollUtil.isEmpty(deptIds)) {
return Collections.emptyMap();
}
return deptMapper.selectList(
new LambdaQueryWrapper<SysDept>()
.select(SysDept::getDeptId, SysDept::getDeptName)
.in(SysDept::getDeptId, deptIds)
).stream()
.collect(Collectors.toMap(SysDept::getDeptId, SysDept::getDeptName));
}
/**
* 根据岗位 ID 列表查询岗位名称映射关系
*
* @param postIds 岗位 ID 列表
* @return Map其中 key 为岗位 IDvalue 为对应的岗位名称
*/
@Override
public Map<Long, String> selectPostNamesByIds(List<Long> postIds) {
if (CollUtil.isEmpty(postIds)) {
return Collections.emptyMap();
}
return postMapper.selectList(
new LambdaQueryWrapper<SysPost>()
.select(SysPost::getPostId, SysPost::getPostName)
.in(SysPost::getPostId, postIds)
).stream()
.collect(Collectors.toMap(SysPost::getPostId, SysPost::getPostName));
} }
} }

View File

@@ -206,7 +206,7 @@ public class FlwTaskController extends BaseController {
*/ */
@GetMapping("/currentTaskAllUser/{taskId}") @GetMapping("/currentTaskAllUser/{taskId}")
public R<List<UserDTO>> currentTaskAllUser(@PathVariable Long taskId) { public R<List<UserDTO>> currentTaskAllUser(@PathVariable Long taskId) {
return R.ok(flwTaskService.currentTaskAllUser(List.of(taskId))); return R.ok(flwTaskService.currentTaskAllUser(taskId));
} }
} }

View File

@@ -145,7 +145,6 @@ public class FlowTaskVo implements Serializable {
/** /**
* 办理人名称 * 办理人名称
*/ */
@Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "assigneeIds")
private String assigneeNames; private String assigneeNames;
/** /**

View File

@@ -3,14 +3,11 @@ package org.dromara.workflow.handler;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; 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.common.satoken.utils.LoginHelper;
import org.dromara.warm.flow.core.dto.FlowParams; import org.dromara.warm.flow.core.dto.FlowParams;
import org.dromara.warm.flow.core.handler.PermissionHandler; import org.dromara.warm.flow.core.handler.PermissionHandler;
import org.dromara.workflow.common.ConditionalOnEnable; import org.dromara.workflow.common.ConditionalOnEnable;
import org.dromara.workflow.service.IFlwTaskAssigneeService; import org.dromara.workflow.service.IFlwCommonService;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.Collections; import java.util.Collections;
@@ -27,7 +24,7 @@ import java.util.List;
@Slf4j @Slf4j
public class WorkflowPermissionHandler implements PermissionHandler { public class WorkflowPermissionHandler implements PermissionHandler {
private final IFlwTaskAssigneeService flwTaskAssigneeService; private final IFlwCommonService flwCommonService;
/** /**
* 办理人权限标识,比如用户,角色,部门等,用于校验是否有权限办理任务 * 办理人权限标识,比如用户,角色,部门等,用于校验是否有权限办理任务
@@ -54,11 +51,9 @@ public class WorkflowPermissionHandler implements PermissionHandler {
*/ */
@Override @Override
public List<String> convertPermissions(List<String> permissions) { public List<String> convertPermissions(List<String> permissions) {
if (CollUtil.isEmpty(permissions)) { if (CollUtil.isNotEmpty(permissions)) {
return permissions; permissions = flwCommonService.buildUser(permissions);
} }
String storageIds = CollUtil.join(permissions, StringUtils.SEPARATOR); return permissions;
List<UserDTO> users = flwTaskAssigneeService.fetchUsersByStorageIds(storageIds);
return StreamUtils.toList(users, userDTO -> String.valueOf(userDTO.getUserId()));
} }
} }

View File

@@ -1,7 +1,6 @@
package org.dromara.workflow.listener; package org.dromara.workflow.listener;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@@ -137,36 +136,33 @@ public class WorkflowGlobalListener implements GlobalListener {
return; return;
} }
// 只有办理或者退回的时候才执行消息通知和抄送 // 只有办理或者退回的时候才执行消息通知和抄送
if (!StringUtils.equalsAny(flowParams.getHisStatus(), if (TaskStatusEnum.PASS.getStatus().equals(flowParams.getHisStatus())
TaskStatusEnum.PASS.getStatus(), TaskStatusEnum.BACK.getStatus())) { || TaskStatusEnum.BACK.getStatus().equals(flowParams.getHisStatus())) {
return; if (variable != null) {
} if (variable.containsKey(FlowConstant.FLOW_COPY_LIST)) {
if (ObjectUtil.isNull(variable)) { List<FlowCopyBo> flowCopyList = (List<FlowCopyBo>) variable.get(FlowConstant.FLOW_COPY_LIST);
return; // 添加抄送人
} flwTaskService.setCopy(task, flowCopyList);
}
if (variable.containsKey(FlowConstant.FLOW_COPY_LIST)) { if (variable.containsKey(FlowConstant.MESSAGE_TYPE)) {
List<FlowCopyBo> flowCopyList = MapUtil.get(variable, FlowConstant.FLOW_COPY_LIST, new TypeReference<>() {}); List<String> messageType = (List<String>) variable.get(FlowConstant.MESSAGE_TYPE);
// 添加抄送人 String notice = (String) variable.get(FlowConstant.MESSAGE_NOTICE);
flwTaskService.setCopy(task, flowCopyList); // 消息通知
} if (CollUtil.isNotEmpty(messageType)) {
if (variable.containsKey(FlowConstant.MESSAGE_TYPE)) { flwCommonService.sendMessage(definition.getFlowName(), instance.getId(), messageType, notice);
List<String> messageType = MapUtil.get(variable, FlowConstant.FLOW_COPY_LIST, new TypeReference<>() {}); }
String notice = MapUtil.getStr(variable, FlowConstant.MESSAGE_NOTICE); }
// 消息通知 FlowInstance ins = new FlowInstance();
if (CollUtil.isNotEmpty(messageType)) { Map<String, Object> variableMap = instance.getVariableMap();
flwCommonService.sendMessage(definition.getFlowName(), instance.getId(), messageType, notice); 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);
} }
} }
FlowInstance ins = new FlowInstance();
Map<String, Object> 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);
} }
/** /**

View File

@@ -9,6 +9,8 @@ import org.dromara.workflow.domain.bo.FlowTaskBo;
import org.dromara.workflow.domain.vo.FlowHisTaskVo; import org.dromara.workflow.domain.vo.FlowHisTaskVo;
import org.dromara.workflow.domain.vo.FlowTaskVo; import org.dromara.workflow.domain.vo.FlowTaskVo;
import java.util.List;
/** /**
* 任务信息Mapper接口 * 任务信息Mapper接口
@@ -27,6 +29,14 @@ public interface FlwTaskMapper {
*/ */
Page<FlowTaskVo> getListRunTask(@Param("page") Page<FlowTaskVo> page, @Param(Constants.WRAPPER) Wrapper<FlowTaskBo> queryWrapper); Page<FlowTaskVo> getListRunTask(@Param("page") Page<FlowTaskVo> page, @Param(Constants.WRAPPER) Wrapper<FlowTaskBo> queryWrapper);
/**
* 获取待办信息
*
* @param queryWrapper 条件
* @return 结果
*/
List<FlowTaskVo> getListRunTask(@Param(Constants.WRAPPER) Wrapper<FlowTaskBo> queryWrapper);
/** /**
* 获取已办 * 获取已办
* *

View File

@@ -9,6 +9,14 @@ import java.util.List;
*/ */
public interface IFlwCommonService { public interface IFlwCommonService {
/**
* 构建工作流用户
*
* @param permissionList 办理用户
* @return 用户
*/
List<String> buildUser(List<String> permissionList);
/** /**
* 发送消息 * 发送消息
* *

View File

@@ -141,6 +141,14 @@ public interface IFlwInstanceService {
*/ */
FlowInstance selectByTaskId(Long taskId); FlowInstance selectByTaskId(Long taskId);
/**
* 按任务id查询实例
*
* @param taskIdList 任务id
* @return 结果
*/
List<FlowInstance> selectByTaskIdList(List<Long> taskIdList);
/** /**
* 作废流程 * 作废流程
* *

View File

@@ -14,6 +14,7 @@ import org.dromara.workflow.domain.vo.FlowHisTaskVo;
import org.dromara.workflow.domain.vo.FlowTaskVo; import org.dromara.workflow.domain.vo.FlowTaskVo;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* 任务 服务层 * 任务 服务层
@@ -149,6 +150,14 @@ public interface IFlwTaskService {
*/ */
List<FlowNode> getNextNodeList(FlowNextNodeBo bo); List<FlowNode> getNextNodeList(FlowNextNodeBo bo);
/**
* 按照任务id查询任务
*
* @param taskIdList 任务id
* @return 结果
*/
List<FlowHisTask> selectHisTaskByIdList(List<Long> taskIdList);
/** /**
* 按照任务id查询任务 * 按照任务id查询任务
* *
@@ -157,6 +166,14 @@ public interface IFlwTaskService {
*/ */
FlowHisTask selectHisTaskById(Long taskId); FlowHisTask selectHisTaskById(Long taskId);
/**
* 按照实例id查询任务
*
* @param instanceIdList 流程实例id
* @return 结果
*/
List<FlowTask> selectByInstIdList(List<Long> instanceIdList);
/** /**
* 按照实例id查询任务 * 按照实例id查询任务
* *
@@ -175,12 +192,20 @@ public interface IFlwTaskService {
boolean taskOperation(TaskOperationBo bo, String taskOperation); boolean taskOperation(TaskOperationBo bo, String taskOperation);
/** /**
* 获取当前任务所有办理人 * 获取任务所有办理人
* *
* @param taskIds 任务id * @param taskIdList 任务id
* @return 结果 * @return 结果
*/ */
List<UserDTO> currentTaskAllUser(List<Long> taskIds); Map<Long, List<UserDTO>> currentTaskAllUser(List<Long> taskIdList);
/**
* 获取当前任务的所有办理人
*
* @param taskId 任务id
* @return 结果
*/
List<UserDTO> currentTaskAllUser(Long taskId);
/** /**
* 按照节点编码查询节点 * 按照节点编码查询节点

View File

@@ -27,12 +27,8 @@ import org.dromara.workflow.common.ConditionalOnEnable;
import org.dromara.workflow.common.constant.FlowConstant; import org.dromara.workflow.common.constant.FlowConstant;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
/** /**
* 流程图提示信息 * 流程图提示信息
@@ -78,26 +74,15 @@ public class FlwChartExtServiceImpl implements ChartExtService {
Map<String, String> dictType = dictService.getAllDictByDictType(FlowConstant.WF_TASK_STATUS); Map<String, String> dictType = dictService.getAllDictByDictType(FlowConstant.WF_TASK_STATUS);
// 遍历流程定义中的每个节点,调用处理方法,将对应节点的任务列表及用户信息传入,生成扩展提示内容
for (NodeJson nodeJson : defJson.getNodeList()) { for (NodeJson nodeJson : defJson.getNodeList()) {
// 获取当前节点对应的历史任务列表,如果没有则返回空列表避免空指针
List<FlowHisTask> taskList = groupedByNode.get(nodeJson.getNodeCode()); List<FlowHisTask> taskList = groupedByNode.get(nodeJson.getNodeCode());
if (CollUtil.isEmpty(taskList)) { if (CollUtil.isEmpty(taskList)) {
continue; continue;
} }
// 处理当前节点的扩展信息,包括构建审批人提示内容等
// 按审批人分组去重,保留最新处理记录,最终转换成 List this.processNodeExtInfo(nodeJson, taskList, userMap, dictType);
List<FlowHisTask> 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);
} }
} }
@@ -255,7 +240,7 @@ public class FlwChartExtServiceImpl implements ChartExtService {
LambdaQueryWrapper<FlowHisTask> wrapper = Wrappers.lambdaQuery(); LambdaQueryWrapper<FlowHisTask> wrapper = Wrappers.lambdaQuery();
wrapper.eq(FlowHisTask::getInstanceId, instanceId) wrapper.eq(FlowHisTask::getInstanceId, instanceId)
.eq(FlowHisTask::getNodeType, NodeType.BETWEEN.getKey()) .eq(FlowHisTask::getNodeType, NodeType.BETWEEN.getKey())
.orderByDesc(FlowHisTask::getUpdateTime); .orderByDesc(FlowHisTask::getCreateTime, FlowHisTask::getUpdateTime);
return flowHisTaskMapper.selectList(wrapper); return flowHisTaskMapper.selectList(wrapper);
} }

View File

@@ -19,6 +19,7 @@ import org.dromara.warm.flow.orm.entity.FlowTask;
import org.dromara.workflow.common.ConditionalOnEnable; import org.dromara.workflow.common.ConditionalOnEnable;
import org.dromara.workflow.common.enums.MessageTypeEnum; import org.dromara.workflow.common.enums.MessageTypeEnum;
import org.dromara.workflow.service.IFlwCommonService; import org.dromara.workflow.service.IFlwCommonService;
import org.dromara.workflow.service.IFlwTaskAssigneeService;
import org.dromara.workflow.service.IFlwTaskService; import org.dromara.workflow.service.IFlwTaskService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -39,6 +40,26 @@ import java.util.stream.Collectors;
public class FlwCommonServiceImpl implements IFlwCommonService { public class FlwCommonServiceImpl implements IFlwCommonService {
private final NodeService nodeService; private final NodeService nodeService;
/**
* 构建工作流用户
*
* @param permissionList 办理用户
* @return 用户
*/
@Override
public List<String> buildUser(List<String> permissionList) {
if (CollUtil.isEmpty(permissionList)) {
return List.of();
}
IFlwTaskAssigneeService taskAssigneeService = SpringUtils.getBean(IFlwTaskAssigneeService.class);
String processedBys = CollUtil.join(permissionList, StringUtils.SEPARATOR);
// 根据 processedBy 前缀判断处理人类型,分别获取用户列表
List<UserDTO> users = taskAssigneeService.fetchUsersByStorageIds(processedBys);
return StreamUtils.toList(users, userDTO -> String.valueOf(userDTO.getUserId()));
}
/** /**
* 发送消息 * 发送消息
* *
@@ -49,36 +70,40 @@ public class FlwCommonServiceImpl implements IFlwCommonService {
@Override @Override
public void sendMessage(String flowName, Long instId, List<String> messageType, String message) { public void sendMessage(String flowName, Long instId, List<String> messageType, String message) {
IFlwTaskService flwTaskService = SpringUtils.getBean(IFlwTaskService.class); IFlwTaskService flwTaskService = SpringUtils.getBean(IFlwTaskService.class);
List<UserDTO> userList = new ArrayList<>();
List<FlowTask> list = flwTaskService.selectByInstId(instId); List<FlowTask> list = flwTaskService.selectByInstId(instId);
if (StringUtils.isBlank(message)) { if (StringUtils.isBlank(message)) {
message = "有新的【" + flowName + "】单据已经提交至您,请您及时处理。"; message = "有新的【" + flowName + "】单据已经提交至您,请您及时处理。";
} }
List<UserDTO> userList = flwTaskService.currentTaskAllUser(StreamUtils.toList(list, FlowTask::getId)); for (Task task : list) {
if (CollUtil.isEmpty(userList)) { List<UserDTO> users = flwTaskService.currentTaskAllUser(task.getId());
return; if (CollUtil.isNotEmpty(users)) {
} userList.addAll(users);
for (String code : messageType) { }
MessageTypeEnum messageTypeEnum = MessageTypeEnum.getByCode(code); }
if (ObjectUtil.isEmpty(messageTypeEnum)) { if (CollUtil.isNotEmpty(userList)) {
continue; for (String code : messageType) {
} MessageTypeEnum messageTypeEnum = MessageTypeEnum.getByCode(code);
switch (messageTypeEnum) { if (ObjectUtil.isNotEmpty(messageTypeEnum)) {
case SYSTEM_MESSAGE -> { switch (messageTypeEnum) {
SseMessageDto dto = new SseMessageDto(); case SYSTEM_MESSAGE:
dto.setUserIds(StreamUtils.toList(userList, UserDTO::getUserId).stream().distinct().collect(Collectors.toList())); SseMessageDto dto = new SseMessageDto();
dto.setMessage(message); dto.setUserIds(StreamUtils.toList(userList, UserDTO::getUserId).stream().distinct().collect(Collectors.toList()));
SseMessageUtils.publishMessage(dto); dto.setMessage(message);
} SseMessageUtils.publishMessage(dto);
case EMAIL_MESSAGE -> { break;
MailUtils.sendText(StreamUtils.join(userList, UserDTO::getEmail), "单据审批提醒", message); case EMAIL_MESSAGE:
} MailUtils.sendText(StreamUtils.join(userList, UserDTO::getEmail), "单据审批提醒", message);
case SMS_MESSAGE -> { break;
//todo 短信发送 case SMS_MESSAGE:
} //todo 短信发送
default -> throw new IllegalStateException("Unexpected value: " + messageTypeEnum); break;
default:
throw new IllegalStateException("Unexpected value: " + messageTypeEnum);
}
}
} }
} }
} }

View File

@@ -121,8 +121,8 @@ public class FlwDefinitionServiceImpl implements IFlwDefinitionService {
List<FlowNode> flowNodes = flowNodeMapper.selectList(new LambdaQueryWrapper<FlowNode>().eq(FlowNode::getDefinitionId, id)); List<FlowNode> flowNodes = flowNodeMapper.selectList(new LambdaQueryWrapper<FlowNode>().eq(FlowNode::getDefinitionId, id));
List<String> errorMsg = new ArrayList<>(); List<String> errorMsg = new ArrayList<>();
if (CollUtil.isNotEmpty(flowNodes)) { if (CollUtil.isNotEmpty(flowNodes)) {
String applyNodeCode = flwCommonService.applyNodeCode(id);
for (FlowNode flowNode : flowNodes) { for (FlowNode flowNode : flowNodes) {
String applyNodeCode = flwCommonService.applyNodeCode(id);
if (StringUtils.isBlank(flowNode.getPermissionFlag()) && !applyNodeCode.equals(flowNode.getNodeCode()) && NodeType.BETWEEN.getKey().equals(flowNode.getNodeType())) { if (StringUtils.isBlank(flowNode.getPermissionFlag()) && !applyNodeCode.equals(flowNode.getNodeCode()) && NodeType.BETWEEN.getKey().equals(flowNode.getNodeType())) {
errorMsg.add(flowNode.getNodeName()); errorMsg.add(flowNode.getNodeName());
} }
@@ -213,8 +213,7 @@ public class FlwDefinitionServiceImpl implements IFlwDefinitionService {
return; return;
} }
FlowCategory flowCategory = flwCategoryMapper.selectOne(new LambdaQueryWrapper<FlowCategory>() FlowCategory flowCategory = flwCategoryMapper.selectOne(new LambdaQueryWrapper<FlowCategory>()
.eq(FlowCategory::getTenantId, DEFAULT_TENANT_ID) .eq(FlowCategory::getTenantId, DEFAULT_TENANT_ID).eq(FlowCategory::getCategoryId, FlowConstant.FLOW_CATEGORY_ID));
.eq(FlowCategory::getCategoryId, FlowConstant.FLOW_CATEGORY_ID));
flowCategory.setCategoryId(null); flowCategory.setCategoryId(null);
flowCategory.setTenantId(tenantId); flowCategory.setTenantId(tenantId);
flowCategory.setCreateDept(null); flowCategory.setCreateDept(null);

View File

@@ -11,6 +11,7 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; 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.enums.BusinessStatusEnum;
import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StreamUtils;
@@ -18,13 +19,11 @@ import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper; 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.constant.ExceptionCons;
import org.dromara.warm.flow.core.dto.FlowParams; import org.dromara.warm.flow.core.dto.FlowParams;
import org.dromara.warm.flow.core.entity.Definition; import org.dromara.warm.flow.core.entity.Definition;
import org.dromara.warm.flow.core.entity.Instance; import org.dromara.warm.flow.core.entity.Instance;
import org.dromara.warm.flow.core.entity.Task; 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.NodeType;
import org.dromara.warm.flow.core.service.DefService; import org.dromara.warm.flow.core.service.DefService;
import org.dromara.warm.flow.core.service.InsService; import org.dromara.warm.flow.core.service.InsService;
@@ -50,7 +49,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.*; import java.util.*;
import java.util.function.Function; import java.util.stream.Collectors;
/** /**
* 流程实例 服务层实现 * 流程实例 服务层实现
@@ -204,11 +203,9 @@ public class FlwInstanceServiceImpl implements IFlwInstanceService {
return false; return false;
} }
// 获取定义信息 // 获取定义信息
Map<Long, Definition> definitionMap = StreamUtils.toMap( Map<Long, Definition> definitionMap = defService.getByIds(
defService.getByIds(StreamUtils.toList(instances, Instance::getDefinitionId)), StreamUtils.toList(instances, Instance::getDefinitionId)
Definition::getId, ).stream().collect(Collectors.toMap(Definition::getId, definition -> definition));
Function.identity()
);
// 逐一触发删除事件 // 逐一触发删除事件
instances.forEach(instance -> { instances.forEach(instance -> {
@@ -284,50 +281,37 @@ public class FlwInstanceServiceImpl implements IFlwInstanceService {
throw new ServiceException(ExceptionCons.NOT_FOUNT_INSTANCE); throw new ServiceException(ExceptionCons.NOT_FOUNT_INSTANCE);
} }
Long instanceId = flowInstance.getId(); Long instanceId = flowInstance.getId();
//运行中的任务
// 先组装待审批任务(运行中的任务) List<FlowHisTaskVo> list = new ArrayList<>();
List<FlowHisTaskVo> runningTaskVos = new ArrayList<>(); List<FlowTask> flowTaskList = flwTaskService.selectByInstId(instanceId);
List<FlowTask> runningTasks = flwTaskService.selectByInstId(instanceId); if (CollUtil.isNotEmpty(flowTaskList)) {
if (CollUtil.isNotEmpty(runningTasks)) { List<FlowHisTaskVo> flowHisTaskVos = BeanUtil.copyToList(flowTaskList, FlowHisTaskVo.class);
runningTaskVos = BeanUtil.copyToList(runningTasks, FlowHisTaskVo.class); for (FlowHisTaskVo flowHisTaskVo : flowHisTaskVos) {
flowHisTaskVo.setFlowStatus(TaskStatusEnum.WAITING.getStatus());
List<User> associatedUsers = FlowEngine.userService() flowHisTaskVo.setUpdateTime(null);
.getByAssociateds(StreamUtils.toList(runningTasks, FlowTask::getId)); flowHisTaskVo.setRunDuration(null);
Map<Long, List<User>> taskUserMap = StreamUtils.groupByKey(associatedUsers, User::getAssociated); List<UserDTO> allUser = flwTaskService.currentTaskAllUser(flowHisTaskVo.getId());
if (CollUtil.isNotEmpty(allUser)) {
for (FlowHisTaskVo vo : runningTaskVos) { String join = StreamUtils.join(allUser, e -> String.valueOf(e.getUserId()));
vo.setFlowStatus(TaskStatusEnum.WAITING.getStatus()); flowHisTaskVo.setApprover(join);
vo.setUpdateTime(null);
vo.setRunDuration(null);
List<User> users = taskUserMap.get(vo.getId());
if (CollUtil.isNotEmpty(users)) {
vo.setApprover(StreamUtils.join(users, User::getProcessedBy));
} }
if (BusinessStatusEnum.isDraftOrCancelOrBack(flowInstance.getFlowStatus())) { if (BusinessStatusEnum.isDraftOrCancelOrBack(flowInstance.getFlowStatus())) {
vo.setApprover(LoginHelper.getUserIdStr()); flowHisTaskVo.setApprover(LoginHelper.getUserIdStr());
flowHisTaskVo.setApproveName(LoginHelper.getLoginUser().getNickname());
} }
} }
list.addAll(flowHisTaskVos);
} }
//历史任务
// 再组装历史任务(已处理任务) LambdaQueryWrapper<FlowHisTask> wrapper = Wrappers.lambdaQuery();
List<FlowHisTaskVo> hisTaskVos = new ArrayList<>(); wrapper.eq(FlowHisTask::getInstanceId, instanceId)
List<FlowHisTask> hisTasks = flowHisTaskMapper.selectList( .eq(FlowHisTask::getNodeType, NodeType.BETWEEN.getKey())
new LambdaQueryWrapper<FlowHisTask>() .orderByDesc(FlowHisTask::getCreateTime, FlowHisTask::getUpdateTime);
.eq(FlowHisTask::getInstanceId, instanceId) List<FlowHisTask> flowHisTasks = flowHisTaskMapper.selectList(wrapper);
.eq(FlowHisTask::getNodeType, NodeType.BETWEEN.getKey()) if (CollUtil.isNotEmpty(flowHisTasks)) {
.orderByDesc(FlowHisTask::getUpdateTime) list.addAll(BeanUtil.copyToList(flowHisTasks, FlowHisTaskVo.class));
);
if (CollUtil.isNotEmpty(hisTasks)) {
hisTaskVos = BeanUtil.copyToList(hisTasks, FlowHisTaskVo.class);
} }
return Map.of("list", list, "instanceId", instanceId);
// 结果列表,待审批任务在前,历史任务在后
List<FlowHisTaskVo> combinedList = new ArrayList<>();
combinedList.addAll(runningTaskVos);
combinedList.addAll(hisTaskVos);
return Map.of("list", combinedList, "instanceId", instanceId);
} }
/** /**
@@ -393,6 +377,31 @@ public class FlwInstanceServiceImpl implements IFlwInstanceService {
return null; return null;
} }
/**
* 按任务id查询实例
*
* @param taskIdList 任务id
*/
@Override
public List<FlowInstance> selectByTaskIdList(List<Long> taskIdList) {
if (CollUtil.isEmpty(taskIdList)) {
return Collections.emptyList();
}
Set<Long> instanceIds = new HashSet<>();
List<FlowTask> flowTaskList = flwTaskService.selectByIdList(taskIdList);
for (FlowTask flowTask : flowTaskList) {
instanceIds.add(flowTask.getInstanceId());
}
List<FlowHisTask> flowHisTaskList = flwTaskService.selectHisTaskByIdList(taskIdList);
for (FlowHisTask flowHisTask : flowHisTaskList) {
instanceIds.add(flowHisTask.getInstanceId());
}
if (!instanceIds.isEmpty()) {
return this.selectInstListByIdList(new ArrayList<>(instanceIds));
}
return Collections.emptyList();
}
/** /**
* 作废流程 * 作废流程
* *

View File

@@ -12,7 +12,9 @@ import org.dromara.common.core.domain.dto.TaskAssigneeDTO;
import org.dromara.common.core.domain.dto.UserDTO; import org.dromara.common.core.domain.dto.UserDTO;
import org.dromara.common.core.domain.model.TaskAssigneeBody; import org.dromara.common.core.domain.model.TaskAssigneeBody;
import org.dromara.common.core.enums.FormatsType; import org.dromara.common.core.enums.FormatsType;
import org.dromara.common.core.service.*; 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.utils.DateUtils; import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.warm.flow.ui.dto.HandlerFunDto; import org.dromara.warm.flow.ui.dto.HandlerFunDto;
@@ -43,8 +45,6 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand
private final TaskAssigneeService taskAssigneeService; private final TaskAssigneeService taskAssigneeService;
private final UserService userService; private final UserService userService;
private final DeptService deptService; private final DeptService deptService;
private final RoleService roleService;
private final PostService postService;
/** /**
* 获取办理人权限设置列表tabs页签 * 获取办理人权限设置列表tabs页签
@@ -216,9 +216,9 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand
private Map<Long, String> getNamesByType(TaskAssigneeEnum type, List<Long> ids) { private Map<Long, String> getNamesByType(TaskAssigneeEnum type, List<Long> ids) {
return switch (type) { return switch (type) {
case USER -> userService.selectUserNamesByIds(ids); case USER -> userService.selectUserNamesByIds(ids);
case ROLE -> roleService.selectRoleNamesByIds(ids); case ROLE -> userService.selectRoleNamesByIds(ids);
case DEPT -> deptService.selectDeptNamesByIds(ids); case DEPT -> userService.selectDeptNamesByIds(ids);
case POST -> postService.selectPostNamesByIds(ids); case POST -> userService.selectPostNamesByIds(ids);
}; };
} }

View File

@@ -55,6 +55,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
import static org.dromara.workflow.common.constant.FlowConstant.*; import static org.dromara.workflow.common.constant.FlowConstant.*;
@@ -251,12 +252,14 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
hisTask.setCreateTime(updateTime); hisTask.setCreateTime(updateTime);
hisTask.setUpdateTime(updateTime); hisTask.setUpdateTime(updateTime);
hisTaskService.save(hisTask); hisTaskService.save(hisTask);
List<User> userList = StreamUtils.toList(flowCopyList, x -> List<User> userList = flowCopyList.stream()
new FlowUser() .map(flowCopy -> {
.setType(TaskAssigneeType.COPY.getCode()) FlowUser flowUser = new FlowUser();
.setProcessedBy(String.valueOf(x.getUserId())) flowUser.setType(TaskAssigneeType.COPY.getCode());
.setAssociated(taskId) flowUser.setProcessedBy(String.valueOf(flowCopy.getUserId()));
); flowUser.setAssociated(taskId);
return flowUser;
}).collect(Collectors.toList());
// 批量保存抄送人员 // 批量保存抄送人员
FlowEngine.userService().saveBatch(userList); FlowEngine.userService().saveBatch(userList);
} }
@@ -273,8 +276,7 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
queryWrapper.eq("t.node_type", NodeType.BETWEEN.getKey()); queryWrapper.eq("t.node_type", NodeType.BETWEEN.getKey());
queryWrapper.in("t.processed_by", LoginHelper.getUserIdStr()); queryWrapper.in("t.processed_by", LoginHelper.getUserIdStr());
queryWrapper.in("t.flow_status", BusinessStatusEnum.WAITING.getStatus()); queryWrapper.in("t.flow_status", BusinessStatusEnum.WAITING.getStatus());
Page<FlowTaskVo> page = flwTaskMapper.getListRunTask(pageQuery.build(), queryWrapper); Page<FlowTaskVo> page = this.getFlowTaskVoPage(pageQuery, queryWrapper);
this.wrapAssigneeInfo(page.getRecords());
return TableDataInfo.build(page); return TableDataInfo.build(page);
} }
@@ -304,28 +306,25 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
public TableDataInfo<FlowTaskVo> pageByAllTaskWait(FlowTaskBo flowTaskBo, PageQuery pageQuery) { public TableDataInfo<FlowTaskVo> pageByAllTaskWait(FlowTaskBo flowTaskBo, PageQuery pageQuery) {
QueryWrapper<FlowTaskBo> queryWrapper = buildQueryWrapper(flowTaskBo); QueryWrapper<FlowTaskBo> queryWrapper = buildQueryWrapper(flowTaskBo);
queryWrapper.eq("t.node_type", NodeType.BETWEEN.getKey()); queryWrapper.eq("t.node_type", NodeType.BETWEEN.getKey());
Page<FlowTaskVo> page = flwTaskMapper.getListRunTask(pageQuery.build(), queryWrapper); Page<FlowTaskVo> page = getFlowTaskVoPage(pageQuery, queryWrapper);
this.wrapAssigneeInfo(page.getRecords());
return TableDataInfo.build(page); return TableDataInfo.build(page);
} }
/** private Page<FlowTaskVo> getFlowTaskVoPage(PageQuery pageQuery, QueryWrapper<FlowTaskBo> queryWrapper) {
* 为流程任务列表封装处理人 IDassigneeIds Page<FlowTaskVo> page = flwTaskMapper.getListRunTask(pageQuery.build(), queryWrapper);
* List<FlowTaskVo> records = page.getRecords();
* @param taskList 流程任务列表 if (CollUtil.isNotEmpty(records)) {
*/ List<Long> taskIds = StreamUtils.toList(records, FlowTaskVo::getId);
private void wrapAssigneeInfo(List<FlowTaskVo> taskList) { Map<Long, List<UserDTO>> listMap = currentTaskAllUser(taskIds);
if (CollUtil.isEmpty(taskList)) { records.forEach(t -> {
return; List<UserDTO> userList = listMap.getOrDefault(t.getId(), Collections.emptyList());
} if (CollUtil.isNotEmpty(userList)) {
List<User> associatedUsers = FlowEngine.userService() t.setAssigneeIds(StreamUtils.join(userList, e -> String.valueOf(e.getUserId())));
.getByAssociateds(StreamUtils.toList(taskList, FlowTaskVo::getId)); t.setAssigneeNames(StreamUtils.join(userList, UserDTO::getNickName));
Map<Long, List<User>> taskUserMap = StreamUtils.groupByKey(associatedUsers, User::getAssociated); }
// 组装用户数据回任务列表 });
for (FlowTaskVo task : taskList) {
List<User> users = taskUserMap.get(task.getId());
task.setAssigneeIds(StreamUtils.join(users, User::getProcessedBy));
} }
return page;
} }
/** /**
@@ -528,15 +527,15 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
// 只获取中间节点 // 只获取中间节点
nextFlowNodes = StreamUtils.filter(nextFlowNodes, node -> NodeType.BETWEEN.getKey().equals(node.getNodeType())); nextFlowNodes = StreamUtils.filter(nextFlowNodes, node -> NodeType.BETWEEN.getKey().equals(node.getNodeType()));
if (CollUtil.isNotEmpty(nextNodeList)) { if (CollUtil.isNotEmpty(nextNodeList)) {
//构建以下节点数据 // 构建以下节点数据
List<Task> buildNextTaskList = StreamUtils.toList(nextNodeList, node -> taskService.addTask(node, instance, definition, FlowParams.build())); List<Task> 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) { for (FlowNode flowNode : nextFlowNodes) {
Optional<Task> first = buildNextTaskList.stream() buildNextTaskList.stream().filter(t -> t.getNodeCode().equals(flowNode.getNodeCode())).findFirst().ifPresent(t -> {
.filter(t -> t.getNodeCode().equals(flowNode.getNodeCode()))
.findFirst();
first.ifPresent(t -> {
if (CollUtil.isNotEmpty(t.getPermissionList())) { if (CollUtil.isNotEmpty(t.getPermissionList())) {
List<UserDTO> users = flwTaskAssigneeService.fetchUsersByStorageIds(String.join(StringUtils.SEPARATOR, t.getPermissionList())); List<UserDTO> users = flwTaskAssigneeService.fetchUsersByStorageIds(String.join(StringUtils.SEPARATOR, t.getPermissionList()));
if (CollUtil.isNotEmpty(users)) { if (CollUtil.isNotEmpty(users)) {
@@ -549,6 +548,18 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
return nextFlowNodes; return nextFlowNodes;
} }
/**
* 按照任务id查询任务
*
* @param taskIdList 任务id
* @return 结果
*/
@Override
public List<FlowHisTask> selectHisTaskByIdList(List<Long> taskIdList) {
return flowHisTaskMapper.selectList(new LambdaQueryWrapper<>(FlowHisTask.class)
.in(FlowHisTask::getId, taskIdList));
}
/** /**
* 按照任务id查询任务 * 按照任务id查询任务
* *
@@ -561,6 +572,17 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
.eq(FlowHisTask::getId, taskId)); .eq(FlowHisTask::getId, taskId));
} }
/**
* 按照实例id查询任务
*
* @param instanceIdList 流程实例id
*/
@Override
public List<FlowTask> selectByInstIdList(List<Long> instanceIdList) {
return flowTaskMapper.selectList(new LambdaQueryWrapper<>(FlowTask.class)
.in(FlowTask::getInstanceId, instanceIdList));
}
/** /**
* 按照实例id查询任务 * 按照实例id查询任务
* *
@@ -661,12 +683,15 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
// 批量删除现有任务的办理人记录 // 批量删除现有任务的办理人记录
if (CollUtil.isNotEmpty(flowTasks)) { if (CollUtil.isNotEmpty(flowTasks)) {
FlowEngine.userService().deleteByTaskIds(StreamUtils.toList(flowTasks, FlowTask::getId)); FlowEngine.userService().deleteByTaskIds(StreamUtils.toList(flowTasks, FlowTask::getId));
List<User> userList = StreamUtils.toList(flowTasks, flowTask -> List<User> userList = flowTasks.stream()
new FlowUser() .map(flowTask -> {
.setType(TaskAssigneeType.APPROVER.getCode()) FlowUser flowUser = new FlowUser();
.setProcessedBy(userId) flowUser.setType(TaskAssigneeType.APPROVER.getCode());
.setAssociated(flowTask.getId()) flowUser.setProcessedBy(userId);
); flowUser.setAssociated(flowTask.getId());
return flowUser;
})
.collect(Collectors.toList());
if (CollUtil.isNotEmpty(userList)) { if (CollUtil.isNotEmpty(userList)) {
FlowEngine.userService().saveBatch(userList); FlowEngine.userService().saveBatch(userList);
} }
@@ -679,14 +704,35 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
} }
/** /**
* 获取当前任务所有办理人 * 获取任务所有办理人
* *
* @param taskIds 任务id * @param taskIdList 任务id
*/ */
@Override @Override
public List<UserDTO> currentTaskAllUser(List<Long> taskIds) { public Map<Long, List<UserDTO>> currentTaskAllUser(List<Long> taskIdList) {
Map<Long, List<UserDTO>> map = new HashMap<>();
// 获取与当前任务关联的用户列表 // 获取与当前任务关联的用户列表
List<User> userList = FlowEngine.userService().getByAssociateds(taskIds); List<User> associatedUsers = FlowEngine.userService().getByAssociateds(taskIdList);
Map<Long, List<User>> listMap = StreamUtils.groupByKey(associatedUsers, User::getAssociated);
for (Map.Entry<Long, List<User>> entry : listMap.entrySet()) {
List<User> value = entry.getValue();
if (CollUtil.isNotEmpty(value)) {
List<UserDTO> userDtoList = userService.selectListByIds(StreamUtils.toList(value, e -> Convert.toLong(e.getProcessedBy())));
map.put(entry.getKey(), userDtoList);
}
}
return map;
}
/**
* 获取当前任务的所有办理人
*
* @param taskId 任务id
*/
@Override
public List<UserDTO> currentTaskAllUser(Long taskId) {
// 获取与当前任务关联的用户列表
List<User> userList = FlowEngine.userService().getByAssociateds(Collections.singletonList(taskId));
if (CollUtil.isEmpty(userList)) { if (CollUtil.isEmpty(userList)) {
return Collections.emptyList(); return Collections.emptyList();
} }