v3.0.0 init

This commit is contained in:
ageerle
2026-02-06 03:00:23 +08:00
parent eb2e8f3ff8
commit 7b8cfe02a1
1524 changed files with 53132 additions and 58866 deletions

View File

@@ -0,0 +1,29 @@
package org.ruoyi.workflow.common;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义条件注解,用于基于配置启用或禁用特定功能
* <p>
* 该注解只会在配置文件中 `warm-flow.enabled=true` 时,标注了此注解的类或方法才会被 Spring 容器加载
* <p>
* 示例配置:
* <pre>
* warm-flow:
* enabled: true # 设置为 true 时,启用工作流功能
* </pre>
* <p>
* 使用此注解时,可以动态控制工作流功能是否启用,而不需要修改代码逻辑
*
* @author Lion Li
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@ConditionalOnProperty(value = "warm-flow.enabled", havingValue = "true")
public @interface ConditionalOnEnable {
}

View File

@@ -0,0 +1,95 @@
package org.ruoyi.workflow.common.constant;
/**
* 工作流常量
*
* @author may
*/
public interface FlowConstant {
/**
* 流程发起人
*/
String INITIATOR = "initiator";
/**
* 业务id
*/
String BUSINESS_ID = "businessId";
/**
* 部门id
*/
String INITIATOR_DEPT_ID = "initiatorDeptId";
/**
* 委托
*/
String DELEGATE_TASK = "delegateTask";
/**
* 转办
*/
String TRANSFER_TASK = "transferTask";
/**
* 加签
*/
String ADD_SIGNATURE = "addSignature";
/**
* 减签
*/
String REDUCTION_SIGNATURE = "reductionSignature";
/**
* 流程分类Id转名称
*/
String CATEGORY_ID_TO_NAME = "category_id_to_name";
/**
* 流程分类名称
*/
String FLOW_CATEGORY_NAME = "flow_category_name#30d";
/**
* 默认租户OA申请分类id
*/
Long FLOW_CATEGORY_ID = 100L;
/**
* 是否为申请人提交常量
*/
String SUBMIT = "submit";
/**
* 抄送常量
*/
String FLOW_COPY_LIST = "flowCopyList";
/**
* 消息类型常量
*/
String MESSAGE_TYPE = "messageType";
/**
* 消息通知常量
*/
String MESSAGE_NOTICE = "messageNotice";
/**
* 任务状态
*/
String WF_TASK_STATUS = "wf_task_status";
/**
* 自动通过
*/
String AUTO_PASS = "autoPass";
/**
* 业务编码
*/
String BUSINESS_CODE = "businessCode";
}

View File

@@ -0,0 +1,65 @@
package org.ruoyi.workflow.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 按钮权限枚举
*
* @author AprilWind
*/
@Getter
@AllArgsConstructor
public enum ButtonPermissionEnum implements NodeExtEnum {
/**
* 是否弹窗选人
*/
POP("是否弹窗选人", "pop", false),
/**
* 是否能委托
*/
TRUST("是否能委托", "trust", false),
/**
* 是否能转办
*/
TRANSFER("是否能转办", "transfer", false),
/**
* 是否能抄送
*/
COPY("是否能抄送", "copy", true),
/**
* 是否显示退回
*/
BACK("是否显示退回", "back", true),
/**
* 是否能加签
*/
ADD_SIGN("是否能加签", "addSign", false),
/**
* 是否能减签
*/
SUB_SIGN("是否能减签", "subSign", false),
/**
* 是否能终止
*/
TERMINATION("是否能终止", "termination", true),
/**
* 是否能上传附件
*/
FILE("是否能上传附件", "file", true);
private final String label;
private final String value;
private final boolean selected;
}

View File

@@ -0,0 +1,20 @@
package org.ruoyi.workflow.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 抄送设置枚举
*
* @author AprilWind
*/
@Getter
@AllArgsConstructor
public enum CopySettingEnum implements NodeExtEnum {
;
private final String label;
private final String value;
private final boolean selected;
}

View File

@@ -0,0 +1,53 @@
package org.ruoyi.workflow.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 消息类型枚举
*
* @author may
*/
@Getter
@AllArgsConstructor
public enum MessageTypeEnum {
/**
* 站内信
*/
SYSTEM_MESSAGE("1", "站内信"),
/**
* 邮箱
*/
EMAIL_MESSAGE("2", "邮箱"),
/**
* 短信
*/
SMS_MESSAGE("3", "短信");
private final String code;
private final String desc;
private static final Map<String, MessageTypeEnum> MESSAGE_TYPE_ENUM_MAP = Arrays.stream(values())
.collect(Collectors.toConcurrentMap(MessageTypeEnum::getCode, Function.identity()));
/**
* 根据消息类型 code 获取 MessageTypeEnum
*
* @param code 消息类型code
* @return MessageTypeEnum
*/
public static MessageTypeEnum getByCode(String code) {
return MESSAGE_TYPE_ENUM_MAP.getOrDefault(code, null);
}
}

View File

@@ -0,0 +1,32 @@
package org.ruoyi.workflow.common.enums;
/**
* 节点扩展属性枚举
*
* @author AprilWind
*/
public interface NodeExtEnum {
/**
* 选项label
*
* @return 选项label
*/
String getLabel();
/**
* 选项值
*
* @return 选项值
*/
String getValue();
/**
* 是否默认选中
*
* @return 是否默认选中
*/
boolean isSelected();
}

View File

@@ -0,0 +1,140 @@
package org.ruoyi.workflow.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.ruoyi.common.core.exception.ServiceException;
import org.ruoyi.common.core.utils.StringUtils;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* 任务分配人枚举
*
* @author AprilWind
*/
@Getter
@AllArgsConstructor
public enum TaskAssigneeEnum {
/**
* 用户
*/
USER("用户", ""),
/**
* 角色
*/
ROLE("角色", "role:"),
/**
* 部门
*/
DEPT("部门", "dept:"),
/**
* 岗位
*/
POST("岗位", "post:"),
/**
* SPEL表达式
*/
SPEL("SpEL表达式", "");
private final String desc;
private final String code;
/**
* 根据描述获取对应的枚举类型
* <p>
* 通过传入描述,查找并返回匹配的枚举项。如果未找到匹配项,会抛出 {@link ServiceException}。
* </p>
*
* @param desc 描述,用于匹配对应的枚举项
* @return TaskAssigneeEnum 返回对应的枚举类型
* @throws ServiceException 如果未找到匹配的枚举项
*/
public static TaskAssigneeEnum fromDesc(String desc) {
for (TaskAssigneeEnum type : values()) {
if (type.getDesc().equals(desc)) {
return type;
}
}
throw new ServiceException("未知的办理人类型: " + desc);
}
/**
* 根据代码获取对应的枚举类型
* <p>
* 通过传入代码,查找并返回匹配的枚举项。如果未找到匹配项,会抛出 {@link ServiceException}。
* </p>
*
* @param code 代码,用于匹配对应的枚举项
* @return TaskAssigneeEnum 返回对应的枚举类型
* @throws IllegalArgumentException 如果未找到匹配的枚举项
*/
public static TaskAssigneeEnum fromCode(String code) {
for (TaskAssigneeEnum type : values()) {
if (type.getCode().equals(code)) {
return type;
}
}
throw new ServiceException("未知的办理人类型代码: " + code);
}
/**
* 获取所有办理人类型的描述列表
* <p>
* 获取当前枚举类所有项的描述字段列表,通常用于展示选择项。
* </p>
*
* @return List<String> 返回所有办理人类型的描述列表
*/
public static List<String> getAssigneeTypeList() {
return Arrays.stream(values())
.map(TaskAssigneeEnum::getDesc)
.collect(Collectors.toList());
}
/**
* 获取所有办理人类型的代码列表
* <p>
* 获取当前枚举类所有项的代码字段列表,通常用于程序内部逻辑的判断。
* </p>
*
* @return List<String> 返回所有办理人类型的代码列表
*/
public static List<String> getAssigneeCodeList() {
return Arrays.stream(values())
.map(TaskAssigneeEnum::getCode)
.collect(Collectors.toList());
}
/**
* 判断当前办理人类型是否需要调用部门服务deptService
*
* @return 如果类型是 USER、DEPT 或 POST则返回 true否则返回 false
*/
public boolean needsDeptService() {
return this == USER || this == DEPT || this == POST;
}
/**
* 判断给定字符串是否符合 SPEL 表达式格式(以 $ 或 # 开头)
*
* @param value 待判断字符串
* @return 是否为 SPEL 表达式
*/
public static boolean isSpelExpression(String value) {
if (value == null) {
return false;
}
// $前缀表示默认办理人变量策略
// #前缀表示spel办理人变量策略
return StringUtils.startsWith(value, "$") || StringUtils.startsWith(value, "#");
}
}

View File

@@ -0,0 +1,49 @@
package org.ruoyi.workflow.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 人员类型
*
* @author AprilWind
*/
@Getter
@AllArgsConstructor
public enum TaskAssigneeType {
/**
* 待办任务的审批人权限
* <p>该权限表示用户是待办任务的审批人,负责审核任务的执行情况。</p>
*/
APPROVER("1", "待办任务的审批人权限"),
/**
* 待办任务的转办人权限
* <p>该权限表示用户是待办任务的转办人,负责将任务分配给其他人员。</p>
*/
TRANSFER("2", "待办任务的转办人权限"),
/**
* 待办任务的委托人权限
* <p>该权限表示用户是待办任务的委托人,能够委托其他人代为处理任务。</p>
*/
DELEGATE("3", "待办任务的委托人权限"),
/**
* 待办任务的抄送人权限
* <p>该权限表示用户是待办任务的抄送人,仅接收任务信息的通知,不参与任务的审批或处理。</p>
*/
COPY("4", "待办任务的抄送人权限");
/**
* 类型
*/
private final String code;
/**
* 描述
*/
private final String description;
}

