diff --git a/db/0pigxx_boot.sql b/db/0pigxx_boot.sql index 028282b29..4d9fa2d92 100644 --- a/db/0pigxx_boot.sql +++ b/db/0pigxx_boot.sql @@ -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 -- ---------------------------- diff --git a/db/3pigxx_flow.sql b/db/3pigxx_flow.sql index 2cbf9b3a1..fefcab043 100644 --- a/db/3pigxx_flow.sql +++ b/db/3pigxx_flow.sql @@ -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 -- ---------------------------- diff --git a/pigx-flow/pigx-flow-biz/src/main/java/com/pig4cloud/pigx/flow/service/IProcessInstanceStatusEventService.java b/pigx-flow/pigx-flow-biz/src/main/java/com/pig4cloud/pigx/flow/service/IProcessInstanceStatusEventService.java deleted file mode 100644 index 20f2c4dbc..000000000 --- a/pigx-flow/pigx-flow-biz/src/main/java/com/pig4cloud/pigx/flow/service/IProcessInstanceStatusEventService.java +++ /dev/null @@ -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); - -} diff --git a/pigx-flow/pigx-flow-biz/src/main/java/com/pig4cloud/pigx/flow/support/expression/ExpressionHandler.java b/pigx-flow/pigx-flow-biz/src/main/java/com/pig4cloud/pigx/flow/support/expression/ExpressionHandler.java index 628cf5f6f..4092f7a45 100644 --- a/pigx-flow/pigx-flow-biz/src/main/java/com/pig4cloud/pigx/flow/support/expression/ExpressionHandler.java +++ b/pigx-flow/pigx-flow-biz/src/main/java/com/pig4cloud/pigx/flow/support/expression/ExpressionHandler.java @@ -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); } + /** + * 角色比较 + *
+ * 检查流程变量中的用户是否拥有指定的角色(属于或不属于指定角色列表)。
+ * 通过角色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
+ * 检查流程变量中的用户是否属于指定的岗位(属于或不属于指定岗位列表)。
+ * 通过岗位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
+ * 处理岗位选择器类型表单控件的条件表达式生成。
+ * 支持判断发起人是否属于指定的岗位。
+ * 支持的比较操作:
+ * 1. 属于(in/==):检查用户是否属于指定岗位中的任意一个
+ * 2. 不属于(notin/!=):检查用户是否不属于指定岗位中的任意一个
+ *
+ * @author pigx
+ * @date 2026-02-10
+ */
+@RequiredArgsConstructor
+@Component("SelectPostNodeConditionStrategy")
+public class SelectPostNodeConditionStrategy implements NodeConditionStrategy {
+
+ private final ObjectMapper objectMapper;
+
+ /**
+ * 处理岗位选择器类型的条件表达式
+ *
+ * 将岗位选择数据序列化为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);
+
+ }
+
+}
diff --git a/pigx-flow/pigx-flow-biz/src/main/java/com/pig4cloud/pigx/flow/support/expression/condition/impl/SelectRoleNodeConditionStrategy.java b/pigx-flow/pigx-flow-biz/src/main/java/com/pig4cloud/pigx/flow/support/expression/condition/impl/SelectRoleNodeConditionStrategy.java
new file mode 100644
index 000000000..aecee655f
--- /dev/null
+++ b/pigx-flow/pigx-flow-biz/src/main/java/com/pig4cloud/pigx/flow/support/expression/condition/impl/SelectRoleNodeConditionStrategy.java
@@ -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;
+
+/**
+ * 角色选择器类型条件处理器
+ *
+ * 处理角色选择器类型表单控件的条件表达式生成。
+ * 支持判断发起人是否拥有指定的角色。
+ * 支持的比较操作:
+ * 1. 属于(in/==):检查用户是否拥有指定角色中的任意一个
+ * 2. 不属于(notin/!=):检查用户是否不拥有指定角色中的任意一个
+ *
+ * @author pigx
+ * @date 2026-02-10
+ */
+@RequiredArgsConstructor
+@Component("SelectRoleNodeConditionStrategy")
+public class SelectRoleNodeConditionStrategy implements NodeConditionStrategy {
+
+ private final ObjectMapper objectMapper;
+
+ /**
+ * 处理角色选择器类型的条件表达式
+ *
+ * 将角色选择数据序列化为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);
+
+ }
+
+}
diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/RemoteUserService.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/RemoteUserService.java
index 64d5a9f96..b157e8775 100644
--- a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/RemoteUserService.java
+++ b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/RemoteUserService.java
@@ -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
> r = remoteUserService.getUserIdListByRoleIdList(roleIdList);
+ if (r.getData() != null) {
+ userIdList.addAll(r.getData());
+ }
+ }
+
+ return inCompare(symbol, Convert.toLong(nodeUserDto.getId()), userIdList);
+ }
+
+ /**
+ * 岗位比较
+ *
>() {
+ });
+
+ List
> 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;
}
diff --git a/pigx-flow/pigx-flow-biz/src/main/java/com/pig4cloud/pigx/flow/support/expression/condition/impl/SelectPostNodeConditionStrategy.java b/pigx-flow/pigx-flow-biz/src/main/java/com/pig4cloud/pigx/flow/support/expression/condition/impl/SelectPostNodeConditionStrategy.java
new file mode 100644
index 000000000..1c7a081f3
--- /dev/null
+++ b/pigx-flow/pigx-flow-biz/src/main/java/com/pig4cloud/pigx/flow/support/expression/condition/impl/SelectPostNodeConditionStrategy.java
@@ -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;
+
+/**
+ * 岗位选择器类型条件处理器
+ *
> getUserIdListByDeptIdList(@RequestParam("deptIdList") List
> getUserIdListByPostIdList(@RequestParam("postIdList") List
> getUserIdListByPostIdList(Long[] postIdList) {
+ return R.ok(userService.listUserIdByPostIds(CollUtil.toList(postIdList)));
+ }
+
/**
* 根据用户名获取用户列表
*
diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/SysUserService.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/SysUserService.java
index ccbb74237..d655bff5e 100644
--- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/SysUserService.java
+++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/SysUserService.java
@@ -36,7 +36,7 @@ import java.util.List;
/**
* @author lengleng
- * @date 2017/10/31
+ * @date 2026-02-10
*/
public interface SysUserService extends IService