first commit
This commit is contained in:
3
template/ruoyi-modules/ruoyi-workflow/README.md
Normal file
3
template/ruoyi-modules/ruoyi-workflow/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# 工作流说明
|
||||
|
||||
工作流目前在未成熟阶段 后续仍会经历重构 甚至重写(生产使用前请慎重考虑后续是否要更新维护)
|
||||
119
template/ruoyi-modules/ruoyi-workflow/pom.xml
Normal file
119
template/ruoyi-modules/ruoyi-workflow/pom.xml
Normal file
@@ -0,0 +1,119 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-modules</artifactId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<packaging>jar</packaging>
|
||||
<artifactId>ruoyi-workflow</artifactId>
|
||||
|
||||
<description>
|
||||
工作流模块
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!--引入flowable依赖-->
|
||||
<dependency>
|
||||
<groupId>org.flowable</groupId>
|
||||
<artifactId>flowable-spring-boot-autoconfigure</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.flowable</groupId>
|
||||
<artifactId>flowable-spring-security</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.flowable</groupId>
|
||||
<artifactId>flowable-spring-configurator</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.flowable</groupId>
|
||||
<artifactId>flowable-spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 绘制flowable流程图 -->
|
||||
<dependency>
|
||||
<groupId>org.flowable</groupId>
|
||||
<artifactId>flowable-image-generator</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- flowable json 转换 -->
|
||||
<dependency>
|
||||
<groupId>org.flowable</groupId>
|
||||
<artifactId>flowable-json-converter</artifactId>
|
||||
<version>6.8.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- svg转png图片工具-->
|
||||
<dependency>
|
||||
<groupId>org.apache.xmlgraphics</groupId>
|
||||
<artifactId>batik-all</artifactId>
|
||||
<version>1.17</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>xalan</groupId>
|
||||
<artifactId>xalan</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-websocket</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-mail</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-sms</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-mybatis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-log</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-idempotent</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-excel</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-translation</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-tenant</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-security</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
package org.dromara.workflow.common.constant;
|
||||
|
||||
|
||||
/**
|
||||
* 工作流常量
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
public interface FlowConstant {
|
||||
|
||||
String MESSAGE_CURRENT_TASK_IS_NULL = "当前任务不存在或你不是任务办理人!";
|
||||
|
||||
String MESSAGE_SUSPENDED = "当前任务已挂起不可审批!";
|
||||
|
||||
/**
|
||||
* 连线
|
||||
*/
|
||||
String SEQUENCE_FLOW = "sequenceFlow";
|
||||
|
||||
/**
|
||||
* 并行网关
|
||||
*/
|
||||
String PARALLEL_GATEWAY = "parallelGateway";
|
||||
|
||||
/**
|
||||
* 排它网关
|
||||
*/
|
||||
String EXCLUSIVE_GATEWAY = "exclusiveGateway";
|
||||
|
||||
/**
|
||||
* 包含网关
|
||||
*/
|
||||
String INCLUSIVE_GATEWAY = "inclusiveGateway";
|
||||
|
||||
/**
|
||||
* 结束节点
|
||||
*/
|
||||
String END_EVENT = "endEvent";
|
||||
|
||||
|
||||
/**
|
||||
* 流程委派标识
|
||||
*/
|
||||
String PENDING = "PENDING";
|
||||
|
||||
/**
|
||||
* 候选人标识
|
||||
*/
|
||||
String CANDIDATE = "candidate";
|
||||
|
||||
/**
|
||||
* 会签任务总数
|
||||
*/
|
||||
String NUMBER_OF_INSTANCES = "nrOfInstances";
|
||||
|
||||
/**
|
||||
* 正在执行的会签总数
|
||||
*/
|
||||
String NUMBER_OF_ACTIVE_INSTANCES = "nrOfActiveInstances";
|
||||
|
||||
/**
|
||||
* 已完成的会签任务总数
|
||||
*/
|
||||
String NUMBER_OF_COMPLETED_INSTANCES = "nrOfCompletedInstances";
|
||||
|
||||
/**
|
||||
* 循环的索引值,可以使用elementIndexVariable属性修改loopCounter的变量名
|
||||
*/
|
||||
String LOOP_COUNTER = "loopCounter";
|
||||
|
||||
String ZIP = "ZIP";
|
||||
|
||||
/**
|
||||
* 业务与流程实例关联对象
|
||||
*/
|
||||
String BUSINESS_INSTANCE_DTO = "businessInstanceDTO";
|
||||
|
||||
/**
|
||||
* 流程定义配置
|
||||
*/
|
||||
String WF_DEFINITION_CONFIG_VO = "wfDefinitionConfigVo";
|
||||
|
||||
/**
|
||||
* 节点配置
|
||||
*/
|
||||
String WF_NODE_CONFIG_VO = "wfNodeConfigVo";
|
||||
|
||||
/**
|
||||
* 流程发起人
|
||||
*/
|
||||
String INITIATOR = "initiator";
|
||||
|
||||
/**
|
||||
* 流程实例id
|
||||
*/
|
||||
String PROCESS_INSTANCE_ID = "processInstanceId";
|
||||
|
||||
/**
|
||||
* 业务id
|
||||
*/
|
||||
String BUSINESS_KEY = "businessKey";
|
||||
|
||||
/**
|
||||
* 流程定义id
|
||||
*/
|
||||
String PROCESS_DEFINITION_ID = "processDefinitionId";
|
||||
|
||||
/**
|
||||
* 开启跳过表达式变量
|
||||
*/
|
||||
String FLOWABLE_SKIP_EXPRESSION_ENABLED = "_FLOWABLE_SKIP_EXPRESSION_ENABLED";
|
||||
|
||||
/**
|
||||
* 模型标识key命名规范正则表达式
|
||||
*/
|
||||
String MODEL_KEY_PATTERN = "^[a-zA-Z][a-zA-Z0-9_]{0,254}$";
|
||||
|
||||
/**
|
||||
* 用户任务
|
||||
*/
|
||||
String USER_TASK = "userTask";
|
||||
|
||||
/**
|
||||
* 会签
|
||||
*/
|
||||
String MULTI_INSTANCE = "multiInstance";
|
||||
|
||||
/**
|
||||
* 是
|
||||
*/
|
||||
String TRUE = "0";
|
||||
|
||||
/**
|
||||
* 否
|
||||
*/
|
||||
String FALSE = "1";
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package org.dromara.workflow.common.enums;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 任务状态枚举
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum FormTypeEnum {
|
||||
/**
|
||||
* 自定义表单
|
||||
*/
|
||||
STATIC("static", "自定义表单"),
|
||||
/**
|
||||
* 动态表单
|
||||
*/
|
||||
DYNAMIC("dynamic", "动态表单");
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private final String type;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private final String desc;
|
||||
|
||||
/**
|
||||
* 表单类型
|
||||
*
|
||||
* @param formType 表单类型
|
||||
*/
|
||||
public static String findByType(String formType) {
|
||||
if (StringUtils.isBlank(formType)) {
|
||||
return StrUtil.EMPTY;
|
||||
}
|
||||
|
||||
return Arrays.stream(FormTypeEnum.values())
|
||||
.filter(statusEnum -> statusEnum.getType().equals(formType))
|
||||
.findFirst()
|
||||
.map(FormTypeEnum::getDesc)
|
||||
.orElse(StrUtil.EMPTY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package org.dromara.workflow.common.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 消息类型枚举
|
||||
*
|
||||
* @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 final static Map<String, MessageTypeEnum> MESSAGE_TYPE_ENUM_MAP = new ConcurrentHashMap<>(MessageTypeEnum.values().length);
|
||||
|
||||
static {
|
||||
for (MessageTypeEnum messageType : MessageTypeEnum.values()) {
|
||||
MESSAGE_TYPE_ENUM_MAP.put(messageType.code, messageType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据消息类型 code 获取 MessageTypeEnum
|
||||
* @param code 消息类型code
|
||||
* @return MessageTypeEnum
|
||||
*/
|
||||
public static MessageTypeEnum getByCode(String code) {
|
||||
return MESSAGE_TYPE_ENUM_MAP.get(code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
package org.dromara.workflow.common.enums;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 任务状态枚举
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum TaskStatusEnum {
|
||||
/**
|
||||
* 撤销
|
||||
*/
|
||||
CANCEL("cancel", "撤销"),
|
||||
/**
|
||||
* 通过
|
||||
*/
|
||||
PASS("pass", "通过"),
|
||||
/**
|
||||
* 待审核
|
||||
*/
|
||||
WAITING("waiting", "待审核"),
|
||||
/**
|
||||
* 作废
|
||||
*/
|
||||
INVALID("invalid", "作废"),
|
||||
/**
|
||||
* 退回
|
||||
*/
|
||||
BACK("back", "退回"),
|
||||
/**
|
||||
* 终止
|
||||
*/
|
||||
TERMINATION("termination", "终止"),
|
||||
/**
|
||||
* 转办
|
||||
*/
|
||||
TRANSFER("transfer", "转办"),
|
||||
/**
|
||||
* 委托
|
||||
*/
|
||||
PENDING("pending", "委托"),
|
||||
/**
|
||||
* 抄送
|
||||
*/
|
||||
COPY("copy", "抄送"),
|
||||
/**
|
||||
* 加签
|
||||
*/
|
||||
SIGN("sign", "加签"),
|
||||
/**
|
||||
* 减签
|
||||
*/
|
||||
SIGN_OFF("sign_off", "减签"),
|
||||
/**
|
||||
* 超时
|
||||
*/
|
||||
TIMEOUT("timeout", "超时");
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private final String status;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private final String desc;
|
||||
|
||||
/**
|
||||
* 任务业务状态
|
||||
*
|
||||
* @param status 状态
|
||||
*/
|
||||
public static String findByStatus(String status) {
|
||||
if (StringUtils.isBlank(status)) {
|
||||
return StrUtil.EMPTY;
|
||||
}
|
||||
|
||||
return Arrays.stream(TaskStatusEnum.values())
|
||||
.filter(statusEnum -> statusEnum.getStatus().equals(status))
|
||||
.findFirst()
|
||||
.map(TaskStatusEnum::getDesc)
|
||||
.orElse(StrUtil.EMPTY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
package org.dromara.workflow.controller;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
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.idempotent.annotation.RepeatSubmit;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.workflow.domain.bo.ModelBo;
|
||||
import org.dromara.workflow.domain.vo.ModelVo;
|
||||
import org.dromara.workflow.service.IActModelService;
|
||||
import org.flowable.engine.RepositoryService;
|
||||
import org.flowable.engine.repository.Model;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 模型管理 控制层
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/workflow/model")
|
||||
public class ActModelController extends BaseController {
|
||||
|
||||
@Autowired(required = false)
|
||||
private RepositoryService repositoryService;
|
||||
private final IActModelService actModelService;
|
||||
|
||||
|
||||
/**
|
||||
* 分页查询模型
|
||||
*
|
||||
* @param modelBo 模型参数
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<Model> page(ModelBo modelBo, PageQuery pageQuery) {
|
||||
return actModelService.page(modelBo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增模型
|
||||
*
|
||||
* @param modelBo 模型请求对象
|
||||
*/
|
||||
@Log(title = "模型管理", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/save")
|
||||
public R<Void> saveNewModel(@Validated(AddGroup.class) @RequestBody ModelBo modelBo) {
|
||||
return toAjax(actModelService.saveNewModel(modelBo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询模型
|
||||
*
|
||||
* @param id 模型id
|
||||
*/
|
||||
@GetMapping("/getInfo/{id}")
|
||||
public R<ModelVo> getInfo(@NotBlank(message = "模型id不能为空") @PathVariable String id) {
|
||||
return R.ok(actModelService.getInfo(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改模型信息
|
||||
*
|
||||
* @param modelBo 模型数据
|
||||
*/
|
||||
@Log(title = "模型管理", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping(value = "/update")
|
||||
public R<Void> update(@RequestBody ModelBo modelBo) {
|
||||
return toAjax(actModelService.update(modelBo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑XMl模型
|
||||
*
|
||||
* @param modelBo 模型数据
|
||||
*/
|
||||
@Log(title = "模型管理", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping(value = "/editModelXml")
|
||||
public R<Void> editModel(@Validated(EditGroup.class) @RequestBody ModelBo modelBo) {
|
||||
return toAjax(actModelService.editModelXml(modelBo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除流程模型
|
||||
*
|
||||
* @param ids 模型id
|
||||
*/
|
||||
@Log(title = "模型管理", businessType = BusinessType.DELETE)
|
||||
@RepeatSubmit()
|
||||
@DeleteMapping("/{ids}")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public R<Void> delete(@NotEmpty(message = "主键不能为空") @PathVariable String[] ids) {
|
||||
Arrays.stream(ids).parallel().forEachOrdered(repositoryService::deleteModel);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 模型部署
|
||||
*
|
||||
* @param id 模型id
|
||||
*/
|
||||
@Log(title = "模型管理", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/modelDeploy/{id}")
|
||||
public R<Void> deploy(@NotBlank(message = "模型id不能为空") @PathVariable("id") String id) {
|
||||
return toAjax(actModelService.modelDeploy(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出模型zip压缩包
|
||||
*
|
||||
* @param modelIds 模型id
|
||||
* @param response 相应
|
||||
*/
|
||||
@GetMapping("/export/zip/{modelIds}")
|
||||
public void exportZip(@NotEmpty(message = "模型id不能为空") @PathVariable List<String> modelIds,
|
||||
HttpServletResponse response) {
|
||||
actModelService.exportZip(modelIds, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制模型
|
||||
*
|
||||
* @param modelBo 模型数据
|
||||
*/
|
||||
@PostMapping("/copyModel")
|
||||
public R<Void> copyModel(@RequestBody ModelBo modelBo) {
|
||||
return toAjax(actModelService.copyModel(modelBo));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package org.dromara.workflow.controller;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.workflow.domain.bo.ProcessDefinitionBo;
|
||||
import org.dromara.workflow.domain.vo.ProcessDefinitionVo;
|
||||
import org.dromara.workflow.service.IActProcessDefinitionService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* 流程定义管理 控制层
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/workflow/processDefinition")
|
||||
public class ActProcessDefinitionController extends BaseController {
|
||||
|
||||
private final IActProcessDefinitionService actProcessDefinitionService;
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param bo 参数
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<ProcessDefinitionVo> page(ProcessDefinitionBo bo, PageQuery pageQuery) {
|
||||
return actProcessDefinitionService.page(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询历史流程定义列表
|
||||
*
|
||||
* @param key 流程定义key
|
||||
*/
|
||||
@GetMapping("/getListByKey/{key}")
|
||||
public R<List<ProcessDefinitionVo>> getListByKey(@NotEmpty(message = "流程定义key不能为空") @PathVariable String key) {
|
||||
return R.ok("操作成功", actProcessDefinitionService.getListByKey(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看流程定义图片
|
||||
*
|
||||
* @param processDefinitionId 流程定义id
|
||||
*/
|
||||
@GetMapping("/definitionImage/{processDefinitionId}")
|
||||
public R<String> definitionImage(@PathVariable String processDefinitionId) {
|
||||
return R.ok("操作成功", actProcessDefinitionService.definitionImage(processDefinitionId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看流程定义xml文件
|
||||
*
|
||||
* @param processDefinitionId 流程定义id
|
||||
*/
|
||||
@GetMapping("/definitionXml/{processDefinitionId}")
|
||||
public R<Map<String, Object>> definitionXml(@NotBlank(message = "流程定义id不能为空") @PathVariable String processDefinitionId) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
String xmlStr = actProcessDefinitionService.definitionXml(processDefinitionId);
|
||||
map.put("xml", Arrays.asList(xmlStr.split("\n")));
|
||||
map.put("xmlStr", xmlStr);
|
||||
return R.ok(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除流程定义
|
||||
*
|
||||
* @param deploymentIds 部署id
|
||||
* @param processDefinitionIds 流程定义id
|
||||
*/
|
||||
@Log(title = "流程定义管理", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{deploymentIds}/{processDefinitionIds}")
|
||||
public R<Void> deleteDeployment(@NotNull(message = "流程部署id不能为空") @PathVariable List<String> deploymentIds,
|
||||
@NotNull(message = "流程定义id不能为空") @PathVariable List<String> processDefinitionIds) {
|
||||
return toAjax(actProcessDefinitionService.deleteDeployment(deploymentIds, processDefinitionIds));
|
||||
}
|
||||
|
||||
/**
|
||||
* 激活或者挂起流程定义
|
||||
*
|
||||
* @param processDefinitionId 流程定义id
|
||||
*/
|
||||
@Log(title = "流程定义管理", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping("/updateDefinitionState/{processDefinitionId}")
|
||||
public R<Void> updateDefinitionState(@NotBlank(message = "流程定义id不能为空") @PathVariable String processDefinitionId) {
|
||||
return toAjax(actProcessDefinitionService.updateDefinitionState(processDefinitionId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 迁移流程定义
|
||||
*
|
||||
* @param currentProcessDefinitionId 当前流程定义id
|
||||
* @param fromProcessDefinitionId 需要迁移到的流程定义id
|
||||
*/
|
||||
@Log(title = "流程定义管理", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping("/migrationDefinition/{currentProcessDefinitionId}/{fromProcessDefinitionId}")
|
||||
public R<Void> migrationDefinition(@NotBlank(message = "当前流程定义id") @PathVariable String currentProcessDefinitionId,
|
||||
@NotBlank(message = "需要迁移到的流程定义id") @PathVariable String fromProcessDefinitionId) {
|
||||
return toAjax(actProcessDefinitionService.migrationDefinition(currentProcessDefinitionId, fromProcessDefinitionId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 流程定义转换为模型
|
||||
*
|
||||
* @param processDefinitionId 流程定义id
|
||||
*/
|
||||
@Log(title = "流程定义管理", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping("/convertToModel/{processDefinitionId}")
|
||||
public R<Void> convertToModel(@NotEmpty(message = "流程定义id不能为空") @PathVariable String processDefinitionId) {
|
||||
return toAjax(actProcessDefinitionService.convertToModel(processDefinitionId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过zip或xml部署流程定义
|
||||
*
|
||||
* @param file 文件
|
||||
* @param categoryCode 分类
|
||||
*/
|
||||
@Log(title = "流程定义管理", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/deployByFile")
|
||||
public void deployByFile(@RequestParam("file") MultipartFile file, @RequestParam("categoryCode") String categoryCode) {
|
||||
actProcessDefinitionService.deployByFile(file, categoryCode);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
package org.dromara.workflow.controller;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.workflow.domain.bo.ProcessInstanceBo;
|
||||
import org.dromara.workflow.domain.bo.ProcessInvalidBo;
|
||||
import org.dromara.workflow.domain.bo.TaskUrgingBo;
|
||||
import org.dromara.workflow.domain.vo.ActHistoryInfoVo;
|
||||
import org.dromara.workflow.domain.vo.ProcessInstanceVo;
|
||||
import org.dromara.workflow.service.IActProcessInstanceService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 流程实例管理 控制层
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/workflow/processInstance")
|
||||
public class ActProcessInstanceController extends BaseController {
|
||||
|
||||
private final IActProcessInstanceService actProcessInstanceService;
|
||||
|
||||
/**
|
||||
* 分页查询正在运行的流程实例
|
||||
*
|
||||
* @param bo 参数
|
||||
*/
|
||||
@GetMapping("/getPageByRunning")
|
||||
public TableDataInfo<ProcessInstanceVo> getPageByRunning(ProcessInstanceBo bo, PageQuery pageQuery) {
|
||||
return actProcessInstanceService.getPageByRunning(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询已结束的流程实例
|
||||
*
|
||||
* @param bo 参数
|
||||
*/
|
||||
@GetMapping("/getPageByFinish")
|
||||
public TableDataInfo<ProcessInstanceVo> getPageByFinish(ProcessInstanceBo bo, PageQuery pageQuery) {
|
||||
return actProcessInstanceService.getPageByFinish(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过业务id获取历史流程图
|
||||
*
|
||||
* @param businessKey 业务id
|
||||
*/
|
||||
@GetMapping("/getHistoryImage/{businessKey}")
|
||||
public R<String> getHistoryImage(@NotBlank(message = "业务id不能为空") @PathVariable String businessKey) {
|
||||
return R.ok("操作成功", actProcessInstanceService.getHistoryImage(businessKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过业务id获取历史流程图运行中,历史等节点
|
||||
*
|
||||
* @param businessKey 业务id
|
||||
*/
|
||||
@GetMapping("/getHistoryList/{businessKey}")
|
||||
public R<Map<String, Object>> getHistoryList(@NotBlank(message = "业务id不能为空") @PathVariable String businessKey) {
|
||||
return R.ok("操作成功", actProcessInstanceService.getHistoryList(businessKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取审批记录
|
||||
*
|
||||
* @param businessKey 业务id
|
||||
*/
|
||||
@GetMapping("/getHistoryRecord/{businessKey}")
|
||||
public R<List<ActHistoryInfoVo>> getHistoryRecord(@NotBlank(message = "业务id不能为空") @PathVariable String businessKey) {
|
||||
return R.ok(actProcessInstanceService.getHistoryRecord(businessKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* 作废流程实例,不会删除历史记录(删除运行中的实例)
|
||||
*
|
||||
* @param processInvalidBo 参数
|
||||
*/
|
||||
@Log(title = "流程实例管理", businessType = BusinessType.DELETE)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/deleteRunInstance")
|
||||
public R<Void> deleteRunInstance(@Validated(AddGroup.class) @RequestBody ProcessInvalidBo processInvalidBo) {
|
||||
return toAjax(actProcessInstanceService.deleteRunInstance(processInvalidBo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息
|
||||
*
|
||||
* @param businessKeys 业务id
|
||||
*/
|
||||
@Log(title = "流程实例管理", businessType = BusinessType.DELETE)
|
||||
@RepeatSubmit()
|
||||
@DeleteMapping("/deleteRunAndHisInstance/{businessKeys}")
|
||||
public R<Void> deleteRunAndHisInstance(@NotNull(message = "业务id不能为空") @PathVariable String[] businessKeys) {
|
||||
return toAjax(actProcessInstanceService.deleteRunAndHisInstance(Arrays.asList(businessKeys)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 已完成的实例 删除程实例,删除历史记录,删除业务与流程关联信息
|
||||
*
|
||||
* @param businessKeys 业务id
|
||||
*/
|
||||
@Log(title = "流程实例管理", businessType = BusinessType.DELETE)
|
||||
@RepeatSubmit()
|
||||
@DeleteMapping("/deleteFinishAndHisInstance/{businessKeys}")
|
||||
public R<Void> deleteFinishAndHisInstance(@NotNull(message = "业务id不能为空") @PathVariable String[] businessKeys) {
|
||||
return toAjax(actProcessInstanceService.deleteFinishAndHisInstance(Arrays.asList(businessKeys)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 撤销流程申请
|
||||
*
|
||||
* @param businessKey 业务id
|
||||
*/
|
||||
@Log(title = "流程实例管理", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/cancelProcessApply/{businessKey}")
|
||||
public R<Void> cancelProcessApply(@NotBlank(message = "业务id不能为空") @PathVariable String businessKey) {
|
||||
return toAjax(actProcessInstanceService.cancelProcessApply(businessKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询当前登录人单据
|
||||
*
|
||||
* @param bo 参数
|
||||
*/
|
||||
@GetMapping("/getPageByCurrent")
|
||||
public TableDataInfo<ProcessInstanceVo> getPageByCurrent(ProcessInstanceBo bo, PageQuery pageQuery) {
|
||||
return actProcessInstanceService.getPageByCurrent(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务催办(给当前任务办理人发送站内信,邮件,短信等)
|
||||
*
|
||||
* @param taskUrgingBo 任务催办
|
||||
*/
|
||||
@Log(title = "流程实例管理", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/taskUrging")
|
||||
public R<Void> taskUrging(@RequestBody TaskUrgingBo taskUrgingBo) {
|
||||
return toAjax(actProcessInstanceService.taskUrging(taskUrgingBo));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,295 @@
|
||||
package org.dromara.workflow.controller;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.satoken.utils.LoginHelper;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.workflow.domain.WfTaskBackNode;
|
||||
import org.dromara.workflow.domain.bo.*;
|
||||
import org.dromara.workflow.domain.vo.TaskVo;
|
||||
import org.dromara.workflow.domain.vo.VariableVo;
|
||||
import org.dromara.workflow.service.IActTaskService;
|
||||
import org.dromara.workflow.service.IWfTaskBackNodeService;
|
||||
import org.dromara.workflow.utils.QueryUtils;
|
||||
import org.flowable.engine.TaskService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 任务管理 控制层
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/workflow/task")
|
||||
public class ActTaskController extends BaseController {
|
||||
|
||||
@Autowired(required = false)
|
||||
private TaskService taskService;
|
||||
private final IActTaskService actTaskService;
|
||||
private final IWfTaskBackNodeService wfTaskBackNodeService;
|
||||
|
||||
|
||||
/**
|
||||
* 启动任务
|
||||
*
|
||||
* @param startProcessBo 启动流程参数
|
||||
*/
|
||||
@Log(title = "任务管理", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/startWorkFlow")
|
||||
public R<Map<String, Object>> startWorkFlow(@Validated(AddGroup.class) @RequestBody StartProcessBo startProcessBo) {
|
||||
Map<String, Object> map = actTaskService.startWorkFlow(startProcessBo);
|
||||
return R.ok("提交成功", map);
|
||||
}
|
||||
|
||||
/**
|
||||
* 办理任务
|
||||
*
|
||||
* @param completeTaskBo 办理任务参数
|
||||
*/
|
||||
@Log(title = "任务管理", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/completeTask")
|
||||
public R<Void> completeTask(@Validated(AddGroup.class) @RequestBody CompleteTaskBo completeTaskBo) {
|
||||
return toAjax(actTaskService.completeTask(completeTaskBo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前用户的待办任务
|
||||
*
|
||||
* @param taskBo 参数
|
||||
*/
|
||||
@GetMapping("/getPageByTaskWait")
|
||||
public TableDataInfo<TaskVo> getPageByTaskWait(TaskBo taskBo, PageQuery pageQuery) {
|
||||
return actTaskService.getPageByTaskWait(taskBo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前租户所有待办任务
|
||||
*
|
||||
* @param taskBo 参数
|
||||
*/
|
||||
@GetMapping("/getPageByAllTaskWait")
|
||||
public TableDataInfo<TaskVo> getPageByAllTaskWait(TaskBo taskBo, PageQuery pageQuery) {
|
||||
return actTaskService.getPageByAllTaskWait(taskBo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前用户的已办任务
|
||||
*
|
||||
* @param taskBo 参数
|
||||
*/
|
||||
@GetMapping("/getPageByTaskFinish")
|
||||
public TableDataInfo<TaskVo> getPageByTaskFinish(TaskBo taskBo, PageQuery pageQuery) {
|
||||
return actTaskService.getPageByTaskFinish(taskBo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前用户的抄送
|
||||
*
|
||||
* @param taskBo 参数
|
||||
*/
|
||||
@GetMapping("/getPageByTaskCopy")
|
||||
public TableDataInfo<TaskVo> getPageByTaskCopy(TaskBo taskBo, PageQuery pageQuery) {
|
||||
return actTaskService.getPageByTaskCopy(taskBo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前租户所有已办任务
|
||||
*
|
||||
* @param taskBo 参数
|
||||
*/
|
||||
@GetMapping("/getPageByAllTaskFinish")
|
||||
public TableDataInfo<TaskVo> getPageByAllTaskFinish(TaskBo taskBo, PageQuery pageQuery) {
|
||||
return actTaskService.getPageByAllTaskFinish(taskBo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 签收(拾取)任务
|
||||
*
|
||||
* @param taskId 任务id
|
||||
*/
|
||||
@Log(title = "任务管理", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/claim/{taskId}")
|
||||
public R<Void> claimTask(@NotBlank(message = "任务id不能为空") @PathVariable String taskId) {
|
||||
try {
|
||||
taskService.claim(taskId, Convert.toStr(LoginHelper.getUserId()));
|
||||
return R.ok();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return R.fail("签收任务失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 归还(拾取的)任务
|
||||
*
|
||||
* @param taskId 任务id
|
||||
*/
|
||||
@Log(title = "任务管理", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/returnTask/{taskId}")
|
||||
public R<Void> returnTask(@NotBlank(message = "任务id不能为空") @PathVariable String taskId) {
|
||||
try {
|
||||
taskService.setAssignee(taskId, null);
|
||||
return R.ok();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return R.fail("归还任务失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 委派任务
|
||||
*
|
||||
* @param delegateBo 参数
|
||||
*/
|
||||
@Log(title = "任务管理", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/delegateTask")
|
||||
public R<Void> delegateTask(@Validated({AddGroup.class}) @RequestBody DelegateBo delegateBo) {
|
||||
return toAjax(actTaskService.delegateTask(delegateBo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 终止任务
|
||||
*
|
||||
* @param terminationBo 参数
|
||||
*/
|
||||
@Log(title = "任务管理", businessType = BusinessType.DELETE)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/terminationTask")
|
||||
public R<Void> terminationTask(@RequestBody TerminationBo terminationBo) {
|
||||
return toAjax(actTaskService.terminationTask(terminationBo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 转办任务
|
||||
*
|
||||
* @param transmitBo 参数
|
||||
*/
|
||||
@Log(title = "任务管理", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/transferTask")
|
||||
public R<Void> transferTask(@Validated({AddGroup.class}) @RequestBody TransmitBo transmitBo) {
|
||||
return toAjax(actTaskService.transferTask(transmitBo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 会签任务加签
|
||||
*
|
||||
* @param addMultiBo 参数
|
||||
*/
|
||||
@Log(title = "任务管理", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/addMultiInstanceExecution")
|
||||
public R<Void> addMultiInstanceExecution(@Validated({AddGroup.class}) @RequestBody AddMultiBo addMultiBo) {
|
||||
return toAjax(actTaskService.addMultiInstanceExecution(addMultiBo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 会签任务减签
|
||||
*
|
||||
* @param deleteMultiBo 参数
|
||||
*/
|
||||
@Log(title = "任务管理", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/deleteMultiInstanceExecution")
|
||||
public R<Void> deleteMultiInstanceExecution(@Validated({AddGroup.class}) @RequestBody DeleteMultiBo deleteMultiBo) {
|
||||
return toAjax(actTaskService.deleteMultiInstanceExecution(deleteMultiBo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 驳回审批
|
||||
*
|
||||
* @param backProcessBo 参数
|
||||
*/
|
||||
@Log(title = "任务管理", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/backProcess")
|
||||
public R<String> backProcess(@Validated({AddGroup.class}) @RequestBody BackProcessBo backProcessBo) {
|
||||
return R.ok("操作成功", actTaskService.backProcess(backProcessBo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前任务
|
||||
*
|
||||
* @param taskId 任务id
|
||||
*/
|
||||
@GetMapping("/getTaskById/{taskId}")
|
||||
public R<TaskVo> getTaskById(@PathVariable String taskId) {
|
||||
return R.ok(QueryUtils.getTask(taskId));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 修改任务办理人
|
||||
*
|
||||
* @param taskIds 任务id
|
||||
* @param userId 办理人id
|
||||
*/
|
||||
@Log(title = "任务管理", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping("/updateAssignee/{taskIds}/{userId}")
|
||||
public R<Void> updateAssignee(@PathVariable String[] taskIds, @PathVariable String userId) {
|
||||
return toAjax(actTaskService.updateAssignee(taskIds, userId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询流程变量
|
||||
*
|
||||
* @param taskId 任务id
|
||||
*/
|
||||
@GetMapping("/getInstanceVariable/{taskId}")
|
||||
public R<List<VariableVo>> getProcessInstVariable(@PathVariable String taskId) {
|
||||
return R.ok(actTaskService.getInstanceVariable(taskId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取可驳回得任务节点
|
||||
*
|
||||
* @param processInstanceId 流程实例id
|
||||
*/
|
||||
@GetMapping("/getTaskNodeList/{processInstanceId}")
|
||||
public R<List<WfTaskBackNode>> getNodeList(@PathVariable String processInstanceId) {
|
||||
return R.ok(CollUtil.reverse(wfTaskBackNodeService.getListByInstanceId(processInstanceId)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询工作流任务用户选择加签人员
|
||||
*
|
||||
* @param taskId 任务id
|
||||
*/
|
||||
@GetMapping("/getTaskUserIdsByAddMultiInstance/{taskId}")
|
||||
public R<String> getTaskUserIdsByAddMultiInstance(@PathVariable String taskId) {
|
||||
return R.ok("操作成功", actTaskService.getTaskUserIdsByAddMultiInstance(taskId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询工作流选择减签人员
|
||||
*
|
||||
* @param taskId 任务id
|
||||
*/
|
||||
@GetMapping("/getListByDeleteMultiInstance/{taskId}")
|
||||
public R<List<TaskVo>> getListByDeleteMultiInstance(@PathVariable String taskId) {
|
||||
return R.ok(actTaskService.getListByDeleteMultiInstance(taskId));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package org.dromara.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.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.workflow.domain.bo.TestLeaveBo;
|
||||
import org.dromara.workflow.domain.vo.TestLeaveVo;
|
||||
import org.dromara.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
|
||||
*/
|
||||
@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: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)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package org.dromara.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.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.workflow.domain.bo.WfCategoryBo;
|
||||
import org.dromara.workflow.domain.vo.WfCategoryVo;
|
||||
import org.dromara.workflow.service.IWfCategoryService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 流程分类
|
||||
*
|
||||
* @author may
|
||||
* @date 2023-06-28
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/workflow/category")
|
||||
public class WfCategoryController extends BaseController {
|
||||
|
||||
private final IWfCategoryService wfCategoryService;
|
||||
|
||||
/**
|
||||
* 查询流程分类列表
|
||||
*/
|
||||
@SaCheckPermission("workflow:category:list")
|
||||
@GetMapping("/list")
|
||||
public R<List<WfCategoryVo>> list(WfCategoryBo bo) {
|
||||
List<WfCategoryVo> list = wfCategoryService.queryList(bo);
|
||||
return R.ok(list);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出流程分类列表
|
||||
*/
|
||||
@SaCheckPermission("workflow:category:export")
|
||||
@Log(title = "流程分类", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(WfCategoryBo bo, HttpServletResponse response) {
|
||||
List<WfCategoryVo> list = wfCategoryService.queryList(bo);
|
||||
ExcelUtil.exportExcel(list, "流程分类", WfCategoryVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取流程分类详细信息
|
||||
*
|
||||
* @param id 主键
|
||||
*/
|
||||
@SaCheckPermission("workflow:category:query")
|
||||
@GetMapping("/{id}")
|
||||
public R<WfCategoryVo> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long id) {
|
||||
return R.ok(wfCategoryService.queryById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增流程分类
|
||||
*/
|
||||
@SaCheckPermission("workflow:category:add")
|
||||
@Log(title = "流程分类", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody WfCategoryBo bo) {
|
||||
return toAjax(wfCategoryService.insertByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改流程分类
|
||||
*/
|
||||
@SaCheckPermission("workflow:category:edit")
|
||||
@Log(title = "流程分类", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody WfCategoryBo bo) {
|
||||
return toAjax(wfCategoryService.updateByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除流程分类
|
||||
*
|
||||
* @param ids 主键串
|
||||
*/
|
||||
@SaCheckPermission("workflow:category:remove")
|
||||
@Log(title = "流程分类", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable Long[] ids) {
|
||||
return toAjax(wfCategoryService.deleteWithValidByIds(List.of(ids), true));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package org.dromara.workflow.controller;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import jakarta.validation.constraints.*;
|
||||
import org.dromara.workflow.domain.bo.WfDefinitionConfigBo;
|
||||
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.core.domain.R;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.workflow.domain.vo.WfDefinitionConfigVo;
|
||||
import org.dromara.workflow.service.IWfDefinitionConfigService;
|
||||
|
||||
/**
|
||||
* 流程定义配置
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-03-18
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/workflow/definitionConfig")
|
||||
public class WfDefinitionConfigController extends BaseController {
|
||||
|
||||
private final IWfDefinitionConfigService wfDefinitionConfigService;
|
||||
|
||||
|
||||
/**
|
||||
* 获取流程定义配置详细信息
|
||||
*
|
||||
* @param definitionId 主键
|
||||
*/
|
||||
@GetMapping("/getByDefId/{definitionId}")
|
||||
public R<WfDefinitionConfigVo> getByDefId(@NotBlank(message = "流程定义ID不能为空")
|
||||
@PathVariable String definitionId) {
|
||||
return R.ok(wfDefinitionConfigService.getByDefId(definitionId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增流程定义配置
|
||||
*/
|
||||
@Log(title = "流程定义配置", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/saveOrUpdate")
|
||||
public R<Void> saveOrUpdate(@Validated(AddGroup.class) @RequestBody WfDefinitionConfigBo bo) {
|
||||
return toAjax(wfDefinitionConfigService.saveOrUpdate(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除流程定义配置
|
||||
*
|
||||
* @param ids 主键串
|
||||
*/
|
||||
@Log(title = "流程定义配置", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable Long[] ids) {
|
||||
return toAjax(wfDefinitionConfigService.deleteByIds(List.of(ids)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询流程定义配置排除当前查询的流程定义
|
||||
*
|
||||
* @param tableName 表名
|
||||
* @param definitionId 流程定义id
|
||||
*/
|
||||
@GetMapping("/getByTableNameNotDefId/{tableName}/{definitionId}")
|
||||
public R<List<WfDefinitionConfigVo>> getByTableNameNotDefId(@NotBlank(message = "表名不能为空") @PathVariable String tableName,
|
||||
@NotBlank(message = "流程定义ID不能为空") @PathVariable String definitionId) {
|
||||
return R.ok(wfDefinitionConfigService.getByTableNameNotDefId(tableName, definitionId));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
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.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.workflow.domain.vo.WfFormManageVo;
|
||||
import org.dromara.workflow.domain.bo.WfFormManageBo;
|
||||
import org.dromara.workflow.service.IWfFormManageService;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* 表单管理
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-03-29
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/workflow/formManage")
|
||||
public class WfFormManageController extends BaseController {
|
||||
|
||||
private final IWfFormManageService wfFormManageService;
|
||||
|
||||
/**
|
||||
* 查询表单管理列表
|
||||
*/
|
||||
@SaCheckPermission("workflow:formManage:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<WfFormManageVo> list(WfFormManageBo bo, PageQuery pageQuery) {
|
||||
return wfFormManageService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询表单管理列表
|
||||
*/
|
||||
@SaCheckPermission("workflow:formManage:list")
|
||||
@GetMapping("/list/selectList")
|
||||
public R<List<WfFormManageVo>> selectList() {
|
||||
return R.ok(wfFormManageService.selectList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出表单管理列表
|
||||
*/
|
||||
@SaCheckPermission("workflow:formManage:export")
|
||||
@Log(title = "表单管理", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(WfFormManageBo bo, HttpServletResponse response) {
|
||||
List<WfFormManageVo> list = wfFormManageService.queryList(bo);
|
||||
ExcelUtil.exportExcel(list, "表单管理", WfFormManageVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取表单管理详细信息
|
||||
*
|
||||
* @param id 主键
|
||||
*/
|
||||
@SaCheckPermission("workflow:formManage:query")
|
||||
@GetMapping("/{id}")
|
||||
public R<WfFormManageVo> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long id) {
|
||||
return R.ok(wfFormManageService.queryById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增表单管理
|
||||
*/
|
||||
@SaCheckPermission("workflow:formManage:add")
|
||||
@Log(title = "表单管理", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody WfFormManageBo bo) {
|
||||
return toAjax(wfFormManageService.insertByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改表单管理
|
||||
*/
|
||||
@SaCheckPermission("workflow:formManage:edit")
|
||||
@Log(title = "表单管理", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody WfFormManageBo bo) {
|
||||
return toAjax(wfFormManageService.updateByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除表单管理
|
||||
*
|
||||
* @param ids 主键串
|
||||
*/
|
||||
@SaCheckPermission("workflow:formManage:remove")
|
||||
@Log(title = "表单管理", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable Long[] ids) {
|
||||
return toAjax(wfFormManageService.deleteByIds(List.of(ids)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
package org.dromara.workflow.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 流程实例对象 act_hi_procinst
|
||||
*
|
||||
* @author may
|
||||
* @date 2023-07-22
|
||||
*/
|
||||
@Data
|
||||
@TableName("act_hi_procinst")
|
||||
public class ActHiProcinst implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableId(value = "ID_")
|
||||
private String id;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableField(value = "REV_")
|
||||
private Long rev;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableField(value = "PROC_INST_ID_")
|
||||
private String procInstId;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableField(value = "BUSINESS_KEY_")
|
||||
private String businessKey;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableField(value = "PROC_DEF_ID_")
|
||||
private String procDefId;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableField(value = "START_TIME_")
|
||||
private Date startTime;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableField(value = "END_TIME_")
|
||||
private Date endTime;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableField(value = "DURATION_")
|
||||
private Long duration;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableField(value = "START_USER_ID_")
|
||||
private String startUserId;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableField(value = "START_ACT_ID_")
|
||||
private String startActId;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableField(value = "END_ACT_ID_")
|
||||
private String endActId;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableField(value = "SUPER_PROCESS_INSTANCE_ID_")
|
||||
private String superProcessInstanceId;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableField(value = "DELETE_REASON_")
|
||||
private String deleteReason;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableField(value = "TENANT_ID_")
|
||||
private String tenantId;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableField(value = "NAME_")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableField(value = "CALLBACK_ID_")
|
||||
private String callbackId;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableField(value = "CALLBACK_TYPE_")
|
||||
private String callbackType;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableField(value = "REFERENCE_ID_")
|
||||
private String referenceId;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableField(value = "REFERENCE_TYPE_")
|
||||
private String referenceType;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableField(value = "PROPAGATED_STAGE_INST_ID_")
|
||||
private String propagatedStageInstId;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableField(value = "BUSINESS_STATUS_")
|
||||
private String businessStatus;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
package org.dromara.workflow.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 流程历史任务对象 act_hi_taskinst
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-03-02
|
||||
*/
|
||||
@Data
|
||||
@TableName("act_hi_taskinst")
|
||||
public class ActHiTaskinst implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableId(value = "ID_")
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 版本
|
||||
*/
|
||||
@TableField(value = "REV_")
|
||||
private Long rev;
|
||||
|
||||
/**
|
||||
* 流程定义id
|
||||
*/
|
||||
@TableField(value = "PROC_DEF_ID_")
|
||||
private String procDefId;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableField(value = "TASK_DEF_ID_")
|
||||
private String taskDefId;
|
||||
|
||||
/**
|
||||
* 任务节点id
|
||||
*/
|
||||
@TableField(value = "TASK_DEF_KEY_")
|
||||
private String taskDefKey;
|
||||
|
||||
/**
|
||||
* 流程实例id
|
||||
*/
|
||||
@TableField(value = "PROC_INST_ID_")
|
||||
private String procInstId;
|
||||
|
||||
/**
|
||||
* 流程执行id
|
||||
*/
|
||||
@TableField(value = "EXECUTION_ID")
|
||||
private String executionId;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableField(value = "SCOPE_ID_")
|
||||
private String scopeId;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableField(value = "SUB_SCOPE_ID_")
|
||||
private String subScopeId;
|
||||
|
||||
/**
|
||||
* 先用当前字段标识抄送类型
|
||||
*/
|
||||
@TableField(value = "SCOPE_TYPE_")
|
||||
private String scopeType;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableField(value = "SCOPE_DEFINITION_ID_")
|
||||
private String scopeDefinitionId;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableField(value = "PROPAGATED_STAGE_INST_ID_")
|
||||
private String propagatedStageInstId;
|
||||
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
@TableField(value = "NAME_")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 父级id
|
||||
*/
|
||||
@TableField(value = "PARENT_TASK_ID_")
|
||||
private String parentTaskId;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
@TableField(value = "DESCRIPTION_")
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 办理人
|
||||
*/
|
||||
@TableField(value = "OWNER_")
|
||||
private String owner;
|
||||
|
||||
/**
|
||||
* 办理人
|
||||
*/
|
||||
@TableField(value = "ASSIGNEE_")
|
||||
private String assignee;
|
||||
|
||||
/**
|
||||
* 开始事件
|
||||
*/
|
||||
@TableField(value = "START_TIME_")
|
||||
private Date startTime;
|
||||
|
||||
/**
|
||||
* 认领时间
|
||||
*/
|
||||
@TableField(value = "CLAIM_TIME_")
|
||||
private Date claimTime;
|
||||
|
||||
/**
|
||||
* 结束时间
|
||||
*/
|
||||
@TableField(value = "END_TIME_")
|
||||
private Date endTime;
|
||||
|
||||
/**
|
||||
* 持续时间
|
||||
*/
|
||||
@TableField(value = "DURATION_")
|
||||
private Long duration;
|
||||
|
||||
/**
|
||||
* 删除原因
|
||||
*/
|
||||
@TableField(value = "DELETE_REASON_")
|
||||
private String deleteReason;
|
||||
|
||||
/**
|
||||
* 优先级
|
||||
*/
|
||||
@TableField(value = "PRIORITY_")
|
||||
private Long priority;
|
||||
|
||||
/**
|
||||
* 到期时间
|
||||
*/
|
||||
@TableField(value = "DUE_DATE_")
|
||||
private Date dueDate;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableField(value = "FORM_KEY_")
|
||||
private String formKey;
|
||||
|
||||
/**
|
||||
* 分类
|
||||
*/
|
||||
@TableField(value = "CATEGORY_")
|
||||
private String category;
|
||||
|
||||
/**
|
||||
* 最后修改时间
|
||||
*/
|
||||
@TableField(value = "LAST_UPDATED_TIME_")
|
||||
private Date lastUpdatedTime;
|
||||
|
||||
/**
|
||||
* 租户id
|
||||
*/
|
||||
@TableField(value = "TENANT_ID_")
|
||||
private String tenantId;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package org.dromara.workflow.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.dromara.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 leaveType;
|
||||
|
||||
/**
|
||||
* 开始时间
|
||||
*/
|
||||
private Date startDate;
|
||||
|
||||
/**
|
||||
* 结束时间
|
||||
*/
|
||||
private Date endDate;
|
||||
|
||||
/**
|
||||
* 请假天数
|
||||
*/
|
||||
private Integer leaveDays;
|
||||
|
||||
/**
|
||||
* 请假原因
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private String status;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package org.dromara.workflow.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.dromara.common.tenant.core.TenantEntity;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 流程分类对象 wf_category
|
||||
*
|
||||
* @author may
|
||||
* @date 2023-06-27
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("wf_category")
|
||||
public class WfCategory extends TenantEntity {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@TableId(value = "id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 分类名称
|
||||
*/
|
||||
private String categoryName;
|
||||
|
||||
/**
|
||||
* 分类编码
|
||||
*/
|
||||
private String categoryCode;
|
||||
|
||||
/**
|
||||
* 父级id
|
||||
*/
|
||||
private Long parentId;
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
private Long sortNum;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package org.dromara.workflow.domain;
|
||||
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 流程定义配置对象 wf_definition_config
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-03-18
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("wf_definition_config")
|
||||
public class WfDefinitionConfig extends BaseEntity {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@TableId(value = "id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 表名
|
||||
*/
|
||||
private String tableName;
|
||||
|
||||
/**
|
||||
* 流程定义ID
|
||||
*/
|
||||
private String definitionId;
|
||||
|
||||
/**
|
||||
* 流程KEY
|
||||
*/
|
||||
private String processKey;
|
||||
|
||||
/**
|
||||
* 流程版本
|
||||
*/
|
||||
private Integer version;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* 表单管理对象 wf_form_manage
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-03-29
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("wf_form_manage")
|
||||
public class WfFormManage extends TenantEntity {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@TableId(value = "id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 表单名称
|
||||
*/
|
||||
private String formName;
|
||||
|
||||
/**
|
||||
* 表单类型
|
||||
*/
|
||||
private String formType;
|
||||
|
||||
/**
|
||||
* 路由地址/表单ID
|
||||
*/
|
||||
private String router;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* 节点配置对象 wf_node_config
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-03-30
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("wf_node_config")
|
||||
public class WfNodeConfig extends TenantEntity {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@TableId(value = "id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 表单id
|
||||
*/
|
||||
private Long formId;
|
||||
|
||||
/**
|
||||
* 表单类型
|
||||
*/
|
||||
private String formType;
|
||||
|
||||
/**
|
||||
* 节点名称
|
||||
*/
|
||||
private String nodeName;
|
||||
|
||||
/**
|
||||
* 节点id
|
||||
*/
|
||||
private String nodeId;
|
||||
|
||||
/**
|
||||
* 流程定义id
|
||||
*/
|
||||
private String definitionId;
|
||||
|
||||
/**
|
||||
* 是否为申请人节点 (0是 1否)
|
||||
*/
|
||||
private String applyUserTask;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package org.dromara.workflow.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.dromara.common.tenant.core.TenantEntity;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 节点驳回记录 wf_task_back_node
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-03-13
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("wf_task_back_node")
|
||||
public class WfTaskBackNode extends TenantEntity {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@TableId(value = "id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 实例id
|
||||
*/
|
||||
private String instanceId;
|
||||
|
||||
/**
|
||||
* 节点id
|
||||
*/
|
||||
private String nodeId;
|
||||
|
||||
/**
|
||||
* 节点名称
|
||||
*/
|
||||
private String nodeName;
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
private Integer orderNo;
|
||||
|
||||
/**
|
||||
* 节点类型
|
||||
*/
|
||||
private String taskType;
|
||||
|
||||
/**
|
||||
* 办理人
|
||||
*/
|
||||
private String assignee;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package org.dromara.workflow.domain.bo;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 加签参数请求
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Data
|
||||
public class AddMultiBo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 任务ID
|
||||
*/
|
||||
@NotBlank(message = "任务ID不能为空", groups = AddGroup.class)
|
||||
private String taskId;
|
||||
|
||||
/**
|
||||
* 加签人员id
|
||||
*/
|
||||
@NotEmpty(message = "加签人员不能为空", groups = AddGroup.class)
|
||||
private List<Long> assignees;
|
||||
|
||||
/**
|
||||
* 加签人员名称
|
||||
*/
|
||||
@NotEmpty(message = "加签人员不能为空", groups = AddGroup.class)
|
||||
private List<String> assigneeNames;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package org.dromara.workflow.domain.bo;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* 驳回参数请求
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Data
|
||||
public class BackProcessBo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 任务ID
|
||||
*/
|
||||
@NotBlank(message = "任务ID不能为空", groups = AddGroup.class)
|
||||
private String taskId;
|
||||
|
||||
/**
|
||||
* 消息类型
|
||||
*/
|
||||
private List<String> messageType;
|
||||
|
||||
/**
|
||||
* 驳回的节点id(目前未使用,直接驳回到申请人)
|
||||
*/
|
||||
@NotBlank(message = "驳回的节点不能为空", groups = AddGroup.class)
|
||||
private String targetActivityId;
|
||||
|
||||
/**
|
||||
* 办理意见
|
||||
*/
|
||||
private String message;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package org.dromara.workflow.domain.bo;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.workflow.domain.vo.WfCopy;
|
||||
|
||||
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
|
||||
*/
|
||||
@NotBlank(message = "任务id不能为空", groups = {AddGroup.class})
|
||||
private String taskId;
|
||||
|
||||
/**
|
||||
* 附件id
|
||||
*/
|
||||
private String fileId;
|
||||
|
||||
/**
|
||||
* 抄送人员
|
||||
*/
|
||||
private List<WfCopy> wfCopyList;
|
||||
|
||||
/**
|
||||
* 消息类型
|
||||
*/
|
||||
private List<String> messageType;
|
||||
|
||||
/**
|
||||
* 办理意见
|
||||
*/
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* 流程变量
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.dromara.workflow.domain.bo;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 委派任务请求对象
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Data
|
||||
public class DelegateBo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 委派人id
|
||||
*/
|
||||
@NotBlank(message = "委派人id不能为空", groups = {AddGroup.class})
|
||||
private String userId;
|
||||
|
||||
/**
|
||||
* 委派人名称
|
||||
*/
|
||||
@NotBlank(message = "委派人名称不能为空", groups = {AddGroup.class})
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 任务id
|
||||
*/
|
||||
@NotBlank(message = "任务id不能为空", groups = {AddGroup.class})
|
||||
private String taskId;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package org.dromara.workflow.domain.bo;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 减签参数请求
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Data
|
||||
public class DeleteMultiBo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 任务ID
|
||||
*/
|
||||
@NotBlank(message = "任务ID不能为空", groups = AddGroup.class)
|
||||
private String taskId;
|
||||
|
||||
/**
|
||||
* 减签人员
|
||||
*/
|
||||
@NotEmpty(message = "减签人员不能为空", groups = AddGroup.class)
|
||||
private List<String> taskIds;
|
||||
|
||||
/**
|
||||
* 执行id
|
||||
*/
|
||||
@NotEmpty(message = "执行id不能为空", groups = AddGroup.class)
|
||||
private List<String> executionIds;
|
||||
|
||||
/**
|
||||
* 人员id
|
||||
*/
|
||||
@NotEmpty(message = "减签人员id不能为空", groups = AddGroup.class)
|
||||
private List<Long> assigneeIds;
|
||||
|
||||
/**
|
||||
* 人员名称
|
||||
*/
|
||||
@NotEmpty(message = "减签人员不能为空", groups = AddGroup.class)
|
||||
private List<String> assigneeNames;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package org.dromara.workflow.domain.bo;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import lombok.Data;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.workflow.common.constant.FlowConstant;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 模型请求对象
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Data
|
||||
public class ModelBo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 模型id
|
||||
*/
|
||||
@NotBlank(message = "模型ID不能为空", groups = {EditGroup.class})
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 模型名称
|
||||
*/
|
||||
@NotBlank(message = "模型名称不能为空", groups = {AddGroup.class})
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 模型标识key
|
||||
*/
|
||||
@NotBlank(message = "模型标识key不能为空", groups = {AddGroup.class})
|
||||
@Pattern(regexp = FlowConstant.MODEL_KEY_PATTERN, message = "模型标识key只能字符或者下划线开头", groups = {AddGroup.class})
|
||||
private String key;
|
||||
|
||||
/**
|
||||
* 模型分类
|
||||
*/
|
||||
@NotBlank(message = "模型分类不能为空", groups = {AddGroup.class})
|
||||
private String categoryCode;
|
||||
|
||||
/**
|
||||
* 模型XML
|
||||
*/
|
||||
@NotBlank(message = "模型XML不能为空", groups = {AddGroup.class})
|
||||
private String xml;
|
||||
|
||||
/**
|
||||
* 模型SVG图片
|
||||
*/
|
||||
@NotBlank(message = "模型SVG不能为空", groups = {EditGroup.class})
|
||||
private String svg;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String description;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package org.dromara.workflow.domain.bo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 流程定义请求对象
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Data
|
||||
public class ProcessDefinitionBo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 流程定义名称key
|
||||
*/
|
||||
private String key;
|
||||
|
||||
/**
|
||||
* 流程定义名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 模型分类
|
||||
*/
|
||||
private String categoryCode;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package org.dromara.workflow.domain.bo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 流程实例请求对象
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Data
|
||||
public class ProcessInstanceBo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 流程名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 流程key
|
||||
*/
|
||||
private String key;
|
||||
|
||||
/**
|
||||
* 任务发起人
|
||||
*/
|
||||
private String startUserId;
|
||||
|
||||
/**
|
||||
* 业务id
|
||||
*/
|
||||
private String businessKey;
|
||||
|
||||
/**
|
||||
* 模型分类
|
||||
*/
|
||||
private String categoryCode;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.dromara.workflow.domain.bo;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 流程实例作废请求对象
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Data
|
||||
public class ProcessInvalidBo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 业务id
|
||||
*/
|
||||
@NotBlank(message = "业务id不能为空", groups = {AddGroup.class})
|
||||
private String businessKey;
|
||||
|
||||
/**
|
||||
* 作废原因
|
||||
*/
|
||||
private String deleteReason;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package org.dromara.workflow.domain.bo;
|
||||
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
|
||||
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 businessKey;
|
||||
|
||||
/**
|
||||
* 表名
|
||||
*/
|
||||
@NotBlank(message = "表名不能为空", groups = {AddGroup.class})
|
||||
private String tableName;
|
||||
|
||||
/**
|
||||
* 流程变量,前端会提交一个元素{'entity': {业务详情数据对象}}
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.dromara.workflow.domain.bo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
* 用户加签查询
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Data
|
||||
public class SysUserMultiBo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 人员名称
|
||||
*/
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 人员名称
|
||||
*/
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 部门id
|
||||
*/
|
||||
private String deptId;
|
||||
|
||||
/**
|
||||
* 任务id
|
||||
*/
|
||||
private String taskId;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package org.dromara.workflow.domain.bo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 任务请求对象
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Data
|
||||
public class TaskBo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 流程定义名称
|
||||
*/
|
||||
private String processDefinitionName;
|
||||
|
||||
/**
|
||||
* 流程定义key
|
||||
*/
|
||||
private String processDefinitionKey;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package org.dromara.workflow.domain.bo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 任务催办
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Data
|
||||
public class TaskUrgingBo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 流程实例id
|
||||
*/
|
||||
private String processInstanceId;
|
||||
|
||||
/**
|
||||
* 消息类型
|
||||
*/
|
||||
private List<String> messageType;
|
||||
|
||||
/**
|
||||
* 催办内容(为空默认系统内置信息)
|
||||
*/
|
||||
private String message;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.dromara.workflow.domain.bo;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 终止任务请求对象
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Data
|
||||
public class TerminationBo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 任务id
|
||||
*/
|
||||
@NotBlank(message = "任务id为空", groups = AddGroup.class)
|
||||
private String taskId;
|
||||
|
||||
/**
|
||||
* 审批意见
|
||||
*/
|
||||
private String comment;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package org.dromara.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.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
import org.dromara.workflow.domain.TestLeave;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* 请假类型
|
||||
*/
|
||||
@NotBlank(message = "请假类型不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private String leaveType;
|
||||
|
||||
/**
|
||||
* 开始时间
|
||||
*/
|
||||
@NotNull(message = "开始时间不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date startDate;
|
||||
|
||||
/**
|
||||
* 结束时间
|
||||
*/
|
||||
@NotNull(message = "结束时间不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date endDate;
|
||||
|
||||
/**
|
||||
* 请假天数
|
||||
*/
|
||||
@NotNull(message = "请假天数不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private Integer leaveDays;
|
||||
|
||||
/**
|
||||
* 开始时间
|
||||
*/
|
||||
private Integer startLeaveDays;
|
||||
|
||||
/**
|
||||
* 结束时间
|
||||
*/
|
||||
private Integer endLeaveDays;
|
||||
|
||||
/**
|
||||
* 请假原因
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private String status;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.dromara.workflow.domain.bo;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 终转办务请求对象
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Data
|
||||
public class TransmitBo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 任务id
|
||||
*/
|
||||
@NotBlank(message = "任务id为空", groups = AddGroup.class)
|
||||
private String taskId;
|
||||
|
||||
/**
|
||||
* 转办人id
|
||||
*/
|
||||
@NotBlank(message = "转办人不能为空", groups = AddGroup.class)
|
||||
private String userId;
|
||||
|
||||
/**
|
||||
* 审批意见
|
||||
*/
|
||||
private String comment;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package org.dromara.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.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
import org.dromara.workflow.domain.WfCategory;
|
||||
|
||||
/**
|
||||
* 流程分类业务对象 wf_category
|
||||
*
|
||||
* @author may
|
||||
* @date 2023-06-27
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = WfCategory.class, reverseConvertGenerate = false)
|
||||
public class WfCategoryBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@NotNull(message = "主键不能为空", groups = {EditGroup.class})
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 分类名称
|
||||
*/
|
||||
@NotBlank(message = "分类名称不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private String categoryName;
|
||||
|
||||
/**
|
||||
* 分类编码
|
||||
*/
|
||||
@NotBlank(message = "分类编码不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private String categoryCode;
|
||||
|
||||
/**
|
||||
* 父级id
|
||||
*/
|
||||
@NotNull(message = "父级id不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private Long parentId;
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
private Long sortNum;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.dromara.workflow.domain.bo;
|
||||
|
||||
import org.dromara.workflow.domain.WfDefinitionConfig;
|
||||
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.*;
|
||||
|
||||
/**
|
||||
* 流程定义配置业务对象 wf_form_definition
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-03-18
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = WfDefinitionConfig.class, reverseConvertGenerate = false)
|
||||
public class WfDefinitionConfigBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@NotNull(message = "主键不能为空", groups = {EditGroup.class})
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 表名
|
||||
*/
|
||||
@NotBlank(message = "表名不能为空", groups = {AddGroup.class})
|
||||
private String tableName;
|
||||
|
||||
/**
|
||||
* 流程定义ID
|
||||
*/
|
||||
@NotBlank(message = "流程定义ID不能为空", groups = {AddGroup.class})
|
||||
private String definitionId;
|
||||
|
||||
/**
|
||||
* 流程KEY
|
||||
*/
|
||||
@NotBlank(message = "流程KEY不能为空", groups = {AddGroup.class})
|
||||
private String processKey;
|
||||
|
||||
/**
|
||||
* 流程版本
|
||||
*/
|
||||
@NotNull(message = "流程版本不能为空", groups = {AddGroup.class})
|
||||
private Integer version;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package org.dromara.workflow.domain.bo;
|
||||
|
||||
import org.dromara.workflow.domain.WfFormManage;
|
||||
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.*;
|
||||
|
||||
/**
|
||||
* 表单管理业务对象 wf_form_manage
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-03-29
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = WfFormManage.class, reverseConvertGenerate = false)
|
||||
public class WfFormManageBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@NotNull(message = "主键不能为空", groups = { EditGroup.class })
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 表单名称
|
||||
*/
|
||||
@NotBlank(message = "表单名称不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String formName;
|
||||
|
||||
/**
|
||||
* 表单类型
|
||||
*/
|
||||
@NotBlank(message = "表单类型不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String formType;
|
||||
/**
|
||||
* 路由地址/表单ID
|
||||
*/
|
||||
@NotBlank(message = "路由地址/表单ID不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String router;
|
||||
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package org.dromara.workflow.domain.bo;
|
||||
|
||||
import org.dromara.workflow.domain.WfNodeConfig;
|
||||
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.*;
|
||||
|
||||
/**
|
||||
* 节点配置业务对象 wf_node_config
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-03-30
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = WfNodeConfig.class, reverseConvertGenerate = false)
|
||||
public class WfNodeConfigBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@NotNull(message = "主键不能为空", groups = {EditGroup.class})
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 表单id
|
||||
*/
|
||||
private Long formId;
|
||||
|
||||
/**
|
||||
* 表单类型
|
||||
*/
|
||||
private String formType;
|
||||
|
||||
/**
|
||||
* 节点名称
|
||||
*/
|
||||
@NotBlank(message = "节点名称不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private String nodeName;
|
||||
|
||||
/**
|
||||
* 节点id
|
||||
*/
|
||||
@NotBlank(message = "节点id不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private String nodeId;
|
||||
|
||||
/**
|
||||
* 流程定义id
|
||||
*/
|
||||
@NotBlank(message = "流程定义id不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private String definitionId;
|
||||
|
||||
/**
|
||||
* 是否为申请人节点 (0是 1否)
|
||||
*/
|
||||
@NotBlank(message = "是否为申请人节点不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private String applyUserTask;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package org.dromara.workflow.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import org.dromara.common.translation.annotation.Translation;
|
||||
import org.dromara.common.translation.constant.TransConstant;
|
||||
import org.flowable.engine.task.Attachment;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 流程审批记录视图
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Data
|
||||
public class ActHistoryInfoVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
/**
|
||||
* 任务id
|
||||
*/
|
||||
private String id;
|
||||
/**
|
||||
* 节点id
|
||||
*/
|
||||
private String taskDefinitionKey;
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 流程实例id
|
||||
*/
|
||||
private String processInstanceId;
|
||||
/**
|
||||
* 版本
|
||||
*/
|
||||
private Integer version;
|
||||
/**
|
||||
* 开始时间
|
||||
*/
|
||||
private Date startTime;
|
||||
/**
|
||||
* 结束时间
|
||||
*/
|
||||
private Date endTime;
|
||||
/**
|
||||
* 运行时长
|
||||
*/
|
||||
private String runDuration;
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private String status;
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private String statusName;
|
||||
/**
|
||||
* 办理人id
|
||||
*/
|
||||
private String assignee;
|
||||
|
||||
/**
|
||||
* 办理人名称
|
||||
*/
|
||||
@Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "assignee")
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 办理人id
|
||||
*/
|
||||
private String owner;
|
||||
|
||||
/**
|
||||
* 审批信息id
|
||||
*/
|
||||
private String commentId;
|
||||
|
||||
/**
|
||||
* 审批信息
|
||||
*/
|
||||
private String comment;
|
||||
|
||||
/**
|
||||
* 审批附件
|
||||
*/
|
||||
private List<Attachment> attachmentList;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package org.dromara.workflow.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 节点图形信息
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Data
|
||||
public class GraphicInfoVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
/**
|
||||
* x坐标
|
||||
*/
|
||||
private double x;
|
||||
|
||||
/**
|
||||
* y坐标
|
||||
*/
|
||||
private double y;
|
||||
|
||||
/**
|
||||
* 节点高度
|
||||
*/
|
||||
private double height;
|
||||
|
||||
/**
|
||||
* 节点宽度
|
||||
*/
|
||||
private double width;
|
||||
|
||||
/**
|
||||
* 节点id
|
||||
*/
|
||||
private String nodeId;
|
||||
|
||||
/**
|
||||
* 节点名称
|
||||
*/
|
||||
private String nodeName;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package org.dromara.workflow.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 模型视图对象
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Data
|
||||
public class ModelVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 模型id
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 模型名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 模型标识key
|
||||
*/
|
||||
private String key;
|
||||
|
||||
/**
|
||||
* 模型分类
|
||||
*/
|
||||
private String categoryCode;
|
||||
|
||||
/**
|
||||
* 模型XML
|
||||
*/
|
||||
private String xml;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String description;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package org.dromara.workflow.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 多实例信息
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Data
|
||||
public class MultiInstanceVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 会签类型(串行,并行)
|
||||
*/
|
||||
private Object type;
|
||||
|
||||
/**
|
||||
* 会签人员KEY
|
||||
*/
|
||||
private String assignee;
|
||||
|
||||
/**
|
||||
* 会签人员集合KEY
|
||||
*/
|
||||
private String assigneeList;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package org.dromara.workflow.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 参与者
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Data
|
||||
public class ParticipantVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 组id(角色id)
|
||||
*/
|
||||
private List<Long> groupIds;
|
||||
|
||||
/**
|
||||
* 候选人id(用户id) 当组id不为空时,将组内人员查出放入candidate
|
||||
*/
|
||||
private List<Long> candidate;
|
||||
|
||||
/**
|
||||
* 候选人名称(用户名称) 当组id不为空时,将组内人员查出放入candidateName
|
||||
*/
|
||||
private List<String> candidateName;
|
||||
|
||||
/**
|
||||
* 是否认领标识
|
||||
* 当为空时默认当前任务不需要认领
|
||||
* 当为true时当前任务说明为候选模式并且有人已经认领了任务可以归还,
|
||||
* 当为false时当前任务说明为候选模式该任务未认领,
|
||||
*/
|
||||
private Boolean claim;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package org.dromara.workflow.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 流程定义视图
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Data
|
||||
public class ProcessDefinitionVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 流程定义id
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 流程定义名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 流程定义标识key
|
||||
*/
|
||||
private String key;
|
||||
|
||||
/**
|
||||
* 流程定义版本
|
||||
*/
|
||||
private int version;
|
||||
|
||||
/**
|
||||
* 流程定义挂起或激活 1激活 2挂起
|
||||
*/
|
||||
private int suspensionState;
|
||||
|
||||
/**
|
||||
* 流程xml名称
|
||||
*/
|
||||
private String resourceName;
|
||||
|
||||
/**
|
||||
* 流程图片名称
|
||||
*/
|
||||
private String diagramResourceName;
|
||||
|
||||
/**
|
||||
* 流程部署id
|
||||
*/
|
||||
private String deploymentId;
|
||||
|
||||
/**
|
||||
* 流程部署时间
|
||||
*/
|
||||
private Date deploymentTime;
|
||||
|
||||
/**
|
||||
* 流程定义配置
|
||||
*/
|
||||
private WfDefinitionConfigVo wfDefinitionConfigVo;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package org.dromara.workflow.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 流程实例视图
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Data
|
||||
public class ProcessInstanceVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 流程实例id
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 流程定义id
|
||||
*/
|
||||
private String processDefinitionId;
|
||||
|
||||
/**
|
||||
* 流程定义名称
|
||||
*/
|
||||
private String processDefinitionName;
|
||||
|
||||
/**
|
||||
* 流程定义key
|
||||
*/
|
||||
private String processDefinitionKey;
|
||||
|
||||
/**
|
||||
* 流程定义版本
|
||||
*/
|
||||
private Integer processDefinitionVersion;
|
||||
|
||||
/**
|
||||
* 部署id
|
||||
*/
|
||||
private String deploymentId;
|
||||
|
||||
/**
|
||||
* 业务id
|
||||
*/
|
||||
private String businessKey;
|
||||
|
||||
/**
|
||||
* 是否挂起
|
||||
*/
|
||||
private Boolean isSuspended;
|
||||
|
||||
/**
|
||||
* 租户id
|
||||
*/
|
||||
private String tenantId;
|
||||
|
||||
/**
|
||||
* 启动时间
|
||||
*/
|
||||
private Date startTime;
|
||||
|
||||
/**
|
||||
* 结束时间
|
||||
*/
|
||||
private Date endTime;
|
||||
|
||||
/**
|
||||
* 启动人id
|
||||
*/
|
||||
private String startUserId;
|
||||
|
||||
/**
|
||||
* 流程状态
|
||||
*/
|
||||
private String businessStatus;
|
||||
|
||||
/**
|
||||
* 流程状态
|
||||
*/
|
||||
private String businessStatusName;
|
||||
|
||||
/**
|
||||
* 待办任务集合
|
||||
*/
|
||||
private List<TaskVo> taskVoList;
|
||||
|
||||
/**
|
||||
* 节点配置
|
||||
*/
|
||||
private WfNodeConfigVo wfNodeConfigVo;
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
package org.dromara.workflow.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import org.dromara.common.translation.annotation.Translation;
|
||||
import org.dromara.common.translation.constant.TransConstant;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 任务视图
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Data
|
||||
public class TaskVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 任务id
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 优先级
|
||||
*/
|
||||
private Integer priority;
|
||||
|
||||
/**
|
||||
* 负责此任务的人员的用户id
|
||||
*/
|
||||
private String owner;
|
||||
|
||||
/**
|
||||
* 办理人id
|
||||
*/
|
||||
private Long assignee;
|
||||
|
||||
/**
|
||||
* 办理人
|
||||
*/
|
||||
@Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "assignee")
|
||||
private String assigneeName;
|
||||
|
||||
|
||||
/**
|
||||
* 流程实例id
|
||||
*/
|
||||
private String processInstanceId;
|
||||
|
||||
/**
|
||||
* 执行id
|
||||
*/
|
||||
private String executionId;
|
||||
|
||||
/**
|
||||
* 无用
|
||||
*/
|
||||
private String taskDefinitionId;
|
||||
|
||||
/**
|
||||
* 流程定义id
|
||||
*/
|
||||
private String processDefinitionId;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 已办任务-创建时间
|
||||
*/
|
||||
private Date startTime;
|
||||
|
||||
/**
|
||||
* 结束时间
|
||||
*/
|
||||
private Date endTime;
|
||||
|
||||
/**
|
||||
* 节点id
|
||||
*/
|
||||
private String taskDefinitionKey;
|
||||
|
||||
/**
|
||||
* 任务截止日期
|
||||
*/
|
||||
private Date dueDate;
|
||||
|
||||
/**
|
||||
* 流程类别
|
||||
*/
|
||||
private String category;
|
||||
|
||||
/**
|
||||
* 父级任务id
|
||||
*/
|
||||
private String parentTaskId;
|
||||
|
||||
/**
|
||||
* 租户id
|
||||
*/
|
||||
private String tenantId;
|
||||
|
||||
/**
|
||||
* 认领时间
|
||||
*/
|
||||
private Date claimTime;
|
||||
|
||||
/**
|
||||
* 流程状态
|
||||
*/
|
||||
private String businessStatus;
|
||||
|
||||
/**
|
||||
* 流程状态
|
||||
*/
|
||||
private String businessStatusName;
|
||||
|
||||
/**
|
||||
* 流程定义名称
|
||||
*/
|
||||
private String processDefinitionName;
|
||||
|
||||
/**
|
||||
* 流程定义key
|
||||
*/
|
||||
private String processDefinitionKey;
|
||||
|
||||
/**
|
||||
* 流程定义版本
|
||||
*/
|
||||
private Integer processDefinitionVersion;
|
||||
|
||||
/**
|
||||
* 参与者
|
||||
*/
|
||||
private ParticipantVo participantVo;
|
||||
|
||||
/**
|
||||
* 是否会签
|
||||
*/
|
||||
private Boolean multiInstance;
|
||||
|
||||
/**
|
||||
* 业务id
|
||||
*/
|
||||
private String businessKey;
|
||||
|
||||
/**
|
||||
* 流程定义配置
|
||||
*/
|
||||
private WfDefinitionConfigVo wfDefinitionConfigVo;
|
||||
|
||||
/**
|
||||
* 节点配置
|
||||
*/
|
||||
private WfNodeConfigVo wfNodeConfigVo;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package org.dromara.workflow.domain.vo;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import org.dromara.workflow.domain.TestLeave;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* 请假视图对象 test_leave
|
||||
*
|
||||
* @author may
|
||||
* @date 2023-07-21
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@AutoMapper(target = TestLeave.class)
|
||||
public class TestLeaveVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@ExcelProperty(value = "主键")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 请假类型
|
||||
*/
|
||||
@ExcelProperty(value = "请假类型")
|
||||
private String leaveType;
|
||||
|
||||
/**
|
||||
* 开始时间
|
||||
*/
|
||||
@ExcelProperty(value = "开始时间")
|
||||
private Date startDate;
|
||||
|
||||
/**
|
||||
* 结束时间
|
||||
*/
|
||||
@ExcelProperty(value = "结束时间")
|
||||
private Date endDate;
|
||||
|
||||
/**
|
||||
* 请假天数
|
||||
*/
|
||||
@ExcelProperty(value = "请假天数")
|
||||
private Integer leaveDays;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@ExcelProperty(value = "请假原因")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
@ExcelProperty(value = "状态")
|
||||
private String status;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.dromara.workflow.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 流程变量
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Data
|
||||
public class VariableVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 变量key
|
||||
*/
|
||||
private String key;
|
||||
|
||||
/**
|
||||
* 变量值
|
||||
*/
|
||||
private String value;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package org.dromara.workflow.domain.vo;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import org.dromara.workflow.domain.WfCategory;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
* 流程分类视图对象 wf_category
|
||||
*
|
||||
* @author may
|
||||
* @date 2023-06-27
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@AutoMapper(target = WfCategory.class)
|
||||
public class WfCategoryVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@ExcelProperty(value = "主键")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 分类名称
|
||||
*/
|
||||
@ExcelProperty(value = "分类名称")
|
||||
private String categoryName;
|
||||
|
||||
/**
|
||||
* 分类编码
|
||||
*/
|
||||
@ExcelProperty(value = "分类编码")
|
||||
private String categoryCode;
|
||||
|
||||
/**
|
||||
* 父级id
|
||||
*/
|
||||
@ExcelProperty(value = "父级id")
|
||||
private Long parentId;
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
@ExcelProperty(value = "排序")
|
||||
private Long sortNum;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.dromara.workflow.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 抄送
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Data
|
||||
public class WfCopy implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 用户名称
|
||||
*/
|
||||
private String userName;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package org.dromara.workflow.domain.vo;
|
||||
|
||||
import org.dromara.workflow.domain.WfDefinitionConfig;
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
* 流程定义配置视图对象 wf_definition_config
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-03-18
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@AutoMapper(target = WfDefinitionConfig.class)
|
||||
public class WfDefinitionConfigVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@ExcelProperty(value = "主键")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 表名
|
||||
*/
|
||||
@ExcelProperty(value = "表名")
|
||||
private String tableName;
|
||||
|
||||
/**
|
||||
* 流程定义ID
|
||||
*/
|
||||
@ExcelProperty(value = "流程定义ID")
|
||||
private String definitionId;
|
||||
|
||||
/**
|
||||
* 流程KEY
|
||||
*/
|
||||
@ExcelProperty(value = "流程KEY")
|
||||
private String processKey;
|
||||
|
||||
|
||||
/**
|
||||
* 流程版本
|
||||
*/
|
||||
@ExcelProperty(value = "流程版本")
|
||||
private Integer version;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@ExcelProperty(value = "备注")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 表单管理
|
||||
*/
|
||||
private WfFormManageVo wfFormManageVo;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package org.dromara.workflow.domain.vo;
|
||||
|
||||
import org.dromara.workflow.domain.WfFormManage;
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
* 表单管理视图对象 wf_form_manage
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-03-29
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@AutoMapper(target = WfFormManage.class)
|
||||
public class WfFormManageVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@ExcelProperty(value = "主键")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 表单名称
|
||||
*/
|
||||
@ExcelProperty(value = "表单名称")
|
||||
private String formName;
|
||||
|
||||
/**
|
||||
* 表单类型
|
||||
*/
|
||||
@ExcelProperty(value = "表单类型")
|
||||
private String formType;
|
||||
|
||||
/**
|
||||
* 表单类型名称
|
||||
*/
|
||||
private String formTypeName;
|
||||
|
||||
/**
|
||||
* 路由地址/表单ID
|
||||
*/
|
||||
@ExcelProperty(value = "路由地址/表单ID")
|
||||
private String router;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@ExcelProperty(value = "备注")
|
||||
private String remark;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package org.dromara.workflow.domain.vo;
|
||||
|
||||
import org.dromara.workflow.domain.WfNodeConfig;
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
* 节点配置视图对象 wf_node_config
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-03-30
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@AutoMapper(target = WfNodeConfig.class)
|
||||
public class WfNodeConfigVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@ExcelProperty(value = "主键")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 表单id
|
||||
*/
|
||||
@ExcelProperty(value = "表单id")
|
||||
private Long formId;
|
||||
|
||||
/**
|
||||
* 表单类型
|
||||
*/
|
||||
@ExcelProperty(value = "表单类型")
|
||||
private String formType;
|
||||
|
||||
/**
|
||||
* 节点名称
|
||||
*/
|
||||
@ExcelProperty(value = "节点名称")
|
||||
private String nodeName;
|
||||
|
||||
/**
|
||||
* 节点id
|
||||
*/
|
||||
@ExcelProperty(value = "节点id")
|
||||
private String nodeId;
|
||||
|
||||
/**
|
||||
* 流程定义id
|
||||
*/
|
||||
@ExcelProperty(value = "流程定义id")
|
||||
private String definitionId;
|
||||
|
||||
/**
|
||||
* 是否为申请人节点 (0是 1否)
|
||||
*/
|
||||
@ExcelProperty(value = "是否为申请人节点 (0是 1否)")
|
||||
private String applyUserTask;
|
||||
|
||||
/**
|
||||
* 表单管理
|
||||
*/
|
||||
private WfFormManageVo wfFormManageVo;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package org.dromara.workflow.flowable;
|
||||
|
||||
import org.flowable.bpmn.model.AssociationDirection;
|
||||
import org.flowable.image.impl.DefaultProcessDiagramCanvas;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Line2D;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
|
||||
public class CustomDefaultProcessDiagramCanvas extends DefaultProcessDiagramCanvas {
|
||||
//设置高亮线的颜色 这里我设置成绿色
|
||||
protected static Color HIGHLIGHT_SEQUENCEFLOW_COLOR = Color.GREEN;
|
||||
|
||||
public CustomDefaultProcessDiagramCanvas(int width, int height, int minX, int minY, String imageType, String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader) {
|
||||
super(width, height, minX, minY, imageType, activityFontName, labelFontName, annotationFontName, customClassLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* 画线颜色设置
|
||||
*/
|
||||
public void drawConnection(int[] xPoints, int[] yPoints, boolean conditional, boolean isDefault, String connectionType,
|
||||
AssociationDirection associationDirection, boolean highLighted, double scaleFactor) {
|
||||
|
||||
Paint originalPaint = g.getPaint();
|
||||
Stroke originalStroke = g.getStroke();
|
||||
|
||||
g.setPaint(CONNECTION_COLOR);
|
||||
if (connectionType.equals("association")) {
|
||||
g.setStroke(ASSOCIATION_STROKE);
|
||||
} else if (highLighted) {
|
||||
//设置线的颜色
|
||||
g.setPaint(HIGHLIGHT_SEQUENCEFLOW_COLOR);
|
||||
g.setStroke(HIGHLIGHT_FLOW_STROKE);
|
||||
}
|
||||
|
||||
for (int i = 1; i < xPoints.length; i++) {
|
||||
Integer sourceX = xPoints[i - 1];
|
||||
Integer sourceY = yPoints[i - 1];
|
||||
Integer targetX = xPoints[i];
|
||||
Integer targetY = yPoints[i];
|
||||
Line2D.Double line = new Line2D.Double(sourceX, sourceY, targetX, targetY);
|
||||
g.draw(line);
|
||||
}
|
||||
|
||||
if (isDefault) {
|
||||
Line2D.Double line = new Line2D.Double(xPoints[0], yPoints[0], xPoints[1], yPoints[1]);
|
||||
drawDefaultSequenceFlowIndicator(line, scaleFactor);
|
||||
}
|
||||
|
||||
if (conditional) {
|
||||
Line2D.Double line = new Line2D.Double(xPoints[0], yPoints[0], xPoints[1], yPoints[1]);
|
||||
drawConditionalSequenceFlowIndicator(line, scaleFactor);
|
||||
}
|
||||
|
||||
if (associationDirection == AssociationDirection.ONE || associationDirection == AssociationDirection.BOTH) {
|
||||
Line2D.Double line = new Line2D.Double(xPoints[xPoints.length - 2], yPoints[xPoints.length - 2], xPoints[xPoints.length - 1], yPoints[xPoints.length - 1]);
|
||||
drawArrowHead(line, scaleFactor);
|
||||
}
|
||||
if (associationDirection == AssociationDirection.BOTH) {
|
||||
Line2D.Double line = new Line2D.Double(xPoints[1], yPoints[1], xPoints[0], yPoints[0]);
|
||||
drawArrowHead(line, scaleFactor);
|
||||
}
|
||||
g.setPaint(originalPaint);
|
||||
g.setStroke(originalStroke);
|
||||
}
|
||||
|
||||
/**
|
||||
* 高亮节点设置
|
||||
*/
|
||||
public void drawHighLight(int x, int y, int width, int height) {
|
||||
Paint originalPaint = g.getPaint();
|
||||
Stroke originalStroke = g.getStroke();
|
||||
//设置高亮节点的颜色
|
||||
g.setPaint(HIGHLIGHT_COLOR);
|
||||
g.setStroke(THICK_TASK_BORDER_STROKE);
|
||||
|
||||
RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20);
|
||||
g.draw(rect);
|
||||
|
||||
g.setPaint(originalPaint);
|
||||
g.setStroke(originalStroke);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 高亮节点红色
|
||||
* @param: x
|
||||
* @param: y
|
||||
* @param: width
|
||||
* @param: height
|
||||
* @return: void
|
||||
* @author: gssong
|
||||
* @date: 2022/4/12
|
||||
*/
|
||||
public void drawHighLightRed(int x, int y, int width, int height) {
|
||||
Paint originalPaint = g.getPaint();
|
||||
Stroke originalStroke = g.getStroke();
|
||||
//设置高亮节点的颜色
|
||||
g.setPaint(Color.green);
|
||||
g.setStroke(THICK_TASK_BORDER_STROKE);
|
||||
|
||||
RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20);
|
||||
g.draw(rect);
|
||||
|
||||
g.setPaint(originalPaint);
|
||||
g.setStroke(originalStroke);
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,61 @@
|
||||
package org.dromara.workflow.flowable.cmd;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import org.flowable.common.engine.impl.interceptor.Command;
|
||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager;
|
||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.dromara.workflow.common.constant.FlowConstant.NUMBER_OF_INSTANCES;
|
||||
|
||||
/**
|
||||
* 串行加签
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
public class AddSequenceMultiInstanceCmd implements Command<Void> {
|
||||
|
||||
/**
|
||||
* 执行id
|
||||
*/
|
||||
private final String executionId;
|
||||
|
||||
/**
|
||||
* 会签人员集合KEY
|
||||
*/
|
||||
private final String assigneeList;
|
||||
|
||||
/**
|
||||
* 加签人员
|
||||
*/
|
||||
private final List<Long> assignees;
|
||||
|
||||
public AddSequenceMultiInstanceCmd(String executionId, String assigneeList, List<Long> assignees) {
|
||||
this.executionId = executionId;
|
||||
this.assigneeList = assigneeList;
|
||||
this.assignees = assignees;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void execute(CommandContext commandContext) {
|
||||
ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager();
|
||||
ExecutionEntity entity = executionEntityManager.findById(executionId);
|
||||
// 多实例任务总数加 assignees.size()
|
||||
if (entity.getVariable(NUMBER_OF_INSTANCES) instanceof Integer nrOfInstances) {
|
||||
entity.setVariable(NUMBER_OF_INSTANCES, nrOfInstances + assignees.size());
|
||||
}
|
||||
// 设置流程变量
|
||||
if (entity.getVariable(assigneeList) instanceof List<?> userIds) {
|
||||
CollUtil.addAll(userIds, assignees);
|
||||
Map<String, Object> variables = new HashMap<>(16);
|
||||
variables.put(assigneeList, userIds);
|
||||
entity.setVariables(variables);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package org.dromara.workflow.flowable.cmd;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import org.dromara.common.core.domain.dto.OssDTO;
|
||||
import org.dromara.common.core.service.OssService;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.satoken.utils.LoginHelper;
|
||||
import org.flowable.common.engine.impl.interceptor.Command;
|
||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||
import org.flowable.engine.impl.persistence.entity.AttachmentEntity;
|
||||
import org.flowable.engine.impl.persistence.entity.AttachmentEntityManager;
|
||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 附件上传
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
public class AttachmentCmd implements Command<Boolean> {
|
||||
|
||||
private final String fileId;
|
||||
|
||||
private final String taskId;
|
||||
|
||||
private final String processInstanceId;
|
||||
|
||||
private final OssService ossService;
|
||||
|
||||
public AttachmentCmd(String fileId, String taskId, String processInstanceId, OssService ossService) {
|
||||
this.fileId = fileId;
|
||||
this.taskId = taskId;
|
||||
this.processInstanceId = processInstanceId;
|
||||
this.ossService = ossService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean execute(CommandContext commandContext) {
|
||||
try {
|
||||
if (StringUtils.isNotBlank(fileId)) {
|
||||
List<OssDTO> ossList = ossService.selectByIds(fileId);
|
||||
if (CollUtil.isNotEmpty(ossList)) {
|
||||
for (OssDTO oss : ossList) {
|
||||
AttachmentEntityManager attachmentEntityManager = CommandContextUtil.getAttachmentEntityManager();
|
||||
AttachmentEntity attachmentEntity = attachmentEntityManager.create();
|
||||
attachmentEntity.setRevision(1);
|
||||
attachmentEntity.setUserId(LoginHelper.getUserId().toString());
|
||||
attachmentEntity.setName(oss.getOriginalName());
|
||||
attachmentEntity.setDescription(oss.getOriginalName());
|
||||
attachmentEntity.setType(oss.getFileSuffix());
|
||||
attachmentEntity.setTaskId(taskId);
|
||||
attachmentEntity.setProcessInstanceId(processInstanceId);
|
||||
attachmentEntity.setContentId(oss.getOssId().toString());
|
||||
attachmentEntity.setTime(new Date());
|
||||
attachmentEntityManager.insert(attachmentEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package org.dromara.workflow.flowable.cmd;
|
||||
|
||||
import org.flowable.common.engine.impl.interceptor.Command;
|
||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager;
|
||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 删除执行数据
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
public class DeleteExecutionCmd implements Command<Void>, Serializable {
|
||||
|
||||
/**
|
||||
* 执行id
|
||||
*/
|
||||
private final String executionId;
|
||||
|
||||
public DeleteExecutionCmd(String executionId) {
|
||||
this.executionId = executionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void execute(CommandContext commandContext) {
|
||||
ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager();
|
||||
ExecutionEntity entity = executionEntityManager.findById(executionId);
|
||||
if (entity != null) {
|
||||
executionEntityManager.deleteExecutionAndRelatedData(entity, "", false, false);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package org.dromara.workflow.flowable.cmd;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.dromara.common.core.utils.StreamUtils;
|
||||
import org.flowable.common.engine.impl.interceptor.Command;
|
||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager;
|
||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.dromara.workflow.common.constant.FlowConstant.LOOP_COUNTER;
|
||||
import static org.dromara.workflow.common.constant.FlowConstant.NUMBER_OF_INSTANCES;
|
||||
|
||||
|
||||
/**
|
||||
* 串行减签
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public class DeleteSequenceMultiInstanceCmd implements Command<Void> {
|
||||
|
||||
/**
|
||||
* 当前节点审批人员id
|
||||
*/
|
||||
private final String currentUserId;
|
||||
|
||||
/**
|
||||
* 执行id
|
||||
*/
|
||||
private final String executionId;
|
||||
|
||||
/**
|
||||
* 会签人员集合KEY
|
||||
*/
|
||||
private final String assigneeList;
|
||||
|
||||
/**
|
||||
* 减签人员
|
||||
*/
|
||||
private final List<Long> assignees;
|
||||
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Void execute(CommandContext commandContext) {
|
||||
ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager();
|
||||
ExecutionEntity entity = executionEntityManager.findById(executionId);
|
||||
// 设置流程变量
|
||||
List<Long> userIds = new ArrayList<>();
|
||||
List<Object> variable = (List<Object>) entity.getVariable(assigneeList);
|
||||
for (Object o : variable) {
|
||||
userIds.add(Long.valueOf(o.toString()));
|
||||
}
|
||||
List<Long> userIdList = new ArrayList<>();
|
||||
userIds.forEach(e -> {
|
||||
Long userId = StreamUtils.findFirst(assignees, id -> ObjectUtil.equals(id, e));
|
||||
if (userId == null) {
|
||||
userIdList.add(e);
|
||||
}
|
||||
});
|
||||
// 当前任务执行位置
|
||||
int loopCounterIndex = -1;
|
||||
for (int i = 0; i < userIdList.size(); i++) {
|
||||
Long userId = userIdList.get(i);
|
||||
if (currentUserId.equals(userId.toString())) {
|
||||
loopCounterIndex = i;
|
||||
}
|
||||
}
|
||||
Map<String, Object> variables = new HashMap<>(16);
|
||||
variables.put(NUMBER_OF_INSTANCES, userIdList.size());
|
||||
variables.put(assigneeList, userIdList);
|
||||
variables.put(LOOP_COUNTER, loopCounterIndex);
|
||||
entity.setVariables(variables);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.dromara.workflow.flowable.cmd;
|
||||
|
||||
import org.dromara.common.core.utils.StreamUtils;
|
||||
import org.flowable.common.engine.impl.interceptor.Command;
|
||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager;
|
||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 获取并行网关执行后保留的执行实例数据
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
public class ExecutionChildByExecutionIdCmd implements Command<List<ExecutionEntity>>, Serializable {
|
||||
|
||||
/**
|
||||
* 当前任务执行实例id
|
||||
*/
|
||||
private final String executionId;
|
||||
|
||||
public ExecutionChildByExecutionIdCmd(String executionId) {
|
||||
this.executionId = executionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ExecutionEntity> execute(CommandContext commandContext) {
|
||||
ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager();
|
||||
// 获取当前执行数据
|
||||
ExecutionEntity executionEntity = executionEntityManager.findById(executionId);
|
||||
// 通过当前执行数据的父执行,查询所有子执行数据
|
||||
List<ExecutionEntity> allChildrenExecution =
|
||||
executionEntityManager.collectChildren(executionEntity.getParent());
|
||||
return StreamUtils.filter(allChildrenExecution, e -> !e.isActive());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.dromara.workflow.flowable.cmd;
|
||||
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.flowable.common.engine.impl.interceptor.Command;
|
||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||
import org.flowable.engine.impl.persistence.entity.HistoricProcessInstanceEntity;
|
||||
import org.flowable.engine.impl.persistence.entity.HistoricProcessInstanceEntityManager;
|
||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||
|
||||
/**
|
||||
* 修改流程状态
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
public class UpdateBusinessStatusCmd implements Command<Boolean> {
|
||||
|
||||
private final String processInstanceId;
|
||||
private final String status;
|
||||
|
||||
public UpdateBusinessStatusCmd(String processInstanceId, String status) {
|
||||
this.processInstanceId = processInstanceId;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean execute(CommandContext commandContext) {
|
||||
try {
|
||||
HistoricProcessInstanceEntityManager manager = CommandContextUtil.getHistoricProcessInstanceEntityManager();
|
||||
HistoricProcessInstanceEntity processInstance = manager.findById(processInstanceId);
|
||||
processInstance.setBusinessStatus(status);
|
||||
manager.update(processInstance);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package org.dromara.workflow.flowable.cmd;
|
||||
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.flowable.common.engine.impl.interceptor.Command;
|
||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||
import org.flowable.task.service.HistoricTaskService;
|
||||
import org.flowable.task.service.impl.persistence.entity.HistoricTaskInstanceEntity;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* 修改流程历史
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
public class UpdateHiTaskInstCmd implements Command<Boolean> {
|
||||
|
||||
private final List<String> taskIds;
|
||||
|
||||
private final String processDefinitionId;
|
||||
|
||||
private final String processInstanceId;
|
||||
|
||||
public UpdateHiTaskInstCmd(List<String> taskIds, String processDefinitionId, String processInstanceId) {
|
||||
this.taskIds = taskIds;
|
||||
this.processDefinitionId = processDefinitionId;
|
||||
this.processInstanceId = processInstanceId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean execute(CommandContext commandContext) {
|
||||
try {
|
||||
HistoricTaskService historicTaskService = CommandContextUtil.getHistoricTaskService();
|
||||
for (String taskId : taskIds) {
|
||||
HistoricTaskInstanceEntity historicTask = historicTaskService.getHistoricTask(taskId);
|
||||
if (historicTask != null) {
|
||||
historicTask.setProcessDefinitionId(processDefinitionId);
|
||||
historicTask.setProcessInstanceId(processInstanceId);
|
||||
historicTask.setCreateTime(new Date());
|
||||
CommandContextUtil.getHistoricTaskService().updateHistoricTask(historicTask, true);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package org.dromara.workflow.flowable.config;
|
||||
|
||||
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
|
||||
import org.dromara.workflow.flowable.handler.TaskTimeoutJobHandler;
|
||||
import org.flowable.spring.SpringProcessEngineConfiguration;
|
||||
import org.flowable.spring.boot.EngineConfigurationConfigurer;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
|
||||
/**
|
||||
* flowable配置
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Configuration
|
||||
public class FlowableConfig implements EngineConfigurationConfigurer<SpringProcessEngineConfiguration> {
|
||||
|
||||
@Autowired
|
||||
private GlobalFlowableListener globalFlowableListener;
|
||||
@Autowired
|
||||
private IdentifierGenerator identifierGenerator;
|
||||
|
||||
@Override
|
||||
public void configure(SpringProcessEngineConfiguration processEngineConfiguration) {
|
||||
processEngineConfiguration.setIdGenerator(() -> identifierGenerator.nextId(null).toString());
|
||||
processEngineConfiguration.setEventListeners(Collections.singletonList(globalFlowableListener));
|
||||
processEngineConfiguration.addCustomJobHandler(new TaskTimeoutJobHandler());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
package org.dromara.workflow.flowable.config;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.tenant.helper.TenantHelper;
|
||||
import org.dromara.workflow.common.enums.TaskStatusEnum;
|
||||
import org.dromara.workflow.flowable.handler.TaskTimeoutJobHandler;
|
||||
import org.dromara.workflow.utils.QueryUtils;
|
||||
import org.flowable.bpmn.model.BoundaryEvent;
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.bpmn.model.FlowElement;
|
||||
import org.flowable.common.engine.api.delegate.event.*;
|
||||
import org.flowable.common.engine.impl.cfg.TransactionState;
|
||||
import org.flowable.engine.RepositoryService;
|
||||
import org.flowable.engine.RuntimeService;
|
||||
import org.flowable.engine.TaskService;
|
||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||
import org.flowable.engine.runtime.Execution;
|
||||
import org.flowable.engine.task.Comment;
|
||||
import org.flowable.job.service.TimerJobService;
|
||||
import org.flowable.job.service.impl.persistence.entity.JobEntity;
|
||||
import org.flowable.job.service.impl.persistence.entity.TimerJobEntity;
|
||||
import org.flowable.task.api.Task;
|
||||
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* 引擎调度监听
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Component
|
||||
public class GlobalFlowableListener implements FlowableEventListener {
|
||||
|
||||
@Autowired
|
||||
@Lazy
|
||||
private TaskService taskService;
|
||||
|
||||
@Autowired
|
||||
@Lazy
|
||||
private RuntimeService runtimeService;
|
||||
|
||||
@Autowired
|
||||
@Lazy
|
||||
private RepositoryService repositoryService;
|
||||
|
||||
@Value("${flowable.async-executor-activate}")
|
||||
private boolean asyncExecutorActivate;
|
||||
|
||||
@Override
|
||||
public void onEvent(FlowableEvent flowableEvent) {
|
||||
if (flowableEvent instanceof FlowableEngineEvent flowableEngineEvent) {
|
||||
FlowableEngineEventType engineEventType = (FlowableEngineEventType) flowableEvent.getType();
|
||||
switch (engineEventType) {
|
||||
case JOB_EXECUTION_SUCCESS -> jobExecutionSuccess((FlowableEngineEntityEvent) flowableEngineEvent);
|
||||
case TASK_DUEDATE_CHANGED, TASK_CREATED -> {
|
||||
FlowableEntityEvent flowableEntityEvent = (FlowableEntityEvent) flowableEngineEvent;
|
||||
Object entityObject = flowableEntityEvent.getEntity();
|
||||
TaskEntity task = (TaskEntity) entityObject;
|
||||
if (asyncExecutorActivate && task.getDueDate() != null && task.getDueDate().after(new Date())) {
|
||||
//删除之前已经存在的定时任务
|
||||
TimerJobService timerJobService = CommandContextUtil.getTimerJobService();
|
||||
List<TimerJobEntity> timerJobEntityList = timerJobService.findTimerJobsByProcessInstanceId(task.getProcessInstanceId());
|
||||
if (!CollUtil.isEmpty(timerJobEntityList)) {
|
||||
for (TimerJobEntity timerJobEntity : timerJobEntityList) {
|
||||
String taskId = timerJobEntity.getJobHandlerConfiguration();
|
||||
if (task.getId().equals(taskId)) {
|
||||
timerJobService.deleteTimerJob(timerJobEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
//创建job对象
|
||||
TimerJobEntity timer = timerJobService.createTimerJob();
|
||||
timer.setTenantId(TenantHelper.getTenantId());
|
||||
//设置job类型
|
||||
timer.setJobType(JobEntity.JOB_TYPE_TIMER);
|
||||
timer.setJobHandlerType(TaskTimeoutJobHandler.TYPE);
|
||||
timer.setDuedate(task.getDueDate());
|
||||
timer.setProcessInstanceId(task.getProcessInstanceId());
|
||||
//设置任务id
|
||||
timer.setJobHandlerConfiguration(task.getId());
|
||||
//保存并触发事件
|
||||
timerJobService.scheduleTimerJob(timer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFailOnException() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFireOnTransactionLifecycleEvent() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOnTransaction() {
|
||||
return TransactionState.COMMITTED.name();
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理边界定时事件自动审批记录
|
||||
*
|
||||
* @param event 事件
|
||||
*/
|
||||
protected void jobExecutionSuccess(FlowableEngineEntityEvent event) {
|
||||
if (event != null && StringUtils.isNotBlank(event.getExecutionId())) {
|
||||
Execution execution = runtimeService.createExecutionQuery().executionId(event.getExecutionId()).singleResult();
|
||||
if (execution != null) {
|
||||
BpmnModel bpmnModel = repositoryService.getBpmnModel(event.getProcessDefinitionId());
|
||||
FlowElement flowElement = bpmnModel.getFlowElement(execution.getActivityId());
|
||||
if (flowElement instanceof BoundaryEvent) {
|
||||
String attachedToRefId = ((BoundaryEvent) flowElement).getAttachedToRefId();
|
||||
List<Execution> list = runtimeService.createExecutionQuery().activityId(attachedToRefId).list();
|
||||
for (Execution ex : list) {
|
||||
Task task = QueryUtils.taskQuery().executionId(ex.getId()).singleResult();
|
||||
if (task != null) {
|
||||
List<Comment> taskComments = taskService.getTaskComments(task.getId());
|
||||
if (CollUtil.isEmpty(taskComments)) {
|
||||
taskService.addComment(task.getId(), task.getProcessInstanceId(), TaskStatusEnum.PASS.getStatus(), "超时自动审批!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package org.dromara.workflow.flowable.handler;
|
||||
|
||||
import org.dromara.common.core.domain.event.ProcessEvent;
|
||||
import org.dromara.common.core.domain.event.ProcessTaskEvent;
|
||||
import org.dromara.common.core.utils.SpringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 流程监听服务
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-06-02
|
||||
*/
|
||||
@Component
|
||||
public class FlowProcessEventHandler {
|
||||
|
||||
/**
|
||||
* 总体流程监听(例如: 提交 退回 撤销 终止 作废等)
|
||||
*
|
||||
* @param key 流程key
|
||||
* @param businessKey 业务id
|
||||
* @param status 状态
|
||||
* @param submit 当为true时为申请人节点办理
|
||||
*/
|
||||
public void processHandler(String key, String businessKey, String status, boolean submit) {
|
||||
ProcessEvent processEvent = new ProcessEvent();
|
||||
processEvent.setKey(key);
|
||||
processEvent.setBusinessKey(businessKey);
|
||||
processEvent.setStatus(status);
|
||||
processEvent.setSubmit(submit);
|
||||
SpringUtils.context().publishEvent(processEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行办理任务监听
|
||||
*
|
||||
* @param key 流程key
|
||||
* @param taskDefinitionKey 审批节点key
|
||||
* @param taskId 任务id
|
||||
* @param businessKey 业务id
|
||||
*/
|
||||
public void processTaskHandler(String key, String taskDefinitionKey, String taskId, String businessKey) {
|
||||
ProcessTaskEvent processTaskEvent = new ProcessTaskEvent();
|
||||
processTaskEvent.setKey(key);
|
||||
processTaskEvent.setTaskDefinitionKey(taskDefinitionKey);
|
||||
processTaskEvent.setTaskId(taskId);
|
||||
processTaskEvent.setBusinessKey(businessKey);
|
||||
SpringUtils.context().publishEvent(processTaskEvent);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.dromara.workflow.flowable.handler;
|
||||
|
||||
import org.dromara.workflow.common.enums.TaskStatusEnum;
|
||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||
import org.flowable.engine.TaskService;
|
||||
import org.flowable.engine.impl.jobexecutor.TimerEventHandler;
|
||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||
import org.flowable.job.service.JobHandler;
|
||||
import org.flowable.job.service.impl.persistence.entity.JobEntity;
|
||||
import org.flowable.task.api.Task;
|
||||
import org.flowable.variable.api.delegate.VariableScope;
|
||||
|
||||
/**
|
||||
* 办理超时(过期)任务
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
public class TaskTimeoutJobHandler extends TimerEventHandler implements JobHandler {
|
||||
|
||||
public static final String TYPE = "taskTimeout";
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(JobEntity job, String configuration, VariableScope variableScope, CommandContext commandContext) {
|
||||
TaskService taskService = CommandContextUtil.getProcessEngineConfiguration(commandContext)
|
||||
.getTaskService();
|
||||
Task task = taskService.createTaskQuery().taskId(configuration).singleResult();
|
||||
if (task != null) {
|
||||
taskService.addComment(task.getId(), task.getProcessInstanceId(), TaskStatusEnum.TIMEOUT.getStatus(), "超时自动审批!");
|
||||
taskService.complete(configuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.dromara.workflow.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
import org.dromara.workflow.domain.ActHiProcinst;
|
||||
|
||||
/**
|
||||
* 流程实例Mapper接口
|
||||
*
|
||||
* @author may
|
||||
* @date 2023-07-22
|
||||
*/
|
||||
@InterceptorIgnore(tenantLine = "true")
|
||||
public interface ActHiProcinstMapper extends BaseMapperPlus<ActHiProcinst, ActHiProcinst> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.dromara.workflow.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
|
||||
import org.dromara.workflow.domain.ActHiTaskinst;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
|
||||
/**
|
||||
* 流程历史任务Mapper接口
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-03-02
|
||||
*/
|
||||
@InterceptorIgnore(tenantLine = "true")
|
||||
public interface ActHiTaskinstMapper extends BaseMapperPlus<ActHiTaskinst, ActHiTaskinst> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package org.dromara.workflow.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
import org.dromara.workflow.domain.vo.TaskVo;
|
||||
|
||||
|
||||
/**
|
||||
* 任务信息Mapper接口
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-03-02
|
||||
*/
|
||||
@InterceptorIgnore(tenantLine = "true")
|
||||
public interface ActTaskMapper extends BaseMapperPlus<TaskVo, TaskVo> {
|
||||
/**
|
||||
* 获取待办信息
|
||||
*
|
||||
* @param page 分页
|
||||
* @param queryWrapper 条件
|
||||
* @return 结果
|
||||
*/
|
||||
Page<TaskVo> getTaskWaitByPage(@Param("page") Page<TaskVo> page, @Param(Constants.WRAPPER) Wrapper<TaskVo> queryWrapper);
|
||||
|
||||
/**
|
||||
* 获取已办
|
||||
*
|
||||
* @param page 分页
|
||||
* @param queryWrapper 条件
|
||||
* @return 结果
|
||||
*/
|
||||
Page<TaskVo> getTaskFinishByPage(@Param("page") Page<TaskVo> page, @Param(Constants.WRAPPER) Wrapper<TaskVo> queryWrapper);
|
||||
|
||||
/**
|
||||
* 查询当前用户的抄送
|
||||
*
|
||||
* @param page 分页
|
||||
* @param queryWrapper 条件
|
||||
* @return 结果
|
||||
*/
|
||||
Page<TaskVo> getTaskCopyByPage(@Param("page") Page<TaskVo> page, @Param(Constants.WRAPPER) QueryWrapper<TaskVo> queryWrapper);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.dromara.workflow.mapper;
|
||||
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
import org.dromara.workflow.domain.TestLeave;
|
||||
import org.dromara.workflow.domain.vo.TestLeaveVo;
|
||||
|
||||
/**
|
||||
* 请假Mapper接口
|
||||
*
|
||||
* @author may
|
||||
* @date 2023-07-21
|
||||
*/
|
||||
public interface TestLeaveMapper extends BaseMapperPlus<TestLeave, TestLeaveVo> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.dromara.workflow.mapper;
|
||||
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
import org.dromara.workflow.domain.WfCategory;
|
||||
import org.dromara.workflow.domain.vo.WfCategoryVo;
|
||||
|
||||
/**
|
||||
* 流程分类Mapper接口
|
||||
*
|
||||
* @author may
|
||||
* @date 2023-06-27
|
||||
*/
|
||||
public interface WfCategoryMapper extends BaseMapperPlus<WfCategory, WfCategoryVo> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.dromara.workflow.mapper;
|
||||
|
||||
import org.dromara.workflow.domain.WfDefinitionConfig;
|
||||
import org.dromara.workflow.domain.vo.WfDefinitionConfigVo;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
|
||||
/**
|
||||
* 流程定义配置Mapper接口
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-03-18
|
||||
*/
|
||||
public interface WfDefinitionConfigMapper extends BaseMapperPlus<WfDefinitionConfig, WfDefinitionConfigVo> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.dromara.workflow.mapper;
|
||||
|
||||
import org.dromara.workflow.domain.WfFormManage;
|
||||
import org.dromara.workflow.domain.vo.WfFormManageVo;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
|
||||
/**
|
||||
* 表单管理Mapper接口
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-03-29
|
||||
*/
|
||||
public interface WfFormManageMapper extends BaseMapperPlus<WfFormManage, WfFormManageVo> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.dromara.workflow.mapper;
|
||||
|
||||
import org.dromara.workflow.domain.WfNodeConfig;
|
||||
import org.dromara.workflow.domain.vo.WfNodeConfigVo;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
|
||||
/**
|
||||
* 节点配置Mapper接口
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-03-30
|
||||
*/
|
||||
public interface WfNodeConfigMapper extends BaseMapperPlus<WfNodeConfig, WfNodeConfigVo> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.dromara.workflow.mapper;
|
||||
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
import org.dromara.workflow.domain.WfTaskBackNode;
|
||||
|
||||
/**
|
||||
* 节点驳回记录Mapper接口
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-03-13
|
||||
*/
|
||||
public interface WfTaskBackNodeMapper extends BaseMapperPlus<WfTaskBackNode, WfTaskBackNode> {
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.dromara.workflow.service;
|
||||
|
||||
|
||||
import org.dromara.workflow.domain.ActHiProcinst;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 流程实例Service接口
|
||||
*
|
||||
* @author may
|
||||
* @date 2023-07-22
|
||||
*/
|
||||
public interface IActHiProcinstService {
|
||||
|
||||
/**
|
||||
* 按照业务id查询
|
||||
*
|
||||
* @param businessKeys 业务id
|
||||
* @return 结果
|
||||
*/
|
||||
List<ActHiProcinst> selectByBusinessKeyIn(List<String> businessKeys);
|
||||
|
||||
/**
|
||||
* 按照业务id查询
|
||||
*
|
||||
* @param businessKey 业务id
|
||||
* @return 结果
|
||||
*/
|
||||
ActHiProcinst selectByBusinessKey(String businessKey);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package org.dromara.workflow.service;
|
||||
|
||||
|
||||
/**
|
||||
* 流程历史任务Service接口
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-03-02
|
||||
*/
|
||||
public interface IActHiTaskinstService {
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package org.dromara.workflow.service;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.workflow.domain.bo.ModelBo;
|
||||
import org.dromara.workflow.domain.vo.ModelVo;
|
||||
import org.flowable.engine.repository.Model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* 模型管理 服务层
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
public interface IActModelService {
|
||||
/**
|
||||
* 分页查询模型
|
||||
*
|
||||
* @param modelBo 模型参数
|
||||
* @param pageQuery 参数
|
||||
* @return 返回分页列表
|
||||
*/
|
||||
TableDataInfo<Model> page(ModelBo modelBo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 新增模型
|
||||
*
|
||||
* @param modelBo 模型请求对象
|
||||
* @return 结果
|
||||
*/
|
||||
boolean saveNewModel(ModelBo modelBo);
|
||||
|
||||
/**
|
||||
* 查询模型
|
||||
*
|
||||
* @param modelId 模型id
|
||||
* @return 模型数据
|
||||
*/
|
||||
ModelVo getInfo(String modelId);
|
||||
|
||||
/**
|
||||
* 修改模型信息
|
||||
*
|
||||
* @param modelBo 模型数据
|
||||
* @return 结果
|
||||
*/
|
||||
boolean update(ModelBo modelBo);
|
||||
|
||||
/**
|
||||
* 编辑模型XML
|
||||
*
|
||||
* @param modelBo 模型数据
|
||||
* @return 结果
|
||||
*/
|
||||
boolean editModelXml(ModelBo modelBo);
|
||||
|
||||
/**
|
||||
* 模型部署
|
||||
*
|
||||
* @param id 模型id
|
||||
* @return 结果
|
||||
*/
|
||||
boolean modelDeploy(String id);
|
||||
|
||||
/**
|
||||
* 导出模型zip压缩包
|
||||
*
|
||||
* @param modelIds 模型id
|
||||
* @param response 响应
|
||||
*/
|
||||
void exportZip(List<String> modelIds, HttpServletResponse response);
|
||||
|
||||
/**
|
||||
* 复制模型
|
||||
*
|
||||
* @param modelBo 模型数据
|
||||
* @return 结果
|
||||
*/
|
||||
boolean copyModel(ModelBo modelBo);
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package org.dromara.workflow.service;
|
||||
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.workflow.domain.bo.ProcessDefinitionBo;
|
||||
import org.dromara.workflow.domain.vo.ProcessDefinitionVo;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 流程定义 服务层
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
public interface IActProcessDefinitionService {
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param processDefinitionBo 参数
|
||||
* @param pageQuery 分页
|
||||
* @return 返回分页列表
|
||||
*/
|
||||
TableDataInfo<ProcessDefinitionVo> page(ProcessDefinitionBo processDefinitionBo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询历史流程定义列表
|
||||
*
|
||||
* @param key 流程定义key
|
||||
* @return 结果
|
||||
*/
|
||||
List<ProcessDefinitionVo> getListByKey(String key);
|
||||
|
||||
/**
|
||||
* 查看流程定义图片
|
||||
*
|
||||
* @param processDefinitionId 流程定义id
|
||||
* @return 结果
|
||||
*/
|
||||
String definitionImage(String processDefinitionId);
|
||||
|
||||
/**
|
||||
* 查看流程定义xml文件
|
||||
*
|
||||
* @param processDefinitionId 流程定义id
|
||||
* @return 结果
|
||||
*/
|
||||
String definitionXml(String processDefinitionId);
|
||||
|
||||
/**
|
||||
* 删除流程定义
|
||||
*
|
||||
* @param deploymentIds 部署id
|
||||
* @param processDefinitionIds 流程定义id
|
||||
* @return 结果
|
||||
*/
|
||||
boolean deleteDeployment(List<String> deploymentIds, List<String> processDefinitionIds);
|
||||
|
||||
/**
|
||||
* 激活或者挂起流程定义
|
||||
*
|
||||
* @param processDefinitionId 流程定义id
|
||||
* @return 结果
|
||||
*/
|
||||
boolean updateDefinitionState(String processDefinitionId);
|
||||
|
||||
/**
|
||||
* 迁移流程定义
|
||||
*
|
||||
* @param currentProcessDefinitionId 当前流程定义id
|
||||
* @param fromProcessDefinitionId 需要迁移到的流程定义id
|
||||
* @return 结果
|
||||
*/
|
||||
boolean migrationDefinition(String currentProcessDefinitionId, String fromProcessDefinitionId);
|
||||
|
||||
/**
|
||||
* 流程定义转换为模型
|
||||
*
|
||||
* @param processDefinitionId 流程定义id
|
||||
* @return 结果
|
||||
*/
|
||||
boolean convertToModel(String processDefinitionId);
|
||||
|
||||
/**
|
||||
* 通过zip或xml部署流程定义
|
||||
*
|
||||
* @param file 文件
|
||||
* @param categoryCode 分类
|
||||
*/
|
||||
void deployByFile(MultipartFile file, String categoryCode);
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package org.dromara.workflow.service;
|
||||
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.workflow.domain.bo.ProcessInstanceBo;
|
||||
import org.dromara.workflow.domain.bo.ProcessInvalidBo;
|
||||
import org.dromara.workflow.domain.bo.TaskUrgingBo;
|
||||
import org.dromara.workflow.domain.vo.ActHistoryInfoVo;
|
||||
import org.dromara.workflow.domain.vo.ProcessInstanceVo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 流程实例 服务层
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
public interface IActProcessInstanceService {
|
||||
/**
|
||||
* 通过流程实例id获取历史流程图
|
||||
*
|
||||
* @param businessKey 流程实例id
|
||||
* @return 结果
|
||||
*/
|
||||
String getHistoryImage(String businessKey);
|
||||
|
||||
/**
|
||||
* 通过业务id获取历史流程图运行中,历史等节点
|
||||
*
|
||||
* @param businessKey 业务id
|
||||
* @return 结果
|
||||
*/
|
||||
Map<String, Object> getHistoryList(String businessKey);
|
||||
|
||||
/**
|
||||
* 分页查询正在运行的流程实例
|
||||
*
|
||||
* @param processInstanceBo 参数
|
||||
* @param pageQuery 分页
|
||||
* @return 结果
|
||||
*/
|
||||
TableDataInfo<ProcessInstanceVo> getPageByRunning(ProcessInstanceBo processInstanceBo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 分页查询已结束的流程实例
|
||||
*
|
||||
* @param processInstanceBo 参数
|
||||
* @param pageQuery 分页
|
||||
* @return 结果
|
||||
*/
|
||||
TableDataInfo<ProcessInstanceVo> getPageByFinish(ProcessInstanceBo processInstanceBo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 获取审批记录
|
||||
*
|
||||
* @param businessKey 业务id
|
||||
* @return 结果
|
||||
*/
|
||||
List<ActHistoryInfoVo> getHistoryRecord(String businessKey);
|
||||
|
||||
/**
|
||||
* 作废流程实例,不会删除历史记录(删除运行中的实例)
|
||||
*
|
||||
* @param processInvalidBo 参数
|
||||
* @return 结果
|
||||
*/
|
||||
boolean deleteRunInstance(ProcessInvalidBo processInvalidBo);
|
||||
|
||||
/**
|
||||
* 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息
|
||||
*
|
||||
* @param businessKeys 业务id
|
||||
* @return 结果
|
||||
*/
|
||||
boolean deleteRunAndHisInstance(List<String> businessKeys);
|
||||
|
||||
/**
|
||||
* 已完成的实例 删除程实例,删除历史记录,删除业务与流程关联信息
|
||||
*
|
||||
* @param businessKeys 业务id
|
||||
* @return 结果
|
||||
*/
|
||||
boolean deleteFinishAndHisInstance(List<String> businessKeys);
|
||||
|
||||
/**
|
||||
* 撤销流程申请
|
||||
*
|
||||
* @param businessKey 业务id
|
||||
* @return 结果
|
||||
*/
|
||||
boolean cancelProcessApply(String businessKey);
|
||||
|
||||
/**
|
||||
* 分页查询当前登录人单据
|
||||
*
|
||||
* @param processInstanceBo 参数
|
||||
* @param pageQuery 分页
|
||||
* @return 结果
|
||||
*/
|
||||
TableDataInfo<ProcessInstanceVo> getPageByCurrent(ProcessInstanceBo processInstanceBo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 任务催办(给当前任务办理人发送站内信,邮件,短信等)
|
||||
*
|
||||
* @param taskUrgingBo 任务催办
|
||||
* @return 结果
|
||||
*/
|
||||
boolean taskUrging(TaskUrgingBo taskUrgingBo);
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
package org.dromara.workflow.service;
|
||||
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.workflow.domain.bo.*;
|
||||
import org.dromara.workflow.domain.vo.TaskVo;
|
||||
import org.dromara.workflow.domain.vo.VariableVo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 任务 服务层
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
public interface IActTaskService {
|
||||
/**
|
||||
* 启动任务
|
||||
*
|
||||
* @param startProcessBo 启动流程参数
|
||||
* @return 结果
|
||||
*/
|
||||
Map<String, Object> startWorkFlow(StartProcessBo startProcessBo);
|
||||
|
||||
|
||||
/**
|
||||
* 办理任务
|
||||
*
|
||||
* @param completeTaskBo 办理任务参数
|
||||
* @return 结果
|
||||
*/
|
||||
boolean completeTask(CompleteTaskBo completeTaskBo);
|
||||
|
||||
/**
|
||||
* 查询当前用户的待办任务
|
||||
*
|
||||
* @param taskBo 参数
|
||||
* @param pageQuery 分页
|
||||
* @return 结果
|
||||
*/
|
||||
TableDataInfo<TaskVo> getPageByTaskWait(TaskBo taskBo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询当前租户所有待办任务
|
||||
*
|
||||
* @param taskBo 参数
|
||||
* @param pageQuery 分页
|
||||
* @return 结果
|
||||
*/
|
||||
TableDataInfo<TaskVo> getPageByAllTaskWait(TaskBo taskBo, PageQuery pageQuery);
|
||||
|
||||
|
||||
/**
|
||||
* 查询当前用户的已办任务
|
||||
*
|
||||
* @param taskBo 参数
|
||||
* @param pageQuery 参数
|
||||
* @return 结果
|
||||
*/
|
||||
TableDataInfo<TaskVo> getPageByTaskFinish(TaskBo taskBo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询当前用户的抄送
|
||||
*
|
||||
* @param taskBo 参数
|
||||
* @param pageQuery 参数
|
||||
* @return 结果
|
||||
*/
|
||||
TableDataInfo<TaskVo> getPageByTaskCopy(TaskBo taskBo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询当前租户所有已办任务
|
||||
*
|
||||
* @param taskBo 参数
|
||||
* @param pageQuery 参数
|
||||
* @return 结果
|
||||
*/
|
||||
TableDataInfo<TaskVo> getPageByAllTaskFinish(TaskBo taskBo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 委派任务
|
||||
*
|
||||
* @param delegateBo 参数
|
||||
* @return 结果
|
||||
*/
|
||||
boolean delegateTask(DelegateBo delegateBo);
|
||||
|
||||
/**
|
||||
* 终止任务
|
||||
*
|
||||
* @param terminationBo 参数
|
||||
* @return 结果
|
||||
*/
|
||||
boolean terminationTask(TerminationBo terminationBo);
|
||||
|
||||
/**
|
||||
* 转办任务
|
||||
*
|
||||
* @param transmitBo 参数
|
||||
* @return 结果
|
||||
*/
|
||||
boolean transferTask(TransmitBo transmitBo);
|
||||
|
||||
/**
|
||||
* 会签任务加签
|
||||
*
|
||||
* @param addMultiBo 参数
|
||||
* @return 结果
|
||||
*/
|
||||
boolean addMultiInstanceExecution(AddMultiBo addMultiBo);
|
||||
|
||||
/**
|
||||
* 会签任务减签
|
||||
*
|
||||
* @param deleteMultiBo 参数
|
||||
* @return 结果
|
||||
*/
|
||||
boolean deleteMultiInstanceExecution(DeleteMultiBo deleteMultiBo);
|
||||
|
||||
/**
|
||||
* 驳回审批
|
||||
*
|
||||
* @param backProcessBo 参数
|
||||
* @return 流程实例id
|
||||
*/
|
||||
String backProcess(BackProcessBo backProcessBo);
|
||||
|
||||
/**
|
||||
* 修改任务办理人
|
||||
*
|
||||
* @param taskIds 任务id
|
||||
* @param userId 办理人id
|
||||
* @return 结果
|
||||
*/
|
||||
boolean updateAssignee(String[] taskIds, String userId);
|
||||
|
||||
/**
|
||||
* 查询流程变量
|
||||
*
|
||||
* @param taskId 任务id
|
||||
* @return 结果
|
||||
*/
|
||||
List<VariableVo> getInstanceVariable(String taskId);
|
||||
|
||||
/**
|
||||
* 查询工作流任务用户选择加签人员
|
||||
*
|
||||
* @param taskId 任务id
|
||||
* @return 结果
|
||||
*/
|
||||
String getTaskUserIdsByAddMultiInstance(String taskId);
|
||||
|
||||
/**
|
||||
* 查询工作流选择减签人员
|
||||
*
|
||||
* @param taskId 任务id
|
||||
* @return 结果
|
||||
*/
|
||||
List<TaskVo> getListByDeleteMultiInstance(String taskId);
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package org.dromara.workflow.service;
|
||||
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.workflow.domain.bo.TestLeaveBo;
|
||||
import org.dromara.workflow.domain.vo.TestLeaveVo;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 请假Service接口
|
||||
*
|
||||
* @author may
|
||||
* @date 2023-07-21
|
||||
*/
|
||||
public interface ITestLeaveService {
|
||||
|
||||
/**
|
||||
* 查询请假
|
||||
*/
|
||||
TestLeaveVo queryById(Long id);
|
||||
|
||||
/**
|
||||
* 查询请假列表
|
||||
*/
|
||||
TableDataInfo<TestLeaveVo> queryPageList(TestLeaveBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询请假列表
|
||||
*/
|
||||
List<TestLeaveVo> queryList(TestLeaveBo bo);
|
||||
|
||||
/**
|
||||
* 新增请假
|
||||
*/
|
||||
TestLeaveVo insertByBo(TestLeaveBo bo);
|
||||
|
||||
/**
|
||||
* 修改请假
|
||||
*/
|
||||
TestLeaveVo updateByBo(TestLeaveBo bo);
|
||||
|
||||
/**
|
||||
* 校验并批量删除请假信息
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package org.dromara.workflow.service;
|
||||
|
||||
import org.dromara.workflow.domain.WfCategory;
|
||||
import org.dromara.workflow.domain.bo.WfCategoryBo;
|
||||
import org.dromara.workflow.domain.vo.WfCategoryVo;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 流程分类Service接口
|
||||
*
|
||||
* @author may
|
||||
* @date 2023-06-28
|
||||
*/
|
||||
public interface IWfCategoryService {
|
||||
|
||||
/**
|
||||
* 查询流程分类
|
||||
*/
|
||||
WfCategoryVo queryById(Long id);
|
||||
|
||||
|
||||
/**
|
||||
* 查询流程分类列表
|
||||
*/
|
||||
List<WfCategoryVo> queryList(WfCategoryBo bo);
|
||||
|
||||
/**
|
||||
* 新增流程分类
|
||||
*/
|
||||
Boolean insertByBo(WfCategoryBo bo);
|
||||
|
||||
/**
|
||||
* 修改流程分类
|
||||
*/
|
||||
Boolean updateByBo(WfCategoryBo bo);
|
||||
|
||||
/**
|
||||
* 校验并批量删除流程分类信息
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
|
||||
/**
|
||||
* 按照类别编码查询
|
||||
*
|
||||
* @param categoryCode 分类比吗
|
||||
* @return 结果
|
||||
*/
|
||||
WfCategory queryByCategoryCode(String categoryCode);
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package org.dromara.workflow.service;
|
||||
|
||||
import org.dromara.workflow.domain.vo.WfDefinitionConfigVo;
|
||||
import org.dromara.workflow.domain.bo.WfDefinitionConfigBo;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 流程定义配置Service接口
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-03-18
|
||||
*/
|
||||
public interface IWfDefinitionConfigService {
|
||||
|
||||
/**
|
||||
* 查询流程定义配置
|
||||
*
|
||||
* @param definitionId 流程定义id
|
||||
* @return 结果
|
||||
*/
|
||||
WfDefinitionConfigVo getByDefId(String definitionId);
|
||||
|
||||
/**
|
||||
* 查询流程定义配置
|
||||
*
|
||||
* @param tableName 表名
|
||||
* @return 结果
|
||||
*/
|
||||
WfDefinitionConfigVo getByTableNameLastVersion(String tableName);
|
||||
|
||||
/**
|
||||
* 查询流程定义配置
|
||||
*
|
||||
* @param definitionId 流程定义id
|
||||
* @param tableName 表名
|
||||
* @return 结果
|
||||
*/
|
||||
WfDefinitionConfigVo getByDefIdAndTableName(String definitionId, String tableName);
|
||||
|
||||
/**
|
||||
* 查询流程定义配置排除当前查询的流程定义
|
||||
*
|
||||
* @param definitionId 流程定义id
|
||||
* @param tableName 表名
|
||||
* @return 结果
|
||||
*/
|
||||
List<WfDefinitionConfigVo> getByTableNameNotDefId(String tableName, String definitionId);
|
||||
|
||||
/**
|
||||
* 查询流程定义配置列表
|
||||
*
|
||||
* @param definitionIds 流程定义id
|
||||
* @return 结果
|
||||
*/
|
||||
List<WfDefinitionConfigVo> queryList(List<String> definitionIds);
|
||||
|
||||
|
||||
/**
|
||||
* 新增流程定义配置
|
||||
*
|
||||
* @param bo 参数
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean saveOrUpdate(WfDefinitionConfigBo bo);
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*
|
||||
* @param ids id
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean deleteByIds(Collection<Long> ids);
|
||||
|
||||
/**
|
||||
* 按照流程定义id删除
|
||||
*
|
||||
* @param ids 流程定义id
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean deleteByDefIds(Collection<String> ids);
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package org.dromara.workflow.service;
|
||||
|
||||
import org.dromara.workflow.domain.vo.WfFormManageVo;
|
||||
import org.dromara.workflow.domain.bo.WfFormManageBo;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 表单管理Service接口
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-03-29
|
||||
*/
|
||||
public interface IWfFormManageService {
|
||||
|
||||
/**
|
||||
* 查询表单管理
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 结果
|
||||
*/
|
||||
WfFormManageVo queryById(Long id);
|
||||
|
||||
/**
|
||||
* 查询表单管理
|
||||
*
|
||||
* @param ids 主键
|
||||
* @return 结果
|
||||
*/
|
||||
List<WfFormManageVo> queryByIds(List<Long> ids);
|
||||
|
||||
/**
|
||||
* 查询表单管理列表
|
||||
*
|
||||
* @param bo 参数
|
||||
* @param pageQuery 分页
|
||||
* @return 结果
|
||||
*/
|
||||
TableDataInfo<WfFormManageVo> queryPageList(WfFormManageBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询表单管理列表
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
List<WfFormManageVo> selectList();
|
||||
/**
|
||||
* 查询表单管理列表
|
||||
*
|
||||
* @param bo 参数
|
||||
* @return 结果
|
||||
*/
|
||||
List<WfFormManageVo> queryList(WfFormManageBo bo);
|
||||
|
||||
/**
|
||||
* 新增表单管理
|
||||
*
|
||||
* @param bo 参数
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean insertByBo(WfFormManageBo bo);
|
||||
|
||||
/**
|
||||
* 修改表单管理
|
||||
*
|
||||
* @param bo 参数
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean updateByBo(WfFormManageBo bo);
|
||||
|
||||
/**
|
||||
* 批量删除表单管理信息
|
||||
*
|
||||
* @param ids 主键
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean deleteByIds(Collection<Long> ids);
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package org.dromara.workflow.service;
|
||||
|
||||
import org.dromara.workflow.domain.WfNodeConfig;
|
||||
import org.dromara.workflow.domain.vo.WfNodeConfigVo;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 节点配置Service接口
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-03-30
|
||||
*/
|
||||
public interface IWfNodeConfigService {
|
||||
|
||||
/**
|
||||
* 查询节点配置
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 结果
|
||||
*/
|
||||
WfNodeConfigVo queryById(Long id);
|
||||
|
||||
/**
|
||||
* 保存节点配置
|
||||
*
|
||||
* @param list 参数
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean saveOrUpdate(List<WfNodeConfig> list);
|
||||
|
||||
/**
|
||||
* 批量删除节点配置信息
|
||||
*
|
||||
* @param ids 主键
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean deleteByIds(Collection<Long> ids);
|
||||
|
||||
/**
|
||||
* 按照流程定义id删除
|
||||
*
|
||||
* @param ids 流程定义id
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean deleteByDefIds(Collection<String> ids);
|
||||
|
||||
/**
|
||||
* 按照流程定义id查询
|
||||
*
|
||||
* @param ids 流程定义id
|
||||
* @return 结果
|
||||
*/
|
||||
List<WfNodeConfigVo> selectByDefIds(Collection<String> ids);
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package org.dromara.workflow.service;
|
||||
|
||||
|
||||
import org.dromara.workflow.domain.WfTaskBackNode;
|
||||
import org.flowable.task.api.Task;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 节点驳回记录Service接口
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-03-13
|
||||
*/
|
||||
public interface IWfTaskBackNodeService {
|
||||
|
||||
/**
|
||||
* 记录审批节点
|
||||
*
|
||||
* @param task 任务
|
||||
*/
|
||||
void recordExecuteNode(Task task);
|
||||
|
||||
/**
|
||||
* 按流程实例id查询
|
||||
*
|
||||
* @param processInstanceId 流程实例id
|
||||
* @return 结果
|
||||
*/
|
||||
List<WfTaskBackNode> getListByInstanceId(String processInstanceId);
|
||||
|
||||
/**
|
||||
* 按照流程实例id,节点id查询
|
||||
*
|
||||
* @param processInstanceId 流程实例id
|
||||
* @param nodeId 节点id
|
||||
* @return 结果
|
||||
*/
|
||||
WfTaskBackNode getListByInstanceIdAndNodeId(String processInstanceId, String nodeId);
|
||||
|
||||
/**
|
||||
* 删除驳回后的节点
|
||||
*
|
||||
* @param processInstanceId 流程实例id
|
||||
* @param targetActivityId 节点id
|
||||
* @return 结果
|
||||
*/
|
||||
boolean deleteBackTaskNode(String processInstanceId, String targetActivityId);
|
||||
|
||||
/**
|
||||
* 按流程实例id删除
|
||||
*
|
||||
* @param processInstanceId 流程实例id
|
||||
* @return 结果
|
||||
*/
|
||||
boolean deleteByInstanceId(String processInstanceId);
|
||||
|
||||
/**
|
||||
* 按流程实例id删除
|
||||
*
|
||||
* @param processInstanceIds 流程实例id
|
||||
* @return 结果
|
||||
*/
|
||||
boolean deleteByInstanceIds(List<String> processInstanceIds);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package org.dromara.workflow.service.impl;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.tenant.helper.TenantHelper;
|
||||
import org.dromara.workflow.domain.ActHiProcinst;
|
||||
import org.dromara.workflow.mapper.ActHiProcinstMapper;
|
||||
import org.dromara.workflow.service.IActHiProcinstService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* 流程实例Service业务层处理
|
||||
*
|
||||
* @author may
|
||||
* @date 2023-07-22
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class ActHiProcinstServiceImpl implements IActHiProcinstService {
|
||||
|
||||
private final ActHiProcinstMapper baseMapper;
|
||||
|
||||
/**
|
||||
* 按照业务id查询
|
||||
*
|
||||
* @param businessKeys 业务id
|
||||
*/
|
||||
@Override
|
||||
public List<ActHiProcinst> selectByBusinessKeyIn(List<String> businessKeys) {
|
||||
return baseMapper.selectList(new LambdaQueryWrapper<ActHiProcinst>()
|
||||
.in(ActHiProcinst::getBusinessKey, businessKeys)
|
||||
.eq(TenantHelper.isEnable(), ActHiProcinst::getTenantId, TenantHelper.getTenantId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 按照业务id查询
|
||||
*
|
||||
* @param businessKey 业务id
|
||||
*/
|
||||
@Override
|
||||
public ActHiProcinst selectByBusinessKey(String businessKey) {
|
||||
return baseMapper.selectOne(new LambdaQueryWrapper<ActHiProcinst>()
|
||||
.eq(ActHiProcinst::getBusinessKey, businessKey)
|
||||
.eq(TenantHelper.isEnable(), ActHiProcinst::getTenantId, TenantHelper.getTenantId()));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.dromara.workflow.service.impl;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.dromara.workflow.service.IActHiTaskinstService;
|
||||
|
||||
|
||||
/**
|
||||
* 流程历史任务Service业务层处理
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-03-02
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class ActHiTaskinstServiceImpl implements IActHiTaskinstService {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,431 @@
|
||||
package org.dromara.workflow.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Validator;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.ZipUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.alibaba.excel.util.StringUtils;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.batik.transcoder.TranscoderInput;
|
||||
import org.apache.batik.transcoder.TranscoderOutput;
|
||||
import org.apache.batik.transcoder.image.PNGTranscoder;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.tenant.helper.TenantHelper;
|
||||
import org.dromara.workflow.common.constant.FlowConstant;
|
||||
import org.dromara.workflow.domain.WfNodeConfig;
|
||||
import org.dromara.workflow.domain.bo.ModelBo;
|
||||
import org.dromara.workflow.domain.bo.WfDefinitionConfigBo;
|
||||
import org.dromara.workflow.domain.vo.ModelVo;
|
||||
import org.dromara.workflow.domain.vo.WfDefinitionConfigVo;
|
||||
import org.dromara.workflow.service.IActModelService;
|
||||
import org.dromara.workflow.service.IWfDefinitionConfigService;
|
||||
import org.dromara.workflow.service.IWfNodeConfigService;
|
||||
import org.dromara.workflow.utils.ModelUtils;
|
||||
import org.dromara.workflow.utils.QueryUtils;
|
||||
import org.flowable.bpmn.converter.BpmnXMLConverter;
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.bpmn.model.Process;
|
||||
import org.flowable.bpmn.model.UserTask;
|
||||
import org.flowable.engine.RepositoryService;
|
||||
import org.flowable.engine.repository.Deployment;
|
||||
import org.flowable.engine.repository.Model;
|
||||
import org.flowable.engine.repository.ModelQuery;
|
||||
import org.flowable.engine.repository.ProcessDefinition;
|
||||
import org.flowable.validation.ValidationError;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
/**
|
||||
* 模型管理 服务层实现
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class ActModelServiceImpl implements IActModelService {
|
||||
|
||||
@Autowired(required = false)
|
||||
private RepositoryService repositoryService;
|
||||
private final IWfNodeConfigService wfNodeConfigService;
|
||||
private final IWfDefinitionConfigService wfDefinitionConfigService;
|
||||
|
||||
/**
|
||||
* 分页查询模型
|
||||
*
|
||||
* @param modelBo 模型参数
|
||||
* @return 返回分页列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<Model> page(ModelBo modelBo, PageQuery pageQuery) {
|
||||
ModelQuery query = QueryUtils.modelQuery();
|
||||
if (StringUtils.isNotBlank(modelBo.getName())) {
|
||||
query.modelNameLike("%" + modelBo.getName() + "%");
|
||||
}
|
||||
if (StringUtils.isNotBlank(modelBo.getKey())) {
|
||||
query.modelKey(modelBo.getKey());
|
||||
}
|
||||
if (StringUtils.isNotBlank(modelBo.getCategoryCode())) {
|
||||
query.modelCategory(modelBo.getCategoryCode());
|
||||
}
|
||||
query.orderByLastUpdateTime().desc();
|
||||
// 创建时间降序排列
|
||||
query.orderByCreateTime().desc();
|
||||
// 分页查询
|
||||
List<Model> modelList = query.listPage(pageQuery.getFirstNum(), pageQuery.getPageSize());
|
||||
// 总记录数
|
||||
long total = query.count();
|
||||
TableDataInfo<Model> build = TableDataInfo.build();
|
||||
build.setRows(modelList);
|
||||
build.setTotal(total);
|
||||
return build;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增模型
|
||||
*
|
||||
* @param modelBo 模型请求对象
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean saveNewModel(ModelBo modelBo) {
|
||||
try {
|
||||
int version = 0;
|
||||
String key = modelBo.getKey();
|
||||
String name = modelBo.getName();
|
||||
String description = modelBo.getDescription();
|
||||
String categoryCode = modelBo.getCategoryCode();
|
||||
String xml = modelBo.getXml();
|
||||
Model checkModel = QueryUtils.modelQuery().modelKey(key).singleResult();
|
||||
if (ObjectUtil.isNotNull(checkModel)) {
|
||||
throw new ServiceException("模型key已存在!");
|
||||
}
|
||||
//初始空的模型
|
||||
Model model = repositoryService.newModel();
|
||||
model.setKey(key);
|
||||
model.setName(name);
|
||||
model.setVersion(version);
|
||||
model.setCategory(categoryCode);
|
||||
model.setMetaInfo(description);
|
||||
model.setTenantId(TenantHelper.getTenantId());
|
||||
//保存初始化的模型基本信息数据
|
||||
repositoryService.saveModel(model);
|
||||
repositoryService.addModelEditorSource(model.getId(), StrUtil.utf8Bytes(xml));
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询模型
|
||||
*
|
||||
* @param id 模型id
|
||||
* @return 模型数据
|
||||
*/
|
||||
@Override
|
||||
public ModelVo getInfo(String id) {
|
||||
ModelVo modelVo = new ModelVo();
|
||||
Model model = repositoryService.getModel(id);
|
||||
if (model != null) {
|
||||
try {
|
||||
byte[] modelEditorSource = repositoryService.getModelEditorSource(model.getId());
|
||||
modelVo.setXml(StrUtil.utf8Str(modelEditorSource));
|
||||
modelVo.setId(model.getId());
|
||||
modelVo.setKey(model.getKey());
|
||||
modelVo.setName(model.getName());
|
||||
modelVo.setCategoryCode(model.getCategory());
|
||||
modelVo.setDescription(model.getMetaInfo());
|
||||
return modelVo;
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
return modelVo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改模型信息
|
||||
*
|
||||
* @param modelBo 模型数据
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public boolean update(ModelBo modelBo) {
|
||||
try {
|
||||
Model model = repositoryService.getModel(modelBo.getId());
|
||||
List<Model> list = QueryUtils.modelQuery().modelKey(modelBo.getKey()).list();
|
||||
list.stream().filter(e -> !e.getId().equals(model.getId())).findFirst().ifPresent(e -> {
|
||||
throw new ServiceException("模型KEY已存在!");
|
||||
});
|
||||
model.setCategory(modelBo.getCategoryCode());
|
||||
model.setMetaInfo(modelBo.getDescription());
|
||||
repositoryService.saveModel(model);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑模型XML
|
||||
*
|
||||
* @param modelBo 模型数据
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean editModelXml(ModelBo modelBo) {
|
||||
try {
|
||||
String xml = modelBo.getXml();
|
||||
String svg = modelBo.getSvg();
|
||||
String modelId = modelBo.getId();
|
||||
String key = modelBo.getKey();
|
||||
String name = modelBo.getName();
|
||||
BpmnModel bpmnModel = ModelUtils.xmlToBpmnModel(xml);
|
||||
ModelUtils.checkBpmnModel(bpmnModel);
|
||||
Model model = repositoryService.getModel(modelId);
|
||||
List<Model> list = QueryUtils.modelQuery().modelKey(key).list();
|
||||
list.stream().filter(e -> !e.getId().equals(model.getId())).findFirst().ifPresent(e -> {
|
||||
throw new ServiceException("模型KEY已存在!");
|
||||
});
|
||||
// 校验key命名规范
|
||||
if (!Validator.isMatchRegex(FlowConstant.MODEL_KEY_PATTERN, key)) {
|
||||
throw new ServiceException("模型标识KEY只能字符或者下划线开头!");
|
||||
}
|
||||
model.setKey(key);
|
||||
model.setName(name);
|
||||
model.setVersion(model.getVersion() + 1);
|
||||
repositoryService.saveModel(model);
|
||||
repositoryService.addModelEditorSource(model.getId(), StrUtil.utf8Bytes(xml));
|
||||
// 转换图片
|
||||
InputStream svgStream = new ByteArrayInputStream(StrUtil.utf8Bytes(svg));
|
||||
TranscoderInput input = new TranscoderInput(svgStream);
|
||||
|
||||
PNGTranscoder transcoder = new PNGTranscoder();
|
||||
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
|
||||
TranscoderOutput output = new TranscoderOutput(outStream);
|
||||
|
||||
transcoder.transcode(input, output);
|
||||
final byte[] result = outStream.toByteArray();
|
||||
repositoryService.addModelEditorSourceExtra(model.getId(), result);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 模型部署
|
||||
*
|
||||
* @param id 模型id
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean modelDeploy(String id) {
|
||||
try {
|
||||
// 查询流程定义模型xml
|
||||
byte[] xmlBytes = repositoryService.getModelEditorSource(id);
|
||||
if (ArrayUtil.isEmpty(xmlBytes)) {
|
||||
throw new ServiceException("模型数据为空,请先设计流程定义模型,再进行部署!");
|
||||
}
|
||||
if (JSONUtil.isTypeJSON(new String(xmlBytes, StandardCharsets.UTF_8))) {
|
||||
byte[] bytes = ModelUtils.bpmnJsonToXmlBytes(xmlBytes);
|
||||
if (ArrayUtil.isEmpty(bytes)) {
|
||||
throw new ServiceException("模型不能为空,请至少设计一条主线流程!");
|
||||
}
|
||||
}
|
||||
BpmnModel bpmnModel = ModelUtils.xmlToBpmnModel(xmlBytes);
|
||||
// 校验模型
|
||||
ModelUtils.checkBpmnModel(bpmnModel);
|
||||
List<ValidationError> validationErrors = repositoryService.validateProcess(bpmnModel);
|
||||
if (CollUtil.isNotEmpty(validationErrors)) {
|
||||
String errorMsg = validationErrors.stream().map(ValidationError::getProblem).distinct().collect(Collectors.joining(","));
|
||||
throw new ServiceException(errorMsg);
|
||||
}
|
||||
// 查询模型的基本信息
|
||||
Model model = repositoryService.getModel(id);
|
||||
ProcessDefinition processDefinition = QueryUtils.definitionQuery().processDefinitionKey(model.getKey()).latestVersion().singleResult();
|
||||
// xml资源的名称 ,对应act_ge_bytearray表中的name_字段
|
||||
String processName = model.getName() + ".bpmn20.xml";
|
||||
// 调用部署相关的api方法进行部署流程定义
|
||||
Deployment deployment = repositoryService.createDeployment()
|
||||
// 部署名称
|
||||
.name(model.getName())
|
||||
// 部署标识key
|
||||
.key(model.getKey())
|
||||
// 部署流程分类
|
||||
.category(model.getCategory())
|
||||
// bpmn20.xml资源
|
||||
.addBytes(processName, xmlBytes)
|
||||
// 租户id
|
||||
.tenantId(TenantHelper.getTenantId())
|
||||
.deploy();
|
||||
|
||||
// 更新 部署id 到流程定义模型数据表中
|
||||
model.setDeploymentId(deployment.getId());
|
||||
repositoryService.saveModel(model);
|
||||
// 更新分类
|
||||
ProcessDefinition definition = QueryUtils.definitionQuery().deploymentId(deployment.getId()).singleResult();
|
||||
repositoryService.setProcessDefinitionCategory(definition.getId(), model.getCategory());
|
||||
//更新流程定义配置
|
||||
if (processDefinition != null) {
|
||||
WfDefinitionConfigVo definitionVo = wfDefinitionConfigService.getByDefId(processDefinition.getId());
|
||||
if (definitionVo != null) {
|
||||
wfDefinitionConfigService.deleteByDefIds(Collections.singletonList(processDefinition.getId()));
|
||||
WfDefinitionConfigBo wfFormDefinition = new WfDefinitionConfigBo();
|
||||
wfFormDefinition.setDefinitionId(definition.getId());
|
||||
wfFormDefinition.setProcessKey(definition.getKey());
|
||||
wfFormDefinition.setTableName(definitionVo.getTableName());
|
||||
wfFormDefinition.setVersion(definition.getVersion());
|
||||
wfFormDefinition.setRemark(definitionVo.getRemark());
|
||||
wfDefinitionConfigService.saveOrUpdate(wfFormDefinition);
|
||||
}
|
||||
}
|
||||
//更新流程节点配置表单
|
||||
List<UserTask> userTasks = ModelUtils.getUserTaskFlowElements(definition.getId());
|
||||
UserTask applyUserTask = ModelUtils.getApplyUserTask(definition.getId());
|
||||
List<WfNodeConfig> wfNodeConfigList = new ArrayList<>();
|
||||
for (UserTask userTask : userTasks) {
|
||||
if (StringUtils.isNotBlank(userTask.getFormKey()) && userTask.getFormKey().contains(StrUtil.COLON)) {
|
||||
WfNodeConfig wfNodeConfig = new WfNodeConfig();
|
||||
wfNodeConfig.setNodeId(userTask.getId());
|
||||
wfNodeConfig.setNodeName(userTask.getName());
|
||||
wfNodeConfig.setDefinitionId(definition.getId());
|
||||
String[] split = userTask.getFormKey().split(StrUtil.COLON);
|
||||
wfNodeConfig.setFormType(split[0]);
|
||||
wfNodeConfig.setFormId(Long.valueOf(split[1]));
|
||||
wfNodeConfig.setApplyUserTask(applyUserTask.getId().equals(userTask.getId()) ? FlowConstant.TRUE : FlowConstant.FALSE);
|
||||
wfNodeConfigList.add(wfNodeConfig);
|
||||
}
|
||||
}
|
||||
if (CollUtil.isNotEmpty(wfNodeConfigList)) {
|
||||
wfNodeConfigService.saveOrUpdate(wfNodeConfigList);
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出模型zip压缩包
|
||||
*
|
||||
* @param modelIds 模型id
|
||||
* @param response 相应
|
||||
*/
|
||||
@Override
|
||||
public void exportZip(List<String> modelIds, HttpServletResponse response) {
|
||||
try (ZipOutputStream zos = ZipUtil.getZipOutputStream(response.getOutputStream(), StandardCharsets.UTF_8)) {
|
||||
// 压缩包文件名
|
||||
String zipName = "模型不存在";
|
||||
// 查询模型基本信息
|
||||
for (String modelId : modelIds) {
|
||||
Model model = repositoryService.getModel(modelId);
|
||||
byte[] xmlBytes = repositoryService.getModelEditorSource(modelId);
|
||||
if (ObjectUtil.isNotNull(model)) {
|
||||
if (JSONUtil.isTypeJSON(new String(xmlBytes, StandardCharsets.UTF_8)) && ArrayUtil.isEmpty(ModelUtils.bpmnJsonToXmlBytes(xmlBytes))) {
|
||||
zipName = "模型不能为空,请至少设计一条主线流程!";
|
||||
zos.putNextEntry(new ZipEntry(zipName + ".txt"));
|
||||
zos.write(zipName.getBytes(StandardCharsets.UTF_8));
|
||||
} else if (ArrayUtil.isEmpty(xmlBytes)) {
|
||||
zipName = "模型数据为空,请先设计流程定义模型,再进行部署!";
|
||||
zos.putNextEntry(new ZipEntry(zipName + ".txt"));
|
||||
zos.write(zipName.getBytes(StandardCharsets.UTF_8));
|
||||
} else {
|
||||
String fileName = model.getName() + "-" + model.getKey();
|
||||
// 压缩包文件名
|
||||
zipName = fileName + ".zip";
|
||||
// 将xml添加到压缩包中(指定xml文件名:请假流程.bpmn20.xml
|
||||
zos.putNextEntry(new ZipEntry(fileName + ".bpmn20.xml"));
|
||||
zos.write(xmlBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
response.setHeader("Content-Disposition",
|
||||
"attachment; filename=" + URLEncoder.encode(zipName, StandardCharsets.UTF_8) + ".zip");
|
||||
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
|
||||
// 刷出响应流
|
||||
response.flushBuffer();
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制模型
|
||||
*
|
||||
* @param modelBo 模型数据
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean copyModel(ModelBo modelBo) {
|
||||
try {
|
||||
String key = modelBo.getKey();
|
||||
if (StringUtils.isNotBlank(key)) {
|
||||
// 查询模型
|
||||
Model model = repositoryService.createModelQuery().modelId(modelBo.getId()).singleResult();
|
||||
if (ObjectUtil.isNotNull(model)) {
|
||||
byte[] modelEditorSource = repositoryService.getModelEditorSource(model.getId());
|
||||
List<Model> list = QueryUtils.modelQuery().modelKey(key).list();
|
||||
if (CollUtil.isNotEmpty(list)) {
|
||||
throw new ServiceException("模型KEY已存在!");
|
||||
}
|
||||
// 校验key命名规范
|
||||
if (!Validator.isMatchRegex(FlowConstant.MODEL_KEY_PATTERN, key)) {
|
||||
throw new ServiceException("模型标识KEY只能字符或者下划线开头!");
|
||||
}
|
||||
// 复制模型数据
|
||||
Model newModel = repositoryService.newModel();
|
||||
newModel.setKey(modelBo.getKey());
|
||||
newModel.setName(modelBo.getName());
|
||||
newModel.setCategory(modelBo.getCategoryCode());
|
||||
newModel.setVersion(1);
|
||||
newModel.setMetaInfo(modelBo.getDescription());
|
||||
newModel.setTenantId(TenantHelper.getTenantId());
|
||||
String xml = StrUtil.utf8Str(modelEditorSource);
|
||||
BpmnModel bpmnModel = ModelUtils.xmlToBpmnModel(xml);
|
||||
Process mainProcess = bpmnModel.getMainProcess();
|
||||
mainProcess.setId(modelBo.getKey());
|
||||
mainProcess.setName(modelBo.getName());
|
||||
byte[] xmlBytes = new BpmnXMLConverter().convertToXML(bpmnModel);
|
||||
repositoryService.saveModel(newModel);
|
||||
repositoryService.addModelEditorSource(newModel.getId(), xmlBytes);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,444 @@
|
||||
package org.dromara.workflow.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.utils.StreamUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.tenant.helper.TenantHelper;
|
||||
import org.dromara.workflow.common.constant.FlowConstant;
|
||||
import org.dromara.workflow.domain.WfCategory;
|
||||
import org.dromara.workflow.domain.WfDefinitionConfig;
|
||||
import org.dromara.workflow.domain.WfNodeConfig;
|
||||
import org.dromara.workflow.domain.bo.ProcessDefinitionBo;
|
||||
import org.dromara.workflow.domain.bo.WfDefinitionConfigBo;
|
||||
import org.dromara.workflow.domain.vo.ProcessDefinitionVo;
|
||||
import org.dromara.workflow.domain.vo.WfDefinitionConfigVo;
|
||||
import org.dromara.workflow.mapper.WfDefinitionConfigMapper;
|
||||
import org.dromara.workflow.service.IActProcessDefinitionService;
|
||||
import org.dromara.workflow.service.IWfCategoryService;
|
||||
import org.dromara.workflow.service.IWfDefinitionConfigService;
|
||||
import org.dromara.workflow.service.IWfNodeConfigService;
|
||||
import org.dromara.workflow.utils.ModelUtils;
|
||||
import org.dromara.workflow.utils.QueryUtils;
|
||||
import org.flowable.bpmn.model.UserTask;
|
||||
import org.flowable.engine.ProcessMigrationService;
|
||||
import org.flowable.engine.RepositoryService;
|
||||
import org.flowable.engine.history.HistoricProcessInstance;
|
||||
import org.flowable.engine.impl.bpmn.deployer.ResourceNameUtil;
|
||||
import org.flowable.engine.repository.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
/**
|
||||
* 流程定义 服务层实现
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class ActProcessDefinitionServiceImpl implements IActProcessDefinitionService {
|
||||
|
||||
@Autowired(required = false)
|
||||
private RepositoryService repositoryService;
|
||||
@Autowired(required = false)
|
||||
private ProcessMigrationService processMigrationService;
|
||||
private final IWfCategoryService wfCategoryService;
|
||||
private final IWfDefinitionConfigService wfDefinitionConfigService;
|
||||
private final WfDefinitionConfigMapper wfDefinitionConfigMapper;
|
||||
private final IWfNodeConfigService wfNodeConfigService;
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param bo 参数
|
||||
* @return 返回分页列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<ProcessDefinitionVo> page(ProcessDefinitionBo bo, PageQuery pageQuery) {
|
||||
ProcessDefinitionQuery query = QueryUtils.definitionQuery();
|
||||
if (StringUtils.isNotEmpty(bo.getKey())) {
|
||||
query.processDefinitionKey(bo.getKey());
|
||||
}
|
||||
if (StringUtils.isNotEmpty(bo.getCategoryCode())) {
|
||||
query.processDefinitionCategory(bo.getCategoryCode());
|
||||
}
|
||||
if (StringUtils.isNotEmpty(bo.getName())) {
|
||||
query.processDefinitionNameLike("%" + bo.getName() + "%");
|
||||
}
|
||||
query.orderByDeploymentId().desc();
|
||||
// 分页查询
|
||||
List<ProcessDefinitionVo> processDefinitionVoList = new ArrayList<>();
|
||||
List<ProcessDefinition> definitionList = query.latestVersion().listPage(pageQuery.getFirstNum(), pageQuery.getPageSize());
|
||||
List<Deployment> deploymentList = null;
|
||||
if (CollUtil.isNotEmpty(definitionList)) {
|
||||
List<String> deploymentIds = StreamUtils.toList(definitionList, ProcessDefinition::getDeploymentId);
|
||||
deploymentList = QueryUtils.deploymentQuery(deploymentIds).list();
|
||||
}
|
||||
if (CollUtil.isNotEmpty(definitionList)) {
|
||||
List<String> ids = StreamUtils.toList(definitionList, ProcessDefinition::getId);
|
||||
List<WfDefinitionConfigVo> wfDefinitionConfigVos = wfDefinitionConfigService.queryList(ids);
|
||||
for (ProcessDefinition processDefinition : definitionList) {
|
||||
ProcessDefinitionVo processDefinitionVo = BeanUtil.toBean(processDefinition, ProcessDefinitionVo.class);
|
||||
if (CollUtil.isNotEmpty(deploymentList)) {
|
||||
// 部署时间
|
||||
deploymentList.stream().filter(e -> e.getId().equals(processDefinition.getDeploymentId())).findFirst().ifPresent(e -> {
|
||||
processDefinitionVo.setDeploymentTime(e.getDeploymentTime());
|
||||
});
|
||||
}
|
||||
if (CollUtil.isNotEmpty(wfDefinitionConfigVos)) {
|
||||
wfDefinitionConfigVos.stream().filter(e -> e.getDefinitionId().equals(processDefinition.getId())).findFirst().ifPresent(processDefinitionVo::setWfDefinitionConfigVo);
|
||||
}
|
||||
processDefinitionVoList.add(processDefinitionVo);
|
||||
}
|
||||
}
|
||||
// 总记录数
|
||||
long total = query.count();
|
||||
TableDataInfo<ProcessDefinitionVo> build = TableDataInfo.build();
|
||||
build.setRows(processDefinitionVoList);
|
||||
build.setTotal(total);
|
||||
return build;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询历史流程定义列表
|
||||
*
|
||||
* @param key 流程定义key
|
||||
*/
|
||||
@Override
|
||||
public List<ProcessDefinitionVo> getListByKey(String key) {
|
||||
List<ProcessDefinitionVo> processDefinitionVoList = new ArrayList<>();
|
||||
ProcessDefinitionQuery query = QueryUtils.definitionQuery();
|
||||
List<ProcessDefinition> definitionList = query.processDefinitionKey(key).list();
|
||||
List<Deployment> deploymentList = null;
|
||||
if (CollUtil.isNotEmpty(definitionList)) {
|
||||
List<String> deploymentIds = StreamUtils.toList(definitionList, ProcessDefinition::getDeploymentId);
|
||||
deploymentList = QueryUtils.deploymentQuery(deploymentIds).list();
|
||||
}
|
||||
if (CollUtil.isNotEmpty(definitionList)) {
|
||||
List<String> ids = StreamUtils.toList(definitionList, ProcessDefinition::getId);
|
||||
List<WfDefinitionConfigVo> wfDefinitionConfigVos = wfDefinitionConfigService.queryList(ids);
|
||||
for (ProcessDefinition processDefinition : definitionList) {
|
||||
ProcessDefinitionVo processDefinitionVo = BeanUtil.toBean(processDefinition, ProcessDefinitionVo.class);
|
||||
if (CollUtil.isNotEmpty(deploymentList)) {
|
||||
// 部署时间
|
||||
deploymentList.stream().filter(e -> e.getId().equals(processDefinition.getDeploymentId())).findFirst().ifPresent(e -> {
|
||||
processDefinitionVo.setDeploymentTime(e.getDeploymentTime());
|
||||
});
|
||||
if (CollUtil.isNotEmpty(wfDefinitionConfigVos)) {
|
||||
wfDefinitionConfigVos.stream().filter(e -> e.getDefinitionId().equals(processDefinition.getId())).findFirst().ifPresent(processDefinitionVo::setWfDefinitionConfigVo);
|
||||
}
|
||||
}
|
||||
processDefinitionVoList.add(processDefinitionVo);
|
||||
}
|
||||
}
|
||||
return CollUtil.reverse(processDefinitionVoList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看流程定义图片
|
||||
*
|
||||
* @param processDefinitionId 流程定义id
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public String definitionImage(String processDefinitionId) {
|
||||
InputStream inputStream = repositoryService.getProcessDiagram(processDefinitionId);
|
||||
return Base64.encode(IoUtil.readBytes(inputStream));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看流程定义xml文件
|
||||
*
|
||||
* @param processDefinitionId 流程定义id
|
||||
*/
|
||||
@Override
|
||||
public String definitionXml(String processDefinitionId) {
|
||||
StringBuilder xml = new StringBuilder();
|
||||
ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId);
|
||||
InputStream inputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getResourceName());
|
||||
xml.append(IoUtil.read(inputStream, StandardCharsets.UTF_8));
|
||||
return xml.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除流程定义
|
||||
*
|
||||
* @param deploymentIds 部署id
|
||||
* @param processDefinitionIds 流程定义id
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean deleteDeployment(List<String> deploymentIds, List<String> processDefinitionIds) {
|
||||
try {
|
||||
List<HistoricProcessInstance> historicProcessInstances = QueryUtils.hisInstanceQuery().deploymentIdIn(deploymentIds).list();
|
||||
if (CollUtil.isNotEmpty(historicProcessInstances)) {
|
||||
Set<String> defIds = StreamUtils.toSet(historicProcessInstances, HistoricProcessInstance::getProcessDefinitionId);
|
||||
List<ProcessDefinition> processDefinitions = QueryUtils.definitionQuery().processDefinitionIds(defIds).list();
|
||||
if (CollUtil.isNotEmpty(processDefinitions)) {
|
||||
Set<String> keys = StreamUtils.toSet(processDefinitions, ProcessDefinition::getKey);
|
||||
throw new ServiceException("当前【" + String.join(",", keys) + "】流程定义已被使用不可删除!");
|
||||
}
|
||||
}
|
||||
//删除流程定义
|
||||
for (String deploymentId : deploymentIds) {
|
||||
repositoryService.deleteDeployment(deploymentId);
|
||||
}
|
||||
//删除流程定义配置
|
||||
wfDefinitionConfigService.deleteByDefIds(processDefinitionIds);
|
||||
//删除节点配置
|
||||
wfNodeConfigService.deleteByDefIds(processDefinitionIds);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 激活或者挂起流程定义
|
||||
*
|
||||
* @param processDefinitionId 流程定义id
|
||||
*/
|
||||
@Override
|
||||
public boolean updateDefinitionState(String processDefinitionId) {
|
||||
try {
|
||||
ProcessDefinition processDefinition = QueryUtils.definitionQuery()
|
||||
.processDefinitionId(processDefinitionId).singleResult();
|
||||
//将当前为挂起状态更新为激活状态
|
||||
//参数说明:参数1:流程定义id,参数2:是否激活(true是否级联对应流程实例,激活了则对应流程实例都可以审批),
|
||||
//参数3:什么时候激活,如果为null则立即激活,如果为具体时间则到达此时间后激活
|
||||
if (processDefinition.isSuspended()) {
|
||||
repositoryService.activateProcessDefinitionById(processDefinitionId, true, null);
|
||||
} else {
|
||||
repositoryService.suspendProcessDefinitionById(processDefinitionId, true, null);
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
throw new ServiceException("操作失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 迁移流程定义
|
||||
*
|
||||
* @param currentProcessDefinitionId 当前流程定义id
|
||||
* @param fromProcessDefinitionId 需要迁移到的流程定义id
|
||||
*/
|
||||
|
||||
@Override
|
||||
public boolean migrationDefinition(String currentProcessDefinitionId, String fromProcessDefinitionId) {
|
||||
try {
|
||||
// 迁移验证
|
||||
boolean migrationValid = processMigrationService.createProcessInstanceMigrationBuilder()
|
||||
.migrateToProcessDefinition(currentProcessDefinitionId)
|
||||
.validateMigrationOfProcessInstances(fromProcessDefinitionId)
|
||||
.isMigrationValid();
|
||||
if (!migrationValid) {
|
||||
throw new ServiceException("流程定义差异过大无法迁移,请修改流程图");
|
||||
}
|
||||
// 已结束的流程实例不会迁移
|
||||
processMigrationService.createProcessInstanceMigrationBuilder()
|
||||
.migrateToProcessDefinition(currentProcessDefinitionId)
|
||||
.migrateProcessInstances(fromProcessDefinitionId);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 流程定义转换为模型
|
||||
*
|
||||
* @param processDefinitionId 流程定义id
|
||||
*/
|
||||
@Override
|
||||
public boolean convertToModel(String processDefinitionId) {
|
||||
ProcessDefinition pd = QueryUtils.definitionQuery()
|
||||
.processDefinitionId(processDefinitionId).singleResult();
|
||||
InputStream inputStream = repositoryService.getResourceAsStream(pd.getDeploymentId(), pd.getResourceName());
|
||||
ModelQuery query = QueryUtils.modelQuery();
|
||||
Model model = query.modelKey(pd.getKey()).singleResult();
|
||||
try {
|
||||
if (ObjectUtil.isNotNull(model)) {
|
||||
repositoryService.addModelEditorSource(model.getId(), IoUtil.readBytes(inputStream));
|
||||
} else {
|
||||
Model modelData = repositoryService.newModel();
|
||||
modelData.setKey(pd.getKey());
|
||||
modelData.setName(pd.getName());
|
||||
modelData.setCategory(pd.getCategory());
|
||||
modelData.setTenantId(pd.getTenantId());
|
||||
repositoryService.saveModel(modelData);
|
||||
repositoryService.addModelEditorSource(modelData.getId(), IoUtil.readBytes(inputStream));
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过zip或xml部署流程定义
|
||||
*
|
||||
* @param file 文件
|
||||
* @param categoryCode 分类
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deployByFile(MultipartFile file, String categoryCode) {
|
||||
|
||||
WfCategory wfCategory = wfCategoryService.queryByCategoryCode(categoryCode);
|
||||
if (wfCategory == null) {
|
||||
throw new ServiceException("流程分类不存在");
|
||||
}
|
||||
// 文件后缀名
|
||||
String suffix = FileUtil.extName(file.getOriginalFilename());
|
||||
InputStream inputStream = file.getInputStream();
|
||||
if (FlowConstant.ZIP.equalsIgnoreCase(suffix)) {
|
||||
ZipInputStream zipInputStream = null;
|
||||
try {
|
||||
zipInputStream = new ZipInputStream(inputStream);
|
||||
ZipEntry zipEntry;
|
||||
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
|
||||
String filename = zipEntry.getName();
|
||||
String[] splitFilename = filename.substring(0, filename.lastIndexOf(".")).split("-");
|
||||
//流程名称
|
||||
String processName = splitFilename[0];
|
||||
//流程key
|
||||
String processKey = splitFilename[1];
|
||||
ProcessDefinition oldProcessDefinition = QueryUtils.definitionQuery().processDefinitionKey(processKey).latestVersion().singleResult();
|
||||
DeploymentBuilder builder = repositoryService.createDeployment();
|
||||
Deployment deployment = builder.addInputStream(filename, zipInputStream)
|
||||
.tenantId(TenantHelper.getTenantId())
|
||||
.name(processName).key(processKey).category(categoryCode).deploy();
|
||||
ProcessDefinition definition = QueryUtils.definitionQuery().deploymentId(deployment.getId()).singleResult();
|
||||
repositoryService.setProcessDefinitionCategory(definition.getId(), categoryCode);
|
||||
setWfConfig(oldProcessDefinition, definition);
|
||||
zipInputStream.closeEntry();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
if (zipInputStream != null) {
|
||||
zipInputStream.close();
|
||||
}
|
||||
}
|
||||
//初始化配置数据(demo使用,不用可删除)
|
||||
initWfDefConfig();
|
||||
} else {
|
||||
String originalFilename = file.getOriginalFilename();
|
||||
if (StringUtils.containsAny(originalFilename, ResourceNameUtil.BPMN_RESOURCE_SUFFIXES)) {
|
||||
// 文件名 = 流程名称-流程key
|
||||
String[] splitFilename = originalFilename.substring(0, originalFilename.lastIndexOf(".")).split("-");
|
||||
if (splitFilename.length < 2) {
|
||||
throw new ServiceException("文件名 = 流程名称-流程KEY");
|
||||
}
|
||||
//流程名称
|
||||
String processName = splitFilename[0];
|
||||
//流程key
|
||||
String processKey = splitFilename[1];
|
||||
ProcessDefinition oldProcessDefinition = QueryUtils.definitionQuery().processDefinitionKey(processKey).latestVersion().singleResult();
|
||||
DeploymentBuilder builder = repositoryService.createDeployment();
|
||||
Deployment deployment = builder.addInputStream(originalFilename, inputStream)
|
||||
.tenantId(TenantHelper.getTenantId())
|
||||
.name(processName).key(processKey).category(categoryCode).deploy();
|
||||
// 更新分类
|
||||
ProcessDefinition definition = QueryUtils.definitionQuery().deploymentId(deployment.getId()).singleResult();
|
||||
repositoryService.setProcessDefinitionCategory(definition.getId(), categoryCode);
|
||||
setWfConfig(oldProcessDefinition, definition);
|
||||
} else {
|
||||
throw new ServiceException("文件类型上传错误!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化配置数据(demo使用,不用可删除)
|
||||
*/
|
||||
private void initWfDefConfig() {
|
||||
List<WfDefinitionConfig> wfDefinitionConfigs = wfDefinitionConfigMapper.selectList();
|
||||
if (CollUtil.isEmpty(wfDefinitionConfigs)) {
|
||||
ProcessDefinition processDefinition = QueryUtils.definitionQuery().processDefinitionKey("leave1").latestVersion().singleResult();
|
||||
if (processDefinition != null) {
|
||||
WfDefinitionConfigBo wfDefinitionConfigBo = new WfDefinitionConfigBo();
|
||||
wfDefinitionConfigBo.setDefinitionId(processDefinition.getId());
|
||||
wfDefinitionConfigBo.setProcessKey(processDefinition.getKey());
|
||||
wfDefinitionConfigBo.setTableName("test_leave");
|
||||
wfDefinitionConfigBo.setVersion(processDefinition.getVersion());
|
||||
wfDefinitionConfigService.saveOrUpdate(wfDefinitionConfigBo);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置表单内容
|
||||
*
|
||||
* @param oldProcessDefinition 部署前最新流程定义
|
||||
* @param definition 部署后最新流程定义
|
||||
*/
|
||||
private void setWfConfig(ProcessDefinition oldProcessDefinition, ProcessDefinition definition) {
|
||||
//更新流程定义表单
|
||||
if (oldProcessDefinition != null) {
|
||||
WfDefinitionConfigVo definitionVo = wfDefinitionConfigService.getByDefId(oldProcessDefinition.getId());
|
||||
if (definitionVo != null) {
|
||||
wfDefinitionConfigService.deleteByDefIds(Collections.singletonList(oldProcessDefinition.getId()));
|
||||
WfDefinitionConfigBo wfDefinitionConfigBo = new WfDefinitionConfigBo();
|
||||
wfDefinitionConfigBo.setDefinitionId(definition.getId());
|
||||
wfDefinitionConfigBo.setProcessKey(definition.getKey());
|
||||
wfDefinitionConfigBo.setTableName(definitionVo.getTableName());
|
||||
wfDefinitionConfigBo.setVersion(definition.getVersion());
|
||||
wfDefinitionConfigBo.setRemark(definitionVo.getRemark());
|
||||
wfDefinitionConfigService.saveOrUpdate(wfDefinitionConfigBo);
|
||||
}
|
||||
}
|
||||
//更新流程节点配置表单
|
||||
List<UserTask> userTasks = ModelUtils.getUserTaskFlowElements(definition.getId());
|
||||
UserTask applyUserTask = ModelUtils.getApplyUserTask(definition.getId());
|
||||
List<WfNodeConfig> wfNodeConfigList = new ArrayList<>();
|
||||
for (UserTask userTask : userTasks) {
|
||||
if (StringUtils.isNotBlank(userTask.getFormKey()) && userTask.getFormKey().contains(StrUtil.COLON)) {
|
||||
WfNodeConfig wfNodeConfig = new WfNodeConfig();
|
||||
wfNodeConfig.setNodeId(userTask.getId());
|
||||
wfNodeConfig.setNodeName(userTask.getName());
|
||||
wfNodeConfig.setDefinitionId(definition.getId());
|
||||
String[] split = userTask.getFormKey().split(StrUtil.COLON);
|
||||
wfNodeConfig.setFormType(split[0]);
|
||||
wfNodeConfig.setFormId(Long.valueOf(split[1]));
|
||||
wfNodeConfig.setApplyUserTask(applyUserTask.getId().equals(userTask.getId()) ? FlowConstant.TRUE : FlowConstant.FALSE);
|
||||
wfNodeConfigList.add(wfNodeConfig);
|
||||
}
|
||||
}
|
||||
if (CollUtil.isNotEmpty(wfNodeConfigList)) {
|
||||
wfNodeConfigService.saveOrUpdate(wfNodeConfigList);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,691 @@
|
||||
package org.dromara.workflow.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.enums.BusinessStatusEnum;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.service.UserService;
|
||||
import org.dromara.common.core.utils.StreamUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.satoken.utils.LoginHelper;
|
||||
import org.dromara.workflow.common.constant.FlowConstant;
|
||||
import org.dromara.workflow.common.enums.TaskStatusEnum;
|
||||
import org.dromara.workflow.domain.ActHiProcinst;
|
||||
import org.dromara.workflow.domain.bo.ProcessInstanceBo;
|
||||
import org.dromara.workflow.domain.bo.ProcessInvalidBo;
|
||||
import org.dromara.workflow.domain.bo.TaskUrgingBo;
|
||||
import org.dromara.workflow.domain.vo.*;
|
||||
import org.dromara.workflow.flowable.CustomDefaultProcessDiagramGenerator;
|
||||
import org.dromara.workflow.flowable.cmd.DeleteExecutionCmd;
|
||||
import org.dromara.workflow.flowable.cmd.ExecutionChildByExecutionIdCmd;
|
||||
import org.dromara.workflow.flowable.handler.FlowProcessEventHandler;
|
||||
import org.dromara.workflow.service.IActHiProcinstService;
|
||||
import org.dromara.workflow.service.IActProcessInstanceService;
|
||||
import org.dromara.workflow.service.IWfNodeConfigService;
|
||||
import org.dromara.workflow.service.IWfTaskBackNodeService;
|
||||
import org.dromara.workflow.utils.QueryUtils;
|
||||
import org.dromara.workflow.utils.WorkflowUtils;
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.engine.*;
|
||||
import org.flowable.engine.history.HistoricActivityInstance;
|
||||
import org.flowable.engine.history.HistoricProcessInstance;
|
||||
import org.flowable.engine.history.HistoricProcessInstanceQuery;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
|
||||
import org.flowable.engine.repository.ProcessDefinition;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.flowable.engine.runtime.ProcessInstanceQuery;
|
||||
import org.flowable.engine.task.Attachment;
|
||||
import org.flowable.engine.task.Comment;
|
||||
import org.flowable.task.api.Task;
|
||||
import org.flowable.task.api.history.HistoricTaskInstance;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 流程实例 服务层实现
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class ActProcessInstanceServiceImpl implements IActProcessInstanceService {
|
||||
|
||||
@Autowired(required = false)
|
||||
private RepositoryService repositoryService;
|
||||
@Autowired(required = false)
|
||||
private RuntimeService runtimeService;
|
||||
@Autowired(required = false)
|
||||
private HistoryService historyService;
|
||||
@Autowired(required = false)
|
||||
private TaskService taskService;
|
||||
@Autowired(required = false)
|
||||
private ManagementService managementService;
|
||||
private final IActHiProcinstService actHiProcinstService;
|
||||
private final IWfTaskBackNodeService wfTaskBackNodeService;
|
||||
private final IWfNodeConfigService wfNodeConfigService;
|
||||
private final FlowProcessEventHandler flowProcessEventHandler;
|
||||
private final UserService userService;
|
||||
|
||||
@Value("${flowable.activity-font-name}")
|
||||
private String activityFontName;
|
||||
|
||||
@Value("${flowable.label-font-name}")
|
||||
private String labelFontName;
|
||||
|
||||
@Value("${flowable.annotation-font-name}")
|
||||
private String annotationFontName;
|
||||
|
||||
/**
|
||||
* 分页查询正在运行的流程实例
|
||||
*
|
||||
* @param bo 参数
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<ProcessInstanceVo> getPageByRunning(ProcessInstanceBo bo, PageQuery pageQuery) {
|
||||
List<ProcessInstanceVo> list = new ArrayList<>();
|
||||
ProcessInstanceQuery query = QueryUtils.instanceQuery();
|
||||
if (StringUtils.isNotBlank(bo.getName())) {
|
||||
query.processInstanceNameLikeIgnoreCase("%" + bo.getName() + "%");
|
||||
}
|
||||
if (StringUtils.isNotBlank(bo.getKey())) {
|
||||
query.processDefinitionKey(bo.getKey());
|
||||
}
|
||||
if (StringUtils.isNotBlank(bo.getStartUserId())) {
|
||||
query.startedBy(bo.getStartUserId());
|
||||
}
|
||||
if (StringUtils.isNotBlank(bo.getBusinessKey())) {
|
||||
query.processInstanceBusinessKey(bo.getBusinessKey());
|
||||
}
|
||||
if (StringUtils.isNotBlank(bo.getCategoryCode())) {
|
||||
query.processDefinitionCategory(bo.getCategoryCode());
|
||||
}
|
||||
query.orderByStartTime().desc();
|
||||
List<ProcessInstance> processInstances = query.listPage(pageQuery.getFirstNum(), pageQuery.getPageSize());
|
||||
for (ProcessInstance processInstance : processInstances) {
|
||||
ProcessInstanceVo processInstanceVo = BeanUtil.toBean(processInstance, ProcessInstanceVo.class);
|
||||
processInstanceVo.setIsSuspended(processInstance.isSuspended());
|
||||
processInstanceVo.setBusinessStatusName(BusinessStatusEnum.findByStatus(processInstance.getBusinessStatus()));
|
||||
list.add(processInstanceVo);
|
||||
}
|
||||
if (CollUtil.isNotEmpty(list)) {
|
||||
List<String> processDefinitionIds = StreamUtils.toList(list, ProcessInstanceVo::getProcessDefinitionId);
|
||||
List<WfNodeConfigVo> wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds);
|
||||
for (ProcessInstanceVo processInstanceVo : list) {
|
||||
if (CollUtil.isNotEmpty(wfNodeConfigVoList)) {
|
||||
wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(processInstanceVo.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(processInstanceVo::setWfNodeConfigVo);
|
||||
}
|
||||
}
|
||||
}
|
||||
long count = query.count();
|
||||
TableDataInfo<ProcessInstanceVo> build = TableDataInfo.build();
|
||||
build.setRows(list);
|
||||
build.setTotal(count);
|
||||
return build;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询已结束的流程实例
|
||||
*
|
||||
* @param bo 参数
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<ProcessInstanceVo> getPageByFinish(ProcessInstanceBo bo, PageQuery pageQuery) {
|
||||
List<ProcessInstanceVo> list = new ArrayList<>();
|
||||
HistoricProcessInstanceQuery query = QueryUtils.hisInstanceQuery()
|
||||
.finished().orderByProcessInstanceEndTime().desc();
|
||||
if (StringUtils.isNotEmpty(bo.getName())) {
|
||||
query.processInstanceNameLikeIgnoreCase("%" + bo.getName() + "%");
|
||||
}
|
||||
if (StringUtils.isNotBlank(bo.getKey())) {
|
||||
query.processDefinitionKey(bo.getKey());
|
||||
}
|
||||
if (StringUtils.isNotEmpty(bo.getStartUserId())) {
|
||||
query.startedBy(bo.getStartUserId());
|
||||
}
|
||||
if (StringUtils.isNotBlank(bo.getBusinessKey())) {
|
||||
query.processInstanceBusinessKey(bo.getBusinessKey());
|
||||
}
|
||||
if (StringUtils.isNotBlank(bo.getCategoryCode())) {
|
||||
query.processDefinitionCategory(bo.getCategoryCode());
|
||||
}
|
||||
List<HistoricProcessInstance> historicProcessInstances = query.listPage(pageQuery.getFirstNum(), pageQuery.getPageSize());
|
||||
for (HistoricProcessInstance historicProcessInstance : historicProcessInstances) {
|
||||
ProcessInstanceVo processInstanceVo = BeanUtil.toBean(historicProcessInstance, ProcessInstanceVo.class);
|
||||
processInstanceVo.setBusinessStatusName(BusinessStatusEnum.findByStatus(historicProcessInstance.getBusinessStatus()));
|
||||
list.add(processInstanceVo);
|
||||
}
|
||||
if (CollUtil.isNotEmpty(list)) {
|
||||
List<String> processDefinitionIds = StreamUtils.toList(list, ProcessInstanceVo::getProcessDefinitionId);
|
||||
List<WfNodeConfigVo> wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds);
|
||||
for (ProcessInstanceVo processInstanceVo : list) {
|
||||
if (CollUtil.isNotEmpty(wfNodeConfigVoList)) {
|
||||
wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(processInstanceVo.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(processInstanceVo::setWfNodeConfigVo);
|
||||
}
|
||||
}
|
||||
}
|
||||
long count = query.count();
|
||||
TableDataInfo<ProcessInstanceVo> build = TableDataInfo.build();
|
||||
build.setRows(list);
|
||||
build.setTotal(count);
|
||||
return build;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过业务id获取历史流程图
|
||||
*
|
||||
* @param businessKey 业务id
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public String getHistoryImage(String businessKey) {
|
||||
String processDefinitionId;
|
||||
// 获取当前的流程实例
|
||||
ProcessInstance processInstance = QueryUtils.businessKeyQuery(businessKey).singleResult();
|
||||
// 如果流程已经结束,则得到结束节点
|
||||
if (Objects.isNull(processInstance)) {
|
||||
HistoricProcessInstance pi = QueryUtils.hisInstanceQuery().processInstanceBusinessKey(businessKey).singleResult();
|
||||
processDefinitionId = pi.getProcessDefinitionId();
|
||||
} else {
|
||||
// 根据流程实例ID获得当前处于活动状态的ActivityId合集
|
||||
ProcessInstance pi = QueryUtils.instanceQuery(processInstance.getProcessInstanceId()).singleResult();
|
||||
processDefinitionId = pi.getProcessDefinitionId();
|
||||
}
|
||||
|
||||
// 获得活动的节点
|
||||
List<HistoricActivityInstance> highLightedFlowList = QueryUtils.hisActivityInstanceQuery(processInstance.getProcessInstanceId()).orderByHistoricActivityInstanceStartTime().asc().list();
|
||||
|
||||
List<String> highLightedFlows = new ArrayList<>();
|
||||
List<String> highLightedNodes = new ArrayList<>();
|
||||
//高亮
|
||||
for (HistoricActivityInstance tempActivity : highLightedFlowList) {
|
||||
if (FlowConstant.SEQUENCE_FLOW.equals(tempActivity.getActivityType())) {
|
||||
//高亮线
|
||||
highLightedFlows.add(tempActivity.getActivityId());
|
||||
} else {
|
||||
//高亮节点
|
||||
if (tempActivity.getEndTime() == null) {
|
||||
highLightedNodes.add(Color.RED.toString() + tempActivity.getActivityId());
|
||||
} else {
|
||||
highLightedNodes.add(tempActivity.getActivityId());
|
||||
}
|
||||
}
|
||||
}
|
||||
List<String> highLightedNodeList = new ArrayList<>();
|
||||
//运行中的节点
|
||||
List<String> redNodeCollect = StreamUtils.filter(highLightedNodes, e -> e.contains(Color.RED.toString()));
|
||||
//排除与运行中相同的节点
|
||||
for (String nodeId : highLightedNodes) {
|
||||
if (!nodeId.contains(Color.RED.toString()) && !redNodeCollect.contains(Color.RED + nodeId)) {
|
||||
highLightedNodeList.add(nodeId);
|
||||
}
|
||||
}
|
||||
highLightedNodeList.addAll(redNodeCollect);
|
||||
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
|
||||
CustomDefaultProcessDiagramGenerator diagramGenerator = new CustomDefaultProcessDiagramGenerator();
|
||||
InputStream inputStream = diagramGenerator.generateDiagram(bpmnModel, "png", highLightedNodeList, highLightedFlows, activityFontName, labelFontName, annotationFontName, null, 1.0, true);
|
||||
return Base64.encode(IoUtil.readBytes(inputStream));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过业务id获取历史流程图运行中,历史等节点
|
||||
*
|
||||
* @param businessKey 业务id
|
||||
*/
|
||||
@Override
|
||||
public Map<String, Object> getHistoryList(String businessKey) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
List<Map<String, Object>> taskList = new ArrayList<>();
|
||||
HistoricProcessInstance historicProcessInstance = QueryUtils.hisBusinessKeyQuery(businessKey).singleResult();
|
||||
String processInstanceId = historicProcessInstance.getId();
|
||||
StringBuilder xml = new StringBuilder();
|
||||
ProcessDefinition processDefinition = repositoryService.getProcessDefinition(historicProcessInstance.getProcessDefinitionId());
|
||||
// 获取节点
|
||||
List<HistoricActivityInstance> highLightedFlowList = QueryUtils.hisActivityInstanceQuery(processInstanceId).orderByHistoricActivityInstanceStartTime().asc().list();
|
||||
for (HistoricActivityInstance tempActivity : highLightedFlowList) {
|
||||
Map<String, Object> task = new HashMap<>();
|
||||
switch (tempActivity.getActivityType()) {
|
||||
case FlowConstant.SEQUENCE_FLOW, FlowConstant.PARALLEL_GATEWAY,
|
||||
FlowConstant.EXCLUSIVE_GATEWAY, FlowConstant.INCLUSIVE_GATEWAY -> {}
|
||||
default -> {
|
||||
task.put("key", tempActivity.getActivityId());
|
||||
task.put("completed", tempActivity.getEndTime() != null);
|
||||
task.put("activityType", tempActivity.getActivityType());
|
||||
taskList.add(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
ProcessInstance processInstance = QueryUtils.instanceQuery(processInstanceId).singleResult();
|
||||
if (processInstance != null) {
|
||||
taskList = StreamUtils.filter(taskList, e -> !e.get("activityType").equals(FlowConstant.END_EVENT));
|
||||
}
|
||||
//查询出运行中节点
|
||||
List<Map<String, Object>> runtimeNodeList = StreamUtils.filter(taskList, e -> !(Boolean) e.get("completed"));
|
||||
if (CollUtil.isNotEmpty(runtimeNodeList)) {
|
||||
Iterator<Map<String, Object>> iterator = taskList.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map<String, Object> next = iterator.next();
|
||||
runtimeNodeList.stream().filter(t -> t.get("key").equals(next.get("key")) && (Boolean) next.get("completed")).findFirst().ifPresent(t -> iterator.remove());
|
||||
}
|
||||
}
|
||||
map.put("taskList", taskList);
|
||||
List<ActHistoryInfoVo> historyTaskList = getHistoryTaskList(processInstanceId, processDefinition.getVersion());
|
||||
map.put("historyList", historyTaskList);
|
||||
InputStream inputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getResourceName());
|
||||
xml.append(IoUtil.read(inputStream, StandardCharsets.UTF_8));
|
||||
map.put("xml", xml.toString());
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取历史任务节点信息
|
||||
*
|
||||
* @param processInstanceId 流程实例id
|
||||
* @param version 版本
|
||||
*/
|
||||
private List<ActHistoryInfoVo> getHistoryTaskList(String processInstanceId, Integer version) {
|
||||
//查询任务办理记录
|
||||
List<HistoricTaskInstance> list = QueryUtils.hisTaskInstanceQuery(processInstanceId).orderByHistoricTaskInstanceEndTime().desc().list();
|
||||
list = StreamUtils.sorted(list, Comparator.comparing(HistoricTaskInstance::getEndTime, Comparator.nullsFirst(Date::compareTo)).reversed());
|
||||
List<ActHistoryInfoVo> actHistoryInfoVoList = new ArrayList<>();
|
||||
for (HistoricTaskInstance historicTaskInstance : list) {
|
||||
ActHistoryInfoVo actHistoryInfoVo = new ActHistoryInfoVo();
|
||||
BeanUtils.copyProperties(historicTaskInstance, actHistoryInfoVo);
|
||||
actHistoryInfoVo.setStatus(actHistoryInfoVo.getEndTime() == null ? "待处理" : "已处理");
|
||||
if (ObjectUtil.isNotEmpty(historicTaskInstance.getDurationInMillis())) {
|
||||
actHistoryInfoVo.setRunDuration(getDuration(historicTaskInstance.getDurationInMillis()));
|
||||
}
|
||||
actHistoryInfoVo.setVersion(version);
|
||||
actHistoryInfoVoList.add(actHistoryInfoVo);
|
||||
}
|
||||
List<ActHistoryInfoVo> historyInfoVoList = new ArrayList<>();
|
||||
Map<String, List<ActHistoryInfoVo>> groupByKey = StreamUtils.groupByKey(actHistoryInfoVoList, ActHistoryInfoVo::getTaskDefinitionKey);
|
||||
for (Map.Entry<String, List<ActHistoryInfoVo>> entry : groupByKey.entrySet()) {
|
||||
ActHistoryInfoVo historyInfoVo = new ActHistoryInfoVo();
|
||||
if (entry.getValue().size() > 1) {
|
||||
List<ActHistoryInfoVo> historyInfoVos = StreamUtils.filter(entry.getValue(), e -> StringUtils.isNotBlank(e.getAssignee()));
|
||||
if (CollUtil.isNotEmpty(historyInfoVos)) {
|
||||
ActHistoryInfoVo infoVo = historyInfoVos.get(0);
|
||||
BeanUtils.copyProperties(infoVo, historyInfoVo);
|
||||
historyInfoVo.setStatus(infoVo.getEndTime() == null ? "待处理" : "已处理");
|
||||
historyInfoVo.setStartTime(infoVo.getStartTime());
|
||||
historyInfoVo.setEndTime(infoVo.getEndTime() == null ? null : infoVo.getEndTime());
|
||||
historyInfoVo.setRunDuration(infoVo.getEndTime() == null ? null : infoVo.getRunDuration());
|
||||
if (ObjectUtil.isEmpty(infoVo.getAssignee())) {
|
||||
ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(infoVo.getId(), userService);
|
||||
if (ObjectUtil.isNotEmpty(participantVo) && CollUtil.isNotEmpty(participantVo.getCandidate())) {
|
||||
historyInfoVo.setAssignee(StreamUtils.join(participantVo.getCandidate(), Convert::toStr));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
actHistoryInfoVoList.stream().filter(e -> e.getTaskDefinitionKey().equals(entry.getKey())).findFirst()
|
||||
.ifPresent(e -> {
|
||||
BeanUtils.copyProperties(e, historyInfoVo);
|
||||
historyInfoVo.setStatus(e.getEndTime() == null ? "待处理" : "已处理");
|
||||
historyInfoVo.setStartTime(e.getStartTime());
|
||||
historyInfoVo.setEndTime(e.getEndTime() == null ? null : e.getEndTime());
|
||||
historyInfoVo.setRunDuration(e.getEndTime() == null ? null : e.getRunDuration());
|
||||
if (ObjectUtil.isEmpty(e.getAssignee())) {
|
||||
ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(e.getId(), userService);
|
||||
if (ObjectUtil.isNotEmpty(participantVo) && CollUtil.isNotEmpty(participantVo.getCandidate())) {
|
||||
historyInfoVo.setAssignee(StreamUtils.join(participantVo.getCandidate(), Convert::toStr));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
historyInfoVoList.add(historyInfoVo);
|
||||
|
||||
}
|
||||
return historyInfoVoList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取审批记录
|
||||
*
|
||||
* @param businessKey 业务id
|
||||
*/
|
||||
@Override
|
||||
public List<ActHistoryInfoVo> getHistoryRecord(String businessKey) {
|
||||
// 查询任务办理记录
|
||||
List<HistoricTaskInstance> list = QueryUtils.hisTaskBusinessKeyQuery(businessKey).orderByHistoricTaskInstanceEndTime().desc().list();
|
||||
list = StreamUtils.sorted(list, Comparator.comparing(HistoricTaskInstance::getEndTime, Comparator.nullsFirst(Date::compareTo)).reversed());
|
||||
HistoricProcessInstance historicProcessInstance = QueryUtils.hisBusinessKeyQuery(businessKey).singleResult();
|
||||
String processInstanceId = historicProcessInstance.getId();
|
||||
List<ActHistoryInfoVo> actHistoryInfoVoList = new ArrayList<>();
|
||||
List<Comment> processInstanceComments = taskService.getProcessInstanceComments(processInstanceId);
|
||||
//附件
|
||||
List<Attachment> attachmentList = taskService.getProcessInstanceAttachments(processInstanceId);
|
||||
for (HistoricTaskInstance historicTaskInstance : list) {
|
||||
ActHistoryInfoVo actHistoryInfoVo = new ActHistoryInfoVo();
|
||||
BeanUtils.copyProperties(historicTaskInstance, actHistoryInfoVo);
|
||||
if (actHistoryInfoVo.getEndTime() == null) {
|
||||
actHistoryInfoVo.setStatus(TaskStatusEnum.WAITING.getStatus());
|
||||
actHistoryInfoVo.setStatusName(TaskStatusEnum.WAITING.getDesc());
|
||||
}
|
||||
if (CollUtil.isNotEmpty(processInstanceComments)) {
|
||||
processInstanceComments.stream().filter(e -> e.getTaskId().equals(historicTaskInstance.getId())).findFirst().ifPresent(e -> {
|
||||
actHistoryInfoVo.setComment(e.getFullMessage());
|
||||
actHistoryInfoVo.setStatus(e.getType());
|
||||
actHistoryInfoVo.setStatusName(TaskStatusEnum.findByStatus(e.getType()));
|
||||
});
|
||||
}
|
||||
if (ObjectUtil.isNotEmpty(historicTaskInstance.getDurationInMillis())) {
|
||||
actHistoryInfoVo.setRunDuration(getDuration(historicTaskInstance.getDurationInMillis()));
|
||||
}
|
||||
//附件
|
||||
if (CollUtil.isNotEmpty(attachmentList)) {
|
||||
List<Attachment> attachments = StreamUtils.filter(attachmentList, e -> e.getTaskId().equals(historicTaskInstance.getId()));
|
||||
if (CollUtil.isNotEmpty(attachments)) {
|
||||
actHistoryInfoVo.setAttachmentList(attachments);
|
||||
}
|
||||
}
|
||||
//设置人员id
|
||||
if (ObjectUtil.isEmpty(historicTaskInstance.getAssignee())) {
|
||||
ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(historicTaskInstance.getId(), userService);
|
||||
if (ObjectUtil.isNotEmpty(participantVo) && CollUtil.isNotEmpty(participantVo.getCandidate())) {
|
||||
actHistoryInfoVo.setAssignee(StreamUtils.join(participantVo.getCandidate(), Convert::toStr));
|
||||
}
|
||||
}
|
||||
actHistoryInfoVoList.add(actHistoryInfoVo);
|
||||
}
|
||||
// 审批记录
|
||||
Map<String, List<ActHistoryInfoVo>> groupByKey = StreamUtils.groupByKey(actHistoryInfoVoList, ActHistoryInfoVo::getTaskDefinitionKey);
|
||||
for (Map.Entry<String, List<ActHistoryInfoVo>> entry : groupByKey.entrySet()) {
|
||||
ActHistoryInfoVo actHistoryInfoVo = BeanUtil.toBean(entry.getValue().get(0), ActHistoryInfoVo.class);
|
||||
actHistoryInfoVoList.stream().filter(e -> e.getTaskDefinitionKey().equals(entry.getKey()) && e.getEndTime() != null).findFirst()
|
||||
.ifPresent(e -> {
|
||||
actHistoryInfoVo.setStatus("已处理");
|
||||
actHistoryInfoVo.setStartTime(e.getStartTime());
|
||||
});
|
||||
actHistoryInfoVoList.stream().filter(e -> e.getTaskDefinitionKey().equals(entry.getKey()) && e.getEndTime() == null).findFirst()
|
||||
.ifPresent(e -> {
|
||||
actHistoryInfoVo.setStatus("待处理");
|
||||
actHistoryInfoVo.setStartTime(e.getStartTime());
|
||||
actHistoryInfoVo.setEndTime(null);
|
||||
actHistoryInfoVo.setRunDuration(null);
|
||||
});
|
||||
}
|
||||
List<ActHistoryInfoVo> recordList = new ArrayList<>();
|
||||
// 待办理
|
||||
recordList.addAll(StreamUtils.filter(actHistoryInfoVoList, e -> e.getEndTime() == null));
|
||||
// 已办理
|
||||
recordList.addAll(StreamUtils.filter(actHistoryInfoVoList, e -> e.getEndTime() != null));
|
||||
|
||||
return recordList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务完成时间处理
|
||||
*
|
||||
* @param time 时间
|
||||
*/
|
||||
private String getDuration(long time) {
|
||||
|
||||
long day = time / (24 * 60 * 60 * 1000);
|
||||
long hour = (time / (60 * 60 * 1000) - day * 24);
|
||||
long minute = ((time / (60 * 1000)) - day * 24 * 60 - hour * 60);
|
||||
long second = (time / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60);
|
||||
|
||||
if (day > 0) {
|
||||
return day + "天" + hour + "小时" + minute + "分钟";
|
||||
}
|
||||
if (hour > 0) {
|
||||
return hour + "小时" + minute + "分钟";
|
||||
}
|
||||
if (minute > 0) {
|
||||
return minute + "分钟";
|
||||
}
|
||||
if (second > 0) {
|
||||
return second + "秒";
|
||||
} else {
|
||||
return 0 + "秒";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 作废流程实例,不会删除历史记录(删除运行中的实例)
|
||||
*
|
||||
* @param processInvalidBo 参数
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean deleteRunInstance(ProcessInvalidBo processInvalidBo) {
|
||||
try {
|
||||
List<Task> list = QueryUtils.taskQuery().processInstanceBusinessKey(processInvalidBo.getBusinessKey()).list();
|
||||
String processInstanceId = list.get(0).getProcessInstanceId();
|
||||
List<Task> subTasks = StreamUtils.filter(list, e -> StringUtils.isNotBlank(e.getParentTaskId()));
|
||||
if (CollUtil.isNotEmpty(subTasks)) {
|
||||
subTasks.forEach(e -> taskService.deleteTask(e.getId()));
|
||||
}
|
||||
String deleteReason = LoginHelper.getLoginUser().getNickname() + "作废了当前申请!";
|
||||
if (StringUtils.isNotBlank(processInvalidBo.getDeleteReason())) {
|
||||
deleteReason = LoginHelper.getLoginUser().getNickname() + "作废理由:" + processInvalidBo.getDeleteReason();
|
||||
}
|
||||
for (Task task : StreamUtils.filter(list, e -> StringUtils.isBlank(e.getParentTaskId()))) {
|
||||
taskService.addComment(task.getId(), task.getProcessInstanceId(), TaskStatusEnum.INVALID.getStatus(), deleteReason);
|
||||
}
|
||||
HistoricProcessInstance historicProcessInstance = QueryUtils.hisInstanceQuery(processInstanceId).singleResult();
|
||||
BusinessStatusEnum.checkInvalidStatus(historicProcessInstance.getBusinessStatus());
|
||||
runtimeService.updateBusinessStatus(processInstanceId, BusinessStatusEnum.INVALID.getStatus());
|
||||
runtimeService.deleteProcessInstance(processInstanceId, deleteReason);
|
||||
//流程作废监听
|
||||
flowProcessEventHandler.processHandler(historicProcessInstance.getProcessDefinitionKey(),
|
||||
historicProcessInstance.getBusinessKey(), BusinessStatusEnum.INVALID.getStatus(), false);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息
|
||||
*
|
||||
* @param businessKeys 业务id
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean deleteRunAndHisInstance(List<String> businessKeys) {
|
||||
try {
|
||||
// 1.删除运行中流程实例
|
||||
List<ActHiProcinst> actHiProcinsts = actHiProcinstService.selectByBusinessKeyIn(businessKeys);
|
||||
if (CollUtil.isEmpty(actHiProcinsts)) {
|
||||
log.warn("当前业务ID:{}查询到流程实例为空!", businessKeys);
|
||||
return false;
|
||||
}
|
||||
List<String> processInstanceIds = StreamUtils.toList(actHiProcinsts, ActHiProcinst::getId);
|
||||
List<Task> list = QueryUtils.taskQuery(processInstanceIds).list();
|
||||
List<Task> subTasks = StreamUtils.filter(list, e -> StringUtils.isNotBlank(e.getParentTaskId()));
|
||||
if (CollUtil.isNotEmpty(subTasks)) {
|
||||
subTasks.forEach(e -> taskService.deleteTask(e.getId()));
|
||||
}
|
||||
runtimeService.bulkDeleteProcessInstances(processInstanceIds, LoginHelper.getUserId() + "删除了当前流程申请");
|
||||
// 2.删除历史记录
|
||||
List<HistoricProcessInstance> historicProcessInstanceList = QueryUtils.hisInstanceQuery(new HashSet<>(processInstanceIds)).list();
|
||||
if (ObjectUtil.isNotEmpty(historicProcessInstanceList)) {
|
||||
historyService.bulkDeleteHistoricProcessInstances(processInstanceIds);
|
||||
}
|
||||
wfTaskBackNodeService.deleteByInstanceIds(processInstanceIds);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 已完成的实例 删除程实例,删除历史记录,删除业务与流程关联信息
|
||||
*
|
||||
* @param businessKeys 业务id
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean deleteFinishAndHisInstance(List<String> businessKeys) {
|
||||
try {
|
||||
List<ActHiProcinst> actHiProcinsts = actHiProcinstService.selectByBusinessKeyIn(businessKeys);
|
||||
if (CollUtil.isEmpty(actHiProcinsts)) {
|
||||
log.warn("当前业务ID:{}查询到流程实例为空!", businessKeys);
|
||||
return false;
|
||||
}
|
||||
List<String> processInstanceIds = StreamUtils.toList(actHiProcinsts, ActHiProcinst::getId);
|
||||
historyService.bulkDeleteHistoricProcessInstances(processInstanceIds);
|
||||
wfTaskBackNodeService.deleteByInstanceIds(processInstanceIds);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 撤销流程申请
|
||||
*
|
||||
* @param businessKey 业务id
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean cancelProcessApply(String businessKey) {
|
||||
try {
|
||||
ProcessInstance processInstance = QueryUtils.businessKeyQuery(businessKey)
|
||||
.startedBy(String.valueOf(LoginHelper.getUserId())).singleResult();
|
||||
if (ObjectUtil.isNull(processInstance)) {
|
||||
throw new ServiceException("您不是流程发起人,撤销失败!");
|
||||
}
|
||||
if (processInstance.isSuspended()) {
|
||||
throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED);
|
||||
}
|
||||
String processInstanceId = processInstance.getId();
|
||||
BusinessStatusEnum.checkCancelStatus(processInstance.getBusinessStatus());
|
||||
List<Task> taskList = QueryUtils.taskQuery(processInstanceId).list();
|
||||
for (Task task : taskList) {
|
||||
taskService.setAssignee(task.getId(), null);
|
||||
taskService.addComment(task.getId(), processInstanceId, TaskStatusEnum.CANCEL.getStatus(), LoginHelper.getLoginUser().getNickname() + ":撤销申请");
|
||||
}
|
||||
HistoricTaskInstance historicTaskInstance = QueryUtils.hisTaskInstanceQuery(processInstanceId).finished().orderByHistoricTaskInstanceEndTime().asc().list().get(0);
|
||||
List<String> nodeIds = StreamUtils.toList(taskList, Task::getTaskDefinitionKey);
|
||||
runtimeService.createChangeActivityStateBuilder()
|
||||
.processInstanceId(processInstanceId)
|
||||
.moveActivityIdsToSingleActivityId(nodeIds, historicTaskInstance.getTaskDefinitionKey()).changeState();
|
||||
Task task = QueryUtils.taskQuery(processInstanceId).list().get(0);
|
||||
taskService.setAssignee(task.getId(), historicTaskInstance.getAssignee());
|
||||
//获取并行网关执行后保留的执行实例数据
|
||||
ExecutionChildByExecutionIdCmd childByExecutionIdCmd = new ExecutionChildByExecutionIdCmd(task.getExecutionId());
|
||||
List<ExecutionEntity> executionEntities = managementService.executeCommand(childByExecutionIdCmd);
|
||||
//删除流程实例垃圾数据
|
||||
for (ExecutionEntity executionEntity : executionEntities) {
|
||||
DeleteExecutionCmd deleteExecutionCmd = new DeleteExecutionCmd(executionEntity.getId());
|
||||
managementService.executeCommand(deleteExecutionCmd);
|
||||
}
|
||||
runtimeService.updateBusinessStatus(processInstanceId, BusinessStatusEnum.CANCEL.getStatus());
|
||||
//流程作废监听
|
||||
flowProcessEventHandler.processHandler(processInstance.getProcessDefinitionKey(),
|
||||
processInstance.getBusinessKey(), BusinessStatusEnum.CANCEL.getStatus(), false);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error("撤销失败:" + e.getMessage(), e);
|
||||
throw new ServiceException("撤销失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询当前登录人单据
|
||||
*
|
||||
* @param bo 参数
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<ProcessInstanceVo> getPageByCurrent(ProcessInstanceBo bo, PageQuery pageQuery) {
|
||||
List<ProcessInstanceVo> list = new ArrayList<>();
|
||||
HistoricProcessInstanceQuery query = QueryUtils.hisInstanceQuery();
|
||||
query.startedBy(String.valueOf(LoginHelper.getUserId()));
|
||||
if (StringUtils.isNotBlank(bo.getName())) {
|
||||
query.processInstanceNameLikeIgnoreCase("%" + bo.getName() + "%");
|
||||
}
|
||||
if (StringUtils.isNotBlank(bo.getKey())) {
|
||||
query.processDefinitionKey(bo.getKey());
|
||||
}
|
||||
if (StringUtils.isNotBlank(bo.getBusinessKey())) {
|
||||
query.processInstanceBusinessKey(bo.getBusinessKey());
|
||||
}
|
||||
if (StringUtils.isNotBlank(bo.getCategoryCode())) {
|
||||
query.processDefinitionCategory(bo.getCategoryCode());
|
||||
}
|
||||
query.orderByProcessInstanceStartTime().desc();
|
||||
List<HistoricProcessInstance> historicProcessInstanceList = query.listPage(pageQuery.getFirstNum(), pageQuery.getPageSize());
|
||||
List<TaskVo> taskVoList = new ArrayList<>();
|
||||
if (CollUtil.isNotEmpty(historicProcessInstanceList)) {
|
||||
List<String> processInstanceIds = StreamUtils.toList(historicProcessInstanceList, HistoricProcessInstance::getId);
|
||||
List<Task> taskList = QueryUtils.taskQuery(processInstanceIds).list();
|
||||
for (Task task : taskList) {
|
||||
taskVoList.add(BeanUtil.toBean(task, TaskVo.class));
|
||||
}
|
||||
}
|
||||
for (HistoricProcessInstance processInstance : historicProcessInstanceList) {
|
||||
ProcessInstanceVo processInstanceVo = BeanUtil.toBean(processInstance, ProcessInstanceVo.class);
|
||||
processInstanceVo.setBusinessStatusName(BusinessStatusEnum.findByStatus(processInstance.getBusinessStatus()));
|
||||
if (CollUtil.isNotEmpty(taskVoList)) {
|
||||
List<TaskVo> collect = StreamUtils.filter(taskVoList, e -> e.getProcessInstanceId().equals(processInstance.getId()));
|
||||
processInstanceVo.setTaskVoList(CollUtil.isNotEmpty(collect) ? collect : Collections.emptyList());
|
||||
}
|
||||
list.add(processInstanceVo);
|
||||
}
|
||||
if (CollUtil.isNotEmpty(list)) {
|
||||
List<String> processDefinitionIds = StreamUtils.toList(list, ProcessInstanceVo::getProcessDefinitionId);
|
||||
List<WfNodeConfigVo> wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds);
|
||||
for (ProcessInstanceVo processInstanceVo : list) {
|
||||
if (CollUtil.isNotEmpty(wfNodeConfigVoList)) {
|
||||
wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(processInstanceVo.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(processInstanceVo::setWfNodeConfigVo);
|
||||
}
|
||||
}
|
||||
}
|
||||
long count = query.count();
|
||||
TableDataInfo<ProcessInstanceVo> build = TableDataInfo.build();
|
||||
build.setRows(list);
|
||||
build.setTotal(count);
|
||||
return build;
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务催办(给当前任务办理人发送站内信,邮件,短信等)
|
||||
*
|
||||
* @param taskUrgingBo 任务催办
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean taskUrging(TaskUrgingBo taskUrgingBo) {
|
||||
try {
|
||||
ProcessInstance processInstance = QueryUtils.instanceQuery(taskUrgingBo.getProcessInstanceId()).singleResult();
|
||||
if (processInstance == null) {
|
||||
throw new ServiceException("任务已结束!");
|
||||
}
|
||||
String message = taskUrgingBo.getMessage();
|
||||
if (StringUtils.isBlank(message)) {
|
||||
message = "您的【" + processInstance.getName() + "】单据还未审批,请您及时处理。";
|
||||
}
|
||||
List<Task> list = QueryUtils.taskQuery(taskUrgingBo.getProcessInstanceId()).list();
|
||||
WorkflowUtils.sendMessage(list, processInstance.getName(), taskUrgingBo.getMessageType(), message, userService);
|
||||
} catch (ServiceException e) {
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,861 @@
|
||||
package org.dromara.workflow.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.domain.dto.RoleDTO;
|
||||
import org.dromara.common.core.domain.dto.UserDTO;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.service.OssService;
|
||||
import org.dromara.common.core.service.UserService;
|
||||
import org.dromara.common.core.utils.StreamUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.satoken.utils.LoginHelper;
|
||||
import org.dromara.common.tenant.helper.TenantHelper;
|
||||
import org.dromara.workflow.common.constant.FlowConstant;
|
||||
import org.dromara.common.core.enums.BusinessStatusEnum;
|
||||
import org.dromara.workflow.common.enums.TaskStatusEnum;
|
||||
import org.dromara.workflow.domain.ActHiTaskinst;
|
||||
import org.dromara.workflow.domain.WfTaskBackNode;
|
||||
import org.dromara.workflow.domain.bo.*;
|
||||
import org.dromara.workflow.domain.vo.*;
|
||||
import org.dromara.workflow.flowable.cmd.*;
|
||||
import org.dromara.workflow.flowable.handler.FlowProcessEventHandler;
|
||||
import org.dromara.workflow.mapper.ActHiTaskinstMapper;
|
||||
import org.dromara.workflow.mapper.ActTaskMapper;
|
||||
import org.dromara.workflow.service.IActTaskService;
|
||||
import org.dromara.workflow.service.IWfDefinitionConfigService;
|
||||
import org.dromara.workflow.service.IWfNodeConfigService;
|
||||
import org.dromara.workflow.service.IWfTaskBackNodeService;
|
||||
import org.dromara.workflow.utils.ModelUtils;
|
||||
import org.dromara.workflow.utils.QueryUtils;
|
||||
import org.dromara.workflow.utils.WorkflowUtils;
|
||||
import org.flowable.common.engine.api.FlowableObjectNotFoundException;
|
||||
import org.flowable.common.engine.impl.identity.Authentication;
|
||||
import org.flowable.engine.*;
|
||||
import org.flowable.engine.history.HistoricProcessInstance;
|
||||
import org.flowable.engine.history.HistoricProcessInstanceQuery;
|
||||
import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior;
|
||||
import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.flowable.identitylink.api.history.HistoricIdentityLink;
|
||||
import org.flowable.task.api.Task;
|
||||
import org.flowable.task.api.TaskQuery;
|
||||
import org.flowable.task.api.history.HistoricTaskInstance;
|
||||
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||
import org.flowable.variable.api.persistence.entity.VariableInstance;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.dromara.workflow.common.constant.FlowConstant.*;
|
||||
|
||||
/**
|
||||
* 任务 服务层实现
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class ActTaskServiceImpl implements IActTaskService {
|
||||
|
||||
@Autowired(required = false)
|
||||
private RuntimeService runtimeService;
|
||||
@Autowired(required = false)
|
||||
private TaskService taskService;
|
||||
@Autowired(required = false)
|
||||
private HistoryService historyService;
|
||||
@Autowired(required = false)
|
||||
private IdentityService identityService;
|
||||
@Autowired(required = false)
|
||||
private ManagementService managementService;
|
||||
private final ActTaskMapper actTaskMapper;
|
||||
private final IWfTaskBackNodeService wfTaskBackNodeService;
|
||||
private final ActHiTaskinstMapper actHiTaskinstMapper;
|
||||
private final IWfNodeConfigService wfNodeConfigService;
|
||||
private final IWfDefinitionConfigService wfDefinitionConfigService;
|
||||
private final FlowProcessEventHandler flowProcessEventHandler;
|
||||
private final UserService userService;
|
||||
private final OssService ossService;
|
||||
|
||||
/**
|
||||
* 启动任务
|
||||
*
|
||||
* @param startProcessBo 启动流程参数
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Map<String, Object> startWorkFlow(StartProcessBo startProcessBo) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
if (StringUtils.isBlank(startProcessBo.getBusinessKey())) {
|
||||
throw new ServiceException("启动工作流时必须包含业务ID");
|
||||
}
|
||||
// 判断当前业务是否启动过流程
|
||||
HistoricProcessInstanceQuery query = QueryUtils.hisInstanceQuery();
|
||||
HistoricProcessInstance historicProcessInstance = query.processInstanceBusinessKey(startProcessBo.getBusinessKey()).singleResult();
|
||||
if (ObjectUtil.isNotEmpty(historicProcessInstance)) {
|
||||
BusinessStatusEnum.checkStartStatus(historicProcessInstance.getBusinessStatus());
|
||||
}
|
||||
List<Task> taskResult = QueryUtils.taskQuery().processInstanceBusinessKey(startProcessBo.getBusinessKey()).list();
|
||||
if (CollUtil.isNotEmpty(taskResult)) {
|
||||
if (CollUtil.isNotEmpty(startProcessBo.getVariables())) {
|
||||
taskService.setVariables(taskResult.get(0).getId(), startProcessBo.getVariables());
|
||||
}
|
||||
map.put(PROCESS_INSTANCE_ID, taskResult.get(0).getProcessInstanceId());
|
||||
map.put("taskId", taskResult.get(0).getId());
|
||||
return map;
|
||||
}
|
||||
WfDefinitionConfigVo wfDefinitionConfigVo = wfDefinitionConfigService.getByTableNameLastVersion(startProcessBo.getTableName());
|
||||
if (wfDefinitionConfigVo == null) {
|
||||
throw new ServiceException("请到流程定义绑定业务表名与流程KEY!");
|
||||
}
|
||||
// 设置启动人
|
||||
identityService.setAuthenticatedUserId(String.valueOf(LoginHelper.getUserId()));
|
||||
Authentication.setAuthenticatedUserId(String.valueOf(LoginHelper.getUserId()));
|
||||
// 启动流程实例(提交申请)
|
||||
Map<String, Object> variables = startProcessBo.getVariables();
|
||||
// 启动跳过表达式
|
||||
variables.put(FLOWABLE_SKIP_EXPRESSION_ENABLED, true);
|
||||
// 流程发起人
|
||||
variables.put(INITIATOR, (String.valueOf(LoginHelper.getUserId())));
|
||||
ProcessInstance pi;
|
||||
try {
|
||||
if (TenantHelper.isEnable()) {
|
||||
pi = runtimeService.startProcessInstanceByKeyAndTenantId(wfDefinitionConfigVo.getProcessKey(), startProcessBo.getBusinessKey(), variables, TenantHelper.getTenantId());
|
||||
} else {
|
||||
pi = runtimeService.startProcessInstanceByKey(wfDefinitionConfigVo.getProcessKey(), startProcessBo.getBusinessKey(), variables);
|
||||
}
|
||||
} catch (FlowableObjectNotFoundException e) {
|
||||
throw new ServiceException("找不到当前【" + wfDefinitionConfigVo.getProcessKey() + "】流程定义!");
|
||||
}
|
||||
// 将流程定义名称 作为 流程实例名称
|
||||
runtimeService.setProcessInstanceName(pi.getProcessInstanceId(), pi.getProcessDefinitionName());
|
||||
// 申请人执行流程
|
||||
List<Task> taskList = QueryUtils.taskQuery(pi.getId()).list();
|
||||
if (taskList.size() > 1) {
|
||||
throw new ServiceException("请检查流程第一个环节是否为申请人!");
|
||||
}
|
||||
|
||||
runtimeService.updateBusinessStatus(pi.getProcessInstanceId(), BusinessStatusEnum.DRAFT.getStatus());
|
||||
taskService.setAssignee(taskList.get(0).getId(), LoginHelper.getUserId().toString());
|
||||
taskService.setVariable(taskList.get(0).getId(), PROCESS_INSTANCE_ID, pi.getProcessInstanceId());
|
||||
taskService.setVariable(taskList.get(0).getId(), BUSINESS_KEY, pi.getBusinessKey());
|
||||
map.put("processInstanceId", pi.getProcessInstanceId());
|
||||
map.put("taskId", taskList.get(0).getId());
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 办理任务
|
||||
*
|
||||
* @param completeTaskBo 办理任务参数
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean completeTask(CompleteTaskBo completeTaskBo) {
|
||||
try {
|
||||
String userId = String.valueOf(LoginHelper.getUserId());
|
||||
Task task = WorkflowUtils.getTaskByCurrentUser(completeTaskBo.getTaskId());
|
||||
if (task == null) {
|
||||
throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL);
|
||||
}
|
||||
if (task.isSuspended()) {
|
||||
throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED);
|
||||
}
|
||||
ProcessInstance processInstance = QueryUtils.instanceQuery(task.getProcessInstanceId()).singleResult();
|
||||
//办理委托任务
|
||||
if (ObjectUtil.isNotEmpty(task.getDelegationState()) && FlowConstant.PENDING.equals(task.getDelegationState().name())) {
|
||||
taskService.resolveTask(completeTaskBo.getTaskId());
|
||||
TaskEntity newTask = WorkflowUtils.createNewTask(task);
|
||||
taskService.addComment(newTask.getId(), task.getProcessInstanceId(), TaskStatusEnum.PASS.getStatus(), StringUtils.isNotBlank(completeTaskBo.getMessage()) ? completeTaskBo.getMessage() : StrUtil.EMPTY);
|
||||
taskService.complete(newTask.getId());
|
||||
return true;
|
||||
}
|
||||
//附件上传
|
||||
AttachmentCmd attachmentCmd = new AttachmentCmd(completeTaskBo.getFileId(), task.getId(), task.getProcessInstanceId(), ossService);
|
||||
managementService.executeCommand(attachmentCmd);
|
||||
String businessStatus = WorkflowUtils.getBusinessStatus(processInstance.getBusinessKey());
|
||||
//流程提交监听
|
||||
if (BusinessStatusEnum.DRAFT.getStatus().equals(businessStatus) || BusinessStatusEnum.BACK.getStatus().equals(businessStatus) || BusinessStatusEnum.CANCEL.getStatus().equals(businessStatus)) {
|
||||
flowProcessEventHandler.processHandler(processInstance.getProcessDefinitionKey(), processInstance.getBusinessKey(), businessStatus, true);
|
||||
}
|
||||
runtimeService.updateBusinessStatus(task.getProcessInstanceId(), BusinessStatusEnum.WAITING.getStatus());
|
||||
//办理监听
|
||||
flowProcessEventHandler.processTaskHandler(processInstance.getProcessDefinitionKey(), task.getTaskDefinitionKey(),
|
||||
task.getId(), processInstance.getBusinessKey());
|
||||
//办理意见
|
||||
taskService.addComment(completeTaskBo.getTaskId(), task.getProcessInstanceId(), TaskStatusEnum.PASS.getStatus(), StringUtils.isBlank(completeTaskBo.getMessage()) ? "同意" : completeTaskBo.getMessage());
|
||||
//办理任务
|
||||
taskService.setAssignee(task.getId(), userId);
|
||||
if (CollUtil.isNotEmpty(completeTaskBo.getVariables())) {
|
||||
taskService.complete(completeTaskBo.getTaskId(), completeTaskBo.getVariables());
|
||||
} else {
|
||||
taskService.complete(completeTaskBo.getTaskId());
|
||||
}
|
||||
//记录执行过的流程任务节点
|
||||
wfTaskBackNodeService.recordExecuteNode(task);
|
||||
ProcessInstance pi = QueryUtils.instanceQuery(task.getProcessInstanceId()).singleResult();
|
||||
if (pi == null) {
|
||||
UpdateBusinessStatusCmd updateBusinessStatusCmd = new UpdateBusinessStatusCmd(task.getProcessInstanceId(), BusinessStatusEnum.FINISH.getStatus());
|
||||
managementService.executeCommand(updateBusinessStatusCmd);
|
||||
flowProcessEventHandler.processHandler(processInstance.getProcessDefinitionKey(), processInstance.getBusinessKey(),
|
||||
BusinessStatusEnum.FINISH.getStatus(), false);
|
||||
} else {
|
||||
List<Task> list = QueryUtils.taskQuery(task.getProcessInstanceId()).list();
|
||||
for (Task t : list) {
|
||||
if (ModelUtils.isUserTask(t.getProcessDefinitionId(), t.getTaskDefinitionKey())) {
|
||||
List<HistoricIdentityLink> links = historyService.getHistoricIdentityLinksForTask(t.getId());
|
||||
if (CollUtil.isEmpty(links) && StringUtils.isBlank(t.getAssignee())) {
|
||||
throw new ServiceException("下一节点【" + t.getName() + "】没有办理人!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (CollUtil.isNotEmpty(list) && CollUtil.isNotEmpty(completeTaskBo.getWfCopyList())) {
|
||||
TaskEntity newTask = WorkflowUtils.createNewTask(task);
|
||||
taskService.addComment(newTask.getId(), task.getProcessInstanceId(), TaskStatusEnum.COPY.getStatus(), LoginHelper.getLoginUser().getNickname() + "【抄送】给" + String.join(",", StreamUtils.toList(completeTaskBo.getWfCopyList(), WfCopy::getUserName)));
|
||||
taskService.complete(newTask.getId());
|
||||
List<Task> taskList = QueryUtils.taskQuery(task.getProcessInstanceId()).list();
|
||||
WorkflowUtils.createCopyTask(taskList, StreamUtils.toList(completeTaskBo.getWfCopyList(), WfCopy::getUserId));
|
||||
}
|
||||
sendMessage(list, processInstance.getName(), completeTaskBo.getMessageType(), null);
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
*
|
||||
* @param list 任务
|
||||
* @param name 流程名称
|
||||
* @param messageType 消息类型
|
||||
* @param message 消息内容,为空则发送默认配置的消息内容
|
||||
*/
|
||||
@Async
|
||||
public void sendMessage(List<Task> list, String name, List<String> messageType, String message) {
|
||||
WorkflowUtils.sendMessage(list, name, messageType, message, userService);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前用户的待办任务
|
||||
*
|
||||
* @param taskBo 参数
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<TaskVo> getPageByTaskWait(TaskBo taskBo, PageQuery pageQuery) {
|
||||
QueryWrapper<TaskVo> queryWrapper = new QueryWrapper<>();
|
||||
List<RoleDTO> roles = LoginHelper.getLoginUser().getRoles();
|
||||
List<String> roleIds = StreamUtils.toList(roles, e -> String.valueOf(e.getRoleId()));
|
||||
String userId = String.valueOf(LoginHelper.getUserId());
|
||||
queryWrapper.eq("t.business_status_", BusinessStatusEnum.WAITING.getStatus());
|
||||
queryWrapper.eq(TenantHelper.isEnable(), "t.tenant_id_", TenantHelper.getTenantId());
|
||||
String ids = StreamUtils.join(roleIds, x -> "'" + x + "'");
|
||||
queryWrapper.and(w1 -> w1.eq("t.assignee_", userId).or(w2 -> w2.isNull("t.assignee_").apply("exists ( select LINK.ID_ from ACT_RU_IDENTITYLINK LINK where LINK.TASK_ID_ = t.ID_ and LINK.TYPE_ = 'candidate' and (LINK.USER_ID_ = {0} or ( LINK.GROUP_ID_ IN (" + ids + ") ) ))", userId)));
|
||||
if (StringUtils.isNotBlank(taskBo.getName())) {
|
||||
queryWrapper.like("t.name_", taskBo.getName());
|
||||
}
|
||||
if (StringUtils.isNotBlank(taskBo.getProcessDefinitionName())) {
|
||||
queryWrapper.like("t.processDefinitionName", taskBo.getProcessDefinitionName());
|
||||
}
|
||||
if (StringUtils.isNotBlank(taskBo.getProcessDefinitionKey())) {
|
||||
queryWrapper.eq("t.processDefinitionKey", taskBo.getProcessDefinitionKey());
|
||||
}
|
||||
queryWrapper.orderByDesc("t.CREATE_TIME_");
|
||||
Page<TaskVo> page = actTaskMapper.getTaskWaitByPage(pageQuery.build(), queryWrapper);
|
||||
|
||||
List<TaskVo> taskList = page.getRecords();
|
||||
if (CollUtil.isNotEmpty(taskList)) {
|
||||
List<String> processDefinitionIds = StreamUtils.toList(taskList, TaskVo::getProcessDefinitionId);
|
||||
List<WfNodeConfigVo> wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds);
|
||||
for (TaskVo task : taskList) {
|
||||
task.setBusinessStatusName(BusinessStatusEnum.findByStatus(task.getBusinessStatus()));
|
||||
task.setParticipantVo(WorkflowUtils.getCurrentTaskParticipant(task.getId(), userService));
|
||||
task.setMultiInstance(WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()) != null);
|
||||
if (CollUtil.isNotEmpty(wfNodeConfigVoList)) {
|
||||
wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(task::setWfNodeConfigVo);
|
||||
wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && e.getNodeId().equals(task.getTaskDefinitionKey()) && FlowConstant.FALSE.equals(e.getApplyUserTask())).findFirst().ifPresent(task::setWfNodeConfigVo);
|
||||
}
|
||||
}
|
||||
}
|
||||
return TableDataInfo.build(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前租户所有待办任务
|
||||
*
|
||||
* @param taskBo 参数
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<TaskVo> getPageByAllTaskWait(TaskBo taskBo, PageQuery pageQuery) {
|
||||
TaskQuery query = QueryUtils.taskQuery();
|
||||
if (StringUtils.isNotBlank(taskBo.getName())) {
|
||||
query.taskNameLike("%" + taskBo.getName() + "%");
|
||||
}
|
||||
if (StringUtils.isNotBlank(taskBo.getProcessDefinitionName())) {
|
||||
query.processDefinitionNameLike("%" + taskBo.getProcessDefinitionName() + "%");
|
||||
}
|
||||
if (StringUtils.isNotBlank(taskBo.getProcessDefinitionKey())) {
|
||||
query.processDefinitionKey(taskBo.getProcessDefinitionKey());
|
||||
}
|
||||
query.orderByTaskCreateTime().desc();
|
||||
List<Task> taskList = query.listPage(pageQuery.getFirstNum(), pageQuery.getPageSize());
|
||||
List<ProcessInstance> processInstanceList = null;
|
||||
if (CollUtil.isNotEmpty(taskList)) {
|
||||
Set<String> processInstanceIds = StreamUtils.toSet(taskList, Task::getProcessInstanceId);
|
||||
processInstanceList = QueryUtils.instanceQuery(processInstanceIds).list();
|
||||
}
|
||||
List<TaskVo> list = new ArrayList<>();
|
||||
if (CollUtil.isNotEmpty(taskList)) {
|
||||
List<String> processDefinitionIds = StreamUtils.toList(taskList, Task::getProcessDefinitionId);
|
||||
List<WfNodeConfigVo> wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds);
|
||||
for (Task task : taskList) {
|
||||
TaskVo taskVo = BeanUtil.toBean(task, TaskVo.class);
|
||||
if (CollUtil.isNotEmpty(processInstanceList)) {
|
||||
processInstanceList.stream().filter(e -> e.getId().equals(task.getProcessInstanceId())).findFirst().ifPresent(e -> {
|
||||
taskVo.setBusinessStatus(e.getBusinessStatus());
|
||||
taskVo.setBusinessStatusName(BusinessStatusEnum.findByStatus(taskVo.getBusinessStatus()));
|
||||
taskVo.setProcessDefinitionKey(e.getProcessDefinitionKey());
|
||||
taskVo.setProcessDefinitionName(e.getProcessDefinitionName());
|
||||
taskVo.setProcessDefinitionVersion(e.getProcessDefinitionVersion());
|
||||
taskVo.setBusinessKey(e.getBusinessKey());
|
||||
});
|
||||
}
|
||||
taskVo.setAssignee(StringUtils.isNotBlank(task.getAssignee()) ? Long.valueOf(task.getAssignee()) : null);
|
||||
taskVo.setParticipantVo(WorkflowUtils.getCurrentTaskParticipant(task.getId(), userService));
|
||||
taskVo.setMultiInstance(WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()) != null);
|
||||
if (CollUtil.isNotEmpty(wfNodeConfigVoList)) {
|
||||
wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(taskVo::setWfNodeConfigVo);
|
||||
wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && e.getNodeId().equals(task.getTaskDefinitionKey()) && FlowConstant.FALSE.equals(e.getApplyUserTask())).findFirst().ifPresent(taskVo::setWfNodeConfigVo);
|
||||
}
|
||||
list.add(taskVo);
|
||||
}
|
||||
}
|
||||
long count = query.count();
|
||||
TableDataInfo<TaskVo> build = TableDataInfo.build();
|
||||
build.setRows(list);
|
||||
build.setTotal(count);
|
||||
return build;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前用户的已办任务
|
||||
*
|
||||
* @param taskBo 参数
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<TaskVo> getPageByTaskFinish(TaskBo taskBo, PageQuery pageQuery) {
|
||||
String userId = String.valueOf(LoginHelper.getUserId());
|
||||
QueryWrapper<TaskVo> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.like(StringUtils.isNotBlank(taskBo.getName()), "t.name_", taskBo.getName());
|
||||
queryWrapper.like(StringUtils.isNotBlank(taskBo.getProcessDefinitionName()), "t.processDefinitionName", taskBo.getProcessDefinitionName());
|
||||
queryWrapper.eq(StringUtils.isNotBlank(taskBo.getProcessDefinitionKey()), "t.processDefinitionKey", taskBo.getProcessDefinitionKey());
|
||||
queryWrapper.eq("t.assignee_", userId);
|
||||
queryWrapper.orderByDesc("t.START_TIME_");
|
||||
Page<TaskVo> page = actTaskMapper.getTaskFinishByPage(pageQuery.build(), queryWrapper);
|
||||
|
||||
List<TaskVo> taskList = page.getRecords();
|
||||
if (CollUtil.isNotEmpty(taskList)) {
|
||||
List<String> processDefinitionIds = StreamUtils.toList(taskList, TaskVo::getProcessDefinitionId);
|
||||
List<WfNodeConfigVo> wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds);
|
||||
for (TaskVo task : taskList) {
|
||||
task.setBusinessStatusName(BusinessStatusEnum.findByStatus(task.getBusinessStatus()));
|
||||
if (CollUtil.isNotEmpty(wfNodeConfigVoList)) {
|
||||
wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(task::setWfNodeConfigVo);
|
||||
wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && e.getNodeId().equals(task.getTaskDefinitionKey()) && FlowConstant.FALSE.equals(e.getApplyUserTask())).findFirst().ifPresent(task::setWfNodeConfigVo);
|
||||
}
|
||||
}
|
||||
}
|
||||
return TableDataInfo.build(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前用户的抄送
|
||||
*
|
||||
* @param taskBo 参数
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<TaskVo> getPageByTaskCopy(TaskBo taskBo, PageQuery pageQuery) {
|
||||
QueryWrapper<TaskVo> queryWrapper = new QueryWrapper<>();
|
||||
String userId = String.valueOf(LoginHelper.getUserId());
|
||||
if (StringUtils.isNotBlank(taskBo.getName())) {
|
||||
queryWrapper.like("t.name_", taskBo.getName());
|
||||
}
|
||||
if (StringUtils.isNotBlank(taskBo.getProcessDefinitionName())) {
|
||||
queryWrapper.like("t.processDefinitionName", taskBo.getProcessDefinitionName());
|
||||
}
|
||||
if (StringUtils.isNotBlank(taskBo.getProcessDefinitionKey())) {
|
||||
queryWrapper.eq("t.processDefinitionKey", taskBo.getProcessDefinitionKey());
|
||||
}
|
||||
queryWrapper.eq("t.assignee_", userId);
|
||||
queryWrapper.orderByDesc("t.START_TIME_");
|
||||
Page<TaskVo> page = actTaskMapper.getTaskCopyByPage(pageQuery.build(), queryWrapper);
|
||||
|
||||
List<TaskVo> taskList = page.getRecords();
|
||||
if (CollUtil.isNotEmpty(taskList)) {
|
||||
List<String> processDefinitionIds = StreamUtils.toList(taskList, TaskVo::getProcessDefinitionId);
|
||||
List<WfNodeConfigVo> wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds);
|
||||
for (TaskVo task : taskList) {
|
||||
task.setBusinessStatusName(BusinessStatusEnum.findByStatus(task.getBusinessStatus()));
|
||||
if (CollUtil.isNotEmpty(wfNodeConfigVoList)) {
|
||||
wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(task::setWfNodeConfigVo);
|
||||
wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && e.getNodeId().equals(task.getTaskDefinitionKey()) && FlowConstant.FALSE.equals(e.getApplyUserTask())).findFirst().ifPresent(task::setWfNodeConfigVo);
|
||||
}
|
||||
}
|
||||
}
|
||||
return TableDataInfo.build(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前租户所有已办任务
|
||||
*
|
||||
* @param taskBo 参数
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<TaskVo> getPageByAllTaskFinish(TaskBo taskBo, PageQuery pageQuery) {
|
||||
QueryWrapper<TaskVo> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.like(StringUtils.isNotBlank(taskBo.getName()), "t.name_", taskBo.getName());
|
||||
queryWrapper.like(StringUtils.isNotBlank(taskBo.getProcessDefinitionName()), "t.processDefinitionName", taskBo.getProcessDefinitionName());
|
||||
queryWrapper.eq(StringUtils.isNotBlank(taskBo.getProcessDefinitionKey()), "t.processDefinitionKey", taskBo.getProcessDefinitionKey());
|
||||
Page<TaskVo> page = actTaskMapper.getTaskFinishByPage(pageQuery.build(), queryWrapper);
|
||||
|
||||
List<TaskVo> taskList = page.getRecords();
|
||||
if (CollUtil.isNotEmpty(taskList)) {
|
||||
List<String> processDefinitionIds = StreamUtils.toList(taskList, TaskVo::getProcessDefinitionId);
|
||||
List<WfNodeConfigVo> wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds);
|
||||
for (TaskVo task : taskList) {
|
||||
task.setBusinessStatusName(BusinessStatusEnum.findByStatus(task.getBusinessStatus()));
|
||||
if (CollUtil.isNotEmpty(wfNodeConfigVoList)) {
|
||||
wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(task::setWfNodeConfigVo);
|
||||
wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && e.getNodeId().equals(task.getTaskDefinitionKey()) && FlowConstant.FALSE.equals(e.getApplyUserTask())).findFirst().ifPresent(task::setWfNodeConfigVo);
|
||||
}
|
||||
}
|
||||
}
|
||||
return TableDataInfo.build(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 委派任务
|
||||
*
|
||||
* @param delegateBo 参数
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean delegateTask(DelegateBo delegateBo) {
|
||||
Task task = WorkflowUtils.getTaskByCurrentUser(delegateBo.getTaskId());
|
||||
|
||||
if (ObjectUtil.isEmpty(task)) {
|
||||
throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL);
|
||||
}
|
||||
if (task.isSuspended()) {
|
||||
throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED);
|
||||
}
|
||||
try {
|
||||
TaskEntity newTask = WorkflowUtils.createNewTask(task);
|
||||
taskService.addComment(newTask.getId(), task.getProcessInstanceId(), TaskStatusEnum.PENDING.getStatus(), "【" + LoginHelper.getLoginUser().getNickname() + "】委派给【" + delegateBo.getNickName() + "】");
|
||||
//委托任务
|
||||
taskService.delegateTask(delegateBo.getTaskId(), delegateBo.getUserId());
|
||||
//办理生成的任务记录
|
||||
taskService.complete(newTask.getId());
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 终止任务
|
||||
*
|
||||
* @param terminationBo 参数
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean terminationTask(TerminationBo terminationBo) {
|
||||
TaskQuery query = QueryUtils.taskQuery();
|
||||
Task task = query.taskId(terminationBo.getTaskId()).singleResult();
|
||||
|
||||
if (ObjectUtil.isEmpty(task)) {
|
||||
throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL);
|
||||
}
|
||||
if (task.isSuspended()) {
|
||||
throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED);
|
||||
}
|
||||
HistoricProcessInstance historicProcessInstance = QueryUtils.hisInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
|
||||
BusinessStatusEnum.checkInvalidStatus(historicProcessInstance.getBusinessStatus());
|
||||
try {
|
||||
if (StringUtils.isBlank(terminationBo.getComment())) {
|
||||
terminationBo.setComment(LoginHelper.getLoginUser().getNickname() + "终止了申请");
|
||||
} else {
|
||||
terminationBo.setComment(LoginHelper.getLoginUser().getNickname() + "终止了申请:" + terminationBo.getComment());
|
||||
}
|
||||
taskService.addComment(task.getId(), task.getProcessInstanceId(), TaskStatusEnum.TERMINATION.getStatus(), terminationBo.getComment());
|
||||
List<Task> list = QueryUtils.taskQuery(task.getProcessInstanceId()).list();
|
||||
if (CollUtil.isNotEmpty(list)) {
|
||||
List<Task> subTasks = StreamUtils.filter(list, e -> StringUtils.isNotBlank(e.getParentTaskId()));
|
||||
if (CollUtil.isNotEmpty(subTasks)) {
|
||||
subTasks.forEach(e -> taskService.deleteTask(e.getId()));
|
||||
}
|
||||
runtimeService.updateBusinessStatus(task.getProcessInstanceId(), BusinessStatusEnum.TERMINATION.getStatus());
|
||||
runtimeService.deleteProcessInstance(task.getProcessInstanceId(), StrUtil.EMPTY);
|
||||
}
|
||||
//流程终止监听
|
||||
flowProcessEventHandler.processHandler(historicProcessInstance.getProcessDefinitionKey(),
|
||||
historicProcessInstance.getBusinessKey(), BusinessStatusEnum.TERMINATION.getStatus(), false);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转办任务
|
||||
*
|
||||
* @param transmitBo 参数
|
||||
*/
|
||||
@Override
|
||||
public boolean transferTask(TransmitBo transmitBo) {
|
||||
Task task = WorkflowUtils.getTaskByCurrentUser(transmitBo.getTaskId());
|
||||
if (ObjectUtil.isEmpty(task)) {
|
||||
throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL);
|
||||
}
|
||||
if (task.isSuspended()) {
|
||||
throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED);
|
||||
}
|
||||
try {
|
||||
TaskEntity newTask = WorkflowUtils.createNewTask(task);
|
||||
taskService.addComment(newTask.getId(), task.getProcessInstanceId(), TaskStatusEnum.TRANSFER.getStatus(), StringUtils.isNotBlank(transmitBo.getComment()) ? transmitBo.getComment() : LoginHelper.getUsername() + "转办了任务");
|
||||
taskService.complete(newTask.getId());
|
||||
taskService.setAssignee(task.getId(), transmitBo.getUserId());
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 会签任务加签
|
||||
*
|
||||
* @param addMultiBo 参数
|
||||
*/
|
||||
@Override
|
||||
public boolean addMultiInstanceExecution(AddMultiBo addMultiBo) {
|
||||
TaskQuery taskQuery = QueryUtils.taskQuery();
|
||||
taskQuery.taskId(addMultiBo.getTaskId());
|
||||
if (!LoginHelper.isSuperAdmin() && !LoginHelper.isTenantAdmin()) {
|
||||
taskQuery.taskCandidateOrAssigned(String.valueOf(LoginHelper.getUserId()));
|
||||
}
|
||||
Task task = taskQuery.singleResult();
|
||||
if (ObjectUtil.isEmpty(task)) {
|
||||
throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL);
|
||||
}
|
||||
if (task.isSuspended()) {
|
||||
throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED);
|
||||
}
|
||||
String taskDefinitionKey = task.getTaskDefinitionKey();
|
||||
String processInstanceId = task.getProcessInstanceId();
|
||||
String processDefinitionId = task.getProcessDefinitionId();
|
||||
|
||||
try {
|
||||
MultiInstanceVo multiInstanceVo = WorkflowUtils.isMultiInstance(processDefinitionId, taskDefinitionKey);
|
||||
if (multiInstanceVo == null) {
|
||||
throw new ServiceException("当前环节不是会签节点");
|
||||
}
|
||||
if (multiInstanceVo.getType() instanceof ParallelMultiInstanceBehavior) {
|
||||
for (Long assignee : addMultiBo.getAssignees()) {
|
||||
runtimeService.addMultiInstanceExecution(taskDefinitionKey, processInstanceId, Collections.singletonMap(multiInstanceVo.getAssignee(), assignee));
|
||||
}
|
||||
} else if (multiInstanceVo.getType() instanceof SequentialMultiInstanceBehavior) {
|
||||
AddSequenceMultiInstanceCmd addSequenceMultiInstanceCmd = new AddSequenceMultiInstanceCmd(task.getExecutionId(), multiInstanceVo.getAssigneeList(), addMultiBo.getAssignees());
|
||||
managementService.executeCommand(addSequenceMultiInstanceCmd);
|
||||
}
|
||||
List<String> assigneeNames = addMultiBo.getAssigneeNames();
|
||||
String username = LoginHelper.getUsername();
|
||||
TaskEntity newTask = WorkflowUtils.createNewTask(task);
|
||||
taskService.addComment(newTask.getId(), processInstanceId, TaskStatusEnum.SIGN.getStatus(), username + "加签【" + String.join(StringUtils.SEPARATOR, assigneeNames) + "】");
|
||||
taskService.complete(newTask.getId());
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 会签任务减签
|
||||
*
|
||||
* @param deleteMultiBo 参数
|
||||
*/
|
||||
@Override
|
||||
public boolean deleteMultiInstanceExecution(DeleteMultiBo deleteMultiBo) {
|
||||
TaskQuery taskQuery = QueryUtils.taskQuery();
|
||||
taskQuery.taskId(deleteMultiBo.getTaskId());
|
||||
if (!LoginHelper.isSuperAdmin() && !LoginHelper.isTenantAdmin()) {
|
||||
taskQuery.taskCandidateOrAssigned(String.valueOf(LoginHelper.getUserId()));
|
||||
}
|
||||
Task task = taskQuery.singleResult();
|
||||
if (ObjectUtil.isEmpty(task)) {
|
||||
throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL);
|
||||
}
|
||||
if (task.isSuspended()) {
|
||||
throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED);
|
||||
}
|
||||
String taskDefinitionKey = task.getTaskDefinitionKey();
|
||||
String processInstanceId = task.getProcessInstanceId();
|
||||
String processDefinitionId = task.getProcessDefinitionId();
|
||||
try {
|
||||
MultiInstanceVo multiInstanceVo = WorkflowUtils.isMultiInstance(processDefinitionId, taskDefinitionKey);
|
||||
if (multiInstanceVo == null) {
|
||||
throw new ServiceException("当前环节不是会签节点");
|
||||
}
|
||||
if (multiInstanceVo.getType() instanceof ParallelMultiInstanceBehavior) {
|
||||
for (String executionId : deleteMultiBo.getExecutionIds()) {
|
||||
runtimeService.deleteMultiInstanceExecution(executionId, false);
|
||||
}
|
||||
for (String taskId : deleteMultiBo.getTaskIds()) {
|
||||
historyService.deleteHistoricTaskInstance(taskId);
|
||||
}
|
||||
} else if (multiInstanceVo.getType() instanceof SequentialMultiInstanceBehavior) {
|
||||
DeleteSequenceMultiInstanceCmd deleteSequenceMultiInstanceCmd = new DeleteSequenceMultiInstanceCmd(task.getAssignee(), task.getExecutionId(), multiInstanceVo.getAssigneeList(), deleteMultiBo.getAssigneeIds());
|
||||
managementService.executeCommand(deleteSequenceMultiInstanceCmd);
|
||||
}
|
||||
List<String> assigneeNames = deleteMultiBo.getAssigneeNames();
|
||||
String username = LoginHelper.getUsername();
|
||||
TaskEntity newTask = WorkflowUtils.createNewTask(task);
|
||||
taskService.addComment(newTask.getId(), processInstanceId, TaskStatusEnum.SIGN_OFF.getStatus(), username + "减签【" + String.join(StringUtils.SEPARATOR, assigneeNames) + "】");
|
||||
taskService.complete(newTask.getId());
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 驳回审批
|
||||
*
|
||||
* @param backProcessBo 参数
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String backProcess(BackProcessBo backProcessBo) {
|
||||
String userId = String.valueOf(LoginHelper.getUserId());
|
||||
Task task = WorkflowUtils.getTaskByCurrentUser(backProcessBo.getTaskId());
|
||||
|
||||
if (ObjectUtil.isEmpty(task)) {
|
||||
throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL);
|
||||
}
|
||||
if (task.isSuspended()) {
|
||||
throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED);
|
||||
}
|
||||
try {
|
||||
String processInstanceId = task.getProcessInstanceId();
|
||||
ProcessInstance processInstance = QueryUtils.instanceQuery(task.getProcessInstanceId()).singleResult();
|
||||
//获取并行网关执行后保留的执行实例数据
|
||||
ExecutionChildByExecutionIdCmd childByExecutionIdCmd = new ExecutionChildByExecutionIdCmd(task.getExecutionId());
|
||||
List<ExecutionEntity> executionEntities = managementService.executeCommand(childByExecutionIdCmd);
|
||||
//校验单据
|
||||
BusinessStatusEnum.checkBackStatus(processInstance.getBusinessStatus());
|
||||
//判断是否有多个任务
|
||||
List<Task> taskList = QueryUtils.taskQuery(processInstanceId).list();
|
||||
String backTaskDefinitionKey = backProcessBo.getTargetActivityId();
|
||||
taskService.addComment(task.getId(), processInstanceId, TaskStatusEnum.BACK.getStatus(), StringUtils.isNotBlank(backProcessBo.getMessage()) ? backProcessBo.getMessage() : "退回");
|
||||
if (taskList.size() > 1) {
|
||||
//当前多个任务驳回到单个节点
|
||||
runtimeService.createChangeActivityStateBuilder().processInstanceId(processInstanceId).moveActivityIdsToSingleActivityId(taskList.stream().map(Task::getTaskDefinitionKey).distinct().collect(Collectors.toList()), backTaskDefinitionKey).changeState();
|
||||
ActHiTaskinst actHiTaskinst = new ActHiTaskinst();
|
||||
actHiTaskinst.setAssignee(userId);
|
||||
actHiTaskinst.setId(task.getId());
|
||||
actHiTaskinstMapper.updateById(actHiTaskinst);
|
||||
} else {
|
||||
//当前单个节点驳回单个节点
|
||||
runtimeService.createChangeActivityStateBuilder().processInstanceId(processInstanceId).moveActivityIdTo(task.getTaskDefinitionKey(), backTaskDefinitionKey).changeState();
|
||||
}
|
||||
//删除并行环节未办理记录
|
||||
MultiInstanceVo multiInstance = WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
|
||||
if (multiInstance == null && taskList.size() > 1) {
|
||||
List<Task> tasks = StreamUtils.filter(taskList, e -> !e.getTaskDefinitionKey().equals(task.getTaskDefinitionKey()));
|
||||
if (CollUtil.isNotEmpty(tasks)) {
|
||||
actHiTaskinstMapper.deleteByIds(StreamUtils.toList(tasks, Task::getId));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
List<HistoricTaskInstance> instanceList = QueryUtils.hisTaskInstanceQuery(processInstanceId).finished().orderByHistoricTaskInstanceEndTime().desc().list();
|
||||
List<Task> list = QueryUtils.taskQuery(processInstanceId).list();
|
||||
for (Task t : list) {
|
||||
instanceList.stream().filter(e -> e.getTaskDefinitionKey().equals(t.getTaskDefinitionKey())).findFirst().ifPresent(e -> {
|
||||
taskService.setAssignee(t.getId(), e.getAssignee());
|
||||
});
|
||||
}
|
||||
//发送消息
|
||||
String message = "您的【" + processInstance.getName() + "】单据已经被驳回,请您注意查收。";
|
||||
sendMessage(list, processInstance.getName(), backProcessBo.getMessageType(), message);
|
||||
//删除流程实例垃圾数据
|
||||
for (ExecutionEntity executionEntity : executionEntities) {
|
||||
DeleteExecutionCmd deleteExecutionCmd = new DeleteExecutionCmd(executionEntity.getId());
|
||||
managementService.executeCommand(deleteExecutionCmd);
|
||||
}
|
||||
|
||||
WfTaskBackNode wfTaskBackNode = wfTaskBackNodeService.getListByInstanceIdAndNodeId(task.getProcessInstanceId(), backProcessBo.getTargetActivityId());
|
||||
if (ObjectUtil.isNotNull(wfTaskBackNode) && wfTaskBackNode.getOrderNo() == 0) {
|
||||
runtimeService.updateBusinessStatus(processInstanceId, BusinessStatusEnum.BACK.getStatus());
|
||||
flowProcessEventHandler.processHandler(processInstance.getProcessDefinitionKey(),
|
||||
processInstance.getBusinessKey(), BusinessStatusEnum.BACK.getStatus(), false);
|
||||
}
|
||||
//删除驳回后的流程节点
|
||||
wfTaskBackNodeService.deleteBackTaskNode(processInstanceId, backProcessBo.getTargetActivityId());
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
return task.getProcessInstanceId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改任务办理人
|
||||
*
|
||||
* @param taskIds 任务id
|
||||
* @param userId 办理人id
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean updateAssignee(String[] taskIds, String userId) {
|
||||
try {
|
||||
List<Task> list = QueryUtils.taskQuery().taskIds(Arrays.asList(taskIds)).list();
|
||||
for (Task task : list) {
|
||||
taskService.setAssignee(task.getId(), userId);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("修改失败:" + e.getMessage(), e);
|
||||
throw new ServiceException("修改失败:" + e.getMessage());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询流程变量
|
||||
*
|
||||
* @param taskId 任务id
|
||||
*/
|
||||
@Override
|
||||
public List<VariableVo> getInstanceVariable(String taskId) {
|
||||
List<VariableVo> variableVoList = new ArrayList<>();
|
||||
Map<String, VariableInstance> variableInstances = taskService.getVariableInstances(taskId);
|
||||
if (CollUtil.isNotEmpty(variableInstances)) {
|
||||
for (Map.Entry<String, VariableInstance> entry : variableInstances.entrySet()) {
|
||||
VariableVo variableVo = new VariableVo();
|
||||
variableVo.setKey(entry.getKey());
|
||||
variableVo.setValue(entry.getValue().getValue().toString());
|
||||
variableVoList.add(variableVo);
|
||||
}
|
||||
}
|
||||
return variableVoList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询工作流任务用户选择加签人员
|
||||
*
|
||||
* @param taskId 任务id
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public String getTaskUserIdsByAddMultiInstance(String taskId) {
|
||||
Task task = QueryUtils.taskQuery().taskId(taskId).singleResult();
|
||||
if (task == null) {
|
||||
throw new ServiceException("任务不存在");
|
||||
}
|
||||
MultiInstanceVo multiInstance = WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
|
||||
if (multiInstance == null) {
|
||||
return "";
|
||||
}
|
||||
List<Long> userIds;
|
||||
if (multiInstance.getType() instanceof SequentialMultiInstanceBehavior) {
|
||||
userIds = (List<Long>) runtimeService.getVariable(task.getExecutionId(), multiInstance.getAssigneeList());
|
||||
} else {
|
||||
List<Task> list = QueryUtils.taskQuery(task.getProcessInstanceId()).list();
|
||||
userIds = StreamUtils.toList(list, e -> Long.valueOf(e.getAssignee()));
|
||||
}
|
||||
return StringUtils.join(userIds, StringUtils.SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询工作流选择减签人员
|
||||
*
|
||||
* @param taskId 任务id 任务id
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<TaskVo> getListByDeleteMultiInstance(String taskId) {
|
||||
Task task = QueryUtils.taskQuery().taskId(taskId).singleResult();
|
||||
List<Task> taskList = QueryUtils.taskQuery(task.getProcessInstanceId()).list();
|
||||
MultiInstanceVo multiInstance = WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
|
||||
List<TaskVo> taskListVo = new ArrayList<>();
|
||||
if (multiInstance == null) {
|
||||
return List.of();
|
||||
}
|
||||
List<Long> assigneeList = new ArrayList<>();
|
||||
if (multiInstance.getType() instanceof SequentialMultiInstanceBehavior) {
|
||||
List<Object> variable = (List<Object>) runtimeService.getVariable(task.getExecutionId(), multiInstance.getAssigneeList());
|
||||
for (Object o : variable) {
|
||||
assigneeList.add(Long.valueOf(o.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
if (multiInstance.getType() instanceof SequentialMultiInstanceBehavior) {
|
||||
List<Long> userIds = StreamUtils.filter(assigneeList, e -> !String.valueOf(e).equals(task.getAssignee()));
|
||||
List<UserDTO> userList = userService.selectListByIds(userIds);
|
||||
for (Long userId : userIds) {
|
||||
TaskVo taskVo = new TaskVo();
|
||||
taskVo.setId("串行会签");
|
||||
taskVo.setExecutionId("串行会签");
|
||||
taskVo.setProcessInstanceId(task.getProcessInstanceId());
|
||||
taskVo.setName(task.getName());
|
||||
taskVo.setAssignee(userId);
|
||||
if (CollUtil.isNotEmpty(userList)) {
|
||||
userList.stream().filter(u -> u.getUserId().toString().equals(userId.toString())).findFirst().ifPresent(u -> taskVo.setAssigneeName(u.getNickName()));
|
||||
}
|
||||
taskListVo.add(taskVo);
|
||||
}
|
||||
return taskListVo;
|
||||
} else if (multiInstance.getType() instanceof ParallelMultiInstanceBehavior) {
|
||||
List<Task> tasks = StreamUtils.filter(taskList, e -> StringUtils.isBlank(e.getParentTaskId()) && !e.getExecutionId().equals(task.getExecutionId()) && e.getTaskDefinitionKey().equals(task.getTaskDefinitionKey()));
|
||||
if (CollUtil.isNotEmpty(tasks)) {
|
||||
List<Long> userIds = StreamUtils.toList(tasks, e -> Long.valueOf(e.getAssignee()));
|
||||
List<UserDTO> userList = userService.selectListByIds(userIds);
|
||||
for (Task t : tasks) {
|
||||
TaskVo taskVo = new TaskVo();
|
||||
taskVo.setId(t.getId());
|
||||
taskVo.setExecutionId(t.getExecutionId());
|
||||
taskVo.setProcessInstanceId(t.getProcessInstanceId());
|
||||
taskVo.setName(t.getName());
|
||||
taskVo.setAssignee(Long.valueOf(t.getAssignee()));
|
||||
if (CollUtil.isNotEmpty(userList)) {
|
||||
userList.stream().filter(u -> u.getUserId().toString().equals(t.getAssignee())).findFirst().ifPresent(e -> taskVo.setAssigneeName(e.getNickName()));
|
||||
}
|
||||
taskListVo.add(taskVo);
|
||||
}
|
||||
return taskListVo;
|
||||
}
|
||||
}
|
||||
return List.of();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
package org.dromara.workflow.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.domain.event.ProcessEvent;
|
||||
import org.dromara.common.core.domain.event.ProcessTaskEvent;
|
||||
import org.dromara.common.core.enums.BusinessStatusEnum;
|
||||
import org.dromara.common.core.service.WorkflowService;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StreamUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.workflow.domain.TestLeave;
|
||||
import org.dromara.workflow.domain.bo.TestLeaveBo;
|
||||
import org.dromara.workflow.domain.vo.TestLeaveVo;
|
||||
import org.dromara.workflow.mapper.TestLeaveMapper;
|
||||
import org.dromara.workflow.service.ITestLeaveService;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 请假Service业务层处理
|
||||
*
|
||||
* @author may
|
||||
* @date 2023-07-21
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
@Slf4j
|
||||
public class TestLeaveServiceImpl implements ITestLeaveService {
|
||||
|
||||
private final TestLeaveMapper baseMapper;
|
||||
private final WorkflowService workflowService;
|
||||
|
||||
/**
|
||||
* 查询请假
|
||||
*/
|
||||
@Override
|
||||
public TestLeaveVo queryById(Long id) {
|
||||
return baseMapper.selectVoById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询请假列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<TestLeaveVo> queryPageList(TestLeaveBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<TestLeave> lqw = buildQueryWrapper(bo);
|
||||
Page<TestLeaveVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询请假列表
|
||||
*/
|
||||
@Override
|
||||
public List<TestLeaveVo> queryList(TestLeaveBo bo) {
|
||||
LambdaQueryWrapper<TestLeave> lqw = buildQueryWrapper(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<TestLeave> buildQueryWrapper(TestLeaveBo bo) {
|
||||
LambdaQueryWrapper<TestLeave> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getLeaveType()), TestLeave::getLeaveType, bo.getLeaveType());
|
||||
lqw.ge(bo.getStartLeaveDays() != null, TestLeave::getLeaveDays, bo.getStartLeaveDays());
|
||||
lqw.le(bo.getEndLeaveDays() != null, TestLeave::getLeaveDays, bo.getEndLeaveDays());
|
||||
lqw.orderByDesc(BaseEntity::getCreateTime);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增请假
|
||||
*/
|
||||
@Override
|
||||
public TestLeaveVo insertByBo(TestLeaveBo bo) {
|
||||
TestLeave add = MapstructUtils.convert(bo, TestLeave.class);
|
||||
if (StringUtils.isBlank(add.getStatus())) {
|
||||
add.setStatus(BusinessStatusEnum.DRAFT.getStatus());
|
||||
}
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setId(add.getId());
|
||||
}
|
||||
return MapstructUtils.convert(add, TestLeaveVo.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改请假
|
||||
*/
|
||||
@Override
|
||||
public TestLeaveVo updateByBo(TestLeaveBo bo) {
|
||||
TestLeave update = MapstructUtils.convert(bo, TestLeave.class);
|
||||
baseMapper.updateById(update);
|
||||
return MapstructUtils.convert(update, TestLeaveVo.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除请假
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids) {
|
||||
List<String> idList = StreamUtils.toList(ids, String::valueOf);
|
||||
workflowService.deleteRunAndHisInstance(idList);
|
||||
return baseMapper.deleteByIds(ids) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 总体流程监听(例如: 提交 退回 撤销 终止 作废等)
|
||||
* 正常使用只需#processEvent.key=='leave1'
|
||||
* 示例为了方便则使用startsWith匹配了全部示例key
|
||||
*
|
||||
* @param processEvent 参数
|
||||
*/
|
||||
@EventListener(condition = "#processEvent.key.startsWith('leave')")
|
||||
public void processHandler(ProcessEvent processEvent) {
|
||||
log.info("当前任务执行了{}", processEvent.toString());
|
||||
TestLeave testLeave = baseMapper.selectById(Long.valueOf(processEvent.getBusinessKey()));
|
||||
testLeave.setStatus(processEvent.getStatus());
|
||||
if (processEvent.isSubmit()) {
|
||||
testLeave.setStatus(BusinessStatusEnum.WAITING.getStatus());
|
||||
}
|
||||
baseMapper.updateById(testLeave);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行办理任务监听
|
||||
* 示例:也可通过 @EventListener(condition = "#processTaskEvent.key=='leave1'")进行判断
|
||||
* 在方法中判断流程节点key
|
||||
* if ("xxx".equals(processTaskEvent.getTaskDefinitionKey())) {
|
||||
* //执行业务逻辑
|
||||
* }
|
||||
*
|
||||
* @param processTaskEvent 参数
|
||||
*/
|
||||
@EventListener(condition = "#processTaskEvent.key.startsWith('leave')")
|
||||
public void processTaskHandler(ProcessTaskEvent processTaskEvent) {
|
||||
// 所有demo案例的申请人节点id
|
||||
String[] ids = {"Activity_14633hx", "Activity_19b1i4j", "Activity_0uscrk3",
|
||||
"Activity_0uscrk3", "Activity_0x6b71j", "Activity_0zy3g6j", "Activity_06a55t0"};
|
||||
if (StringUtils.equalsAny(processTaskEvent.getTaskDefinitionKey(), ids)) {
|
||||
log.info("当前任务执行了{}", processTaskEvent.toString());
|
||||
TestLeave testLeave = baseMapper.selectById(Long.valueOf(processTaskEvent.getBusinessKey()));
|
||||
testLeave.setStatus(BusinessStatusEnum.WAITING.getStatus());
|
||||
baseMapper.updateById(testLeave);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
package org.dromara.workflow.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.workflow.domain.WfCategory;
|
||||
import org.dromara.workflow.domain.bo.WfCategoryBo;
|
||||
import org.dromara.workflow.domain.vo.WfCategoryVo;
|
||||
import org.dromara.workflow.mapper.WfCategoryMapper;
|
||||
import org.dromara.workflow.service.IWfCategoryService;
|
||||
import org.dromara.workflow.utils.QueryUtils;
|
||||
import org.flowable.engine.RepositoryService;
|
||||
import org.flowable.engine.repository.Deployment;
|
||||
import org.flowable.engine.repository.Model;
|
||||
import org.flowable.engine.repository.ProcessDefinition;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 流程分类Service业务层处理
|
||||
*
|
||||
* @author may
|
||||
* @date 2023-06-28
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class WfCategoryServiceImpl implements IWfCategoryService {
|
||||
|
||||
private final WfCategoryMapper baseMapper;
|
||||
@Autowired(required = false)
|
||||
private RepositoryService repositoryService;
|
||||
|
||||
/**
|
||||
* 查询流程分类
|
||||
*/
|
||||
@Override
|
||||
public WfCategoryVo queryById(Long id) {
|
||||
return baseMapper.selectVoById(id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询流程分类列表
|
||||
*/
|
||||
@Override
|
||||
public List<WfCategoryVo> queryList(WfCategoryBo bo) {
|
||||
LambdaQueryWrapper<WfCategory> lqw = buildQueryWrapper(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<WfCategory> buildQueryWrapper(WfCategoryBo bo) {
|
||||
LambdaQueryWrapper<WfCategory> lqw = Wrappers.lambdaQuery();
|
||||
lqw.like(StringUtils.isNotBlank(bo.getCategoryName()), WfCategory::getCategoryName, bo.getCategoryName());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getCategoryCode()), WfCategory::getCategoryCode, bo.getCategoryCode());
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增流程分类
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(WfCategoryBo bo) {
|
||||
WfCategory add = MapstructUtils.convert(bo, WfCategory.class);
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setId(add.getId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改流程分类
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean updateByBo(WfCategoryBo bo) {
|
||||
WfCategory update = MapstructUtils.convert(bo, WfCategory.class);
|
||||
validEntityBeforeSave(update);
|
||||
WfCategoryVo wfCategoryVo = baseMapper.selectVoById(bo.getId());
|
||||
List<ProcessDefinition> processDefinitionList = QueryUtils.definitionQuery().processDefinitionCategory(wfCategoryVo.getCategoryCode()).list();
|
||||
for (ProcessDefinition processDefinition : processDefinitionList) {
|
||||
repositoryService.setProcessDefinitionCategory(processDefinition.getId(), bo.getCategoryCode());
|
||||
}
|
||||
List<Deployment> deploymentList = QueryUtils.deploymentQuery().deploymentCategory(wfCategoryVo.getCategoryCode()).list();
|
||||
for (Deployment deployment : deploymentList) {
|
||||
repositoryService.setDeploymentCategory(deployment.getId(), bo.getCategoryCode());
|
||||
}
|
||||
List<Model> modelList = QueryUtils.modelQuery().modelCategory(wfCategoryVo.getCategoryCode()).list();
|
||||
for (Model model : modelList) {
|
||||
model.setCategory(bo.getCategoryCode());
|
||||
repositoryService.saveModel(model);
|
||||
}
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(WfCategory entity) {
|
||||
//TODO 做一些数据校验,如唯一约束
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除流程分类
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if (isValid) {
|
||||
//TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
return baseMapper.deleteByIds(ids) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按照类别编码查询
|
||||
*
|
||||
* @param categoryCode 分类比吗
|
||||
*/
|
||||
@Override
|
||||
public WfCategory queryByCategoryCode(String categoryCode) {
|
||||
return baseMapper.selectOne(new LambdaQueryWrapper<WfCategory>().eq(WfCategory::getCategoryCode, categoryCode));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package org.dromara.workflow.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.workflow.domain.WfDefinitionConfig;
|
||||
import org.dromara.workflow.domain.bo.WfDefinitionConfigBo;
|
||||
import org.dromara.workflow.domain.vo.WfDefinitionConfigVo;
|
||||
import org.dromara.workflow.service.IWfDefinitionConfigService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.dromara.workflow.mapper.WfDefinitionConfigMapper;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 流程定义配置Service业务层处理
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-03-18
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class WfDefinitionConfigServiceImpl implements IWfDefinitionConfigService {
|
||||
|
||||
private final WfDefinitionConfigMapper baseMapper;
|
||||
|
||||
/**
|
||||
* 查询流程定义配置
|
||||
*/
|
||||
@Override
|
||||
public WfDefinitionConfigVo getByDefId(String definitionId) {
|
||||
return baseMapper.selectVoOne(new LambdaQueryWrapper<WfDefinitionConfig>().eq(WfDefinitionConfig::getDefinitionId, definitionId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询流程定义配置
|
||||
*
|
||||
* @param tableName 表名
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public WfDefinitionConfigVo getByTableNameLastVersion(String tableName) {
|
||||
List<WfDefinitionConfigVo> wfDefinitionConfigVos = baseMapper.selectVoList(
|
||||
new LambdaQueryWrapper<WfDefinitionConfig>().eq(WfDefinitionConfig::getTableName, tableName).orderByDesc(WfDefinitionConfig::getVersion));
|
||||
if (CollUtil.isNotEmpty(wfDefinitionConfigVos)) {
|
||||
return wfDefinitionConfigVos.get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询流程定义配置
|
||||
*
|
||||
* @param definitionId 流程定义id
|
||||
* @param tableName 表名
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public WfDefinitionConfigVo getByDefIdAndTableName(String definitionId, String tableName) {
|
||||
return baseMapper.selectVoOne(new LambdaQueryWrapper<WfDefinitionConfig>()
|
||||
.eq(WfDefinitionConfig::getDefinitionId, definitionId)
|
||||
.eq(WfDefinitionConfig::getTableName, tableName));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询流程定义配置排除当前查询的流程定义
|
||||
*
|
||||
* @param tableName 表名
|
||||
* @param definitionId 流程定义id
|
||||
*/
|
||||
@Override
|
||||
public List<WfDefinitionConfigVo> getByTableNameNotDefId(String tableName, String definitionId) {
|
||||
return baseMapper.selectVoList(new LambdaQueryWrapper<WfDefinitionConfig>()
|
||||
.eq(WfDefinitionConfig::getTableName, tableName)
|
||||
.ne(WfDefinitionConfig::getDefinitionId, definitionId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询流程定义配置列表
|
||||
*/
|
||||
@Override
|
||||
public List<WfDefinitionConfigVo> queryList(List<String> definitionIds) {
|
||||
return baseMapper.selectVoList(new LambdaQueryWrapper<WfDefinitionConfig>().in(WfDefinitionConfig::getDefinitionId, definitionIds));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增流程定义配置
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean saveOrUpdate(WfDefinitionConfigBo bo) {
|
||||
WfDefinitionConfig add = MapstructUtils.convert(bo, WfDefinitionConfig.class);
|
||||
baseMapper.delete(new LambdaQueryWrapper<WfDefinitionConfig>().eq(WfDefinitionConfig::getTableName, bo.getTableName()));
|
||||
add.setTableName(add.getTableName().toLowerCase());
|
||||
boolean flag = baseMapper.insertOrUpdate(add);
|
||||
if (flag) {
|
||||
bo.setId(add.getId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除流程定义配置
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteByIds(Collection<Long> ids) {
|
||||
return baseMapper.deleteByIds(ids) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean deleteByDefIds(Collection<String> ids) {
|
||||
return baseMapper.delete(new LambdaQueryWrapper<WfDefinitionConfig>().in(WfDefinitionConfig::getDefinitionId, ids)) > 0;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user