View File

@@ -0,0 +1,114 @@
package org.ruoyi.workflow.common.enums;
import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 任务状态枚举
*
* @author may
*/
@Getter
@AllArgsConstructor
public enum TaskStatusEnum {
/**
* 撤销
*/
CANCEL("cancel", "撤销"),
/**
* 通过
*/
PASS("pass", "通过"),
/**
* 待审核
*/
WAITING("waiting", "待审核"),
/**
* 作废
*/
INVALID("invalid", "作废"),
/**
* 退回
*/
BACK("back", "退回"),
/**
* 终止
*/
TERMINATION("termination", "终止"),
/**
* 转办
*/
TRANSFER("transfer", "转办"),
/**
* 委托
*/
DEPUTE("depute", "委托"),
/**
* 抄送
*/
COPY("copy", "抄送"),
/**
* 加签
*/
SIGN("sign", "加签"),
/**
* 减签
*/
SIGN_OFF("sign_off", "减签"),
/**
* 超时
*/
TIMEOUT("timeout", "超时");
/**
* 状态
*/
private final String status;
/**
* 描述
*/
private final String desc;
private static final Map<String, String> STATUS_DESC_MAP = Arrays.stream(values())
.collect(Collectors.toConcurrentMap(TaskStatusEnum::getStatus, TaskStatusEnum::getDesc));
/**
* 任务业务状态
*
* @param status 状态
*/
public static String findByStatus(String status) {
// 从缓存中直接获取描述
return STATUS_DESC_MAP.getOrDefault(status, StrUtil.EMPTY);
}
/**
* 判断状态是否为通过或退回
*
* @param status 状态值
* @return true 表示是通过或退回状态
*/
public static boolean isPassOrBack(String status) {
return PASS.getStatus().equals(status) || BACK.getStatus().equals(status);
}
}

View File

@@ -0,0 +1,20 @@
package org.ruoyi.workflow.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 变量枚举
*
* @author AprilWind
*/
@Getter
@AllArgsConstructor
public enum VariablesEnum implements NodeExtEnum {
;
private final String label;
private final String value;
private final boolean selected;
}

View File

@@ -0,0 +1,16 @@
package org.ruoyi.workflow.config;
import org.ruoyi.workflow.common.ConditionalOnEnable;
import org.springframework.context.annotation.Configuration;
/**
* warmFlow配置
*
* @author may
*/
@ConditionalOnEnable
@Configuration
public class WarmFlowConfig {
}

View File

@@ -0,0 +1,134 @@
package org.ruoyi.workflow.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.lang.tree.Tree;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.core.validate.AddGroup;
import org.ruoyi.common.core.validate.EditGroup;
import org.ruoyi.common.excel.utils.ExcelUtil;
import org.ruoyi.common.idempotent.annotation.RepeatSubmit;
import org.ruoyi.common.log.annotation.Log;
import org.ruoyi.common.log.enums.BusinessType;
import org.ruoyi.common.web.core.BaseController;
import org.ruoyi.workflow.common.ConditionalOnEnable;
import org.ruoyi.workflow.common.constant.FlowConstant;
import org.ruoyi.workflow.domain.bo.FlowCategoryBo;
import org.ruoyi.workflow.domain.vo.FlowCategoryVo;
import org.ruoyi.workflow.service.IFlwCategoryService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 流程分类
*
* @author may
*/
@ConditionalOnEnable
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/workflow/category")
public class FlwCategoryController extends BaseController {
private final IFlwCategoryService flwCategoryService;
/**
* 查询流程分类列表
*/
@SaCheckPermission("workflow:category:list")
@GetMapping("/list")
public R<List<FlowCategoryVo>> list(FlowCategoryBo bo) {
List<FlowCategoryVo> list = flwCategoryService.queryList(bo);
return R.ok(list);
}
/**
* 导出流程分类列表
*/
@SaCheckPermission("workflow:category:export")
@Log(title = "流程分类", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(FlowCategoryBo bo, HttpServletResponse response) {
List<FlowCategoryVo> list = flwCategoryService.queryList(bo);
ExcelUtil.exportExcel(list, "流程分类", FlowCategoryVo.class, response);
}
/**
* 获取流程分类详细信息
*
* @param categoryId 主键
*/
@SaCheckPermission("workflow:category:query")
@GetMapping("/{categoryId}")
public R<FlowCategoryVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long categoryId) {
return R.ok(flwCategoryService.queryById(categoryId));
}
/**
* 新增流程分类
*/
@SaCheckPermission("workflow:category:add")
@Log(title = "流程分类", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody FlowCategoryBo category) {
if (!flwCategoryService.checkCategoryNameUnique(category)) {
return R.fail("新增流程分类'" + category.getCategoryName() + "'失败,流程分类名称已存在");
}
return toAjax(flwCategoryService.insertByBo(category));
}
/**
* 修改流程分类
*/
@SaCheckPermission("workflow:category:edit")
@Log(title = "流程分类", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody FlowCategoryBo category) {
Long categoryId = category.getCategoryId();
if (!flwCategoryService.checkCategoryNameUnique(category)) {
return R.fail("修改流程分类'" + category.getCategoryName() + "'失败,流程分类名称已存在");
} else if (category.getParentId().equals(categoryId)) {
return R.fail("修改流程分类'" + category.getCategoryName() + "'失败,上级流程分类不能是自己");
}
return toAjax(flwCategoryService.updateByBo(category));
}
/**
* 删除流程分类
*
* @param categoryId 主键
*/
@SaCheckPermission("workflow:category:remove")
@Log(title = "流程分类", businessType = BusinessType.DELETE)
@DeleteMapping("/{categoryId}")
public R<Void> remove(@PathVariable Long categoryId) {
if (FlowConstant.FLOW_CATEGORY_ID.equals(categoryId)) {
return R.warn("默认流程分类,不允许删除");
}
if (flwCategoryService.hasChildByCategoryId(categoryId)) {
return R.warn("存在下级流程分类,不允许删除");
}
if (flwCategoryService.checkCategoryExistDefinition(categoryId)) {
return R.warn("流程分类存在流程定义,不允许删除");
}
return toAjax(flwCategoryService.deleteWithValidById(categoryId));
}
/**
* 获取流程分类树列表
*
* @param categoryBo 流程分类
*/
@GetMapping("/categoryTree")
public R<List<Tree<String>>> categoryTree(FlowCategoryBo categoryBo) {
return R.ok(flwCategoryService.selectCategoryTreeList(categoryBo));
}
}

View File

