mirror of
http://git.pig4cloud.com/pig/pigx.git
synced 2026-11-11 21:29:02 +08:00
feat(pigx-flow-biz): 条件表达式新增角色和岗位选择器条件处理功能
- 新增SelectRoleNodeConditionStrategy类,处理角色选择器类型条件表达式 - 新增SelectPostNodeConditionStrategy类,处理岗位选择器类型条件表达式 - 在ExpressionHandler中新增roleCompare和postCompare方法,支持角色和岗位比较逻辑 - 更新SysUserService接口及实现,新增根据岗位ID列表获取用户ID列表功能 - 在SysUserController中新增根据岗位ID列表获取用户ID列表接口 - 更新RemoteUserService Feign客户端,新增岗位查询方法 - 更新相关文件版权信息和日期注释 - 删除无用的IProcessInstanceStatusEventService接口 - 在数据库中新增bpm_oa_leave请假申请表结构
This commit is contained in:
1 parent
b7631ddeaf
commit
d1858d5844
10 files changed
+306
-30
No files matched your search
@@ -1492,6 +1492,25 @@ SET FOREIGN_KEY_CHECKS = 1;
|
||||
SET NAMES utf8mb4;
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
CREATE TABLE `bpm_oa_leave` (
|
||||
`id` BIGINT NOT NULL COMMENT '主键',
|
||||
`process_instance_id` VARCHAR(64) DEFAULT NULL COMMENT '流程实例编号',
|
||||
`username` VARCHAR(255) NOT NULL COMMENT '申请人',
|
||||
`leave_type` SMALLINT NOT NULL COMMENT '请假类型',
|
||||
`leave_reason` VARCHAR(255) DEFAULT NULL COMMENT '请假原因',
|
||||
`start_time` DATETIME(6) NOT NULL COMMENT '开始时间',
|
||||
`end_time` DATETIME(6) NOT NULL COMMENT '结束时间',
|
||||
`leave_day` SMALLINT NOT NULL COMMENT '请假天数',
|
||||
`leave_status` SMALLINT DEFAULT NULL COMMENT '请假结果',
|
||||
`create_by` VARCHAR(64) DEFAULT '' COMMENT '创建者',
|
||||
`create_time` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
|
||||
`update_by` VARCHAR(64) DEFAULT '' COMMENT '更新者',
|
||||
`update_time` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
|
||||
`del_flag` CHAR(1) NOT NULL DEFAULT '0' COMMENT '是否删除',
|
||||
`tenant_id` BIGINT NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='请假申请表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for process
|
||||
-- ----------------------------
|
||||
|
||||
@@ -3,6 +3,25 @@ USE pigxx_flow;
|
||||
SET NAMES utf8mb4;
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
CREATE TABLE `bpm_oa_leave` (
|
||||
`id` BIGINT NOT NULL COMMENT '主键',
|
||||
`process_instance_id` VARCHAR(64) DEFAULT NULL COMMENT '流程实例编号',
|
||||
`username` VARCHAR(255) NOT NULL COMMENT '申请人',
|
||||
`leave_type` SMALLINT NOT NULL COMMENT '请假类型',
|
||||
`leave_reason` VARCHAR(255) DEFAULT NULL COMMENT '请假原因',
|
||||
`start_time` DATETIME(6) NOT NULL COMMENT '开始时间',
|
||||
`end_time` DATETIME(6) NOT NULL COMMENT '结束时间',
|
||||
`leave_day` SMALLINT NOT NULL COMMENT '请假天数',
|
||||
`leave_status` SMALLINT DEFAULT NULL COMMENT '请假结果',
|
||||
`create_by` VARCHAR(64) DEFAULT '' COMMENT '创建者',
|
||||
`create_time` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
|
||||
`update_by` VARCHAR(64) DEFAULT '' COMMENT '更新者',
|
||||
`update_time` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
|
||||
`del_flag` CHAR(1) NOT NULL DEFAULT '0' COMMENT '是否删除',
|
||||
`tenant_id` BIGINT NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='请假申请表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for process
|
||||
-- ----------------------------
|
||||
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
package com.pig4cloud.pigx.flow.service;
|
||||
|
||||
import com.pig4cloud.pigx.flow.dto.ProcessInstanceParamDto;
|
||||
|
||||
/**
|
||||
* 流程实例状态事件服务接口
|
||||
*
|
||||
* @author lengleng
|
||||
* @date 2025/08/08
|
||||
*/
|
||||
public interface IProcessInstanceStatusEventService {
|
||||
|
||||
/**
|
||||
* 获取监听的流程定义Key
|
||||
* @return 监听的流程定义Key
|
||||
*/
|
||||
String getFlowId();
|
||||
|
||||
/**
|
||||
* 处理状态事件
|
||||
* @param paramDto 流程节点记录分配用户参数DTO
|
||||
*/
|
||||
void handleStatusEvent(ProcessInstanceParamDto paramDto);
|
||||
|
||||
}
|
||||
+112
@@ -35,6 +35,7 @@ import java.util.List;
|
||||
* 使用Aviator表达式引擎进行动态表达式计算,支持在流程定义中配置灵活的条件判断逻辑
|
||||
*
|
||||
* @author pigx
|
||||
* @date 2026-02-10
|
||||
*/
|
||||
@Slf4j
|
||||
@Component("expressionHandler")
|
||||
@@ -376,6 +377,117 @@ public class ExpressionHandler {
|
||||
return inCompare(symbol, Convert.toLong(nodeUserDto.getId()), userIdList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 角色比较
|
||||
* <p>
|
||||
* 检查流程变量中的用户是否拥有指定的角色(属于或不属于指定角色列表)。
|
||||
* 通过角色ID列表查询出拥有这些角色的所有用户ID,再判断当前用户是否在其中。
|
||||
* @param key 表单key,对应流程变量的键名
|
||||
* @param param 角色列表参数(JSON格式)
|
||||
* @param symbol 比较符号(in/==:属于,notin/!=:不属于)
|
||||
* @param execution 流程执行上下文
|
||||
* @return 比较结果
|
||||
*/
|
||||
@SneakyThrows
|
||||
public boolean roleCompare(String key, String param, String symbol, DelegateExecution execution) {
|
||||
param = EscapeUtil.unescape(param);
|
||||
|
||||
Object value = execution.getVariable(key);
|
||||
|
||||
String jsonString = objectMapper.writeValueAsString(value);
|
||||
log.debug("表单值:key={} value={} symbol={}", key, jsonString, symbol);
|
||||
log.debug("条件 参数:{}", param);
|
||||
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 表单值(发起人或表单中的用户)
|
||||
List<NodeUser> nodeUserDtoList = objectMapper.readValue(jsonString, new TypeReference<>() {
|
||||
});
|
||||
|
||||
if (CollUtil.isEmpty(nodeUserDtoList) || nodeUserDtoList.size() != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
NodeUser nodeUserDto = nodeUserDtoList.get(0);
|
||||
|
||||
// 参数 - 解析角色列表
|
||||
List<NodeUser> paramRoleList = objectMapper.readValue(param, new TypeReference<List<NodeUser>>() {
|
||||
});
|
||||
|
||||
List<Long> roleIdList = paramRoleList.stream().map(NodeUser::getId).toList();
|
||||
|
||||
// 根据角色ID列表查询拥有这些角色的所有用户ID
|
||||
List<Long> userIdList = new java.util.ArrayList<>();
|
||||
if (CollUtil.isNotEmpty(roleIdList)) {
|
||||
R<List<Long>> r = remoteUserService.getUserIdListByRoleIdList(roleIdList);
|
||||
if (r.getData() != null) {
|
||||
userIdList.addAll(r.getData());
|
||||
}
|
||||
}
|
||||
|
||||
return inCompare(symbol, Convert.toLong(nodeUserDto.getId()), userIdList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 岗位比较
|
||||
* <p>
|
||||
* 检查流程变量中的用户是否属于指定的岗位(属于或不属于指定岗位列表)。
|
||||
* 通过岗位ID列表查询出属于这些岗位的所有用户ID,再判断当前用户是否在其中。
|
||||
* @param key 表单key,对应流程变量的键名
|
||||
* @param param 岗位列表参数(JSON格式)
|
||||
* @param symbol 比较符号(in/==:属于,notin/!=:不属于)
|
||||
* @param execution 流程执行上下文
|
||||
* @return 比较结果
|
||||
*/
|
||||
@SneakyThrows
|
||||
public boolean postCompare(String key, String param, String symbol, DelegateExecution execution) {
|
||||
param = EscapeUtil.unescape(param);
|
||||
|
||||
Object value = execution.getVariable(key);
|
||||
|
||||
String jsonString = objectMapper.writeValueAsString(value);
|
||||
log.debug("表单值:key={} value={} symbol={}", key, jsonString, symbol);
|
||||
log.debug("条件 参数:{}", param);
|
||||
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 表单值(发起人或表单中的用户)
|
||||
List<NodeUser> nodeUserDtoList = objectMapper.readValue(jsonString, new TypeReference<>() {
|
||||
});
|
||||
|
||||
if (CollUtil.isEmpty(nodeUserDtoList) || nodeUserDtoList.size() != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
NodeUser nodeUserDto = nodeUserDtoList.get(0);
|
||||
|
||||
// 参数 - 解析岗位列表
|
||||
List<NodeUser> paramPostList = objectMapper.readValue(param, new TypeReference<List<NodeUser>>() {
|
||||
});
|
||||
|
||||
List<Long> postIdList = paramPostList.stream().map(NodeUser::getId).toList();
|
||||
|
||||
// 根据岗位ID列表查询属于这些岗位的所有用户ID
|
||||
List<Long> userIdList = new java.util.ArrayList<>();
|
||||
if (CollUtil.isNotEmpty(postIdList)) {
|
||||
R<List<Long>> r = remoteUserService.getUserIdListByPostIdList(postIdList);
|
||||
if (r.getData() != null) {
|
||||
userIdList.addAll(r.getData());
|
||||
}
|
||||
}
|
||||
|
||||
return inCompare(symbol, Convert.toLong(nodeUserDto.getId()), userIdList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 天数条件判断
|
||||
* @param execution 流程执行上下文
|
||||
* @return 始终返回true
|
||||
*/
|
||||
public boolean days(DelegateExecution execution) {
|
||||
return true;
|
||||
}
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
package com.pig4cloud.pigx.flow.support.expression.condition.impl;
|
||||
|
||||
import cn.hutool.core.util.EscapeUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.pig4cloud.pigx.flow.dto.Condition;
|
||||
import com.pig4cloud.pigx.flow.support.expression.condition.NodeConditionStrategy;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 岗位选择器类型条件处理器
|
||||
* <p>
|
||||
* 处理岗位选择器类型表单控件的条件表达式生成。
|
||||
* 支持判断发起人是否属于指定的岗位。
|
||||
* 支持的比较操作:
|
||||
* 1. 属于(in/==):检查用户是否属于指定岗位中的任意一个
|
||||
* 2. 不属于(notin/!=):检查用户是否不属于指定岗位中的任意一个
|
||||
*
|
||||
* @author pigx
|
||||
* @date 2026-02-10
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Component("SelectPostNodeConditionStrategy")
|
||||
public class SelectPostNodeConditionStrategy implements NodeConditionStrategy {
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
/**
|
||||
* 处理岗位选择器类型的条件表达式
|
||||
* <p>
|
||||
* 将岗位选择数据序列化为JSON格式,并生成调用岗位比较方法的SpEL表达式。
|
||||
* 序列化后的JSON会进行转义处理,以确保在表达式中的正确性。
|
||||
*
|
||||
* @param condition 条件配置对象,包含字段名、操作符、岗位列表等信息
|
||||
* @return SpEL表达式字符串
|
||||
*/
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public String handle(Condition condition) {
|
||||
|
||||
String compare = condition.getExpression();
|
||||
String id = condition.getKey();
|
||||
Object value = condition.getValue();
|
||||
|
||||
return StrUtil.format("(expressionHandler.postCompare(\"{}\",\"{}\",\"{}\", execution))", id,
|
||||
EscapeUtil.escape(objectMapper.writeValueAsString(value)), compare);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
package com.pig4cloud.pigx.flow.support.expression.condition.impl;
|
||||
|
||||
import cn.hutool.core.util.EscapeUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.pig4cloud.pigx.flow.dto.Condition;
|
||||
import com.pig4cloud.pigx.flow.support.expression.condition.NodeConditionStrategy;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 角色选择器类型条件处理器
|
||||
* <p>
|
||||
* 处理角色选择器类型表单控件的条件表达式生成。
|
||||
* 支持判断发起人是否拥有指定的角色。
|
||||
* 支持的比较操作:
|
||||
* 1. 属于(in/==):检查用户是否拥有指定角色中的任意一个
|
||||
* 2. 不属于(notin/!=):检查用户是否不拥有指定角色中的任意一个
|
||||
*
|
||||
* @author pigx
|
||||
* @date 2026-02-10
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Component("SelectRoleNodeConditionStrategy")
|
||||
public class SelectRoleNodeConditionStrategy implements NodeConditionStrategy {
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
/**
|
||||
* 处理角色选择器类型的条件表达式
|
||||
* <p>
|
||||
* 将角色选择数据序列化为JSON格式,并生成调用角色比较方法的SpEL表达式。
|
||||
* 序列化后的JSON会进行转义处理,以确保在表达式中的正确性。
|
||||
*
|
||||
* @param condition 条件配置对象,包含字段名、操作符、角色列表等信息
|
||||
* @return SpEL表达式字符串
|
||||
*/
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public String handle(Condition condition) {
|
||||
|
||||
String compare = condition.getExpression();
|
||||
String id = condition.getKey();
|
||||
Object value = condition.getValue();
|
||||
|
||||
return StrUtil.format("(expressionHandler.roleCompare(\"{}\",\"{}\",\"{}\", execution))", id,
|
||||
EscapeUtil.escape(objectMapper.writeValueAsString(value)), compare);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+10
-1
@@ -32,7 +32,7 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2018/6/22
|
||||
* @date 2026-02-10
|
||||
*/
|
||||
@FeignClient(contextId = "remoteUserService", value = ServiceNameConstants.UPMS_SERVICE)
|
||||
public interface RemoteUserService {
|
||||
@@ -103,6 +103,15 @@ public interface RemoteUserService {
|
||||
@GetMapping("/user/getUserIdListByDeptIdList")
|
||||
R<List<SysUser>> getUserIdListByDeptIdList(@RequestParam("deptIdList") List<Long> deptIdList);
|
||||
|
||||
/**
|
||||
* 根据岗位ID列表获取用户ID列表
|
||||
*
|
||||
* @param postIdList 岗位ID列表
|
||||
* @return 用户ID列表
|
||||
*/
|
||||
@GetMapping("/user/getUserIdListByPostIdList")
|
||||
R<List<Long>> getUserIdListByPostIdList(@RequestParam("postIdList") List<Long> postIdList);
|
||||
|
||||
/**
|
||||
* 通过用户名查询用户列表
|
||||
*
|
||||
|
||||
+12
-1
@@ -53,7 +53,7 @@ import java.util.List;
|
||||
* 用户管理控制器:提供用户相关的REST接口
|
||||
*
|
||||
* @author lengleng
|
||||
* @date 2025/07/04
|
||||
* @date 2026-02-10
|
||||
*/
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
@@ -291,6 +291,17 @@ public class SysUserController {
|
||||
return R.ok(userService.listUserIdByDeptIds(CollUtil.toList(deptIdList)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据岗位ID列表获取用户ID列表接口
|
||||
*
|
||||
* @param postIdList 岗位ID列表
|
||||
* @return R 返回结果对象,包含根据岗位ID列表获取到的用户ID列表信息
|
||||
*/
|
||||
@GetMapping("/getUserIdListByPostIdList")
|
||||
public R<List<Long>> getUserIdListByPostIdList(Long[] postIdList) {
|
||||
return R.ok(userService.listUserIdByPostIds(CollUtil.toList(postIdList)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户名获取用户列表
|
||||
*
|
||||
|
||||
+9
-1
@@ -36,7 +36,7 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2017/10/31
|
||||
* @date 2026-02-10
|
||||
*/
|
||||
public interface SysUserService extends IService<SysUser> {
|
||||
|
||||
@@ -180,6 +180,14 @@ public interface SysUserService extends IService<SysUser> {
|
||||
*/
|
||||
List<SysUser> listUserIdByDeptIds(List<Long> deptIdList);
|
||||
|
||||
/**
|
||||
* 根据岗位ID列表获取用户ID列表
|
||||
*
|
||||
* @param postIdList 岗位ID列表
|
||||
* @return List<Long> 用户ID列表
|
||||
*/
|
||||
List<Long> listUserIdByPostIds(List<Long> postIdList);
|
||||
|
||||
/**
|
||||
* 重置用户密码
|
||||
*
|
||||
|
||||
+21
-2
@@ -21,7 +21,6 @@ package com.pig4cloud.pigx.admin.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
@@ -71,7 +70,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2017/10/31
|
||||
* @date 2026-02-10
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@@ -744,6 +743,12 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据角色ID列表获取用户ID列表
|
||||
*
|
||||
* @param roleIdList 角色ID列表
|
||||
* @return 用户ID列表
|
||||
*/
|
||||
@Override
|
||||
public List<Long> listUserIdByRoleIds(List<Long> roleIdList) {
|
||||
return sysUserRoleMapper.selectList(Wrappers.<SysUserRole>lambdaQuery().in(SysUserRole::getRoleId, roleIdList))
|
||||
@@ -768,6 +773,20 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
return baseMapper.selectList(Wrappers.<SysUser>lambdaQuery().in(SysUser::getUserId, userList));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据岗位ID列表获取用户ID列表
|
||||
*
|
||||
* @param postIdList 岗位ID列表
|
||||
* @return 用户ID列表
|
||||
*/
|
||||
@Override
|
||||
public List<Long> listUserIdByPostIds(List<Long> postIdList) {
|
||||
return sysUserPostMapper.selectList(Wrappers.<SysUserPost>lambdaQuery().in(SysUserPost::getPostId, postIdList))
|
||||
.stream()
|
||||
.map(SysUserPost::getUserId)
|
||||
.toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前用户的部门列表
|
||||
*
|
||||
|
||||
Reference in new issue
Block a user