From ab3037dc4fd3055070e67a1523d928f10a6bb8da Mon Sep 17 00:00:00 2001 From: MichelleChung <1242874891@qq.com> Date: Sun, 6 Jul 2025 02:54:04 +0000 Subject: [PATCH] =?UTF-8?q?!723=20=E6=96=B0=E5=A2=9E=E5=B7=A5=E4=BD=9C?= =?UTF-8?q?=E6=B5=81=E6=89=A9=E5=B1=95spel=E8=A1=A8=E8=BE=BE=E5=BC=8F=20*?= =?UTF-8?q?=20update:=20=E6=9B=B4=E6=96=B0=E5=8F=98=E9=87=8F=E5=90=8D?= =?UTF-8?q?=E7=A7=B0=E4=BB=A5=E5=8F=8A=E5=88=9D=E5=A7=8B=E5=8C=96=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=20;=20*=20add:=20=E6=96=B0=E5=A2=9E=20FlowSpel=20sql?= =?UTF-8?q?=20=E8=84=9A=E6=9C=AC=20;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/domain/dto/TaskAssigneeDTO.java | 4 +- .../impl/SysTaskAssigneeServiceImpl.java | 8 +- .../common/constant/FlowConstant.java | 5 + .../common/enums/TaskAssigneeEnum.java | 7 +- .../controller/FlwSpelController.java | 103 +++++++++++ .../org/dromara/workflow/domain/FlowSpel.java | 67 ++++++++ .../workflow/domain/bo/FlowSpelBo.java | 62 +++++++ .../workflow/domain/vo/FlowSpelVo.java | 79 +++++++++ .../workflow/mapper/FlwSpelMapper.java | 15 ++ .../workflow/rule/SpelRuleComponent.java | 36 ++++ .../workflow/service/IFlwSpelService.java | 72 ++++++++ .../service/impl/FlwSpelServiceImpl.java | 160 ++++++++++++++++++ .../impl/FlwTaskAssigneeServiceImpl.java | 5 + .../service/impl/FlwTaskServiceImpl.java | 2 + script/sql/update/update_flow_spel.sql | 26 +++ 15 files changed, 644 insertions(+), 7 deletions(-) create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwSpelController.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/FlowSpel.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowSpelBo.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowSpelVo.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwSpelMapper.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/rule/SpelRuleComponent.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwSpelService.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwSpelServiceImpl.java create mode 100644 script/sql/update/update_flow_spel.sql diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/TaskAssigneeDTO.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/TaskAssigneeDTO.java index 85893e1dc..73281c5a3 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/TaskAssigneeDTO.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/TaskAssigneeDTO.java @@ -52,14 +52,14 @@ public class TaskAssigneeDTO implements Serializable { */ public static List convertToHandlerList( List sourceList, - Function storageId, + Function storageId, Function handlerCode, Function handlerName, Function groupName, Function createTimeMapper) { return sourceList.stream() .map(item -> new TaskHandler( - String.valueOf(storageId.apply(item)), + storageId.apply(item), handlerCode.apply(item), handlerName.apply(item), groupName != null ? String.valueOf(groupName.apply(item)) : null, diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTaskAssigneeServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTaskAssigneeServiceImpl.java index 0bd5873e0..f901748de 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTaskAssigneeServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTaskAssigneeServiceImpl.java @@ -59,7 +59,7 @@ public class SysTaskAssigneeServiceImpl implements TaskAssigneeService { TableDataInfo page = roleService.selectPageRoleList(bo, pageQuery); // 使用封装的字段映射方法进行转换 List handlers = TaskAssigneeDTO.convertToHandlerList(page.getRows(), - SysRoleVo::getRoleId, SysRoleVo::getRoleKey, SysRoleVo::getRoleName, null, SysRoleVo::getCreateTime); + item -> String.valueOf(item.getRoleId()), SysRoleVo::getRoleKey, SysRoleVo::getRoleName, null, SysRoleVo::getCreateTime); return new TaskAssigneeDTO(page.getTotal(), handlers); } @@ -83,7 +83,7 @@ public class SysTaskAssigneeServiceImpl implements TaskAssigneeService { TableDataInfo page = postService.selectPagePostList(bo, pageQuery); // 使用封装的字段映射方法进行转换 List handlers = TaskAssigneeDTO.convertToHandlerList(page.getRows(), - SysPostVo::getPostId, SysPostVo::getPostCategory, SysPostVo::getPostName, SysPostVo::getDeptId, SysPostVo::getCreateTime); + p -> String.valueOf(p.getPostId()), SysPostVo::getPostCategory, SysPostVo::getPostName, SysPostVo::getDeptId, SysPostVo::getCreateTime); return new TaskAssigneeDTO(page.getTotal(), handlers); } @@ -107,7 +107,7 @@ public class SysTaskAssigneeServiceImpl implements TaskAssigneeService { TableDataInfo page = deptService.selectPageDeptList(bo, pageQuery); // 使用封装的字段映射方法进行转换 List handlers = TaskAssigneeDTO.convertToHandlerList(page.getRows(), - SysDeptVo::getDeptId, SysDeptVo::getDeptCategory, SysDeptVo::getDeptName, SysDeptVo::getParentId, SysDeptVo::getCreateTime); + d -> String.valueOf(d.getDeptId()), SysDeptVo::getDeptCategory, SysDeptVo::getDeptName, SysDeptVo::getParentId, SysDeptVo::getCreateTime); return new TaskAssigneeDTO(page.getTotal(), handlers); } @@ -131,7 +131,7 @@ public class SysTaskAssigneeServiceImpl implements TaskAssigneeService { TableDataInfo page = userService.selectPageUserList(bo, pageQuery); // 使用封装的字段映射方法进行转换 List handlers = TaskAssigneeDTO.convertToHandlerList(page.getRows(), - SysUserVo::getUserId, SysUserVo::getUserName, SysUserVo::getNickName, SysUserVo::getDeptId, SysUserVo::getCreateTime); + u -> String.valueOf(u.getUserId()), SysUserVo::getUserName, SysUserVo::getNickName, SysUserVo::getDeptId, SysUserVo::getCreateTime); return new TaskAssigneeDTO(page.getTotal(), handlers); } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java index aaa640bfb..0bc027f6f 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java @@ -18,6 +18,11 @@ public interface FlowConstant { */ String BUSINESS_ID = "businessId"; + /** + * 部门id + */ + String INITIATOR_DEPT_ID = "initiatorDeptId"; + /** * 委托 */ diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskAssigneeEnum.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskAssigneeEnum.java index 60be92fe9..c86e73e42 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskAssigneeEnum.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskAssigneeEnum.java @@ -35,7 +35,12 @@ public enum TaskAssigneeEnum { /** * 岗位 */ - POST("岗位", "post:"); + POST("岗位", "post:"), + + /** + * SPEL表达式 + */ + SPEL("SPEL表达式", ""); private final String desc; private final String code; diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwSpelController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwSpelController.java new file mode 100644 index 000000000..5f44c68bf --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwSpelController.java @@ -0,0 +1,103 @@ +package org.dromara.workflow.controller; + +import java.util.List; + +import lombok.RequiredArgsConstructor; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.constraints.*; +import cn.dev33.satoken.annotation.SaCheckPermission; +import org.dromara.workflow.domain.bo.FlowSpelBo; +import org.dromara.workflow.domain.vo.FlowSpelVo; +import org.dromara.workflow.service.IFlwSpelService; +import org.springframework.web.bind.annotation.*; +import org.springframework.validation.annotation.Validated; +import org.dromara.common.idempotent.annotation.RepeatSubmit; +import org.dromara.common.log.annotation.Log; +import org.dromara.common.web.core.BaseController; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.core.domain.R; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; +import org.dromara.common.log.enums.BusinessType; +import org.dromara.common.excel.utils.ExcelUtil; +import org.dromara.common.mybatis.core.page.TableDataInfo; + +/** + * 流程spel达式定义 + * + * @author Michelle.Chung + * @date 2025-07-04 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/workflow/spel") +public class FlwSpelController extends BaseController { + + private final IFlwSpelService flwSpelService; + + /** + * 查询流程spel达式定义列表 + */ + @SaCheckPermission("workflow:spel:list") + @GetMapping("/list") + public TableDataInfo list(FlowSpelBo bo, PageQuery pageQuery) { + return flwSpelService.queryPageList(bo, pageQuery); + } + + /** + * 导出流程spel达式定义列表 + */ + @SaCheckPermission("workflow:spel:export") + @Log(title = "流程spel达式定义", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(FlowSpelBo bo, HttpServletResponse response) { + List list = flwSpelService.queryList(bo); + ExcelUtil.exportExcel(list, "流程spel达式定义", FlowSpelVo.class, response); + } + + /** + * 获取流程spel达式定义详细信息 + * + * @param id 主键 + */ + @SaCheckPermission("workflow:spel:query") + @GetMapping("/{id}") + public R getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) { + return R.ok(flwSpelService.queryById(id)); + } + + /** + * 新增流程spel达式定义 + */ + @SaCheckPermission("workflow:spel:add") + @Log(title = "流程spel达式定义", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping() + public R add(@Validated(AddGroup.class) @RequestBody FlowSpelBo bo) { + return toAjax(flwSpelService.insertByBo(bo)); + } + + /** + * 修改流程spel达式定义 + */ + @SaCheckPermission("workflow:spel:edit") + @Log(title = "流程spel达式定义", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody FlowSpelBo bo) { + return toAjax(flwSpelService.updateByBo(bo)); + } + + /** + * 删除流程spel达式定义 + * + * @param ids 主键串 + */ + @SaCheckPermission("workflow:spel:remove") + @Log(title = "流程spel达式定义", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) { + return toAjax(flwSpelService.deleteWithValidByIds(List.of(ids), true)); + } +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/FlowSpel.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/FlowSpel.java new file mode 100644 index 000000000..356d69b14 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/FlowSpel.java @@ -0,0 +1,67 @@ +package org.dromara.workflow.domain; + +import org.dromara.common.tenant.core.TenantEntity; +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serial; + +/** + * 流程spel达式定义对象 flow_spel + * + * @author Michelle.Chung + * @date 2025-07-04 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("flow_spel") +public class FlowSpel extends TenantEntity { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId(value = "id") + private Long id; + + /** + * 组件名称 + */ + private String componentName; + + /** + * 方法名 + */ + private String methodName; + + /** + * 参数 + */ + private String methodParams; + + /** + * 预览spel表达式 + */ + private String viewSpel; + + /** + * 状态(0正常 1停用) + */ + private String status; + + /** + * 备注 + */ + private String remark; + + /** + * 删除标志 + */ + @TableLogic + private String delFlag; + + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowSpelBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowSpelBo.java new file mode 100644 index 000000000..692e72c7d --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowSpelBo.java @@ -0,0 +1,62 @@ +package org.dromara.workflow.domain.bo; + +import org.dromara.common.mybatis.core.domain.BaseEntity; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import lombok.EqualsAndHashCode; +import jakarta.validation.constraints.*; +import org.dromara.workflow.domain.FlowSpel; + +/** + * 流程spel达式定义业务对象 flow_spel + * + * @author Michelle.Chung + * @date 2025-07-04 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@AutoMapper(target = FlowSpel.class, reverseConvertGenerate = false) +public class FlowSpelBo extends BaseEntity { + + /** + * 主键id + */ + private Long id; + + /** + * 组件名称 + */ + @NotBlank(message = "组件名称不能为空", groups = { AddGroup.class, EditGroup.class }) + private String componentName; + + /** + * 方法名 + */ + @NotBlank(message = "方法名不能为空", groups = { AddGroup.class, EditGroup.class }) + private String methodName; + + /** + * 参数 + */ + private String methodParams; + + /** + * 预览spel值 + */ + @NotBlank(message = "预览spel值不能为空", groups = { AddGroup.class, EditGroup.class }) + private String viewSpel; + + /** + * 状态(0正常 1停用) + */ + @NotBlank(message = "状态(0正常 1停用)不能为空", groups = { AddGroup.class, EditGroup.class }) + private String status; + + /** + * 备注 + */ + private String remark; + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowSpelVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowSpelVo.java new file mode 100644 index 000000000..24f1437e8 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowSpelVo.java @@ -0,0 +1,79 @@ +package org.dromara.workflow.domain.vo; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import org.dromara.common.excel.annotation.ExcelDictFormat; +import org.dromara.common.excel.convert.ExcelDictConvert; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import org.dromara.workflow.domain.FlowSpel; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + + +/** + * 流程spel达式定义视图对象 flow_spel + * + * @author Michelle.Chung + * @date 2025-07-04 + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = FlowSpel.class) +public class FlowSpelVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @ExcelProperty(value = "主键id") + private Long id; + + /** + * 组件名称 + */ + @ExcelProperty(value = "组件名称") + private String componentName; + + /** + * 方法名 + */ + @ExcelProperty(value = "方法名") + private String methodName; + + /** + * 参数 + */ + @ExcelProperty(value = "参数") + private String methodParams; + + /** + * 预览spel值 + */ + @ExcelProperty(value = "预览spel值") + private String viewSpel; + + /** + * 状态(0正常 1停用) + */ + @ExcelProperty(value = "状态", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "0=正常,1=停用") + private String status; + + /** + * 备注 + */ + @ExcelProperty(value = "备注") + private String remark; + + /** + * 创建时间 + */ + @ExcelProperty(value = "创建时间") + private Date createTime; + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwSpelMapper.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwSpelMapper.java new file mode 100644 index 000000000..d3204958f --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwSpelMapper.java @@ -0,0 +1,15 @@ +package org.dromara.workflow.mapper; + +import org.dromara.workflow.domain.FlowSpel; +import org.dromara.workflow.domain.vo.FlowSpelVo; +import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; + +/** + * 流程spel达式定义Mapper接口 + * + * @author Michelle.Chung + * @date 2025-07-04 + */ +public interface FlwSpelMapper extends BaseMapperPlus { + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/rule/SpelRuleComponent.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/rule/SpelRuleComponent.java new file mode 100644 index 000000000..275eadbad --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/rule/SpelRuleComponent.java @@ -0,0 +1,36 @@ +package org.dromara.workflow.rule; + +import cn.hutool.core.util.ObjectUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.service.DeptService; +import org.springframework.stereotype.Component; + +/** + * spel表达式规则组件 + *

+ * 通过该组件统一管理流程定义中的spel表达式 + *

+ * + * @author Michelle.Chung + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class SpelRuleComponent { + + private final DeptService deptService; + + /** + * 通过发起人部门id获取部门负责人 + */ + public Long selectDeptLeaderById(Long initiatorDeptId) { + Long leaderId = deptService.selectDeptLeaderById(initiatorDeptId); + if (ObjectUtil.isNull(leaderId)) { + throw new ServiceException("当前部门未设置负责人,请联系管理员操作。"); + } + return leaderId; + } + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwSpelService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwSpelService.java new file mode 100644 index 000000000..fbafce0f6 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwSpelService.java @@ -0,0 +1,72 @@ +package org.dromara.workflow.service; + +import org.dromara.common.core.domain.dto.TaskAssigneeDTO; +import org.dromara.common.core.domain.model.TaskAssigneeBody; +import org.dromara.workflow.domain.bo.FlowSpelBo; +import org.dromara.workflow.domain.vo.FlowSpelVo; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.mybatis.core.page.PageQuery; + +import java.util.Collection; +import java.util.List; + +/** + * 流程spel达式定义Service接口 + * + * @author Michelle.Chung + * @date 2025-07-04 + */ +public interface IFlwSpelService { + + TaskAssigneeDTO selectSpelByTaskAssigneeList(TaskAssigneeBody taskQuery); + + /** + * 查询流程spel达式定义 + * + * @param id 主键 + * @return 流程spel达式定义 + */ + FlowSpelVo queryById(Long id); + + /** + * 分页查询流程spel达式定义列表 + * + * @param bo 查询条件 + * @param pageQuery 分页参数 + * @return 流程spel达式定义分页列表 + */ + TableDataInfo queryPageList(FlowSpelBo bo, PageQuery pageQuery); + + /** + * 查询符合条件的流程spel达式定义列表 + * + * @param bo 查询条件 + * @return 流程spel达式定义列表 + */ + List queryList(FlowSpelBo bo); + + /** + * 新增流程spel达式定义 + * + * @param bo 流程spel达式定义 + * @return 是否新增成功 + */ + Boolean insertByBo(FlowSpelBo bo); + + /** + * 修改流程spel达式定义 + * + * @param bo 流程spel达式定义 + * @return 是否修改成功 + */ + Boolean updateByBo(FlowSpelBo bo); + + /** + * 校验并批量删除流程spel达式定义信息 + * + * @param ids 待删除的主键集合 + * @param isValid 是否进行有效性校验 + * @return 是否删除成功 + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwSpelServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwSpelServiceImpl.java new file mode 100644 index 000000000..867762792 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwSpelServiceImpl.java @@ -0,0 +1,160 @@ +package org.dromara.workflow.service.impl; + +import org.dromara.common.core.constant.SystemConstants; +import org.dromara.common.core.domain.dto.TaskAssigneeDTO; +import org.dromara.common.core.domain.model.TaskAssigneeBody; +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.mybatis.core.page.PageQuery; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.workflow.domain.FlowSpel; +import org.dromara.workflow.domain.bo.FlowSpelBo; +import org.dromara.workflow.domain.vo.FlowSpelVo; +import org.dromara.workflow.mapper.FlwSpelMapper; +import org.dromara.workflow.service.IFlwSpelService; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Collection; +import java.util.Map; + +/** + * 流程spel达式定义Service业务层处理 + * + * @author Michelle.Chung + * @date 2025-07-04 + */ +@Slf4j +@RequiredArgsConstructor +@Service +public class FlwSpelServiceImpl implements IFlwSpelService { + + private final FlwSpelMapper baseMapper; + + /** + * 查询流程spel达式定义列表 + */ + @Override + public TaskAssigneeDTO selectSpelByTaskAssigneeList(TaskAssigneeBody taskQuery) { + PageQuery pageQuery = new PageQuery(taskQuery.getPageSize(), taskQuery.getPageNum()); + FlowSpelBo bo = new FlowSpelBo(); + bo.setViewSpel(taskQuery.getHandlerCode()); + bo.setRemark(taskQuery.getHandlerName()); + bo.setStatus(SystemConstants.NORMAL); + Map params = bo.getParams(); + params.put("beginTime", taskQuery.getBeginTime()); + params.put("endTime", taskQuery.getEndTime()); + TableDataInfo page = this.queryPageList(bo, pageQuery); + // 使用封装的字段映射方法进行转换 + List handlers = TaskAssigneeDTO.convertToHandlerList(page.getRows(), + FlowSpelVo::getViewSpel, c -> "", FlowSpelVo::getRemark, null, FlowSpelVo::getCreateTime); + return new TaskAssigneeDTO(page.getTotal(), handlers); + } + + /** + * 查询流程spel达式定义 + * + * @param id 主键 + * @return 流程spel达式定义 + */ + @Override + public FlowSpelVo queryById(Long id){ + return baseMapper.selectVoById(id); + } + + /** + * 分页查询流程spel达式定义列表 + * + * @param bo 查询条件 + * @param pageQuery 分页参数 + * @return 流程spel达式定义分页列表 + */ + @Override + public TableDataInfo queryPageList(FlowSpelBo bo, PageQuery pageQuery) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } + + /** + * 查询符合条件的流程spel达式定义列表 + * + * @param bo 查询条件 + * @return 流程spel达式定义列表 + */ + @Override + public List queryList(FlowSpelBo bo) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + return baseMapper.selectVoList(lqw); + } + + private LambdaQueryWrapper buildQueryWrapper(FlowSpelBo bo) { + Map params = bo.getParams(); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.orderByAsc(FlowSpel::getId); + lqw.like(StringUtils.isNotBlank(bo.getComponentName()), FlowSpel::getComponentName, bo.getComponentName()); + lqw.like(StringUtils.isNotBlank(bo.getMethodName()), FlowSpel::getMethodName, bo.getMethodName()); + lqw.eq(StringUtils.isNotBlank(bo.getMethodParams()), FlowSpel::getMethodParams, bo.getMethodParams()); + lqw.eq(StringUtils.isNotBlank(bo.getViewSpel()), FlowSpel::getViewSpel, bo.getViewSpel()); + lqw.eq(StringUtils.isNotBlank(bo.getStatus()), FlowSpel::getStatus, bo.getStatus()); + lqw.like(StringUtils.isNotBlank(bo.getRemark()), FlowSpel::getRemark, bo.getRemark()); + return lqw; + } + + /** + * 新增流程spel达式定义 + * + * @param bo 流程spel达式定义 + * @return 是否新增成功 + */ + @Override + public Boolean insertByBo(FlowSpelBo bo) { + FlowSpel add = MapstructUtils.convert(bo, FlowSpel.class); + validEntityBeforeSave(add); + boolean flag = baseMapper.insert(add) > 0; + if (flag) { + bo.setId(add.getId()); + } + return flag; + } + + /** + * 修改流程spel达式定义 + * + * @param bo 流程spel达式定义 + * @return 是否修改成功 + */ + @Override + public Boolean updateByBo(FlowSpelBo bo) { + FlowSpel update = MapstructUtils.convert(bo, FlowSpel.class); + validEntityBeforeSave(update); + return baseMapper.updateById(update) > 0; + } + + /** + * 保存前的数据校验 + */ + private void validEntityBeforeSave(FlowSpel entity){ + //TODO 做一些数据校验,如唯一约束 + } + + /** + * 校验并批量删除流程spel达式定义信息 + * + * @param ids 待删除的主键集合 + * @param isValid 是否进行有效性校验 + * @return 是否删除成功 + */ + @Override + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if(isValid){ + //TODO 做一些业务上的校验,判断是否需要校验 + } + return baseMapper.deleteByIds(ids) > 0; + } +} 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 ff720a9e4..3037410e7 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 @@ -23,6 +23,7 @@ import org.dromara.warm.flow.ui.vo.HandlerFeedBackVo; import org.dromara.warm.flow.ui.vo.HandlerSelectVo; import org.dromara.workflow.common.ConditionalOnEnable; import org.dromara.workflow.common.enums.TaskAssigneeEnum; +import org.dromara.workflow.service.IFlwSpelService; import org.dromara.workflow.service.IFlwTaskAssigneeService; import org.springframework.stereotype.Service; @@ -45,6 +46,7 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand private final DeptService deptService; private final RoleService roleService; private final PostService postService; + private final IFlwSpelService spelService; /** * 获取办理人权限设置列表tabs页签 @@ -123,6 +125,7 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand case ROLE -> taskAssigneeService.selectRolesByTaskAssigneeList(taskQuery); case DEPT -> taskAssigneeService.selectDeptsByTaskAssigneeList(taskQuery); case POST -> taskAssigneeService.selectPostsByTaskAssigneeList(taskQuery); + case SPEL -> spelService.selectSpelByTaskAssigneeList(taskQuery); }; } @@ -203,6 +206,7 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand case ROLE -> userService.selectUsersByRoleIds(ids); case DEPT -> userService.selectUsersByDeptIds(ids); case POST -> userService.selectUsersByPostIds(ids); + case SPEL -> new ArrayList<>(); }; } @@ -219,6 +223,7 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand case ROLE -> roleService.selectRoleNamesByIds(ids); case DEPT -> deptService.selectDeptNamesByIds(ids); case POST -> postService.selectPostNamesByIds(ids); + case SPEL -> new HashMap<>(); }; } 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 ab5f1c34f..04ef669dc 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 @@ -102,6 +102,8 @@ public class FlwTaskServiceImpl implements IFlwTaskService { Map variables = startProcessBo.getVariables(); // 流程发起人 variables.put(INITIATOR, LoginHelper.getUserIdStr()); + // 发起人部门id + variables.put(INITIATOR_DEPT_ID, LoginHelper.getDeptId()); // 业务id variables.put(BUSINESS_ID, businessId); FlowInstance flowInstance = flowInstanceMapper.selectOne(new LambdaQueryWrapper<>(FlowInstance.class) diff --git a/script/sql/update/update_flow_spel.sql b/script/sql/update/update_flow_spel.sql new file mode 100644 index 000000000..bbf9da9bd --- /dev/null +++ b/script/sql/update/update_flow_spel.sql @@ -0,0 +1,26 @@ +CREATE TABLE `flow_spel` ( + `id` bigint(20) NOT NULL COMMENT '主键id', + `component_name` varchar(255) DEFAULT NULL COMMENT '组件名称', + `method_name` varchar(255) DEFAULT NULL COMMENT '方法名', + `method_params` varchar(255) DEFAULT NULL COMMENT '参数', + `view_spel` varchar(255) DEFAULT NULL COMMENT '预览spel表达式', + `remark` varchar(255) DEFAULT NULL COMMENT '备注', + `status` char(1) DEFAULT '0' COMMENT '状态(0正常 1停用)', + `del_flag` char(1) DEFAULT '0' COMMENT '删除标志', + `create_dept` bigint(20) DEFAULT NULL COMMENT '创建部门', + `create_by` bigint(20) DEFAULT NULL COMMENT '创建者', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_by` bigint(20) DEFAULT NULL COMMENT '更新者', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `tenant_id` varchar(40) DEFAULT NULL COMMENT '租户id', + PRIMARY KEY (`id`) +) ENGINE = InnoDB COMMENT='流程spel表达式定义表'; + +INSERT INTO `ry-vue`.`flow_spel` (`id`, `component_name`, `method_name`, `method_params`, `view_spel`, `remark`, `status`, `del_flag`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `tenant_id`) VALUES (1, 'spelRuleComponent', 'selectDeptLeaderById', 'initiatorDeptId', '#{@spelRuleComponent.selectDeptLeaderById(#initiatorDeptId)}', '根据部门id获取部门负责人', '0', '0', 103, 1, sysdate(), 1, sysdate(), '000000'); + +INSERT INTO `ry-vue`.`sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query_param`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (11801, '流程spel表达式', 11616, 1, 'spel', 'workflow/spel/index', NULL, 1, 0, 'C', '0', '0', 'workflow:spel:list', 'input', 103, 1, sysdate(), 1, sysdate(), '流程spel达式定义菜单'); +INSERT INTO `ry-vue`.`sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query_param`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (11802, '流程spel达式定义查询', 11801, 1, '#', '', NULL, 1, 0, 'F', '0', '0', 'workflow:spel:query', '#', 103, 1, sysdate(), NULL, NULL, ''); +INSERT INTO `ry-vue`.`sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query_param`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (11803, '流程spel达式定义新增', 11801, 2, '#', '', NULL, 1, 0, 'F', '0', '0', 'workflow:spel:add', '#', 103, 1, sysdate(), NULL, NULL, ''); +INSERT INTO `ry-vue`.`sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query_param`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (11804, '流程spel达式定义修改', 11801, 3, '#', '', NULL, 1, 0, 'F', '0', '0', 'workflow:spel:edit', '#', 103, 1, sysdate(), NULL, NULL, ''); +INSERT INTO `ry-vue`.`sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query_param`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (11805, '流程spel达式定义删除', 11801, 4, '#', '', NULL, 1, 0, 'F', '0', '0', 'workflow:spel:remove', '#', 103, 1, sysdate(), NULL, NULL, ''); +INSERT INTO `ry-vue`.`sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query_param`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (11806, '流程spel达式定义导出', 11801, 5, '#', '', NULL, 1, 0, 'F', '0', '0', 'workflow:spel:export', '#', 103, 1, sysdate(), NULL, NULL, '');