@@ -0,0 +1,194 @@
package org.ruoyi.workflow.controller;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.idempotent.annotation.RepeatSubmit;
import org.ruoyi.common.log.annotation.Log;
import org.ruoyi.common.log.enums.BusinessType;
import org.ruoyi.common.mybatis.core.page.PageQuery;
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
import org.ruoyi.common.web.core.BaseController;
import org.dromara.warm.flow.core.entity.Definition;
import org.dromara.warm.flow.core.service.DefService;
import org.dromara.warm.flow.orm.entity.FlowDefinition;
import org.ruoyi.workflow.common.ConditionalOnEnable;
import org.ruoyi.workflow.domain.vo.FlowDefinitionVo;
import org.ruoyi.workflow.service.IFlwDefinitionService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
/**
* 流程定义管理 控制层
*
* @author may
*/
@ConditionalOnEnable
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/workflow/definition")
public class FlwDefinitionController extends BaseController {
private final DefService defService;
private final IFlwDefinitionService flwDefinitionService;
/**
* 查询流程定义列表
*
* @param flowDefinition 参数
* @param pageQuery 分页
*/
@GetMapping("/list")
public TableDataInfo<FlowDefinitionVo> list(FlowDefinition flowDefinition, PageQuery pageQuery) {
return flwDefinitionService.queryList(flowDefinition, pageQuery);
}
/**
* 查询未发布的流程定义列表
*
* @param flowDefinition 参数
* @param pageQuery 分页
*/
@GetMapping("/unPublishList")
public TableDataInfo<FlowDefinitionVo> unPublishList(FlowDefinition flowDefinition, PageQuery pageQuery) {
return flwDefinitionService.unPublishList(flowDefinition, pageQuery);
}
/**
* 获取流程定义详细信息
*
* @param id 流程定义id
*/
@GetMapping(value = "/{id}")
public R<Definition> getInfo(@PathVariable Long id) {
return R.ok(defService.getById(id));
}
/**
* 新增流程定义
*
* @param flowDefinition 参数
*/
@Log(title = "流程定义", businessType = BusinessType.INSERT)
@PostMapping
@RepeatSubmit()
@Transactional(rollbackFor = Exception.class)
public R<Boolean> add(@RequestBody FlowDefinition flowDefinition) {
return R.ok(defService.checkAndSave(flowDefinition));
}
/**
* 修改流程定义
*
* @param flowDefinition 参数
*/
@Log(title = "流程定义", businessType = BusinessType.UPDATE)
@PutMapping
@RepeatSubmit()
@Transactional(rollbackFor = Exception.class)
public R<Boolean> edit(@RequestBody FlowDefinition flowDefinition) {
return R.ok(defService.updateById(flowDefinition));
}
/**
* 发布流程定义
*
* @param id 流程定义id
*/
@Log(title = "流程定义", businessType = BusinessType.INSERT)
@PutMapping("/publish/{id}")
@RepeatSubmit()
public R<Boolean> publish(@PathVariable Long id) {
return R.ok(flwDefinitionService.publish(id));
}
/**
* 取消发布流程定义
*
* @param id 流程定义id
*/
@Log(title = "流程定义", businessType = BusinessType.INSERT)
@PutMapping("/unPublish/{id}")
@RepeatSubmit()
@Transactional(rollbackFor = Exception.class)
public R<Boolean> unPublish(@PathVariable Long id) {
return R.ok(defService.unPublish(id));
}
/**
* 删除流程定义
*/
@Log(title = "流程定义", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@PathVariable List<Long> ids) {
return toAjax(flwDefinitionService.removeDef(ids));
}
/**
* 复制流程定义
*
* @param id 流程定义id
*/
@Log(title = "流程定义", businessType = BusinessType.INSERT)
@PostMapping("/copy/{id}")
@RepeatSubmit()
@Transactional(rollbackFor = Exception.class)
public R<Boolean> copy(@PathVariable Long id) {
return R.ok(defService.copyDef(id));
}
/**
* 导入流程定义
*
* @param file 文件
* @param category 分类
*/
@Log(title = "流程定义", businessType = BusinessType.IMPORT)
@PostMapping("/importDef")
public R<Boolean> importDef(MultipartFile file, String category) {
return R.ok(flwDefinitionService.importJson(file, category));
}
/**
* 导出流程定义
*
* @param id 流程定义id
* @param response 响应
* @throws IOException 异常
*/
@Log(title = "流程定义", businessType = BusinessType.EXPORT)
@PostMapping("/exportDef/{id}")
public void exportDef(@PathVariable Long id, HttpServletResponse response) throws IOException {
flwDefinitionService.exportDef(id, response);
}
/**
* 获取流程定义JSON字符串
*
* @param id 流程定义id
*/
@GetMapping("/xmlString/{id}")
public R<String> xmlString(@PathVariable Long id) {
return R.ok("操作成功", defService.exportJson(id));
}
/**
* 激活/挂起流程定义
*
* @param id 流程定义id
* @param active 激活/挂起
*/
@RepeatSubmit()
@PutMapping("/active/{id}")
@Transactional(rollbackFor = Exception.class)
public R<Boolean> active(@PathVariable Long id, @RequestParam boolean active) {
return R.ok(active ? defService.active(id) : defService.unActive(id));
}
}

View File

@@ -0,0 +1,179 @@
package org.ruoyi.workflow.controller;
import lombok.RequiredArgsConstructor;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.idempotent.annotation.RepeatSubmit;
import org.ruoyi.common.log.annotation.Log;
import org.ruoyi.common.log.enums.BusinessType;
import org.ruoyi.common.mybatis.core.page.PageQuery;
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
import org.ruoyi.common.web.core.BaseController;
import org.dromara.warm.flow.core.service.InsService;
import org.ruoyi.workflow.common.ConditionalOnEnable;
import org.ruoyi.workflow.domain.bo.FlowCancelBo;
import org.ruoyi.workflow.domain.bo.FlowInstanceBo;
import org.ruoyi.workflow.domain.bo.FlowInvalidBo;
import org.ruoyi.workflow.domain.bo.FlowVariableBo;
import org.ruoyi.workflow.domain.vo.FlowInstanceVo;
import org.ruoyi.workflow.service.IFlwInstanceService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
* 流程实例管理 控制层
*
* @author may
*/
@ConditionalOnEnable
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/workflow/instance")
public class FlwInstanceController extends BaseController {
private final InsService insService;
private final IFlwInstanceService flwInstanceService;
/**
* 查询正在运行的流程实例列表
*
* @param flowInstanceBo 流程实例
* @param pageQuery 分页
*/
@GetMapping("/pageByRunning")
public TableDataInfo<FlowInstanceVo> selectRunningInstanceList(FlowInstanceBo flowInstanceBo, PageQuery pageQuery) {
return flwInstanceService.selectRunningInstanceList(flowInstanceBo, pageQuery);
}
/**
* 查询已结束的流程实例列表
*
* @param flowInstanceBo 流程实例
* @param pageQuery 分页
*/
@GetMapping("/pageByFinish")
public TableDataInfo<FlowInstanceVo> selectFinishInstanceList(FlowInstanceBo flowInstanceBo, PageQuery pageQuery) {
return flwInstanceService.selectFinishInstanceList(flowInstanceBo, pageQuery);
}
/**
* 根据业务id查询流程实例详细信息
*
* @param businessId 业务id
*/
@GetMapping("/getInfo/{businessId}")
public R<FlowInstanceVo> getInfo(@PathVariable Long businessId) {
return R.ok(flwInstanceService.queryByBusinessId(businessId));
}
/**
* 按照业务id删除流程实例
*
* @param businessIds 业务id
*/
@DeleteMapping("/deleteByBusinessIds/{businessIds}")
public R<Void> deleteByBusinessIds(@PathVariable List<Long> businessIds) {
return toAjax(flwInstanceService.deleteByBusinessIds(businessIds));
}
/**
* 按照实例id删除流程实例
*
* @param instanceIds 实例id
*/
@DeleteMapping("/deleteByInstanceIds/{instanceIds}")
public R<Void> deleteByInstanceIds(@PathVariable List<Long> instanceIds) {
return toAjax(flwInstanceService.deleteByInstanceIds(instanceIds));
}
/**
* 按照实例id删除已完成得流程实例
*
* @param instanceIds 实例id
*/
@DeleteMapping("/deleteHisByInstanceIds/{instanceIds}")
public R<Void> deleteHisByInstanceIds(@PathVariable List<Long> instanceIds) {
return toAjax(flwInstanceService.deleteHisByInstanceIds(instanceIds));
}
/**
* 撤销流程
*
* @param bo 参数
*/
@RepeatSubmit()
@PutMapping("/cancelProcessApply")
public R<Void> cancelProcessApply(@RequestBody FlowCancelBo bo) {
return toAjax(flwInstanceService.cancelProcessApply(bo));
}
/**
* 激活/挂起流程实例
*
* @param id 流程实例id
* @param active 激活/挂起
*/
@RepeatSubmit()
@PutMapping("/active/{id}")
public R<Boolean> active(@PathVariable Long id, @RequestParam boolean active) {
return R.ok(active ? insService.active(id) : insService.unActive(id));
}
/**
* 获取当前登陆人发起的流程实例
*
* @param flowInstanceBo 参数
* @param pageQuery 分页
*/
@GetMapping("/pageByCurrent")
public TableDataInfo<FlowInstanceVo> selectCurrentInstanceList(FlowInstanceBo flowInstanceBo, PageQuery pageQuery) {
return flwInstanceService.selectCurrentInstanceList(flowInstanceBo, pageQuery);
}
/**
* 获取流程图,流程记录
*
* @param businessId 业务id
*/
@GetMapping("/flowHisTaskList/{businessId}")
public R<Map<String, Object>> flowHisTaskList(@PathVariable String businessId) {
return R.ok(flwInstanceService.flowHisTaskList(businessId));
}
/**
* 获取流程变量
*
* @param instanceId 流程实例id
*/
@GetMapping("/instanceVariable/{instanceId}")
public R<Map<String, Object>> instanceVariable(@PathVariable Long instanceId) {
return R.ok(flwInstanceService.instanceVariable(instanceId));
}
/**
* 修改流程变量
*
* @param bo 参数
*/
@RepeatSubmit()
@PutMapping("/updateVariable")
public R<Void> updateVariable(@Validated @RequestBody FlowVariableBo bo) {
return toAjax(flwInstanceService.updateVariable(bo));
}
/**
* 作废流程
*
* @param bo 参数
*/
@Log(title = "流程实例管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/invalid")
public R<Boolean> invalid(@Validated @RequestBody FlowInvalidBo bo) {
return R.ok(flwInstanceService.processInvalid(bo));
}
}

View File

@@ -0,0 +1,93 @@
package org.ruoyi.workflow.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.core.validate.AddGroup;
import org.ruoyi.common.core.validate.EditGroup;
import org.ruoyi.common.idempotent.annotation.RepeatSubmit;
import org.ruoyi.common.log.annotation.Log;
import org.ruoyi.common.log.enums.BusinessType;
import org.ruoyi.common.mybatis.core.page.PageQuery;
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
import org.ruoyi.common.web.core.BaseController;
import org.ruoyi.workflow.common.ConditionalOnEnable;
import org.ruoyi.workflow.domain.bo.FlowSpelBo;
import org.ruoyi.workflow.domain.vo.FlowSpelVo;
import org.ruoyi.workflow.service.IFlwSpelService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 流程spel达式定义
*
* @author Michelle.Chung
* @date 2025-07-04
*/
@ConditionalOnEnable
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/workflow/spel")
public class FlwSpelController extends BaseController {
private final IFlwSpelService flwSpelService;
/**
* 查询流程spel达式定义列表
*/
@SaCheckPermission("workflow:spel:list")
@GetMapping("/list")
public TableDataInfo<FlowSpelVo> list(FlowSpelBo bo, PageQuery pageQuery) {
return flwSpelService.queryPageList(bo, pageQuery);
}
/**
* 获取流程spel达式定义详细信息
*
* @param id 主键
*/
@SaCheckPermission("workflow:spel:query")
@GetMapping("/{id}")
public R<FlowSpelVo> 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<Void> 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<Void> 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<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
return toAjax(flwSpelService.deleteWithValidByIds(List.of(ids), true));
}
}

View File

@@ -0,0 +1,224 @@
package org.ruoyi.workflow.controller;
import lombok.RequiredArgsConstructor;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.core.domain.dto.StartProcessReturnDTO;
import org.ruoyi.common.core.domain.dto.UserDTO;
import org.ruoyi.common.core.validate.AddGroup;
import org.ruoyi.common.idempotent.annotation.RepeatSubmit;
import org.ruoyi.common.log.annotation.Log;
import org.ruoyi.common.log.enums.BusinessType;
import org.ruoyi.common.mybatis.core.page.PageQuery;
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
import org.ruoyi.common.web.core.BaseController;
import org.dromara.warm.flow.core.entity.Node;
import org.dromara.warm.flow.orm.entity.FlowNode;
import org.ruoyi.workflow.common.ConditionalOnEnable;
import org.ruoyi.workflow.domain.bo.*;
import org.ruoyi.workflow.domain.vo.FlowHisTaskVo;
import org.ruoyi.workflow.domain.vo.FlowTaskVo;
import org.ruoyi.workflow.service.IFlwTaskService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 任务管理 控制层
*
* @author may
*/
@ConditionalOnEnable
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/workflow/task")
public class FlwTaskController extends BaseController {
private final IFlwTaskService flwTaskService;
/**
* 启动任务
*
* @param startProcessBo 启动流程参数
*/
@Log(title = "任务管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/startWorkFlow")
public R<StartProcessReturnDTO> startWorkFlow(@Validated(AddGroup.class) @RequestBody StartProcessBo startProcessBo) {
StartProcessReturnDTO startProcessReturn = flwTaskService.startWorkFlow(startProcessBo);
return R.ok("提交成功", startProcessReturn);
}
/**
* 办理任务
*
* @param completeTaskBo 办理任务参数
*/
@Log(title = "任务管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/completeTask")
public R<Void> completeTask(@Validated(AddGroup.class) @RequestBody CompleteTaskBo completeTaskBo) {
return toAjax(flwTaskService.completeTask(completeTaskBo));
}
/**
* 查询当前用户的待办任务
*
* @param flowTaskBo 参数
* @param pageQuery 分页
*/
@GetMapping("/pageByTaskWait")
public TableDataInfo<FlowTaskVo> pageByTaskWait(FlowTaskBo flowTaskBo, PageQuery pageQuery) {
return flwTaskService.pageByTaskWait(flowTaskBo, pageQuery);
}
/**
* 查询当前用户的已办任务
*
* @param flowTaskBo 参数
* @param pageQuery 分页
*/
@GetMapping("/pageByTaskFinish")
public TableDataInfo<FlowHisTaskVo> pageByTaskFinish(FlowTaskBo flowTaskBo, PageQuery pageQuery) {
return flwTaskService.pageByTaskFinish(flowTaskBo, pageQuery);
}
/**
* 查询待办任务
*
* @param flowTaskBo 参数
* @param pageQuery 分页
*/
@GetMapping("/pageByAllTaskWait")
public TableDataInfo<FlowTaskVo> pageByAllTaskWait(FlowTaskBo flowTaskBo, PageQuery pageQuery) {
return flwTaskService.pageByAllTaskWait(flowTaskBo, pageQuery);
}
/**
* 查询已办任务
*
* @param flowTaskBo 参数
* @param pageQuery 分页
*/
@GetMapping("/pageByAllTaskFinish")
public TableDataInfo<FlowHisTaskVo> pageByAllTaskFinish(FlowTaskBo flowTaskBo, PageQuery pageQuery) {
return flwTaskService.pageByAllTaskFinish(flowTaskBo, pageQuery);
}
/**
* 查询当前用户的抄送
*
* @param flowTaskBo 参数
* @param pageQuery 分页
*/
@GetMapping("/pageByTaskCopy")
public TableDataInfo<FlowTaskVo> pageByTaskCopy(FlowTaskBo flowTaskBo, PageQuery pageQuery) {
return flwTaskService.pageByTaskCopy(flowTaskBo, pageQuery);
}
/**
* 根据taskId查询代表任务
*
* @param taskId 任务id
*/
@GetMapping("/getTask/{taskId}")
public R<FlowTaskVo> getTask(@PathVariable Long taskId) {
return R.ok(flwTaskService.selectById(taskId));
}
/**
* 获取下一节点信息
*
* @param bo 参数
*/
@PostMapping("/getNextNodeList")
public R<List<FlowNode>> getNextNodeList(@RequestBody FlowNextNodeBo bo) {
return R.ok(flwTaskService.getNextNodeList(bo));
}
/**
* 终止任务
*
* @param bo 参数
*/
@Log(title = "任务管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/terminationTask")
public R<Boolean> terminationTask(@RequestBody FlowTerminationBo bo) {
return R.ok(flwTaskService.terminationTask(bo));
}
/**
* 任务操作
*
* @param bo 参数
* @param taskOperation 操作类型,委派 delegateTask、转办 transferTask、加签 addSignature、减签 reductionSignature
*/
@Log(title = "任务管理", businessType = BusinessType.UPDATE)
@RepeatSubmit
@PostMapping("/taskOperation/{taskOperation}")
public R<Void> taskOperation(@Validated @RequestBody TaskOperationBo bo, @PathVariable String taskOperation) {
return toAjax(flwTaskService.taskOperation(bo, taskOperation));
}
/**
* 修改任务办理人
*
* @param taskIdList 任务id
* @param userId 办理人id
*/
@Log(title = "任务管理", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/updateAssignee/{userId}")
public R<Void> updateAssignee(@RequestBody List<Long> taskIdList, @PathVariable String userId) {
return toAjax(flwTaskService.updateAssignee(taskIdList, userId));
}
/**
* 驳回审批
*
* @param bo 参数
*/
@Log(title = "任务管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/backProcess")
public R<Void> backProcess(@Validated({AddGroup.class}) @RequestBody BackProcessBo bo) {
return toAjax(flwTaskService.backProcess(bo));
}
/**
* 获取可驳回的前置节点
*
* @param taskId 任务id
* @param nowNodeCode 当前节点
*/
@GetMapping("/getBackTaskNode/{taskId}/{nowNodeCode}")
public R<List<Node>> getBackTaskNode(@PathVariable Long taskId, @PathVariable String nowNodeCode) {
return R.ok(flwTaskService.getBackTaskNode(taskId, nowNodeCode));
}
/**
* 获取当前任务的所有办理人
*
* @param taskId 任务id
*/
@GetMapping("/currentTaskAllUser/{taskId}")
public R<List<UserDTO>> currentTaskAllUser(@PathVariable Long taskId) {
return R.ok(flwTaskService.currentTaskAllUser(List.of(taskId)));
}
/**
* 催办任务
*
* @param bo 参数
* @return 结果
*/
@PostMapping("/urgeTask")
public R<Void> urgeTask(@RequestBody FlowUrgeTaskBo bo) {
return toAjax(flwTaskService.urgeTask(bo));
}
}

View File

@@ -0,0 +1,119 @@
package org.ruoyi.workflow.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.core.validate.AddGroup;
import org.ruoyi.common.core.validate.EditGroup;
import org.ruoyi.common.excel.utils.ExcelUtil;
import org.ruoyi.common.idempotent.annotation.RepeatSubmit;
import org.ruoyi.common.log.annotation.Log;
import org.ruoyi.common.log.enums.BusinessType;
import org.ruoyi.common.mybatis.core.page.PageQuery;
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
import org.ruoyi.common.web.core.BaseController;
import org.ruoyi.workflow.common.ConditionalOnEnable;
import org.ruoyi.workflow.domain.bo.TestLeaveBo;
import org.ruoyi.workflow.domain.vo.TestLeaveVo;
import org.ruoyi.workflow.service.ITestLeaveService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 请假
*
* @author may
* @date 2023-07-21
*/
@ConditionalOnEnable
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/workflow/leave")
public class TestLeaveController extends BaseController {
private final ITestLeaveService testLeaveService;
/**
* 查询请假列表
*/
@SaCheckPermission("workflow:leave:list")
@GetMapping("/list")
public TableDataInfo<TestLeaveVo> list(TestLeaveBo bo, PageQuery pageQuery) {
return testLeaveService.queryPageList(bo, pageQuery);
}
/**
* 导出请假列表
*/
@SaCheckPermission("workflow:leave:export")
@Log(title = "请假", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(TestLeaveBo bo, HttpServletResponse response) {
List<TestLeaveVo> list = testLeaveService.queryList(bo);
ExcelUtil.exportExcel(list, "请假", TestLeaveVo.class, response);
}
/**
* 获取请假详细信息
*
* @param id 主键
*/
@SaCheckPermission("workflow:leave:query")
@GetMapping("/{id}")
public R<TestLeaveVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(testLeaveService.queryById(id));
}
/**
* 新增请假
*/
@SaCheckPermission("workflow:leave:add")
@Log(title = "请假", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<TestLeaveVo> add(@Validated(AddGroup.class) @RequestBody TestLeaveBo bo) {
return R.ok(testLeaveService.insertByBo(bo));
}
/**
* 提交请假并提交流程
*/
@SaCheckPermission("workflow:leave:add")
@Log(title = "请假", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/submitAndFlowStart")
public R<TestLeaveVo> submitAndFlowStart(@Validated(AddGroup.class) @RequestBody TestLeaveBo bo) {
return R.ok(testLeaveService.submitAndFlowStart(bo));
}
/**
* 修改请假
*/
@SaCheckPermission("workflow:leave:edit")
@Log(title = "请假", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<TestLeaveVo> edit(@Validated(EditGroup.class) @RequestBody TestLeaveBo bo) {
return R.ok(testLeaveService.updateByBo(bo));
}
/**
* 删除请假
*
* @param ids 主键串
*/
@SaCheckPermission("workflow:leave:remove")
@Log(title = "请假", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(testLeaveService.deleteWithValidByIds(List.of(ids)));
}
}

View File

@@ -1,152 +0,0 @@
package org.ruoyi.workflow.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.workflow.base.ThreadContext;
import org.ruoyi.workflow.dto.workflow.*;
import org.ruoyi.workflow.entity.WorkflowComponent;
import org.ruoyi.workflow.service.WorkflowComponentService;
import org.ruoyi.workflow.service.WorkflowService;
import org.ruoyi.workflow.workflow.WorkflowStarter;
import org.ruoyi.workflow.workflow.node.switcher.OperatorEnum;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/workflow")
@Validated
public class WorkflowController {
@Resource
private WorkflowStarter workflowStarter;
@Resource
private WorkflowService workflowService;
@Resource
private WorkflowComponentService workflowComponentService;
@PostMapping("/add")
public R<WorkflowResp> add(@RequestBody @Validated WfAddReq addReq) {
return R.ok(workflowService.add(addReq.getTitle(), addReq.getRemark(), addReq.getIsPublic()));
}
@PostMapping("/set-public/{wfUuid}")
public R setPublic(@PathVariable String wfUuid, @RequestParam(defaultValue = "true") Boolean isPublic) {
workflowService.setPublic(wfUuid, isPublic);
return R.ok();
}
@PostMapping("/update")
public R<WorkflowResp> update(@RequestBody @Validated WorkflowUpdateReq req) {
return R.ok(workflowService.update(req));
}
@PostMapping("/del/{uuid}")
public R delete(@PathVariable String uuid) {
workflowService.softDelete(uuid);
return R.ok();
}
@PostMapping("/enable/{uuid}")
public R enable(@PathVariable String uuid, @RequestParam Boolean enable) {
workflowService.enable(uuid, enable);
return R.ok();
}
@PostMapping("/base-info/update")
public R<WorkflowResp> updateBaseInfo(@RequestBody @Validated WfBaseInfoUpdateReq req) {
return R.ok(workflowService.updateBaseInfo(req.getUuid(), req.getTitle(), req.getRemark(), req.getIsPublic()));
}
@Operation(summary = "流式响应")
@PostMapping(value = "/run", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter sseAsk(@RequestBody WorkflowRunReq runReq) {
return workflowStarter.streaming(ThreadContext.getCurrentUser(), runReq.getUuid(), runReq.getInputs());
}
@GetMapping("/mine/search")
public R<Page<WorkflowResp>> searchMine(@RequestParam(defaultValue = "") String keyword,
@RequestParam(required = false) Boolean isPublic,
@NotNull @Min(1) Integer currentPage,
@NotNull @Min(10) Integer pageSize) {
return R.ok(workflowService.search(keyword, isPublic, null, currentPage, pageSize));
}
/**
* 获取当前用户可访问的工作流详情
*
* @param uuid 工作流唯一标识
* @return 工作流详情
*/
@GetMapping("/{uuid}")
public R<WorkflowResp> getDetail(@PathVariable String uuid) {
return R.ok(workflowService.getDetail(uuid));
}
/**
* 搜索公开工作流
*
* @param keyword 搜索关键词
* @param currentPage 当前页数
* @param pageSize 每页数量
* @return 工作流列表
*/
@GetMapping("/public/search")
public R<Page<WorkflowResp>> searchPublic(@RequestParam(defaultValue = "") String keyword,
@NotNull @Min(1) Integer currentPage,
@NotNull @Min(10) Integer pageSize) {
return R.ok(workflowService.searchPublic(keyword, currentPage, pageSize));
}
/**
* 搜索公开工作流
*
* @param keyword 搜索关键词
* @param currentPage 当前页数
* @param pageSize 每页数量
* @return 工作流列表
*/
@GetMapping("/search")
public R<Page<WorkflowResp>> search(@RequestParam(defaultValue = "") String keyword,
@NotNull @Min(1) Integer currentPage,
@NotNull @Min(10) Integer pageSize) {
return R.ok(workflowService.search(keyword, currentPage, pageSize));
}
/**
* 获取公开工作流详情
*
* @param uuid 工作流唯一标识
* @return 工作流详情
*/
@GetMapping("/public/{uuid}")
public R<WorkflowResp> getPublicDetail(@PathVariable String uuid) {
return R.ok(workflowService.getPublicDetail(uuid));
}
@GetMapping("/public/operators")
public R<List<Map<String, String>>> searchPublic() {
List<Map<String, String>> result = new ArrayList<>();
for (OperatorEnum operator : OperatorEnum.values()) {
result.add(Map.of("name", operator.getName(), "desc", operator.getDesc()));
}
return R.ok(result);
}
@GetMapping("/public/component/list")
public R<List<WorkflowComponent>> component() {
return R.ok(workflowComponentService.getAllEnable());
}
}

View File

@@ -1,58 +0,0 @@
package org.ruoyi.workflow.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.workflow.dto.workflow.WfRuntimeNodeDto;
import org.ruoyi.workflow.dto.workflow.WfRuntimeResp;
import org.ruoyi.workflow.dto.workflow.WorkflowResumeReq;
import org.ruoyi.workflow.service.WorkflowRuntimeService;
import org.ruoyi.workflow.workflow.WorkflowStarter;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/workflow/runtime")
@Validated
public class WorkflowRuntimeController {
@Resource
private WorkflowRuntimeService workflowRuntimeService;
@Resource
private WorkflowStarter workflowStarter;
@Operation(summary = "接收用户输入以继续执行剩余流程")
@PostMapping(value = "/resume/{runtimeUuid}")
public R resume(@PathVariable String runtimeUuid, @RequestBody WorkflowResumeReq resumeReq) {
workflowStarter.resumeFlow(runtimeUuid, resumeReq.getFeedbackContent());
return R.ok();
}
@GetMapping("/page")
public R<Page<WfRuntimeResp>> search(@RequestParam String wfUuid,
@NotNull @Min(1) Integer currentPage,
@NotNull @Min(10) Integer pageSize) {
return R.ok(workflowRuntimeService.page(wfUuid, currentPage, pageSize));
}
@GetMapping("/nodes/{runtimeUuid}")
public R<List<WfRuntimeNodeDto>> listByRuntimeId(@PathVariable String runtimeUuid) {
return R.ok(workflowRuntimeService.listByRuntimeUuid(runtimeUuid));
}
@PostMapping("/clear")
public R<Boolean> clear(@RequestParam(defaultValue = "") String wfUuid) {
return R.ok(workflowRuntimeService.deleteAll(wfUuid));
}
@PostMapping("/del/{wfRuntimeUuid}")
public R<Boolean> delete(@PathVariable String wfRuntimeUuid) {
return R.ok(workflowRuntimeService.softDelete(wfRuntimeUuid));
}
}

View File

@@ -1,45 +0,0 @@
package org.ruoyi.workflow.controller.admin;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.workflow.dto.workflow.WfComponentReq;
import org.ruoyi.workflow.dto.workflow.WfComponentSearchReq;
import org.ruoyi.workflow.entity.WorkflowComponent;
import org.ruoyi.workflow.service.WorkflowComponentService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/admin/workflow/component")
@Validated
public class AdminWorkflowComponentController {
@Resource
private WorkflowComponentService workflowComponentService;
@PostMapping("/search")
public R<Page<WorkflowComponent>> search(@RequestBody WfComponentSearchReq searchReq, @NotNull @Min(1) Integer currentPage, @NotNull @Min(10) Integer pageSize) {
return R.ok(workflowComponentService.search(searchReq, currentPage, pageSize));
}
@PostMapping("/enable")
public R enable(@RequestParam String uuid, @RequestParam Boolean isEnable) {
workflowComponentService.enable(uuid, isEnable);
return R.ok();
}
@PostMapping("/del/{uuid}")
public R del(@PathVariable String uuid) {
workflowComponentService.deleteByUuid(uuid);
return R.ok();
}
@PostMapping("/addOrUpdate")
public R<WorkflowComponent> addOrUpdate(@Validated @RequestBody WfComponentReq req) {
return R.ok(workflowComponentService.addOrUpdate(req));
}
}

View File

@@ -1,35 +0,0 @@
package org.ruoyi.workflow.controller.admin;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.workflow.dto.workflow.WfSearchReq;
import org.ruoyi.workflow.dto.workflow.WorkflowResp;
import org.ruoyi.workflow.service.WorkflowService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/admin/workflow")
@Validated
public class AdminWorkflowController {
@Resource
private WorkflowService workflowService;
@PostMapping("/search")
public R<Page<WorkflowResp>> search(@RequestBody WfSearchReq req,
@RequestParam @NotNull @Min(1) Integer currentPage,
@RequestParam @NotNull @Min(10) Integer pageSize) {
return R.ok(workflowService.search(req.getTitle(), req.getIsPublic(),
req.getIsEnable(), currentPage, pageSize));
}
@PostMapping("/enable")
public R enable(@RequestParam String uuid, @RequestParam Boolean isEnable) {
workflowService.enable(uuid, isEnable);
return R.ok();
}
}

View File

@@ -0,0 +1,67 @@
package org.ruoyi.workflow.domain;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.ruoyi.common.tenant.core.TenantEntity;
import java.io.Serial;
import java.util.ArrayList;
import java.util.List;
/**
* 流程分类对象 wf_category
*
* @author may
* @date 2023-06-27
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("flow_category")
public class FlowCategory extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 流程分类ID
*/
@TableId(value = "category_id")
private Long categoryId;
/**
* 父流程分类id
*/
private Long parentId;
/**
* 祖级列表
*/
private String ancestors;
/**
* 流程分类名称
*/
private String categoryName;
/**
* 显示顺序
*/
private Long orderNum;
/**
* 删除标志0代表存在 1代表删除
*/
@TableLogic
private String delFlag;
/**
* 子菜单
*/
@TableField(exist = false)
private List<FlowCategory> children = new ArrayList<>();
}

View File

@@ -0,0 +1,59 @@
package org.ruoyi.workflow.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.ruoyi.common.tenant.core.TenantEntity;
import java.io.Serial;
/**
* 流程实例业务扩展对象 flow_instance_biz_ext
*
* @author may
* @date 2025-08-05
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("flow_instance_biz_ext")
public class FlowInstanceBizExt extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(value = "id")
private Long id;
/**
* 流程实例ID
*/
private Long instanceId;
/**
* 业务ID
*/
private String businessId;
/**
* 业务编码
*/
private String businessCode;
/**
* 业务标题
*/
private String businessTitle;
/**
* 删除标志0代表存在 1代表删除
*/
@TableLogic
private String delFlag;
}

View File

@@ -0,0 +1,69 @@
package org.ruoyi.workflow.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.ruoyi.common.mybatis.core.domain.BaseEntity;
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 BaseEntity {
@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;
}

View File

@@ -0,0 +1,68 @@
package org.ruoyi.workflow.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.ruoyi.common.mybatis.core.domain.BaseEntity;
import java.io.Serial;
import java.util.Date;
/**
* 请假对象 test_leave
*
* @author may
* @date 2023-07-21
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("test_leave")
public class TestLeave extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(value = "id")
private Long id;
/**
* 申请编号
*/
private String applyCode;
/**
* 请假类型
*/
private String leaveType;
/**
* 开始时间
*/
private Date startDate;
/**
* 结束时间
*/
private Date endDate;
/**
* 请假天数
*/
private Integer leaveDays;
/**
* 请假原因
*/
private String remark;
/**
* 状态
*/
private String status;
}

View File

@@ -0,0 +1,69 @@
package org.ruoyi.workflow.domain.bo;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.ruoyi.common.core.validate.AddGroup;
import java.io.Serial;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* 驳回参数请求
*
* @author may
*/
@Data
public class BackProcessBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 任务ID
*/
@NotNull(message = "任务ID不能为空", groups = AddGroup.class)
private Long taskId;
/**
* 附件id
*/
private String fileId;
/**
* 消息类型
*/
private List<String> messageType;
/**
* 驳回的节点id(目前未使用,直接驳回到申请人)
*/
private String nodeCode;
/**
* 办理意见
*/
private String message;
/**
* 通知
*/
private String notice;
/**
* 流程变量
*/
private Map<String, Object> variables;
public Map<String, Object> getVariables() {
if (variables == null) {
return new HashMap<>(16);
}
variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue()));
return variables;
}
}

View File

@@ -0,0 +1,85 @@
package org.ruoyi.workflow.domain.bo;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.ruoyi.common.core.validate.AddGroup;
import java.io.Serial;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* 办理任务请求对象
*
* @author may
*/
@Data
public class CompleteTaskBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 任务id
*/
@NotNull(message = "任务id不能为空", groups = {AddGroup.class})
private Long taskId;
/**
* 附件id
*/
private String fileId;
/**
* 抄送人员
*/
private List<FlowCopyBo> flowCopyList;
/**
* 消息类型
*/
private List<String> messageType;
/**
* 办理意见
*/
private String message;
/**
* 消息通知
*/
private String notice;
/**
* 办理人(可不填 用于覆盖当前节点办理人)
*/
private String handler;
/**
* 流程变量
*/
private Map<String, Object> variables;
/**
* 弹窗选择的办理人
*/
private Map<String, Object> assigneeMap;
/**
* 扩展变量(此处为逗号分隔的ossId)
*/
private String ext;
public Map<String, Object> getVariables() {
if (variables == null) {
variables = new HashMap<>(16);
return variables;
}
variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue()));
return variables;
}
}

View File

@@ -0,0 +1,31 @@
package org.ruoyi.workflow.domain.bo;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import org.ruoyi.common.core.validate.AddGroup;
import java.io.Serial;
import java.io.Serializable;
/**
* 撤销任务请求对象
*
* @author may
*/
@Data
public class FlowCancelBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 任务ID
*/
@NotBlank(message = "业务ID不能为空", groups = AddGroup.class)
private String businessId;
/**
* 办理意见
*/
private String message;
}

View File

@@ -0,0 +1,47 @@
package org.ruoyi.workflow.domain.bo;
import io.github.linpeilie.annotations.AutoMapper;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.ruoyi.common.core.validate.AddGroup;
import org.ruoyi.common.core.validate.EditGroup;
import org.ruoyi.common.mybatis.core.domain.BaseEntity;
import org.ruoyi.workflow.domain.FlowCategory;
/**
* 流程分类业务对象 wf_category
*
* @author may
* @date 2023-06-27
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = FlowCategory.class, reverseConvertGenerate = false)
public class FlowCategoryBo extends BaseEntity {
/**
* 流程分类ID
*/
@NotNull(message = "流程分类ID不能为空", groups = { EditGroup.class })
private Long categoryId;
/**
* 父流程分类id
*/
@NotNull(message = "父流程分类id不能为空", groups = {AddGroup.class, EditGroup.class})
private Long parentId;
/**
* 流程分类名称
*/
@NotBlank(message = "流程分类名称不能为空", groups = {AddGroup.class, EditGroup.class})
private String categoryName;
/**
* 显示顺序
*/
private Long orderNum;
}

View File

@@ -0,0 +1,30 @@
package org.ruoyi.workflow.domain.bo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 抄送
*
* @author may
*/
@Data
public class FlowCopyBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 用户id
*/
private Long userId;
/**
* 用户名称
*/
private String userName;
}

View File

@@ -0,0 +1,55 @@
package org.ruoyi.workflow.domain.bo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
* 流程实例请求对象
*
* @author may
*/
@Data
public class FlowInstanceBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 流程定义名称
*/
private String flowName;
/**
* 流程定义编码
*/
private String flowCode;
/**
* 任务发起人
*/
private String startUserId;
/**
* 业务id
*/
private String businessId;
/**
* 流程分类id
*/
private String category;
/**
* 任务名称
*/
private String nodeName;
/**
* 申请人Ids
*/
private List<Long> createByIds;
}

View File

@@ -0,0 +1,31 @@
package org.ruoyi.workflow.domain.bo;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.ruoyi.common.core.validate.AddGroup;
import java.io.Serial;
import java.io.Serializable;
/**
* 作废请求对象
*
* @author may
*/
@Data
public class FlowInvalidBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 流程实例id
*/
@NotNull(message = "流程实例id为空", groups = AddGroup.class)
private Long id;
/**
* 审批意见
*/
private String comment;
}

View File

@@ -0,0 +1,38 @@
package org.ruoyi.workflow.domain.bo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* 下一节点信息
*
* @author may
*/
@Data
public class FlowNextNodeBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 任务id
*/
private Long taskId;
/**
* 流程变量
*/
private Map<String, Object> variables;
public Map<String, Object> getVariables() {
if (variables == null) {
return new HashMap<>(16);
}
variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue()));
return variables;
}
}

View File

@@ -0,0 +1,60 @@
package org.ruoyi.workflow.domain.bo;
import org.ruoyi.common.mybatis.core.domain.BaseEntity;
import org.ruoyi.common.core.validate.AddGroup;
import org.ruoyi.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
import org.ruoyi.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;
/**
* 组件名称
*/
private String componentName;
/**
* 方法名
*/
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;
}

View File

@@ -0,0 +1,55 @@
package org.ruoyi.workflow.domain.bo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
* 任务请求对象
*
* @author may
*/
@Data
public class FlowTaskBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 任务名称
*/
private String nodeName;
/**
* 流程定义名称
*/
private String flowName;
/**
* 流程定义编码
*/
private String flowCode;
/**
* 流程分类id
*/
private String category;
/**
* 流程实例id
*/
private Long instanceId;
/**
* 权限列表
*/
private List<String> permissionList;
/**
* 申请人Ids
*/
private List<Long> createByIds;
}

View File

@@ -0,0 +1,31 @@
package org.ruoyi.workflow.domain.bo;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.ruoyi.common.core.validate.AddGroup;
import java.io.Serial;
import java.io.Serializable;
/**
* 终止任务请求对象
*
* @author may
*/
@Data
public class FlowTerminationBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 任务id
*/
@NotNull(message = "任务id为空", groups = AddGroup.class)
private Long taskId;
/**
* 审批意见
*/
private String comment;
}

View File

@@ -0,0 +1,38 @@
package org.ruoyi.workflow.domain.bo;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.ruoyi.common.core.validate.AddGroup;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
* 流程变量参数
*
* @author may
*/
@Data
public class FlowUrgeTaskBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 任务id
*/
@NotNull(message = "任务id为空", groups = AddGroup.class)
private List<Long> taskIdList;
/**
* 消息类型
*/
private List<String> messageType;
/**
* 催办内容
*/
@NotNull(message = "催办内容为空", groups = AddGroup.class)
private String message;
}

View File

@@ -0,0 +1,39 @@
package org.ruoyi.workflow.domain.bo;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.ruoyi.common.core.validate.AddGroup;
import java.io.Serial;
import java.io.Serializable;
/**
* 流程变量参数
*
* @author may
*/
@Data
public class FlowVariableBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 流程实例id
*/
@NotNull(message = "流程实例id为空", groups = AddGroup.class)
private Long instanceId;
/**
* 流程变量key
*/
@NotNull(message = "流程变量key为空", groups = AddGroup.class)
private String key;
/**
* 流程变量value
*/
@NotNull(message = "流程变量value为空", groups = AddGroup.class)
private String value;
}

View File

@@ -0,0 +1,68 @@
package org.ruoyi.workflow.domain.bo;
import cn.hutool.core.util.ObjectUtil;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import org.ruoyi.common.core.validate.AddGroup;
import org.ruoyi.workflow.domain.FlowInstanceBizExt;
import java.io.Serial;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* 启动流程对象
*
* @author may
*/
@Data
public class StartProcessBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 业务唯一值id
*/
@NotBlank(message = "业务ID不能为空", groups = {AddGroup.class})
private String businessId;
/**
* 流程定义编码
*/
@NotBlank(message = "流程定义编码不能为空", groups = {AddGroup.class})
private String flowCode;
/**
* 办理人(可不填 用于覆盖当前节点办理人)
*/
private String handler;
/**
* 流程变量,前端会提交一个元素{'entity': {业务详情数据对象}}
*/
private Map<String, Object> variables;
/**
* 流程业务扩展信息
*/
private FlowInstanceBizExt bizExt;
public Map<String, Object> getVariables() {
if (variables == null) {
return new HashMap<>(16);
}
variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue()));
return variables;
}
public FlowInstanceBizExt getBizExt() {
if (ObjectUtil.isNull(bizExt)) {
bizExt = new FlowInstanceBizExt();
}
return bizExt;
}
}

View File

@@ -0,0 +1,48 @@
package org.ruoyi.workflow.domain.bo;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.ruoyi.common.core.validate.AddGroup;
import org.ruoyi.common.core.validate.EditGroup;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
* 任务操作业务对象,用于描述任务委派、转办、加签等操作的必要参数
* 包含了用户ID、任务ID、任务相关的消息、以及加签/减签的用户ID
*
* @author AprilWind
*/
@Data
public class TaskOperationBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 委派/转办人的用户ID必填准对委派/转办人操作)
*/
@NotNull(message = "委派/转办人id不能为空", groups = {AddGroup.class})
private String userId;
/**
* 加签/减签人的用户ID列表必填针对加签/减签操作)
*/
@NotNull(message = "加签/减签id不能为空", groups = {EditGroup.class})
private List<String> userIds;
/**
* 任务ID必填
*/
@NotNull(message = "任务id不能为空")
private Long taskId;
/**
* 意见或备注信息(可选)
*/
private String message;
}

View File

@@ -0,0 +1,92 @@
package org.ruoyi.workflow.domain.bo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.github.linpeilie.annotations.AutoMapper;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.ruoyi.common.core.validate.AddGroup;
import org.ruoyi.common.core.validate.EditGroup;
import org.ruoyi.common.mybatis.core.domain.BaseEntity;
import org.ruoyi.workflow.domain.TestLeave;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
* 请假业务对象 test_leave
*
* @author may
* @date 2023-07-21
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = TestLeave.class, reverseConvertGenerate = false)
public class TestLeaveBo extends BaseEntity {
/**
* 主键
*/
@NotNull(message = "主键不能为空", groups = {EditGroup.class})
private Long id;
/**
* 流程code
*/
private String flowCode;
/**
* 申请编号
*/
private String applyCode;
/**
* 请假类型
*/
@NotBlank(message = "请假类型不能为空", groups = {AddGroup.class, EditGroup.class})
private String leaveType;
/**
* 开始时间
*/
@NotNull(message = "开始时间不能为空", groups = {AddGroup.class, EditGroup.class})
@DateTimeFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date startDate;
/**
* 结束时间
*/
@NotNull(message = "结束时间不能为空", groups = {AddGroup.class, EditGroup.class})
@DateTimeFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date endDate;
/**
* 请假天数
*/
private Integer leaveDays;
/**
* 开始时间
*/
private Integer startLeaveDays;
/**
* 结束时间
*/
private Integer endLeaveDays;
/**
* 请假原因
*/
private String remark;
/**
* 状态
*/
private String status;
}

View File

@@ -0,0 +1,43 @@
package org.ruoyi.workflow.domain.vo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 按钮权限
*
* @author may
* @date 2025-02-28
*/
@Data
public class ButtonPermissionVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 唯一编码
*/
private String code;
/**
* 选项值
*/
private String value;
/**
* 是否显示
*/
private Boolean show;
public ButtonPermissionVo() {
}
public ButtonPermissionVo(String code, Boolean show) {
this.code = code;
this.show = show;
}
}

View File

@@ -0,0 +1,69 @@
package org.ruoyi.workflow.domain.vo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.ruoyi.common.translation.annotation.Translation;
import org.ruoyi.workflow.common.constant.FlowConstant;
import org.ruoyi.workflow.domain.FlowCategory;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 流程分类视图对象 wf_category
*
* @author may
* @date 2023-06-27
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = FlowCategory.class)
public class FlowCategoryVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 流程分类ID
*/
@ExcelProperty(value = "流程分类ID")
private Long categoryId;
/**
* 父级分类id
*/
private Long parentId;
/**
* 父级分类名称
*/
@Translation(type = FlowConstant.CATEGORY_ID_TO_NAME, mapper = "parentId")
private String parentName;
/**
* 祖级列表
*/
private String ancestors;
/**
* 流程分类名称
*/
@ExcelProperty(value = "流程分类名称")
private String categoryName;
/**
* 显示顺序
*/
@ExcelProperty(value = "显示顺序")
private Long orderNum;
/**
* 创建时间
*/
@ExcelProperty(value = "创建时间")
private Date createTime;
}

View File

@@ -0,0 +1,36 @@
package org.ruoyi.workflow.domain.vo;
import lombok.Data;
import org.ruoyi.common.translation.annotation.Translation;
import org.ruoyi.common.translation.constant.TransConstant;
import java.io.Serial;
import java.io.Serializable;
/**
* 抄送对象
*
* @author AprilWind
*/
@Data
public class FlowCopyVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 用户id
*/
private Long userId;
/**
* 用户名称
*/
@Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "userId")
private String userName;
public FlowCopyVo(Long userId) {
this.userId = userId;
}
}

View File

@@ -0,0 +1,104 @@
package org.ruoyi.workflow.domain.vo;
import lombok.Data;
import org.ruoyi.common.translation.annotation.Translation;
import org.ruoyi.workflow.common.constant.FlowConstant;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 流程定义视图
*
* @author may
*/
@Data
public class FlowDefinitionVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private Long id;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
/**
* 租户ID
*/
private String tenantId;
/**
* 删除标记
*/
private String delFlag;
/**
* 流程定义编码
*/
private String flowCode;
/**
* 流程定义名称
*/
private String flowName;
/**
* 流程分类id
*/
private String category;
/**
* 流程分类名称
*/
@Translation(type = FlowConstant.CATEGORY_ID_TO_NAME, mapper = "category")
private String categoryName;
/**
* 流程版本
*/
private String version;
/**
* 是否发布0未发布 1已发布 9失效
*/
private Integer isPublish;
/**
* 审批表单是否自定义Y是 N否
*/
private String formCustom;
/**
* 审批表单路径
*/
private String formPath;
/**
* 流程激活状态0挂起 1激活
*/
private Integer activityStatus;
/**
* 监听器类型
*/
private String listenerType;
/**
* 监听器路径
*/
private String listenerPath;
/**
* 扩展字段,预留给业务系统使用
*/
private String ext;
}

View File

@@ -0,0 +1,256 @@
package org.ruoyi.workflow.domain.vo;
import lombok.Data;
import org.ruoyi.common.core.utils.DateUtils;
import org.ruoyi.common.translation.annotation.Translation;
import org.ruoyi.common.translation.constant.TransConstant;
import org.dromara.warm.flow.core.enums.CooperateType;
import org.ruoyi.workflow.common.constant.FlowConstant;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* 历史任务视图
*
* @author may
*/
@Data
public class FlowHisTaskVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private Long id;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
/**
* 租户ID
*/
private String tenantId;
/**
* 删除标记
*/
private String delFlag;
/**
* 对应flow_definition表的id
*/
private Long definitionId;
/**
* 流程定义名称
*/
private String flowName;
/**
* 流程实例表id
*/
private Long instanceId;
/**
* 任务表id
*/
private Long taskId;
/**
* 协作方式(1审批 2转办 3委派 4会签 5票签 6加签 7减签)
*/
private Integer cooperateType;
/**
* 协作方式(1审批 2转办 3委派 4会签 5票签 6加签 7减签)
*/
private String cooperateTypeName;
/**
* 业务id
*/
private String businessId;
/**
* 开始节点编码
*/
private String nodeCode;
/**
* 开始节点名称
*/
private String nodeName;
/**
* 开始节点类型0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关
*/
private Integer nodeType;
/**
* 目标节点编码
*/
private String targetNodeCode;
/**
* 结束节点名称
*/
private String targetNodeName;
/**
* 审批者
*/
private String approver;
/**
* 审批者
*/
@Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "approver")
private String approveName;
/**
* 协作人(只有转办、会签、票签、委派)
*/
private String collaborator;
/**
* 权限标识 permissionFlag的list形式
*/
private List<String> permissionList;
/**
* 跳转类型PASS通过 REJECT退回 NONE无动作
*/
private String skipType;
/**
* 流程状态
*/
private String flowStatus;
/**
* 任务状态
*/
private String flowTaskStatus;
/**
* 流程状态
*/
private String flowStatusName;
/**
* 审批意见
*/
private String message;
/**
* 业务详情 存业务类的json
*/
private String ext;
/**
* 创建者
*/
private String createBy;
/**
* 申请人
*/
@Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "createBy")
private String createByName;
/**
* 流程分类id
*/
private String category;
/**
* 流程分类名称
*/
@Translation(type = FlowConstant.CATEGORY_ID_TO_NAME, mapper = "category")
private String categoryName;
/**
* 审批表单是否自定义Y是 N否
*/
private String formCustom;
/**
* 审批表单路径
*/
private String formPath;
/**
* 流程定义编码
*/
private String flowCode;
/**
* 流程版本号
*/
private String version;
/**
* 运行时长
*/
private String runDuration;
//业务扩展信息开始
/**
* 业务编码
*/
private String businessCode;
/**
* 业务标题
*/
private String businessTitle;
//业务扩展信息结束
/**
* 设置创建时间并计算任务运行时长
*
* @param createTime 创建时间
*/
public void setCreateTime(Date createTime) {
this.createTime = createTime;
updateRunDuration();
}
/**
* 设置更新时间并计算任务运行时长
*
* @param updateTime 更新时间
*/
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
updateRunDuration();
}
/**
* 更新运行时长
*/
private void updateRunDuration() {
// 如果创建时间和更新时间均不为空,计算它们之间的时长
if (this.updateTime != null && this.createTime != null) {
this.runDuration = DateUtils.getTimeDifference(this.updateTime, this.createTime);
}
}
/**
* 设置协作方式,并通过协作方式获取名称
*/
public void setCooperateType(Integer cooperateType) {
this.cooperateType = cooperateType;
this.cooperateTypeName = CooperateType.getValueByKey(cooperateType);
}
}

View File

@@ -0,0 +1,149 @@
package org.ruoyi.workflow.domain.vo;
import lombok.Data;
import org.ruoyi.common.translation.annotation.Translation;
import org.ruoyi.common.translation.constant.TransConstant;
import org.ruoyi.workflow.common.constant.FlowConstant;
import java.util.Date;
/**
* 流程实例视图
*
* @author may
*/
@Data
public class FlowInstanceVo {
private Long id;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
/**
* 租户ID
*/
private String tenantId;
/**
* 删除标记
*/
private String delFlag;
/**
* 对应flow_definition表的id
*/
private Long definitionId;
/**
* 流程定义名称
*/
private String flowName;
/**
* 流程定义编码
*/
private String flowCode;
/**
* 业务id
*/
private String businessId;
/**
* 节点类型0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关
*/
private Integer nodeType;
/**
* 流程节点编码 每个流程的nodeCode是唯一的,即definitionId+nodeCode唯一,在数据库层面做了控制
*/
private String nodeCode;
/**
* 流程节点名称
*/
private String nodeName;
/**
* 流程变量
*/
private String variable;
/**
* 流程状态0待提交 1审批中 2 审批通过 3自动通过 8已完成 9已退回 10失效
*/
private String flowStatus;
/**
* 流程状态
*/
private String flowStatusName;
/**
* 流程激活状态0挂起 1激活
*/
private Integer activityStatus;
/**
* 审批表单是否自定义Y是 N否
*/
private String formCustom;
/**
* 审批表单路径
*/
private String formPath;
/**
* 扩展字段,预留给业务系统使用
*/
private String ext;
/**
* 流程定义版本
*/
private String version;
/**
* 创建者
*/
private String createBy;
/**
* 申请人
*/
@Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "createBy")
private String createByName;
/**
* 流程分类id
*/
private String category;
/**
* 流程分类名称
*/
@Translation(type = FlowConstant.CATEGORY_ID_TO_NAME, mapper = "category")
private String categoryName;
//业务扩展信息开始
/**
* 业务编码
*/
private String businessCode;
/**
* 业务标题
*/
private String businessTitle;
//业务扩展信息结束
}

View File

@@ -0,0 +1,79 @@
package org.ruoyi.workflow.domain.vo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import org.ruoyi.common.excel.annotation.ExcelDictFormat;
import org.ruoyi.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.ruoyi.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;
}

View File

@@ -0,0 +1,215 @@
package org.ruoyi.workflow.domain.vo;
import lombok.Data;
import org.ruoyi.common.translation.annotation.Translation;
import org.ruoyi.common.translation.constant.TransConstant;
import org.dromara.warm.flow.core.entity.User;
import org.ruoyi.workflow.common.constant.FlowConstant;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* 任务视图
*
* @author may
*/
@Data
public class FlowTaskVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private Long id;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
/**
* 租户ID
*/
private String tenantId;
/**
* 删除标记
*/
private String delFlag;
/**
* 对应flow_definition表的id
*/
private Long definitionId;
/**
* 流程实例表id
*/
private Long instanceId;
/**
* 流程定义名称
*/
private String flowName;
/**
* 业务id
*/
private String businessId;
/**
* 节点编码
*/
private String nodeCode;
/**
* 节点名称
*/
private String nodeName;
/**
* 节点类型0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关
*/
private Integer nodeType;
/**
* 权限标识 permissionFlag的list形式
*/
private List<String> permissionList;
/**
* 流程用户列表
*/
private List<User> userList;
/**
* 审批表单是否自定义Y是 N否
*/
private String formCustom;
/**
* 审批表单
*/
private String formPath;
/**
* 流程定义编码
*/
private String flowCode;
/**
* 流程版本号
*/
private String version;
/**
* 流程状态
*/
private String flowStatus;
/**
* 流程分类id
*/
private String category;
/**
* 流程分类名称
*/
@Translation(type = FlowConstant.CATEGORY_ID_TO_NAME, mapper = "category")
private String categoryName;
/**
* 流程状态
*/
@Translation(type = TransConstant.DICT_TYPE_TO_LABEL, mapper = "flowStatus", other = "wf_business_status")
private String flowStatusName;
/**
* 办理人类型
*/
private String type;
/**
* 办理人ids
*/
private String assigneeIds;
/**
* 办理人名称
*/
@Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "assigneeIds")
private String assigneeNames;
/**
* 抄送人id
*/
private String processedBy;
/**
* 抄送人名称
*/
@Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "processedBy")
private String processedByName;
/**
* 流程签署比例值 大于0为票签会签
*/
private BigDecimal nodeRatio;
/**
* 申请人id
*/
private String createBy;
/**
* 申请人名称
*/
@Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "createBy")
private String createByName;
/**
* 是否为申请人节点
*/
private Boolean applyNode;
/**
* 按钮权限
*/
private List<ButtonPermissionVo> buttonList;
/**
* 抄送对象 ID 集合
* <p>
* 根据扩展属性中 CopySettingEnum 类型的数据生成,存储需要抄送的对象 ID
*/
private List<FlowCopyVo> copyList;
/**
* 自定义参数 Map
* <p>
* 根据扩展属性中 VariablesEnum 类型的数据生成,存储 key=value 格式的自定义参数
*/
private Map<String, String> varList;
//业务扩展信息开始
/**
* 业务编码
*/
private String businessCode;
/**
* 业务标题
*/
private String businessTitle;
//业务扩展信息结束
}

View File

@@ -0,0 +1,45 @@
package org.ruoyi.workflow.domain.vo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Node 扩展属性解析结果 VO
* <p>
* 用于封装从扩展属性 JSON 中解析出的各类信息,包括按钮权限、抄送对象和自定义参数。
*
* @author AprilWind
*/
@Data
public class NodeExtVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 按钮权限列表
* <p>
* 根据扩展属性中 ButtonPermissionEnum 类型的数据生成,每个元素表示一个按钮及其是否勾选。
*/
private List<ButtonPermissionVo> buttonPermissions;
/**
* 抄送对象 ID 集合
* <p>
* 根据扩展属性中 CopySettingEnum 类型的数据生成,存储需要抄送的对象 ID
*/
private Set<String> copySettings;
/**
* 自定义参数 Map
* <p>
* 根据扩展属性中 VariablesEnum 类型的数据生成,存储 key=value 格式的自定义参数
*/
private Map<String, String> variables;
}

Some files were not shown because too many files have changed in this diff Show More