refactor(flowable): 移除自定义流程图配置和相关工具类

- 删除 application.yml 中的 Flowable 配置项
- 移除 CustomProcessDiagramCanvas 自定义流程图绘制类
- 移除 CustomProcessDiagramGenerator 自定义流程图生成器
- 移除 FindNextNodeUtil 流程节点查找工具类
- 移除 FlowableConfig 配置类
This commit is contained in:
2025-12-29 16:21:33 +08:00
parent 9b8c5ab80b
commit ee88de3e99
89 changed files with 0 additions and 9274 deletions

View File

@@ -1,50 +0,0 @@
package com.klp.workflow.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotBlank;
/**
* 流程分类对象 wf_category
*
* @author KonBAI
* @date 2022-01-15
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("wf_category")
public class WfCategory extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* 分类ID
*/
@TableId(value = "category_id")
private Long categoryId;
/**
* 分类名称
*/
@NotBlank(message = "分类名称不能为空")
private String categoryName;
/**
* 分类编码
*/
@NotBlank(message = "分类编码不能为空")
private String code;
/**
* 备注
*/
private String remark;
/**
* 删除标志0代表存在 2代表删除
*/
@TableLogic
private String delFlag;
}

View File

@@ -1,74 +0,0 @@
package com.klp.workflow.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 流程抄送对象 wf_copy
*
* @author KonBAI
* @date 2022-05-19
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("wf_copy")
public class WfCopy extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* 抄送主键
*/
@TableId(value = "copy_id")
private Long copyId;
/**
* 抄送标题
*/
private String title;
/**
* 流程主键
*/
private String processId;
/**
* 流程名称
*/
private String processName;
/**
* 流程分类主键
*/
private String categoryId;
/**
* 部署主键
*/
private String deploymentId;
/**
* 流程实例主键
*/
private String instanceId;
/**
* 任务主键
*/
private String taskId;
/**
* 用户主键
*/
private Long userId;
/**
* 发起人Id
*/
private Long originatorId;
/**
* 发起人名称
*/
private String originatorName;
/**
* 删除标志0代表存在 2代表删除
*/
@TableLogic
private String delFlag;
}

View File

@@ -1,46 +0,0 @@
package com.klp.workflow.domain;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 流程实例关联表单对象 sys_instance_form
*
* @author KonBAI
* @createTime 2022/3/7 22:07
*/
@Data
@TableName("wf_deploy_form")
public class WfDeployForm {
private static final long serialVersionUID = 1L;
/**
* 流程部署主键
*/
private String deployId;
/**
* 表单Key
*/
private String formKey;
/**
* 节点Key
*/
private String nodeKey;
/**
* 表单名称
*/
private String formName;
/**
* 节点名称
*/
private String nodeName;
/**
* 表单内容
*/
private String content;
}

View File

@@ -1,41 +0,0 @@
package com.klp.workflow.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 流程表单对象 wf_form
*
* @author KonBAI
* @createTime 2022/3/7 22:07
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("wf_form")
public class WfForm extends BaseEntity {
private static final long serialVersionUID = 1L;
/**
* 表单主键
*/
@TableId(value = "form_id")
private Long formId;
/**
* 表单名称
*/
private String formName;
/**
* 表单内容
*/
private String content;
/**
* 备注
*/
private String remark;
}

View File

@@ -1,75 +0,0 @@
package com.klp.workflow.domain.bo;
import com.klp.common.core.domain.BaseEntity;
import com.klp.common.core.validate.AddGroup;
import com.klp.common.core.validate.EditGroup;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 流程抄送业务对象 wf_copy
*
* @author klp
* @date 2022-05-19
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class WfCopyBo extends BaseEntity {
/**
* 抄送主键
*/
@NotNull(message = "抄送主键不能为空", groups = { EditGroup.class })
private Long copyId;
/**
* 抄送标题
*/
@NotNull(message = "抄送标题不能为空", groups = { AddGroup.class, EditGroup.class })
private String title;
/**
* 流程主键
*/
@NotBlank(message = "流程主键不能为空", groups = { AddGroup.class, EditGroup.class })
private String processId;
/**
* 流程名称
*/
@NotBlank(message = "流程名称不能为空", groups = { AddGroup.class, EditGroup.class })
private String processName;
/**
* 流程分类主键
*/
@NotBlank(message = "流程分类主键不能为空", groups = { AddGroup.class, EditGroup.class })
private String categoryId;
/**
* 任务主键
*/
@NotBlank(message = "任务主键不能为空", groups = { AddGroup.class, EditGroup.class })
private String taskId;
/**
* 用户主键
*/
@NotNull(message = "用户主键不能为空", groups = { AddGroup.class, EditGroup.class })
private Long userId;
/**
* 发起人Id
*/
@NotNull(message = "发起人主键不能为空", groups = { AddGroup.class, EditGroup.class })
private Long originatorId;
/**
* 发起人名称
*/
@NotNull(message = "发起人名称不能为空", groups = { AddGroup.class, EditGroup.class })
private String originatorName;
}

View File

@@ -1,36 +0,0 @@
package com.klp.workflow.domain.bo;
import com.klp.common.core.validate.AddGroup;
import com.klp.common.core.validate.EditGroup;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 流程设计业务对象
*
* @author KonBAI
* @createTime 2022/3/10 00:12
*/
@Data
public class WfDesignerBo {
/**
* 流程名称
*/
@NotNull(message = "流程名称", groups = { AddGroup.class, EditGroup.class })
private String name;
/**
* 流程分类
*/
@NotBlank(message = "流程分类", groups = { AddGroup.class, EditGroup.class })
private String category;
/**
* XML字符串
*/
@NotBlank(message = "XML字符串", groups = { AddGroup.class, EditGroup.class })
private String xml;
}

View File

@@ -1,45 +0,0 @@
package com.klp.workflow.domain.bo;
import com.klp.common.core.domain.BaseEntity;
import com.klp.common.core.validate.AddGroup;
import com.klp.common.core.validate.EditGroup;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 流程表单业务对象
*
* @author KonBAI
* @createTime 2022/3/7 22:07
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class WfFormBo extends BaseEntity {
private static final long serialVersionUID = 1L;
/**
* 表单主键
*/
@NotNull(message = "表单ID不能为空", groups = { EditGroup.class })
private Long formId;
/**
* 表单名称
*/
@NotBlank(message = "表单名称不能为空", groups = { AddGroup.class, EditGroup.class })
private String formName;
/**
* 表单内容
*/
@NotBlank(message = "表单内容不能为空", groups = { AddGroup.class, EditGroup.class })
private String content;
/**
* 备注
*/
private String remark;
}

View File

@@ -1,58 +0,0 @@
package com.klp.workflow.domain.bo;
import com.klp.common.core.validate.AddGroup;
import com.klp.common.core.validate.EditGroup;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 流程模型对象
*
* @author KonBAI
* @createTime 2022/6/21 9:16
*/
@Data
public class WfModelBo {
/**
* 模型主键
*/
@NotNull(message = "模型主键不能为空", groups = { EditGroup.class })
private String modelId;
/**
* 模型名称
*/
@NotNull(message = "模型名称不能为空", groups = { AddGroup.class, EditGroup.class })
private String modelName;
/**
* 模型Key
*/
@NotNull(message = "模型Key不能为空", groups = { AddGroup.class, EditGroup.class })
private String modelKey;
/**
* 流程分类
*/
@NotBlank(message = "流程分类不能为空", groups = { AddGroup.class, EditGroup.class })
private String category;
/**
* 描述
*/
private String description;
/**
* 表单类型
*/
private Integer formType;
/**
* 表单主键
*/
private Long formId;
/**
* 流程xml
*/
private String bpmnXml;
/**
* 是否保存为新版本
*/
private Boolean newVersion;
}

View File

@@ -1,64 +0,0 @@
package com.klp.workflow.domain.bo;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
* 流程任务业务对象
*
* @author KonBAI
* @createTime 2022/3/10 00:12
*/
@Data
public class WfTaskBo {
/**
* 任务Id
*/
private String taskId;
/**
* 任务名称
*/
private String taskName;
/**
* 用户Id
*/
private String userId;
/**
* 任务意见
*/
private String comment;
/**
* 流程实例Id
*/
private String procInsId;
/**
* 节点
*/
private String targetKey;
/**
* 流程变量信息
*/
private Map<String, Object> variables;
/**
* 审批人
*/
private String assignee;
/**
* 候选人
*/
private List<String> candidateUsers;
/**
* 审批组
*/
private List<String> candidateGroups;
/**
* 抄送用户Id
*/
private String copyUserIds;
/**
* 下一节点审批人
*/
private String nextUserIds;
}

View File

@@ -1,25 +0,0 @@
package com.klp.workflow.domain.dto;
import lombok.Builder;
import lombok.Data;
import java.io.Serializable;
/**
* @author KonBAI
* @createTime 2022/3/10 00:12
*/
@Data
@Builder
public class WfCommentDto implements Serializable {
/**
* 意见类别 0 正常意见 1 退回意见 2 驳回意见
*/
private String type;
/**
* 意见内容
*/
private String comment;
}

View File

@@ -1,30 +0,0 @@
package com.klp.workflow.domain.dto;
import lombok.Data;
/**
* @author KonBAI
* @createTime 2022/6/21 9:16
*/
@Data
public class WfMetaInfoDto {
/**
* 创建者username
*/
private String createUser;
/**
* 流程描述
*/
private String description;
/**
* 表单类型
*/
private Integer formType;
/**
* 表单编号
*/
private Long formId;
}

View File

@@ -1,25 +0,0 @@
package com.klp.workflow.domain.dto;
import com.klp.common.core.domain.entity.SysRole;
import com.klp.common.core.domain.entity.SysUser;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 动态人员、组
* @author KonBAI
* @createTime 2022/3/10 00:12
*/
@Data
public class WfNextDto implements Serializable {
private String type;
private String vars;
private List<SysUser> userList;
private List<SysRole> roleList;
}

View File

@@ -1,46 +0,0 @@
package com.klp.workflow.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
/**
* 流程分类视图对象 flow_category
*
* @author KonBAI
* @date 2022-01-15
*/
@Data
@ExcelIgnoreUnannotated
public class WfCategoryVo {
private static final long serialVersionUID = 1L;
/**
* 分类ID
*/
@ExcelProperty(value = "分类ID")
private Long categoryId;
/**
* 分类名称
*/
@ExcelProperty(value = "分类名称")
private String categoryName;
/**
* 分类编码
*/
@ExcelProperty(value = "分类编码")
private String code;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@@ -1,57 +0,0 @@
package com.klp.workflow.domain.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
/**
* 待签流程对象导出VO
*
* @author konbai
*/
@Data
@NoArgsConstructor
public class WfClaimTaskExportVo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 任务编号
*/
@ExcelProperty(value = "任务编号")
private String taskId;
/**
* 流程名称
*/
@ExcelProperty(value = "流程名称")
private String procDefName;
/**
* 任务节点
*/
@ExcelProperty(value = "任务节点")
private String taskName;
/**
* 流程版本
*/
@ExcelProperty(value = "流程版本")
private int procDefVersion;
/**
* 流程发起人名称
*/
@ExcelProperty(value = "流程发起人")
private String startUserName;
/**
* 接收时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ExcelProperty(value = "接收时间")
private Date createTime;
}

View File

@@ -1,32 +0,0 @@
package com.klp.workflow.domain.vo;
import lombok.Data;
import java.util.Date;
/**
* 流程批复视图对象
*
* @author konbai
* @createTime 2022/4/4 02:03
*/
@Data
public class WfCommentVo {
/**
* 审批类别
*/
private String type;
/**
* 批复内容
*/
private String message;
/**
* 批复时间
*/
private Date time;
}

View File

@@ -1,93 +0,0 @@
package com.klp.workflow.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.util.Date;
/**
* 流程抄送视图对象 wf_copy
*
* @author klp
* @date 2022-05-19
*/
@Data
@ExcelIgnoreUnannotated
public class WfCopyVo {
private static final long serialVersionUID = 1L;
/**
* 抄送主键
*/
@ExcelProperty(value = "抄送主键")
private Long copyId;
/**
* 抄送标题
*/
@ExcelProperty(value = "抄送标题")
private String title;
/**
* 流程主键
*/
@ExcelProperty(value = "流程主键")
private String processId;
/**
* 流程名称
*/
@ExcelProperty(value = "流程名称")
private String processName;
/**
* 流程分类主键
*/
@ExcelProperty(value = "流程分类主键")
private String categoryId;
/**
* 部署主键
*/
@ExcelProperty(value = "部署主键")
private String deploymentId;
/**
* 流程实例主键
*/
@ExcelProperty(value = "流程实例主键")
private String instanceId;
/**
* 任务主键
*/
@ExcelProperty(value = "任务主键")
private String taskId;
/**
* 用户主键
*/
@ExcelProperty(value = "用户主键")
private Long userId;
/**
* 发起人Id
*/
@ExcelProperty(value = "发起人主键")
private Long originatorId;
/**
* 发起人名称
*/
@ExcelProperty(value = "发起人名称")
private String originatorName;
/**
* 抄送时间(创建时间)
*/
@ExcelProperty(value = "抄送时间")
private Date createTime;
}

View File

@@ -1,85 +0,0 @@
package com.klp.workflow.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.klp.common.annotation.ExcelDictFormat;
import com.klp.common.convert.ExcelDictConvert;
import lombok.Data;
import java.util.Date;
/**
* 流程定义视图对象 workflow_definition
*
* @author KonBAI
* @date 2022-01-17
*/
@Data
@ExcelIgnoreUnannotated
public class WfDefinitionVo {
private static final long serialVersionUID = 1L;
/**
* 流程定义ID
*/
@ExcelProperty(value = "流程定义ID")
private String definitionId;
/**
* 流程名称
*/
@ExcelProperty(value = "流程名称")
private String processName;
/**
* 流程Key
*/
@ExcelProperty(value = "流程Key")
private String processKey;
/**
* 分类编码
*/
@ExcelProperty(value = "分类编码")
private String category;
/**
* 版本
*/
@ExcelProperty(value = "版本")
private Integer version;
/**
* 表单ID
*/
@ExcelProperty(value = "表单ID")
private Long formId;
/**
* 表单名称
*/
@ExcelProperty(value = "表单名称")
private String formName;
/**
* 部署ID
*/
@ExcelProperty(value = "部署ID")
private String deploymentId;
/**
* 流程是否暂停true:挂起 false:激活
*/
@ExcelProperty(value = "流程是否挂起", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "true=挂起,false=激活")
private Boolean suspended;
/**
* 部署时间
*/
@ExcelProperty(value = "部署时间")
private Date deploymentTime;
}

View File

@@ -1,45 +0,0 @@
package com.klp.workflow.domain.vo;
import lombok.Data;
/**
* 部署实例和表单关联视图对象
*
* @author KonBAI
* @createTime 2022/7/17 18:29
*/
@Data
public class WfDeployFormVo {
private static final long serialVersionUID = 1L;
/**
* 流程部署主键
*/
private String deployId;
/**
* 表单Key
*/
private String formKey;
/**
* 节点Key
*/
private String nodeKey;
/**
* 表单名称
*/
private String formName;
/**
* 节点名称
*/
private String nodeName;
/**
* 表单内容
*/
private String content;
}

View File

@@ -1,80 +0,0 @@
package com.klp.workflow.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.util.Date;
/**
* 流程部署视图对象
*
* @author KonBAI
* @date 2022-06-30
*/
@Data
@ExcelIgnoreUnannotated
public class WfDeployVo {
private static final long serialVersionUID = 1L;
/**
* 流程定义ID
*/
@ExcelProperty(value = "流程定义ID")
private String definitionId;
/**
* 流程名称
*/
@ExcelProperty(value = "流程名称")
private String processName;
/**
* 流程Key
*/
@ExcelProperty(value = "流程Key")
private String processKey;
/**
* 分类编码
*/
@ExcelProperty(value = "分类编码")
private String category;
/**
* 版本
*/
private Integer version;
/**
* 表单ID
*/
@ExcelProperty(value = "表单ID")
private Long formId;
/**
* 表单名称
*/
@ExcelProperty(value = "表单名称")
private String formName;
/**
* 部署ID
*/
@ExcelProperty(value = "部署ID")
private String deploymentId;
/**
* 流程定义状态: 1:激活 , 2:中止
*/
@ExcelProperty(value = "流程定义状态: 1:激活 , 2:中止")
private Boolean suspended;
/**
* 部署时间
*/
@ExcelProperty(value = "部署时间")
private Date deploymentTime;
}

View File

@@ -1,47 +0,0 @@
package com.klp.workflow.domain.vo;
import cn.hutool.core.util.ObjectUtil;
import com.klp.flowable.core.FormConf;
import lombok.Data;
import java.util.List;
/**
* 流程详情视图对象
*
* @author KonBAI
* @createTime 2022/8/7 15:01
*/
@Data
public class WfDetailVo {
/**
* 任务表单信息
*/
private FormConf taskFormData;
/**
* 历史流程节点信息
*/
private List<WfProcNodeVo> historyProcNodeList;
/**
* 流程表单列表
*/
private List<FormConf> processFormList;
/**
* 流程XML
*/
private String bpmnXml;
private WfViewerVo flowViewer;
/**
* 是否存在任务表单信息
* @return true:存在false:不存在
*/
public Boolean isExistTaskForm() {
return ObjectUtil.isNotEmpty(this.taskFormData);
}
}

View File

@@ -1,70 +0,0 @@
package com.klp.workflow.domain.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
/**
* 已办流程对象导出VO
*
* @author konbai
*/
@Data
@NoArgsConstructor
public class WfFinishedTaskExportVo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 任务编号
*/
@ExcelProperty(value = "任务编号")
private String taskId;
/**
* 流程名称
*/
@ExcelProperty(value = "流程名称")
private String procDefName;
/**
* 任务节点
*/
@ExcelProperty(value = "任务节点")
private String taskName;
/**
* 流程版本
*/
@ExcelProperty(value = "流程版本")
private int procDefVersion;
/**
* 流程发起人名称
*/
@ExcelProperty(value = "流程发起人")
private String startUserName;
/**
* 接收时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ExcelProperty(value = "接收时间")
private Date createTime;
/**
* 审批时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ExcelProperty(value = "审批时间")
private Date finishTime;
/**
* 任务耗时
*/
@ExcelProperty(value = "任务耗时")
private String duration;
}

View File

@@ -1,42 +0,0 @@
package com.klp.workflow.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
/**
* 流程分类视图对象
*
* @author KonBAI
* @createTime 2022/3/7 22:07
*/
@Data
@ExcelIgnoreUnannotated
public class WfFormVo {
private static final long serialVersionUID = 1L;
/**
* 表单主键
*/
@ExcelProperty(value = "表单ID")
private Long formId;
/**
* 表单名称
*/
@ExcelProperty(value = "表单名称")
private String formName;
/**
* 表单内容
*/
@ExcelProperty(value = "表单内容")
private String content;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@@ -1,59 +0,0 @@
package com.klp.workflow.domain.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
/**
* 流程模型对象导出VO
*
* @author konbai
*/
@Data
@NoArgsConstructor
public class WfModelExportVo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 模型ID
*/
@ExcelProperty(value = "模型ID")
private String modelId;
/**
* 模型Key
*/
@ExcelProperty(value = "模型Key")
private String modelKey;
/**
* 模型名称
*/
@ExcelProperty(value = "模型名称")
private String modelName;
/**
* 分类编码
*/
@ExcelProperty(value = "分类编码")
private String category;
/**
* 流程分类
*/
@ExcelProperty(value = "流程分类")
private String categoryName;
/**
* 模型版本
*/
@ExcelProperty(value = "模型版本")
private Integer version;
/**
* 模型描述
*/
@ExcelProperty(value = "模型描述")
private String description;
/**
* 创建时间
*/
@ExcelProperty(value = "创建时间")
private Date createTime;
}

View File

@@ -1,59 +0,0 @@
package com.klp.workflow.domain.vo;
import lombok.Data;
import java.util.Date;
/**
* 流程模型视图对象
*
* @author KonBAI
* @createTime 2022/6/21 9:16
*/
@Data
public class WfModelVo {
/**
* 模型ID
*/
private String modelId;
/**
* 模型名称
*/
private String modelName;
/**
* 模型Key
*/
private String modelKey;
/**
* 分类编码
*/
private String category;
/**
* 版本
*/
private Integer version;
/**
* 表单类型
*/
private Integer formType;
/**
* 表单ID
*/
private Long formId;
/**
* 模型描述
*/
private String description;
/**
* 创建时间
*/
private Date createTime;
/**
* 流程xml
*/
private String bpmnXml;
/**
* 表单内容
*/
private String content;
}

View File

@@ -1,75 +0,0 @@
package com.klp.workflow.domain.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
/**
* 我拥有流程对象导出VO
*
* @author konbai
*/
@Data
@NoArgsConstructor
public class WfOwnTaskExportVo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 流程实例ID
*/
@ExcelProperty(value = "流程编号")
private String procInsId;
/**
* 流程名称
*/
@ExcelProperty(value = "流程名称")
private String procDefName;
/**
* 流程类别
*/
@ExcelProperty(value = "流程类别")
private String category;
/**
* 流程版本
*/
@ExcelProperty(value = "流程版本")
private int procDefVersion;
/**
* 提交时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ExcelProperty(value = "提交时间")
private Date createTime;
/**
* 流程状态
*/
@ExcelProperty(value = "流程状态")
private String status;
/**
* 任务耗时
*/
@ExcelProperty(value = "任务耗时")
private String duration;
/**
* 当前节点
*/
@ExcelProperty(value = "当前节点")
private String taskName;
/**
* 任务完成时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date finishTime;
}

View File

@@ -1,67 +0,0 @@
package com.klp.workflow.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.flowable.engine.task.Comment;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* 工作流节点元素视图对象
*
* @author KonBAI
* @createTime 2022/9/11 22:04
*/
@Data
@ExcelIgnoreUnannotated
public class WfProcNodeVo implements Serializable {
/**
* 流程ID
*/
private String procDefId;
/**
* 活动ID
*/
private String activityId;
/**
* 活动名称
*/
private String activityName;
/**
* 活动类型
*/
private String activityType;
/**
* 活动耗时
*/
private String duration;
/**
* 执行人Id
*/
private Long assigneeId;
/**
* 执行人名称
*/
private String assigneeName;
/**
* 候选执行人
*/
private String candidate;
/**
* 任务意见
*/
private List<Comment> commentList;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 结束时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
}

View File

@@ -1,132 +0,0 @@
package com.klp.workflow.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.klp.workflow.domain.dto.WfCommentDto;
import lombok.Data;
import org.flowable.engine.task.Comment;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* 工作流任务视图对象
*
* @author KonBAI
* @createTime 2022/3/10 00:12
*/
@Data
@ExcelIgnoreUnannotated
public class WfTaskVo implements Serializable {
/**
* 任务编号
*/
private String taskId;
/**
* 任务名称
*/
private String taskName;
/**
* 任务Key
*/
private String taskDefKey;
/**
* 任务执行人Id
*/
private Long assigneeId;
/**
* 部门名称
*/
@Deprecated
private String deptName;
/**
* 流程发起人部门名称
*/
@Deprecated
private String startDeptName;
/**
* 任务执行人名称
*/
private String assigneeName;
/**
* 流程发起人Id
*/
private Long startUserId;
/**
* 流程发起人名称
*/
private String startUserName;
/**
* 流程类型
*/
private String category;
/**
* 流程变量信息
*/
private Object procVars;
/**
* 局部变量信息
*/
private Object taskLocalVars;
/**
* 流程部署编号
*/
private String deployId;
/**
* 流程ID
*/
private String procDefId;
/**
* 流程key
*/
private String procDefKey;
/**
* 流程定义名称
*/
private String procDefName;
/**
* 流程定义内置使用版本
*/
private int procDefVersion;
/**
* 流程实例ID
*/
private String procInsId;
/**
* 历史流程实例ID
*/
private String hisProcInsId;
/**
* 任务耗时
*/
private String duration;
/**
* 任务意见
*/
private WfCommentDto comment;
/**
* 任务意见
*/
private List<Comment> commentList;
/**
* 候选执行人
*/
private String candidate;
/**
* 任务创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 任务完成时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date finishTime;
/**
* 流程状态
*/
private String processStatus;
}

View File

@@ -1,57 +0,0 @@
package com.klp.workflow.domain.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
/**
* 待办流程对象导出VO
*
* @author konbai
*/
@Data
@NoArgsConstructor
public class WfTodoTaskExportVo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 任务编号
*/
@ExcelProperty(value = "任务编号")
private String taskId;
/**
* 流程名称
*/
@ExcelProperty(value = "流程名称")
private String procDefName;
/**
* 任务节点
*/
@ExcelProperty(value = "任务节点")
private String taskName;
/**
* 流程版本
*/
@ExcelProperty(value = "流程版本")
private int procDefVersion;
/**
* 流程发起人名称
*/
@ExcelProperty(value = "流程发起人")
private String startUserName;
/**
* 接收时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ExcelProperty(value = "接收时间")
private Date createTime;
}

View File

@@ -1,41 +0,0 @@
package com.klp.workflow.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Set;
/**
* 任务追踪视图对象
*
* @author KonBAI
* @createTime 2022/1/8 19:42
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@ExcelIgnoreUnannotated
public class WfViewerVo {
/**
* 获取流程实例的历史节点(去重)
*/
private Set<String> finishedTaskSet;
/**
* 已完成
*/
private Set<String> finishedSequenceFlowSet;
/**
* 获取流程实例当前正在待办的节点(去重)
*/
private Set<String> unfinishedTaskSet;
/**
* 已拒绝
*/
private Set<String> rejectedTaskSet;
}

View File

@@ -1,62 +0,0 @@
package com.klp.workflow.handler;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.toolkit.SimpleQuery;
import com.klp.common.core.domain.entity.SysUser;
import com.klp.flowable.common.constant.ProcessConstants;
import com.klp.system.domain.SysUserRole;
import lombok.AllArgsConstructor;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.UserTask;
import org.flowable.engine.delegate.DelegateExecution;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 多实例处理类
*
* @author KonBAI
*/
@AllArgsConstructor
@Component("multiInstanceHandler")
public class MultiInstanceHandler {
public Set<String> getUserIds(DelegateExecution execution) {
Set<String> candidateUserIds = new LinkedHashSet<>();
FlowElement flowElement = execution.getCurrentFlowElement();
if (ObjectUtil.isNotEmpty(flowElement) && flowElement instanceof UserTask) {
UserTask userTask = (UserTask) flowElement;
String dataType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_DATA_TYPE);
if ("USERS".equals(dataType) && CollUtil.isNotEmpty(userTask.getCandidateUsers())) {
// 添加候选用户id
candidateUserIds.addAll(userTask.getCandidateUsers());
} else if (CollUtil.isNotEmpty(userTask.getCandidateGroups())) {
// 获取组的ID角色ID集合或部门ID集合
List<Long> groups = userTask.getCandidateGroups().stream()
.map(item -> Long.parseLong(item.substring(4)))
.collect(Collectors.toList());
List<Long> userIds = new ArrayList<>();
if ("ROLES".equals(dataType)) {
// 通过角色id获取所有用户id集合
LambdaQueryWrapper<SysUserRole> lqw = Wrappers.lambdaQuery(SysUserRole.class).select(SysUserRole::getUserId).in(SysUserRole::getRoleId, groups);
userIds = SimpleQuery.list(lqw, SysUserRole::getUserId);
} else if ("DEPTS".equals(dataType)) {
// 通过部门id获取所有用户id集合
LambdaQueryWrapper<SysUser> lqw = Wrappers.lambdaQuery(SysUser.class).select(SysUser::getUserId).in(SysUser::getDeptId, groups);
userIds = SimpleQuery.list(lqw, SysUser::getUserId);
}
// 添加候选用户id
userIds.forEach(id -> candidateUserIds.add(String.valueOf(id)));
}
}
return candidateUserIds;
}
}

View File

@@ -1,15 +0,0 @@
package com.klp.workflow.mapper;
import com.klp.common.core.mapper.BaseMapperPlus;
import com.klp.workflow.domain.WfCategory;
import com.klp.workflow.domain.vo.WfCategoryVo;
/**
* 流程分类Mapper接口
*
* @author KonBAI
* @date 2022-01-15
*/
public interface WfCategoryMapper extends BaseMapperPlus<WfCategoryMapper, WfCategory, WfCategoryVo> {
}

View File

@@ -1,15 +0,0 @@
package com.klp.workflow.mapper;
import com.klp.common.core.mapper.BaseMapperPlus;
import com.klp.workflow.domain.WfCopy;
import com.klp.workflow.domain.vo.WfCopyVo;
/**
* 流程抄送Mapper接口
*
* @author KonBAI
* @date 2022-05-19
*/
public interface WfCopyMapper extends BaseMapperPlus<WfCopyMapper, WfCopy, WfCopyVo> {
}

View File

@@ -1,15 +0,0 @@
package com.klp.workflow.mapper;
import com.klp.common.core.mapper.BaseMapperPlus;
import com.klp.workflow.domain.WfDeployForm;
import com.klp.workflow.domain.vo.WfDeployFormVo;
/**
* 流程实例关联表单Mapper接口
*
* @author KonBAI
* @createTime 2022/3/7 22:07
*/
public interface WfDeployFormMapper extends BaseMapperPlus<WfDeployFormMapper, WfDeployForm, WfDeployFormVo> {
}

View File

@@ -1,21 +0,0 @@
package com.klp.workflow.mapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.klp.common.core.mapper.BaseMapperPlus;
import com.klp.workflow.domain.WfForm;
import com.klp.workflow.domain.vo.WfFormVo;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 流程表单Mapper接口
*
* @author KonBAI
* @createTime 2022/3/7 22:07
*/
public interface WfFormMapper extends BaseMapperPlus<WfFormMapper, WfForm, WfFormVo> {
List<WfFormVo> selectFormVoList(@Param(Constants.WRAPPER) Wrapper<WfForm> queryWrapper);
}

View File

@@ -1,64 +0,0 @@
package com.klp.workflow.service;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.workflow.domain.WfCategory;
import com.klp.workflow.domain.vo.WfCategoryVo;
import java.util.Collection;
import java.util.List;
/**
* 流程分类Service接口
*
* @author KonBAI
* @date 2022-01-15
*/
public interface IWfCategoryService {
/**
* 查询单个
* @return
*/
WfCategoryVo queryById(Long categoryId);
/**
* 查询列表
*/
TableDataInfo<WfCategoryVo> queryPageList(WfCategory category, PageQuery pageQuery);
/**
* 查询列表
*/
List<WfCategoryVo> queryList(WfCategory category);
/**
* 新增流程分类
*
* @param category 流程分类信息
* @return 结果
*/
int insertCategory(WfCategory category);
/**
* 编辑流程分类
* @param category 流程分类信息
* @return 结果
*/
int updateCategory(WfCategory category);
/**
* 校验并删除数据
* @param ids 主键集合
* @param isValid 是否校验,true-删除前校验,false-不校验
* @return 结果
*/
int deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 校验分类编码是否唯一
*
* @param category 流程分类
* @return 结果
*/
boolean checkCategoryCodeUnique(WfCategory category);
}

View File

@@ -1,49 +0,0 @@
package com.klp.workflow.service;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.workflow.domain.bo.WfCopyBo;
import com.klp.workflow.domain.bo.WfTaskBo;
import com.klp.workflow.domain.vo.WfCopyVo;
import java.util.List;
/**
* 流程抄送Service接口
*
* @author KonBAI
* @date 2022-05-19
*/
public interface IWfCopyService {
/**
* 查询流程抄送
*
* @param copyId 流程抄送主键
* @return 流程抄送
*/
WfCopyVo queryById(Long copyId);
/**
* 查询流程抄送列表
*
* @param wfCopy 流程抄送
* @return 流程抄送集合
*/
TableDataInfo<WfCopyVo> selectPageList(WfCopyBo wfCopy, PageQuery pageQuery);
/**
* 查询流程抄送列表
*
* @param wfCopy 流程抄送
* @return 流程抄送集合
*/
List<WfCopyVo> selectList(WfCopyBo wfCopy);
/**
* 抄送
* @param taskBo
* @return
*/
Boolean makeCopy(WfTaskBo taskBo);
}

View File

@@ -1,39 +0,0 @@
package com.klp.workflow.service;
import com.klp.workflow.domain.WfDeployForm;
import com.klp.workflow.domain.vo.WfFormVo;
import org.flowable.bpmn.model.BpmnModel;
/**
* 流程实例关联表单Service接口
*
* @author KonBAI
* @createTime 2022/3/7 22:07
*/
public interface IWfDeployFormService {
/**
* 新增流程实例关联表单
*
* @param wfDeployForm 流程实例关联表单
* @return 结果
*/
int insertWfDeployForm(WfDeployForm wfDeployForm);
/**
* 保存流程实例关联表单
* @param deployId 部署ID
* @param bpmnModel bpmnModel对象
* @return
*/
boolean saveInternalDeployForm(String deployId, BpmnModel bpmnModel);
/**
* 查询流程挂着的表单
*
* @param deployId
* @return
*/
@Deprecated
WfFormVo selectDeployFormByDeployId(String deployId);
}

View File

@@ -1,25 +0,0 @@
package com.klp.workflow.service;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.flowable.core.domain.ProcessQuery;
import com.klp.workflow.domain.vo.WfDeployVo;
import java.util.List;
/**
* @author KonBAI
* @createTime 2022/6/30 9:03
*/
public interface IWfDeployService {
TableDataInfo<WfDeployVo> queryPageList(ProcessQuery processQuery, PageQuery pageQuery);
TableDataInfo<WfDeployVo> queryPublishList(String processKey, PageQuery pageQuery);
void updateState(String definitionId, String stateCode);
String queryBpmnXmlById(String definitionId);
void deleteByIds(List<String> deployIds);
}

View File

@@ -1,65 +0,0 @@
package com.klp.workflow.service;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.workflow.domain.bo.WfFormBo;
import com.klp.workflow.domain.vo.WfFormVo;
import java.util.Collection;
import java.util.List;
/**
* 表单
*
* @author KonBAI
* @createTime 2022/3/7 22:07
*/
public interface IWfFormService {
/**
* 查询流程表单
*
* @param formId 流程表单ID
* @return 流程表单
*/
WfFormVo queryById(Long formId);
/**
* 查询流程表单列表
*
* @param bo 流程表单
* @return 流程表单集合
*/
TableDataInfo<WfFormVo> queryPageList(WfFormBo bo, PageQuery pageQuery);
/**
* 查询流程表单列表
*
* @param bo 流程表单
* @return 流程表单集合
*/
List<WfFormVo> queryList(WfFormBo bo);
/**
* 新增流程表单
*
* @param bo 流程表单
* @return 结果
*/
int insertForm(WfFormBo bo);
/**
* 修改流程表单
*
* @param bo 流程表单
* @return 结果
*/
int updateForm(WfFormBo bo);
/**
* 批量删除流程表单
*
* @param formIds 需要删除的流程表单ID
* @return 结果
*/
Boolean deleteWithValidByIds(Collection<Long> formIds);
}

View File

@@ -1,52 +0,0 @@
package com.klp.workflow.service;
import com.klp.workflow.domain.bo.WfTaskBo;
import org.flowable.engine.history.HistoricProcessInstance;
import java.util.Map;
/**
* @author KonBAI
* @createTime 2022/3/10 00:12
*/
public interface IWfInstanceService {
/**
* 结束流程实例
*
* @param vo
*/
void stopProcessInstance(WfTaskBo vo);
/**
* 激活或挂起流程实例
*
* @param state 状态
* @param instanceId 流程实例ID
*/
void updateState(Integer state, String instanceId);
/**
* 删除流程实例ID
*
* @param instanceId 流程实例ID
* @param deleteReason 删除原因
*/
void delete(String instanceId, String deleteReason);
/**
* 根据实例ID查询历史实例数据
*
* @param processInstanceId
* @return
*/
HistoricProcessInstance getHistoricProcessInstanceById(String processInstanceId);
/**
* 查询流程详情信息
* @param procInsId 流程实例ID
* @param deployId 流程部署ID
*/
Map<String, Object> queryDetailProcess(String procInsId, String deployId);
}

View File

@@ -1,71 +0,0 @@
package com.klp.workflow.service;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.workflow.domain.bo.WfModelBo;
import com.klp.workflow.domain.vo.WfModelVo;
import java.util.Collection;
import java.util.List;
/**
* @author KonBAI
* @createTime 2022/6/21 9:11
*/
public interface IWfModelService {
/**
* 查询流程模型列表
*/
TableDataInfo<WfModelVo> list(WfModelBo modelBo, PageQuery pageQuery);
/**
* 查询流程模型列表
*/
List<WfModelVo> list(WfModelBo modelBo);
/**
* 查询流程模型列表
*/
TableDataInfo<WfModelVo> historyList(WfModelBo modelBo, PageQuery pageQuery);
/**
* 查询流程模型详情信息
*/
WfModelVo getModel(String modelId);
/**
* 查询流程表单详细信息
*/
String queryBpmnXmlById(String modelId);
/**
* 新增模型信息
*/
void insertModel(WfModelBo modelBo);
/**
* 修改模型信息
*/
void updateModel(WfModelBo modelBo);
/**
* 保存流程模型信息
*/
void saveModel(WfModelBo modelBo);
/**
* 设为最新流程模型
*/
void latestModel(String modelId);
/**
* 删除流程模型
*/
void deleteByIds(Collection<String> ids);
/**
* 部署流程模型
*/
boolean deployModel(String modelId);
}

View File

@@ -1,116 +0,0 @@
package com.klp.workflow.service;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.flowable.core.FormConf;
import com.klp.flowable.core.domain.ProcessQuery;
import com.klp.workflow.domain.vo.WfDefinitionVo;
import com.klp.workflow.domain.vo.WfDetailVo;
import com.klp.workflow.domain.vo.WfTaskVo;
import java.util.List;
import java.util.Map;
/**
* @author KonBAI
* @createTime 2022/3/24 18:57
*/
public interface IWfProcessService {
/**
* 查询可发起流程列表
* @param pageQuery 分页参数
* @return
*/
TableDataInfo<WfDefinitionVo> selectPageStartProcessList(ProcessQuery processQuery, PageQuery pageQuery);
/**
* 查询可发起流程列表
*/
List<WfDefinitionVo> selectStartProcessList(ProcessQuery processQuery);
/**
* 查询我的流程列表
* @param pageQuery 分页参数
*/
TableDataInfo<WfTaskVo> selectPageOwnProcessList(ProcessQuery processQuery, PageQuery pageQuery);
/**
* 查询我的流程列表
*/
List<WfTaskVo> selectOwnProcessList(ProcessQuery processQuery);
/**
* 查询代办任务列表
* @param pageQuery 分页参数
*/
TableDataInfo<WfTaskVo> selectPageTodoProcessList(ProcessQuery processQuery, PageQuery pageQuery);
/**
* 查询代办任务列表
*/
List<WfTaskVo> selectTodoProcessList(ProcessQuery processQuery);
/**
* 查询待签任务列表
* @param pageQuery 分页参数
*/
TableDataInfo<WfTaskVo> selectPageClaimProcessList(ProcessQuery processQuery, PageQuery pageQuery);
/**
* 查询待签任务列表
*/
List<WfTaskVo> selectClaimProcessList(ProcessQuery processQuery);
/**
* 查询已办任务列表
* @param pageQuery 分页参数
*/
TableDataInfo<WfTaskVo> selectPageFinishedProcessList(ProcessQuery processQuery, PageQuery pageQuery);
/**
* 查询已办任务列表
*/
List<WfTaskVo> selectFinishedProcessList(ProcessQuery processQuery);
/**
* 查询流程部署关联表单信息
* @param definitionId 流程定义ID
* @param deployId 部署ID
*/
FormConf selectFormContent(String definitionId, String deployId, String procInsId);
/**
* 启动流程实例
* @param procDefId 流程定义ID
* @param variables 扩展参数
*/
void startProcessByDefId(String procDefId, Map<String, Object> variables);
/**
* 通过DefinitionKey启动流程
* @param procDefKey 流程定义Key
* @param variables 扩展参数
*/
void startProcessByDefKey(String procDefKey, Map<String, Object> variables);
/**
* 删除流程实例
*/
void deleteProcessByIds(String[] instanceIds);
/**
* 读取xml文件
* @param processDefId 流程定义ID
*/
String queryBpmnXmlById(String processDefId);
/**
* 查询流程任务详情信息
* @param procInsId 流程实例ID
* @param taskId 任务ID
*/
WfDetailVo queryProcessDetail(String procInsId, String taskId);
}

View File

@@ -1,117 +0,0 @@
package com.klp.workflow.service;
import com.klp.workflow.domain.bo.WfTaskBo;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.engine.runtime.ProcessInstance;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
/**
* @author KonBAI
* @createTime 2022/3/10 00:12
*/
public interface IWfTaskService {
/**
* 审批任务
*
* @param task 请求实体参数
*/
void complete(WfTaskBo task);
/**
* 拒绝任务
*
* @param taskBo
*/
void taskReject(WfTaskBo taskBo);
/**
* 退回任务
*
* @param bo 请求实体参数
*/
void taskReturn(WfTaskBo bo);
/**
* 获取所有可回退的节点
*
* @param bo
* @return
*/
List<FlowElement> findReturnTaskList(WfTaskBo bo);
/**
* 删除任务
*
* @param bo 请求实体参数
*/
void deleteTask(WfTaskBo bo);
/**
* 认领/签收任务
*
* @param bo 请求实体参数
*/
void claim(WfTaskBo bo);
/**
* 取消认领/签收任务
*
* @param bo 请求实体参数
*/
void unClaim(WfTaskBo bo);
/**
* 委派任务
*
* @param bo 请求实体参数
*/
void delegateTask(WfTaskBo bo);
/**
* 转办任务
*
* @param bo 请求实体参数
*/
void transferTask(WfTaskBo bo);
/**
* 取消申请
* @param bo
* @return
*/
void stopProcess(WfTaskBo bo);
/**
* 撤回流程
* @param bo
* @return
*/
void revokeProcess(WfTaskBo bo);
/**
* 获取流程过程图
* @param processId
* @return
*/
InputStream diagram(String processId);
/**
* 获取流程变量
* @param taskId 任务ID
* @return 流程变量
*/
Map<String, Object> getProcessVariables(String taskId);
/**
* 启动第一个任务
* @param processInstance 流程实例
* @param variables 流程参数
*/
void startFirstTask(ProcessInstance processInstance, Map<String, Object> variables);
}

View File

@@ -1,93 +0,0 @@
package com.klp.workflow.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.utils.StringUtils;
import com.klp.workflow.domain.WfCategory;
import com.klp.workflow.domain.vo.WfCategoryVo;
import com.klp.workflow.mapper.WfCategoryMapper;
import com.klp.workflow.service.IWfCategoryService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 流程分类Service业务层处理
*
* @author KonBAI
* @date 2022-01-15
*/
@RequiredArgsConstructor
@Service
public class WfCategoryServiceImpl implements IWfCategoryService {
private final WfCategoryMapper baseMapper;
@Override
public WfCategoryVo queryById(Long categoryId){
return baseMapper.selectVoById(categoryId);
}
@Override
public TableDataInfo<WfCategoryVo> queryPageList(WfCategory category, PageQuery pageQuery) {
LambdaQueryWrapper<WfCategory> lqw = buildQueryWrapper(category);
Page<WfCategoryVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
@Override
public List<WfCategoryVo> queryList(WfCategory category) {
LambdaQueryWrapper<WfCategory> lqw = buildQueryWrapper(category);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<WfCategory> buildQueryWrapper(WfCategory category) {
Map<String, Object> params = category.getParams();
LambdaQueryWrapper<WfCategory> lqw = Wrappers.lambdaQuery();
lqw.like(StringUtils.isNotBlank(category.getCategoryName()), WfCategory::getCategoryName, category.getCategoryName());
lqw.eq(StringUtils.isNotBlank(category.getCode()), WfCategory::getCode, category.getCode());
return lqw;
}
@Override
public int insertCategory(WfCategory categoryBo) {
WfCategory add = BeanUtil.toBean(categoryBo, WfCategory.class);
return baseMapper.insert(add);
}
@Override
public int updateCategory(WfCategory categoryBo) {
WfCategory update = BeanUtil.toBean(categoryBo, WfCategory.class);
return baseMapper.updateById(update);
}
@Override
public int deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids);
}
/**
* 校验分类编码是否唯一
*
* @param category 流程分类
* @return 结果
*/
@Override
public boolean checkCategoryCodeUnique(WfCategory category) {
boolean exist = baseMapper.exists(new LambdaQueryWrapper<WfCategory>()
.eq(WfCategory::getCode, category.getCode())
.ne(ObjectUtil.isNotNull(category.getCategoryId()), WfCategory::getCategoryId, category.getCategoryId()));
return !exist;
}
}

View File

@@ -1,114 +0,0 @@
package com.klp.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 com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.helper.LoginHelper;
import com.klp.common.utils.StringUtils;
import com.klp.workflow.domain.WfCopy;
import com.klp.workflow.domain.bo.WfCopyBo;
import com.klp.workflow.domain.bo.WfTaskBo;
import com.klp.workflow.domain.vo.WfCopyVo;
import com.klp.workflow.mapper.WfCopyMapper;
import com.klp.workflow.service.IWfCopyService;
import lombok.RequiredArgsConstructor;
import org.flowable.engine.HistoryService;
import org.flowable.engine.history.HistoricProcessInstance;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 流程抄送Service业务层处理
*
* @author KonBAI
* @date 2022-05-19
*/
@RequiredArgsConstructor
@Service
public class WfCopyServiceImpl implements IWfCopyService {
private final WfCopyMapper baseMapper;
private final HistoryService historyService;
/**
* 查询流程抄送
*
* @param copyId 流程抄送主键
* @return 流程抄送
*/
@Override
public WfCopyVo queryById(Long copyId){
return baseMapper.selectVoById(copyId);
}
/**
* 查询流程抄送列表
*
* @param bo 流程抄送
* @return 流程抄送
*/
@Override
public TableDataInfo<WfCopyVo> selectPageList(WfCopyBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<WfCopy> lqw = buildQueryWrapper(bo);
lqw.orderByDesc(WfCopy::getCreateTime);
Page<WfCopyVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询流程抄送列表
*
* @param bo 流程抄送
* @return 流程抄送
*/
@Override
public List<WfCopyVo> selectList(WfCopyBo bo) {
LambdaQueryWrapper<WfCopy> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<WfCopy> buildQueryWrapper(WfCopyBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<WfCopy> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getUserId() != null, WfCopy::getUserId, bo.getUserId());
lqw.like(StringUtils.isNotBlank(bo.getProcessName()), WfCopy::getProcessName, bo.getProcessName());
lqw.like(StringUtils.isNotBlank(bo.getOriginatorName()), WfCopy::getOriginatorName, bo.getOriginatorName());
return lqw;
}
@Override
public Boolean makeCopy(WfTaskBo taskBo) {
if (StringUtils.isBlank(taskBo.getCopyUserIds())) {
// 若抄送用户为空,则不需要处理,返回成功
return true;
}
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
.processInstanceId(taskBo.getProcInsId()).singleResult();
String[] ids = taskBo.getCopyUserIds().split(",");
List<WfCopy> copyList = new ArrayList<>(ids.length);
Long originatorId = LoginHelper.getUserId();
String originatorName = LoginHelper.getNickName();
String title = historicProcessInstance.getProcessDefinitionName() + "-" + taskBo.getTaskName();
for (String id : ids) {
Long userId = Long.valueOf(id);
WfCopy copy = new WfCopy();
copy.setTitle(title);
copy.setProcessId(historicProcessInstance.getProcessDefinitionId());
copy.setProcessName(historicProcessInstance.getProcessDefinitionName());
copy.setDeploymentId(historicProcessInstance.getDeploymentId());
copy.setInstanceId(taskBo.getProcInsId());
copy.setTaskId(taskBo.getTaskId());
copy.setUserId(userId);
copy.setOriginatorId(originatorId);
copy.setOriginatorName(originatorName);
copyList.add(copy);
}
return baseMapper.insertBatch(copyList);
}
}

View File

@@ -1,134 +0,0 @@
package com.klp.workflow.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.klp.common.exception.ServiceException;
import com.klp.common.utils.StringUtils;
import com.klp.flowable.utils.ModelUtils;
import com.klp.workflow.domain.WfDeployForm;
import com.klp.workflow.domain.WfForm;
import com.klp.workflow.domain.vo.WfFormVo;
import com.klp.workflow.mapper.WfDeployFormMapper;
import com.klp.workflow.mapper.WfFormMapper;
import com.klp.workflow.service.IWfDeployFormService;
import lombok.RequiredArgsConstructor;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowNode;
import org.flowable.bpmn.model.StartEvent;
import org.flowable.bpmn.model.UserTask;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* 流程实例关联表单Service业务层处理
*
* @author KonBAI
* @createTime 2022/3/7 22:07
*/
@RequiredArgsConstructor
@Service
public class WfDeployFormServiceImpl implements IWfDeployFormService {
private final WfDeployFormMapper baseMapper;
private final WfFormMapper formMapper;
/**
* 新增流程实例关联表单
*
* @param deployForm 流程实例关联表单
* @return 结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int insertWfDeployForm(WfDeployForm deployForm) {
// 删除部署流程和表单的关联关系
baseMapper.delete(new LambdaQueryWrapper<WfDeployForm>().eq(WfDeployForm::getDeployId, deployForm.getDeployId()));
// 新增部署流程和表单关系
return baseMapper.insert(deployForm);
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean saveInternalDeployForm(String deployId, BpmnModel bpmnModel) {
List<WfDeployForm> deployFormList = new ArrayList<>();
// 获取开始节点
StartEvent startEvent = ModelUtils.getStartEvent(bpmnModel);
if (ObjectUtil.isNull(startEvent)) {
throw new RuntimeException("开始节点不存在,请检查流程设计是否有误!");
}
// 保存开始节点表单信息
WfDeployForm startDeployForm = buildDeployForm(deployId, startEvent);
if (ObjectUtil.isNotNull(startDeployForm)) {
deployFormList.add(startDeployForm);
}
// 保存用户节点表单信息
Collection<UserTask> userTasks = ModelUtils.getAllUserTaskEvent(bpmnModel);
if (CollUtil.isNotEmpty(userTasks)) {
for (UserTask userTask : userTasks) {
WfDeployForm userTaskDeployForm = buildDeployForm(deployId, userTask);
if (ObjectUtil.isNotNull(userTaskDeployForm)) {
deployFormList.add(userTaskDeployForm);
}
}
}
// 批量新增部署流程和表单关联信息
return baseMapper.insertBatch(deployFormList);
}
/**
* 查询流程挂着的表单
*
* @param deployId
* @return
*/
@Override
public WfFormVo selectDeployFormByDeployId(String deployId) {
QueryWrapper<WfForm> wrapper = Wrappers.query();
wrapper.eq("t2.deploy_id", deployId);
List<WfFormVo> list = formMapper.selectFormVoList(wrapper);
if (ObjectUtil.isNotEmpty(list)) {
if (list.size() != 1) {
throw new ServiceException("表单信息查询错误");
} else {
return list.get(0);
}
} else {
return null;
}
}
/**
* 构建部署表单关联信息对象
* @param deployId 部署ID
* @param node 节点信息
* @return 部署表单关联对象。若无表单信息formKey则返回null
*/
private WfDeployForm buildDeployForm(String deployId, FlowNode node) {
String formKey = ModelUtils.getFormKey(node);
if (StringUtils.isEmpty(formKey)) {
return null;
}
Long formId = Convert.toLong(StringUtils.substringAfter(formKey, "key_"));
WfForm wfForm = formMapper.selectById(formId);
if (ObjectUtil.isNull(wfForm)) {
throw new ServiceException("表单信息查询错误");
}
WfDeployForm deployForm = new WfDeployForm();
deployForm.setDeployId(deployId);
deployForm.setFormKey(formKey);
deployForm.setNodeKey(node.getId());
deployForm.setFormName(wfForm.getFormName());
deployForm.setNodeName(node.getName());
deployForm.setContent(wfForm.getContent());
return deployForm;
}
}

View File

@@ -1,146 +0,0 @@
package com.klp.workflow.service.impl;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.flowable.core.domain.ProcessQuery;
import com.klp.flowable.utils.ProcessUtils;
import com.klp.workflow.domain.WfDeployForm;
import com.klp.workflow.domain.vo.WfDeployVo;
import com.klp.workflow.mapper.WfDeployFormMapper;
import com.klp.workflow.service.IWfDeployService;
import lombok.RequiredArgsConstructor;
import org.flowable.common.engine.impl.db.SuspensionState;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.repository.ProcessDefinitionQuery;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author KonBAI
* @createTime 2022/6/30 9:04
*/
@RequiredArgsConstructor
@Service
public class WfDeployServiceImpl implements IWfDeployService {
private final RepositoryService repositoryService;
private final WfDeployFormMapper deployFormMapper;
@Override
public TableDataInfo<WfDeployVo> queryPageList(ProcessQuery processQuery, PageQuery pageQuery) {
// 流程定义列表数据查询
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery()
.latestVersion()
.orderByProcessDefinitionKey()
.asc();
// 构建搜索条件
ProcessUtils.buildProcessSearch(processDefinitionQuery, processQuery);
long pageTotal = processDefinitionQuery.count();
if (pageTotal <= 0) {
return TableDataInfo.build();
}
int offset = pageQuery.getPageSize() * (pageQuery.getPageNum() - 1);
List<ProcessDefinition> definitionList = processDefinitionQuery.listPage(offset, pageQuery.getPageSize());
List<WfDeployVo> deployVoList = new ArrayList<>(definitionList.size());
for (ProcessDefinition processDefinition : definitionList) {
String deploymentId = processDefinition.getDeploymentId();
Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();
WfDeployVo vo = new WfDeployVo();
vo.setDefinitionId(processDefinition.getId());
vo.setProcessKey(processDefinition.getKey());
vo.setProcessName(processDefinition.getName());
vo.setVersion(processDefinition.getVersion());
vo.setCategory(processDefinition.getCategory());
vo.setDeploymentId(processDefinition.getDeploymentId());
vo.setSuspended(processDefinition.isSuspended());
// 流程部署信息
vo.setCategory(deployment.getCategory());
vo.setDeploymentTime(deployment.getDeploymentTime());
deployVoList.add(vo);
}
Page<WfDeployVo> page = new Page<>();
page.setRecords(deployVoList);
page.setTotal(pageTotal);
return TableDataInfo.build(page);
}
@Override
public TableDataInfo<WfDeployVo> queryPublishList(String processKey, PageQuery pageQuery) {
// 创建查询条件
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey(processKey)
.orderByProcessDefinitionVersion()
.desc();
long pageTotal = processDefinitionQuery.count();
if (pageTotal <= 0) {
return TableDataInfo.build();
}
// 根据查询条件,查询所有版本
int offset = pageQuery.getPageSize() * (pageQuery.getPageNum() - 1);
List<ProcessDefinition> processDefinitionList = processDefinitionQuery
.listPage(offset, pageQuery.getPageSize());
List<WfDeployVo> deployVoList = processDefinitionList.stream().map(item -> {
WfDeployVo vo = new WfDeployVo();
vo.setDefinitionId(item.getId());
vo.setProcessKey(item.getKey());
vo.setProcessName(item.getName());
vo.setVersion(item.getVersion());
vo.setCategory(item.getCategory());
vo.setDeploymentId(item.getDeploymentId());
vo.setSuspended(item.isSuspended());
return vo;
}).collect(Collectors.toList());
Page<WfDeployVo> page = new Page<>();
page.setRecords(deployVoList);
page.setTotal(pageTotal);
return TableDataInfo.build(page);
}
/**
* 激活或挂起流程
*
* @param state 状态
* @param definitionId 流程定义ID
*/
@Override
public void updateState(String definitionId, String state) {
if (SuspensionState.ACTIVE.toString().equals(state)) {
// 激活
repositoryService.activateProcessDefinitionById(definitionId, true, null);
} else if (SuspensionState.SUSPENDED.toString().equals(state)) {
// 挂起
repositoryService.suspendProcessDefinitionById(definitionId, true, null);
}
}
@Override
public String queryBpmnXmlById(String definitionId) {
InputStream inputStream = repositoryService.getProcessModel(definitionId);
try {
return IoUtil.readUtf8(inputStream);
} catch (IORuntimeException exception) {
throw new RuntimeException("加载xml文件异常");
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteByIds(List<String> deployIds) {
for (String deployId : deployIds) {
repositoryService.deleteDeployment(deployId, true);
deployFormMapper.delete(new LambdaQueryWrapper<WfDeployForm>().eq(WfDeployForm::getDeployId, deployId));
}
}
}

View File

@@ -1,118 +0,0 @@
package com.klp.workflow.service.impl;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.utils.StringUtils;
import com.klp.workflow.domain.WfForm;
import com.klp.workflow.domain.bo.WfFormBo;
import com.klp.workflow.domain.vo.WfFormVo;
import com.klp.workflow.mapper.WfFormMapper;
import com.klp.workflow.service.IWfFormService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 流程表单Service业务层处理
*
* @author KonBAI
* @createTime 2022/3/7 22:07
*/
@RequiredArgsConstructor
@Service
public class WfFormServiceImpl implements IWfFormService {
private final WfFormMapper baseMapper;
/**
* 查询流程表单
*
* @param formId 流程表单ID
* @return 流程表单
*/
@Override
public WfFormVo queryById(Long formId) {
return baseMapper.selectVoById(formId);
}
/**
* 查询流程表单列表
*
* @param bo 流程表单
* @return 流程表单
*/
@Override
public TableDataInfo<WfFormVo> queryPageList(WfFormBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<WfForm> lqw = buildQueryWrapper(bo);
Page<WfFormVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询流程表单列表
*
* @param bo 流程表单
* @return 流程表单
*/
@Override
public List<WfFormVo> queryList(WfFormBo bo) {
LambdaQueryWrapper<WfForm> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
/**
* 新增流程表单
*
* @param bo 流程表单
* @return 结果
*/
@Override
public int insertForm(WfFormBo bo) {
WfForm wfForm = new WfForm();
wfForm.setFormName(bo.getFormName());
wfForm.setContent(bo.getContent());
wfForm.setRemark(bo.getRemark());
return baseMapper.insert(wfForm);
}
/**
* 修改流程表单
*
* @param bo 流程表单
* @return 结果
*/
@Override
public int updateForm(WfFormBo bo) {
return baseMapper.update(new WfForm(), new LambdaUpdateWrapper<WfForm>()
.set(StrUtil.isNotBlank(bo.getFormName()), WfForm::getFormName, bo.getFormName())
.set(StrUtil.isNotBlank(bo.getContent()), WfForm::getContent, bo.getContent())
.set(StrUtil.isNotBlank(bo.getRemark()), WfForm::getRemark, bo.getRemark())
.eq(WfForm::getFormId, bo.getFormId()));
}
/**
* 批量删除流程表单
*
* @param ids 需要删除的流程表单ID
* @return 结果
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids) {
return baseMapper.deleteBatchIds(ids) > 0;
}
private LambdaQueryWrapper<WfForm> buildQueryWrapper(WfFormBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<WfForm> lqw = Wrappers.lambdaQuery();
lqw.like(StringUtils.isNotBlank(bo.getFormName()), WfForm::getFormName, bo.getFormName());
return lqw;
}
}

View File

@@ -1,212 +0,0 @@
package com.klp.workflow.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.BetweenFormatter;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.klp.common.core.domain.entity.SysDept;
import com.klp.common.core.domain.entity.SysRole;
import com.klp.common.core.service.UserService;
import com.klp.common.exception.ServiceException;
import com.klp.common.utils.JsonUtils;
import com.klp.common.utils.StringUtils;
import com.klp.flowable.common.constant.TaskConstants;
import com.klp.flowable.factory.FlowServiceFactory;
import com.klp.system.service.ISysDeptService;
import com.klp.system.service.ISysRoleService;
import com.klp.workflow.domain.bo.WfTaskBo;
import com.klp.workflow.domain.vo.WfFormVo;
import com.klp.workflow.domain.vo.WfTaskVo;
import com.klp.workflow.service.IWfDeployFormService;
import com.klp.workflow.service.IWfInstanceService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.api.FlowableObjectNotFoundException;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.task.Comment;
import org.flowable.identitylink.api.history.HistoricIdentityLink;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
/**
* 工作流流程实例管理
*
* @author KonBAI
* @createTime 2022/3/10 00:12
*/
@RequiredArgsConstructor
@Service
@Slf4j
public class WfInstanceServiceImpl extends FlowServiceFactory implements IWfInstanceService {
private final IWfDeployFormService deployFormService;
private final UserService userService;
private final ISysRoleService roleService;
private final ISysDeptService deptService;
/**
* 结束流程实例
*
* @param vo
*/
@Override
public void stopProcessInstance(WfTaskBo vo) {
String taskId = vo.getTaskId();
}
/**
* 激活或挂起流程实例
*
* @param state 状态
* @param instanceId 流程实例ID
*/
@Override
public void updateState(Integer state, String instanceId) {
// 激活
if (state == 1) {
runtimeService.activateProcessInstanceById(instanceId);
}
// 挂起
if (state == 2) {
runtimeService.suspendProcessInstanceById(instanceId);
}
}
/**
* 删除流程实例ID
*
* @param instanceId 流程实例ID
* @param deleteReason 删除原因
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void delete(String instanceId, String deleteReason) {
// 查询历史数据
HistoricProcessInstance historicProcessInstance = getHistoricProcessInstanceById(instanceId);
if (historicProcessInstance.getEndTime() != null) {
historyService.deleteHistoricProcessInstance(historicProcessInstance.getId());
return;
}
// 删除流程实例
runtimeService.deleteProcessInstance(instanceId, deleteReason);
// 删除历史流程实例
historyService.deleteHistoricProcessInstance(instanceId);
}
/**
* 根据实例ID查询历史实例数据
*
* @param processInstanceId
* @return
*/
@Override
public HistoricProcessInstance getHistoricProcessInstanceById(String processInstanceId) {
HistoricProcessInstance historicProcessInstance =
historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
if (Objects.isNull(historicProcessInstance)) {
throw new FlowableObjectNotFoundException("流程实例不存在: " + processInstanceId);
}
return historicProcessInstance;
}
/**
* 流程历史流转记录
*
* @param procInsId 流程实例Id
* @return
*/
@Override
public Map<String, Object> queryDetailProcess(String procInsId, String deployId) {
Map<String, Object> map = new HashMap<>();
if (StringUtils.isNotBlank(procInsId)) {
List<HistoricTaskInstance> taskInstanceList = historyService.createHistoricTaskInstanceQuery()
.processInstanceId(procInsId)
.orderByHistoricTaskInstanceStartTime().desc()
.list();
List<Comment> commentList = taskService.getProcessInstanceComments(procInsId);
List<WfTaskVo> taskVoList = new ArrayList<>(taskInstanceList.size());
taskInstanceList.forEach(taskInstance -> {
WfTaskVo taskVo = new WfTaskVo();
taskVo.setProcDefId(taskInstance.getProcessDefinitionId());
taskVo.setTaskId(taskInstance.getId());
taskVo.setTaskDefKey(taskInstance.getTaskDefinitionKey());
taskVo.setTaskName(taskInstance.getName());
taskVo.setCreateTime(taskInstance.getStartTime());
taskVo.setFinishTime(taskInstance.getEndTime());
if (StringUtils.isNotBlank(taskInstance.getAssignee())) {
Long userId = Long.parseLong(taskInstance.getAssignee());
String nickName = userService.selectNickNameById(userId);
taskVo.setAssigneeId(userId);
taskVo.setAssigneeName(nickName);
}
// 展示审批人员
List<HistoricIdentityLink> linksForTask = historyService.getHistoricIdentityLinksForTask(taskInstance.getId());
StringBuilder stringBuilder = new StringBuilder();
for (HistoricIdentityLink identityLink : linksForTask) {
if ("candidate".equals(identityLink.getType())) {
if (StringUtils.isNotBlank(identityLink.getUserId())) {
Long userId = Long.parseLong(identityLink.getUserId());
String nickName = userService.selectNickNameById(userId);
stringBuilder.append(nickName).append(",");
}
if (StringUtils.isNotBlank(identityLink.getGroupId())) {
if (identityLink.getGroupId().startsWith(TaskConstants.ROLE_GROUP_PREFIX)) {
Long roleId = Long.parseLong(StringUtils.stripStart(identityLink.getGroupId(), TaskConstants.ROLE_GROUP_PREFIX));
SysRole role = roleService.selectRoleById(roleId);
stringBuilder.append(role.getRoleName()).append(",");
} else if (identityLink.getGroupId().startsWith(TaskConstants.DEPT_GROUP_PREFIX)) {
Long deptId = Long.parseLong(StringUtils.stripStart(identityLink.getGroupId(), TaskConstants.DEPT_GROUP_PREFIX));
SysDept dept = deptService.selectDeptById(deptId);
stringBuilder.append(dept.getDeptName()).append(",");
}
}
}
}
if (StringUtils.isNotBlank(stringBuilder)) {
taskVo.setCandidate(stringBuilder.substring(0, stringBuilder.length() - 1));
}
if (ObjectUtil.isNotNull(taskInstance.getDurationInMillis())) {
taskVo.setDuration(DateUtil.formatBetween(taskInstance.getDurationInMillis(), BetweenFormatter.Level.SECOND));
}
// 获取意见评论内容
if (CollUtil.isNotEmpty(commentList)) {
List<Comment> comments = new ArrayList<>();
// commentList.stream().filter(comment -> taskInstance.getId().equals(comment.getTaskId())).collect(Collectors.toList());
for (Comment comment : commentList) {
if (comment.getTaskId().equals(taskInstance.getId())) {
comments.add(comment);
// taskVo.setComment(WfCommentDto.builder().type(comment.getType()).comment(comment.getFullMessage()).build());
}
}
taskVo.setCommentList(comments);
}
taskVoList.add(taskVo);
});
map.put("flowList", taskVoList);
// // 查询当前任务是否完成
// List<Task> taskList = taskService.createTaskQuery().processInstanceId(procInsId).list();
// if (CollectionUtils.isNotEmpty(taskList)) {
// map.put("finished", true);
// } else {
// map.put("finished", false);
// }
}
// 第一次申请获取初始化表单
if (StringUtils.isNotBlank(deployId)) {
WfFormVo formVo = deployFormService.selectDeployFormByDeployId(deployId);
if (Objects.isNull(formVo)) {
throw new ServiceException("请先配置流程表单");
}
map.put("formData", JsonUtils.parseObject(formVo.getContent(), Map.class));
}
return map;
}
}

View File

@@ -1,359 +0,0 @@
package com.klp.workflow.service.impl;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.helper.LoginHelper;
import com.klp.common.utils.JsonUtils;
import com.klp.common.utils.StringUtils;
import com.klp.flowable.common.constant.ProcessConstants;
import com.klp.flowable.common.enums.FormType;
import com.klp.flowable.factory.FlowServiceFactory;
import com.klp.flowable.utils.ModelUtils;
import com.klp.workflow.domain.bo.WfModelBo;
import com.klp.workflow.domain.dto.WfMetaInfoDto;
import com.klp.workflow.domain.vo.WfFormVo;
import com.klp.workflow.domain.vo.WfModelVo;
import com.klp.workflow.service.IWfDeployFormService;
import com.klp.workflow.service.IWfFormService;
import com.klp.workflow.service.IWfModelService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.StartEvent;
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.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* @author KonBAI
* @createTime 2022/6/21 9:11
*/
@RequiredArgsConstructor
@Service
@Slf4j
public class WfModelServiceImpl extends FlowServiceFactory implements IWfModelService {
private final IWfFormService formService;
private final IWfDeployFormService deployFormService;
@Override
public TableDataInfo<WfModelVo> list(WfModelBo modelBo, PageQuery pageQuery) {
ModelQuery modelQuery = repositoryService.createModelQuery().latestVersion().orderByCreateTime().desc();
// 构建查询条件
if (StringUtils.isNotBlank(modelBo.getModelKey())) {
modelQuery.modelKey(modelBo.getModelKey());
}
if (StringUtils.isNotBlank(modelBo.getModelName())) {
modelQuery.modelNameLike("%" + modelBo.getModelName() + "%");
}
if (StringUtils.isNotBlank(modelBo.getCategory())) {
modelQuery.modelCategory(modelBo.getCategory());
}
// 执行查询
long pageTotal = modelQuery.count();
if (pageTotal <= 0) {
return TableDataInfo.build();
}
int offset = pageQuery.getPageSize() * (pageQuery.getPageNum() - 1);
List<Model> modelList = modelQuery.listPage(offset, pageQuery.getPageSize());
List<WfModelVo> modelVoList = new ArrayList<>(modelList.size());
modelList.forEach(model -> {
WfModelVo modelVo = new WfModelVo();
modelVo.setModelId(model.getId());
modelVo.setModelName(model.getName());
modelVo.setModelKey(model.getKey());
modelVo.setCategory(model.getCategory());
modelVo.setCreateTime(model.getCreateTime());
modelVo.setVersion(model.getVersion());
WfMetaInfoDto metaInfo = JsonUtils.parseObject(model.getMetaInfo(), WfMetaInfoDto.class);
if (metaInfo != null) {
modelVo.setDescription(metaInfo.getDescription());
modelVo.setFormType(metaInfo.getFormType());
modelVo.setFormId(metaInfo.getFormId());
}
modelVoList.add(modelVo);
});
Page<WfModelVo> page = new Page<>();
page.setRecords(modelVoList);
page.setTotal(pageTotal);
return TableDataInfo.build(page);
}
@Override
public List<WfModelVo> list(WfModelBo modelBo) {
ModelQuery modelQuery = repositoryService.createModelQuery().latestVersion().orderByCreateTime().desc();
// 构建查询条件
if (StringUtils.isNotBlank(modelBo.getModelKey())) {
modelQuery.modelKey(modelBo.getModelKey());
}
if (StringUtils.isNotBlank(modelBo.getModelName())) {
modelQuery.modelNameLike("%" + modelBo.getModelName() + "%");
}
if (StringUtils.isNotBlank(modelBo.getCategory())) {
modelQuery.modelCategory(modelBo.getCategory());
}
List<Model> modelList = modelQuery.list();
List<WfModelVo> modelVoList = new ArrayList<>(modelList.size());
modelList.forEach(model -> {
WfModelVo modelVo = new WfModelVo();
modelVo.setModelId(model.getId());
modelVo.setModelName(model.getName());
modelVo.setModelKey(model.getKey());
modelVo.setCategory(model.getCategory());
modelVo.setCreateTime(model.getCreateTime());
modelVo.setVersion(model.getVersion());
WfMetaInfoDto metaInfo = JsonUtils.parseObject(model.getMetaInfo(), WfMetaInfoDto.class);
if (metaInfo != null) {
modelVo.setDescription(metaInfo.getDescription());
modelVo.setFormType(metaInfo.getFormType());
modelVo.setFormId(metaInfo.getFormId());
}
modelVoList.add(modelVo);
});
return modelVoList;
}
@Override
public TableDataInfo<WfModelVo> historyList(WfModelBo modelBo, PageQuery pageQuery) {
ModelQuery modelQuery = repositoryService.createModelQuery()
.modelKey(modelBo.getModelKey())
.orderByModelVersion()
.desc();
// 执行查询(不显示最新版,-1
long pageTotal = modelQuery.count() - 1;
if (pageTotal <= 0) {
return TableDataInfo.build();
}
// offset+1去掉最新版
int offset = 1 + pageQuery.getPageSize() * (pageQuery.getPageNum() - 1);
List<Model> modelList = modelQuery.listPage(offset, pageQuery.getPageSize());
List<WfModelVo> modelVoList = new ArrayList<>(modelList.size());
modelList.forEach(model -> {
WfModelVo modelVo = new WfModelVo();
modelVo.setModelId(model.getId());
modelVo.setModelName(model.getName());
modelVo.setModelKey(model.getKey());
modelVo.setCategory(model.getCategory());
modelVo.setCreateTime(model.getCreateTime());
modelVo.setVersion(model.getVersion());
WfMetaInfoDto metaInfo = JsonUtils.parseObject(model.getMetaInfo(), WfMetaInfoDto.class);
if (metaInfo != null) {
modelVo.setDescription(metaInfo.getDescription());
modelVo.setFormType(metaInfo.getFormType());
modelVo.setFormId(metaInfo.getFormId());
}
modelVoList.add(modelVo);
});
Page<WfModelVo> page = new Page<>();
page.setRecords(modelVoList);
page.setTotal(pageTotal);
return TableDataInfo.build(page);
}
@Override
public WfModelVo getModel(String modelId) {
// 获取流程模型
Model model = repositoryService.getModel(modelId);
if (ObjectUtil.isNull(model)) {
throw new RuntimeException("流程模型不存在!");
}
// 获取流程图
String bpmnXml = queryBpmnXmlById(modelId);
WfModelVo modelVo = new WfModelVo();
modelVo.setModelId(model.getId());
modelVo.setModelName(model.getName());
modelVo.setModelKey(model.getKey());
modelVo.setCategory(model.getCategory());
modelVo.setCreateTime(model.getCreateTime());
modelVo.setVersion(model.getVersion());
modelVo.setBpmnXml(bpmnXml);
WfMetaInfoDto metaInfo = JsonUtils.parseObject(model.getMetaInfo(), WfMetaInfoDto.class);
if (metaInfo != null) {
modelVo.setDescription(metaInfo.getDescription());
modelVo.setFormType(metaInfo.getFormType());
modelVo.setFormId(metaInfo.getFormId());
if (FormType.PROCESS.getType().equals(metaInfo.getFormType())) {
WfFormVo wfFormVo = formService.queryById(metaInfo.getFormId());
modelVo.setContent(wfFormVo.getContent());
}
}
return modelVo;
}
@Override
public String queryBpmnXmlById(String modelId) {
byte[] bpmnBytes = repositoryService.getModelEditorSource(modelId);
return StrUtil.utf8Str(bpmnBytes);
}
@Override
public void insertModel(WfModelBo modelBo) {
Model model = repositoryService.newModel();
model.setName(modelBo.getModelName());
model.setKey(modelBo.getModelKey());
model.setCategory(modelBo.getCategory());
String metaInfo = buildMetaInfo(new WfMetaInfoDto(), modelBo.getDescription());
model.setMetaInfo(metaInfo);
// 保存流程模型
repositoryService.saveModel(model);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateModel(WfModelBo modelBo) {
// 根据模型Key查询模型信息
Model model = repositoryService.getModel(modelBo.getModelId());
if (ObjectUtil.isNull(model)) {
throw new RuntimeException("流程模型不存在!");
}
model.setCategory(modelBo.getCategory());
WfMetaInfoDto metaInfoDto = JsonUtils.parseObject(model.getMetaInfo(), WfMetaInfoDto.class);
String metaInfo = buildMetaInfo(metaInfoDto, modelBo.getDescription());
model.setMetaInfo(metaInfo);
// 保存流程模型
repositoryService.saveModel(model);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void saveModel(WfModelBo modelBo) {
// 查询模型信息
Model model = repositoryService.getModel(modelBo.getModelId());
if (ObjectUtil.isNull(model)) {
throw new RuntimeException("流程模型不存在!");
}
BpmnModel bpmnModel = ModelUtils.getBpmnModel(modelBo.getBpmnXml());
if (ObjectUtil.isEmpty(bpmnModel)) {
throw new RuntimeException("获取模型设计失败!");
}
String processName = bpmnModel.getMainProcess().getName();
// 获取开始节点
StartEvent startEvent = ModelUtils.getStartEvent(bpmnModel);
if (ObjectUtil.isNull(startEvent)) {
throw new RuntimeException("开始节点不存在,请检查流程设计是否有误!");
}
// 获取开始节点配置的表单Key
if (StrUtil.isBlank(startEvent.getFormKey())) {
throw new RuntimeException("请配置流程表单");
}
Model newModel;
if (Boolean.TRUE.equals(modelBo.getNewVersion())) {
newModel = repositoryService.newModel();
newModel.setName(processName);
newModel.setKey(model.getKey());
newModel.setCategory(model.getCategory());
newModel.setMetaInfo(model.getMetaInfo());
newModel.setVersion(model.getVersion() + 1);
} else {
newModel = model;
// 设置流程名称
newModel.setName(processName);
}
// 保存流程模型
repositoryService.saveModel(newModel);
// 保存 BPMN XML
byte[] bpmnXmlBytes = StringUtils.getBytes(modelBo.getBpmnXml(), StandardCharsets.UTF_8);
repositoryService.addModelEditorSource(newModel.getId(), bpmnXmlBytes);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void latestModel(String modelId) {
// 获取流程模型
Model model = repositoryService.getModel(modelId);
if (ObjectUtil.isNull(model)) {
throw new RuntimeException("流程模型不存在!");
}
Integer latestVersion = repositoryService.createModelQuery()
.modelKey(model.getKey())
.latestVersion()
.singleResult()
.getVersion();
if (model.getVersion().equals(latestVersion)) {
throw new RuntimeException("当前版本已是最新版!");
}
// 获取 BPMN XML
byte[] bpmnBytes = repositoryService.getModelEditorSource(modelId);
Model newModel = repositoryService.newModel();
newModel.setName(model.getName());
newModel.setKey(model.getKey());
newModel.setCategory(model.getCategory());
newModel.setMetaInfo(model.getMetaInfo());
newModel.setVersion(latestVersion + 1);
// 保存流程模型
repositoryService.saveModel(newModel);
// 保存 BPMN XML
repositoryService.addModelEditorSource(newModel.getId(), bpmnBytes);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteByIds(Collection<String> ids) {
ids.forEach(id -> {
Model model = repositoryService.getModel(id);
if (ObjectUtil.isNull(model)) {
throw new RuntimeException("流程模型不存在!");
}
repositoryService.deleteModel(id);
});
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean deployModel(String modelId) {
// 获取流程模型
Model model = repositoryService.getModel(modelId);
if (ObjectUtil.isNull(model)) {
throw new RuntimeException("流程模型不存在!");
}
// 获取流程图
byte[] bpmnBytes = repositoryService.getModelEditorSource(modelId);
if (ArrayUtil.isEmpty(bpmnBytes)) {
throw new RuntimeException("请先设计流程图!");
}
String bpmnXml = StringUtils.toEncodedString(bpmnBytes, StandardCharsets.UTF_8);
BpmnModel bpmnModel = ModelUtils.getBpmnModel(bpmnXml);
String processName = model.getName() + ProcessConstants.SUFFIX;
// 部署流程
Deployment deployment = repositoryService.createDeployment()
.name(model.getName())
.key(model.getKey())
.category(model.getCategory())
.addBytes(processName, bpmnBytes)
.deploy();
ProcessDefinition procDef = repositoryService.createProcessDefinitionQuery()
.deploymentId(deployment.getId())
.singleResult();
// 修改流程定义的分类,便于搜索流程
repositoryService.setProcessDefinitionCategory(procDef.getId(), model.getCategory());
// 保存部署表单
return deployFormService.saveInternalDeployForm(deployment.getId(), bpmnModel);
}
/**
* 构建模型扩展信息
* @return
*/
private String buildMetaInfo(WfMetaInfoDto metaInfo, String description) {
// 只有非空,才进行设置,避免更新时的覆盖
if (StringUtils.isNotEmpty(description)) {
metaInfo.setDescription(description);
}
if (StringUtils.isNotEmpty(metaInfo.getCreateUser())) {
metaInfo.setCreateUser(LoginHelper.getUsername());
}
return JsonUtils.toJsonString(metaInfo);
}
}

View File

@@ -1,625 +0,0 @@
package com.klp.workflow.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.klp.common.core.service.UserService;
import com.klp.common.exception.ServiceException;
import com.klp.common.helper.LoginHelper;
import com.klp.common.utils.StringUtils;
import com.klp.flowable.common.constant.ProcessConstants;
import com.klp.flowable.common.constant.TaskConstants;
import com.klp.flowable.common.enums.FlowComment;
import com.klp.flowable.common.enums.ProcessStatus;
import com.klp.flowable.factory.FlowServiceFactory;
import com.klp.flowable.flow.CustomProcessDiagramGenerator;
import com.klp.flowable.flow.FlowableUtils;
import com.klp.flowable.utils.ModelUtils;
import com.klp.flowable.utils.TaskUtils;
import com.klp.workflow.domain.bo.WfTaskBo;
import com.klp.workflow.service.IWfCopyService;
import com.klp.workflow.service.IWfTaskService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.flowable.bpmn.constants.BpmnXMLConstants;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.common.engine.api.FlowableObjectNotFoundException;
import org.flowable.common.engine.impl.identity.Authentication;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.task.api.DelegationState;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author KonBAI
* @createTime 2022/3/10 00:12
*/
@RequiredArgsConstructor
@Service
@Slf4j
public class WfTaskServiceImpl extends FlowServiceFactory implements IWfTaskService {
private final UserService sysUserService;
private final IWfCopyService copyService;
/**
* 完成任务
*
* @param taskBo 请求实体参数
*/
@Transactional(rollbackFor = Exception.class)
@Override
public void complete(WfTaskBo taskBo) {
Task task = taskService.createTaskQuery().taskId(taskBo.getTaskId()).singleResult();
if (Objects.isNull(task)) {
throw new ServiceException("任务不存在");
}
// 获取 bpmn 模型
BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
identityService.setAuthenticatedUserId(TaskUtils.getUserId());
if (DelegationState.PENDING.equals(task.getDelegationState())) {
taskService.addComment(taskBo.getTaskId(), taskBo.getProcInsId(), FlowComment.DELEGATE.getType(), taskBo.getComment());
taskService.resolveTask(taskBo.getTaskId());
} else {
taskService.addComment(taskBo.getTaskId(), taskBo.getProcInsId(), FlowComment.NORMAL.getType(), taskBo.getComment());
taskService.setAssignee(taskBo.getTaskId(), TaskUtils.getUserId());
if (ObjectUtil.isNotEmpty(taskBo.getVariables())) {
// 获取模型信息
String localScopeValue = ModelUtils.getUserTaskAttributeValue(bpmnModel, task.getTaskDefinitionKey(), ProcessConstants.PROCESS_FORM_LOCAL_SCOPE);
boolean localScope = Convert.toBool(localScopeValue, false);
taskService.complete(taskBo.getTaskId(), taskBo.getVariables(), localScope);
} else {
taskService.complete(taskBo.getTaskId());
}
}
// 设置任务节点名称
taskBo.setTaskName(task.getName());
// 处理下一级审批人
if (StringUtils.isNotBlank(taskBo.getNextUserIds())) {
this.assignNextUsers(bpmnModel, taskBo.getProcInsId(), taskBo.getNextUserIds());
}
// 处理抄送用户
if (!copyService.makeCopy(taskBo)) {
throw new RuntimeException("抄送任务失败");
}
}
/**
* 拒绝任务
*
* @param taskBo
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void taskReject(WfTaskBo taskBo) {
// 当前任务 task
Task task = taskService.createTaskQuery().taskId(taskBo.getTaskId()).singleResult();
if (ObjectUtil.isNull(task)) {
throw new RuntimeException("获取任务信息异常!");
}
if (task.isSuspended()) {
throw new RuntimeException("任务处于挂起状态");
}
// 获取流程实例
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
.processInstanceId(taskBo.getProcInsId())
.singleResult();
if (processInstance == null) {
throw new RuntimeException("流程实例不存在,请确认!");
}
// 获取流程定义信息
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.processDefinitionId(task.getProcessDefinitionId())
.singleResult();
identityService.setAuthenticatedUserId(TaskUtils.getUserId());
// 添加审批意见
taskService.addComment(taskBo.getTaskId(), taskBo.getProcInsId(), FlowComment.REJECT.getType(), taskBo.getComment());
// 设置流程状态为已终结
runtimeService.setVariable(processInstance.getId(), ProcessConstants.PROCESS_STATUS_KEY, ProcessStatus.TERMINATED.getStatus());
// 获取所有节点信息
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
EndEvent endEvent = ModelUtils.getEndEvent(bpmnModel);
// 终止流程
List<Execution> executions = runtimeService.createExecutionQuery().parentId(task.getProcessInstanceId()).list();
List<String> executionIds = executions.stream().map(Execution::getId).collect(Collectors.toList());
runtimeService.createChangeActivityStateBuilder()
.processInstanceId(task.getProcessInstanceId())
.moveExecutionsToSingleActivityId(executionIds, endEvent.getId())
.changeState();
// 处理抄送用户
if (!copyService.makeCopy(taskBo)) {
throw new RuntimeException("抄送任务失败");
}
}
/**
* 退回任务
*
* @param bo 请求实体参数
*/
@Transactional(rollbackFor = Exception.class)
@Override
public void taskReturn(WfTaskBo bo) {
// 当前任务 task
Task task = taskService.createTaskQuery().taskId(bo.getTaskId()).singleResult();
if (ObjectUtil.isNull(task)) {
throw new RuntimeException("获取任务信息异常!");
}
if (task.isSuspended()) {
throw new RuntimeException("任务处于挂起状态");
}
// 获取流程定义信息
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
// 获取流程模型信息
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
// 获取当前任务节点元素
FlowElement source = ModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey());
// 获取跳转的节点元素
FlowElement target = ModelUtils.getFlowElementById(bpmnModel, bo.getTargetKey());
// 从当前节点向前扫描,判断当前节点与目标节点是否属于串行,若目标节点是在并行网关上或非同一路线上,不可跳转
boolean isSequential = ModelUtils.isSequentialReachable(source, target, new HashSet<>());
if (!isSequential) {
throw new RuntimeException("当前节点相对于目标节点,不属于串行关系,无法回退");
}
// 获取所有正常进行的任务节点 Key这些任务不能直接使用需要找出其中需要撤回的任务
List<Task> runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list();
List<String> runTaskKeyList = new ArrayList<>();
runTaskList.forEach(item -> runTaskKeyList.add(item.getTaskDefinitionKey()));
// 需退回任务列表
List<String> currentIds = new ArrayList<>();
// 通过父级网关的出口连线,结合 runTaskList 比对,获取需要撤回的任务
List<UserTask> currentUserTaskList = FlowableUtils.iteratorFindChildUserTasks(target, runTaskKeyList, null, null);
currentUserTaskList.forEach(item -> currentIds.add(item.getId()));
// 循环获取那些需要被撤回的节点的ID用来设置驳回原因
List<String> currentTaskIds = new ArrayList<>();
currentIds.forEach(currentId -> runTaskList.forEach(runTask -> {
if (currentId.equals(runTask.getTaskDefinitionKey())) {
currentTaskIds.add(runTask.getId());
}
}));
identityService.setAuthenticatedUserId(TaskUtils.getUserId());
// 设置回退意见
for (String currentTaskId : currentTaskIds) {
taskService.addComment(currentTaskId, task.getProcessInstanceId(), FlowComment.REBACK.getType(), bo.getComment());
}
try {
// 1 对 1 或 多 对 1 情况currentIds 当前要跳转的节点列表(1或多)targetKey 跳转到的节点(1)
runtimeService.createChangeActivityStateBuilder()
.processInstanceId(task.getProcessInstanceId())
.moveActivityIdsToSingleActivityId(currentIds, bo.getTargetKey()).changeState();
} catch (FlowableObjectNotFoundException e) {
throw new RuntimeException("未找到流程实例,流程可能已发生变化");
} catch (FlowableException e) {
throw new RuntimeException("无法取消或开始活动");
}
// 设置任务节点名称
bo.setTaskName(task.getName());
// 处理抄送用户
if (!copyService.makeCopy(bo)) {
throw new RuntimeException("抄送任务失败");
}
}
/**
* 获取所有可回退的节点
*
* @param bo
* @return
*/
@Override
public List<FlowElement> findReturnTaskList(WfTaskBo bo) {
// 当前任务 task
Task task = taskService.createTaskQuery().taskId(bo.getTaskId()).singleResult();
// 获取流程定义信息
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
// 获取流程模型信息
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
// 查询历史节点实例
List<HistoricActivityInstance> activityInstanceList = historyService.createHistoricActivityInstanceQuery()
.processInstanceId(task.getProcessInstanceId())
.activityType(BpmnXMLConstants.ELEMENT_TASK_USER)
.finished()
.orderByHistoricActivityInstanceEndTime().asc()
.list();
List<String> activityIdList = activityInstanceList.stream()
.map(HistoricActivityInstance::getActivityId)
.filter(activityId -> !StringUtils.equals(activityId, task.getTaskDefinitionKey()))
.distinct()
.collect(Collectors.toList());
// 获取当前任务节点元素
FlowElement source = ModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey());
List<FlowElement> elementList = new ArrayList<>();
for (String activityId : activityIdList) {
FlowElement target = ModelUtils.getFlowElementById(bpmnModel, activityId);
boolean isSequential = ModelUtils.isSequentialReachable(source, target, new HashSet<>());
if (isSequential) {
elementList.add(target);
}
}
return elementList;
}
/**
* 删除任务
*
* @param bo 请求实体参数
*/
@Override
public void deleteTask(WfTaskBo bo) {
// todo 待确认删除任务是物理删除任务 还是逻辑删除,让这个任务直接通过?
identityService.setAuthenticatedUserId(TaskUtils.getUserId());
taskService.deleteTask(bo.getTaskId(), bo.getComment());
}
/**
* 认领/签收任务
*
* @param taskBo 请求实体参数
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void claim(WfTaskBo taskBo) {
Task task = taskService.createTaskQuery().taskId(taskBo.getTaskId()).singleResult();
if (Objects.isNull(task)) {
throw new ServiceException("任务不存在");
}
taskService.claim(taskBo.getTaskId(), TaskUtils.getUserId());
}
/**
* 取消认领/签收任务
*
* @param bo 请求实体参数
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void unClaim(WfTaskBo bo) {
taskService.unclaim(bo.getTaskId());
}
/**
* 委派任务
*
* @param bo 请求实体参数
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void delegateTask(WfTaskBo bo) {
// 当前任务 task
Task task = taskService.createTaskQuery().taskId(bo.getTaskId()).singleResult();
if (ObjectUtil.isEmpty(task)) {
throw new ServiceException("获取任务失败!");
}
StringBuilder commentBuilder = new StringBuilder(LoginHelper.getNickName())
.append("->");
String nickName = sysUserService.selectNickNameById(Long.parseLong(bo.getUserId()));
if (StringUtils.isNotBlank(nickName)) {
commentBuilder.append(nickName);
} else {
commentBuilder.append(bo.getUserId());
}
if (StringUtils.isNotBlank(bo.getComment())) {
commentBuilder.append(": ").append(bo.getComment());
}
identityService.setAuthenticatedUserId(TaskUtils.getUserId());
// 添加审批意见
taskService.addComment(bo.getTaskId(), task.getProcessInstanceId(), FlowComment.DELEGATE.getType(), commentBuilder.toString());
// 设置办理人为当前登录人
taskService.setOwner(bo.getTaskId(), TaskUtils.getUserId());
// 执行委派
taskService.delegateTask(bo.getTaskId(), bo.getUserId());
// 设置任务节点名称
bo.setTaskName(task.getName());
// 处理抄送用户
if (!copyService.makeCopy(bo)) {
throw new RuntimeException("抄送任务失败");
}
}
/**
* 转办任务
*
* @param bo 请求实体参数
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void transferTask(WfTaskBo bo) {
// 当前任务 task
Task task = taskService.createTaskQuery().taskId(bo.getTaskId()).singleResult();
if (ObjectUtil.isEmpty(task)) {
throw new ServiceException("获取任务失败!");
}
StringBuilder commentBuilder = new StringBuilder(LoginHelper.getNickName())
.append("->");
String nickName = sysUserService.selectNickNameById(Long.parseLong(bo.getUserId()));
if (StringUtils.isNotBlank(nickName)) {
commentBuilder.append(nickName);
} else {
commentBuilder.append(bo.getUserId());
}
if (StringUtils.isNotBlank(bo.getComment())) {
commentBuilder.append(": ").append(bo.getComment());
}
identityService.setAuthenticatedUserId(TaskUtils.getUserId());
// 添加审批意见
taskService.addComment(bo.getTaskId(), task.getProcessInstanceId(), FlowComment.TRANSFER.getType(), commentBuilder.toString());
// 设置拥有者为当前登录人
taskService.setOwner(bo.getTaskId(), TaskUtils.getUserId());
// 转办任务
taskService.setAssignee(bo.getTaskId(), bo.getUserId());
// 设置任务节点名称
bo.setTaskName(task.getName());
// 处理抄送用户
if (!copyService.makeCopy(bo)) {
throw new RuntimeException("抄送任务失败");
}
}
/**
* 取消申请
*
* @param bo
* @return
*/
@Override
public void stopProcess(WfTaskBo bo) {
List<Task> taskList = taskService.createTaskQuery().processInstanceId(bo.getProcInsId()).list();
if (CollectionUtils.isEmpty(taskList)) {
throw new RuntimeException("流程未启动或已执行完成,取消申请失败");
}
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
.processInstanceId(bo.getProcInsId()).singleResult();
BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
if (Objects.nonNull(bpmnModel)) {
Process process = bpmnModel.getMainProcess();
List<EndEvent> endNodes = process.findFlowElementsOfType(EndEvent.class, false);
if (CollectionUtils.isNotEmpty(endNodes)) {
Authentication.setAuthenticatedUserId(TaskUtils.getUserId());
runtimeService.setVariable(processInstance.getId(), ProcessConstants.PROCESS_STATUS_KEY, ProcessStatus.CANCELED.getStatus());
for (Task task : taskList) {
taskService.addComment(task.getId(), processInstance.getProcessInstanceId(), FlowComment.STOP.getType(), "取消流程");
}
// 获取当前流程最后一个节点
String endId = endNodes.get(0).getId();
List<Execution> executions = runtimeService.createExecutionQuery()
.parentId(processInstance.getProcessInstanceId()).list();
List<String> executionIds = new ArrayList<>();
executions.forEach(execution -> executionIds.add(execution.getId()));
// 变更流程为已结束状态
runtimeService.createChangeActivityStateBuilder()
.moveExecutionsToSingleActivityId(executionIds, endId).changeState();
}
}
}
/**
* 撤回流程
*
* @param taskBo 请求实体参数
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void revokeProcess(WfTaskBo taskBo) {
String procInsId = taskBo.getProcInsId();
String taskId = taskBo.getTaskId();
// 校验流程是否结束
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
.processInstanceId(procInsId)
.active()
.singleResult();
if(ObjectUtil.isNull(processInstance)) {
throw new RuntimeException("流程已结束或已挂起,无法执行撤回操作");
}
// 获取待撤回任务实例
HistoricTaskInstance currTaskIns = historyService.createHistoricTaskInstanceQuery()
.taskId(taskId)
.taskAssignee(TaskUtils.getUserId())
.singleResult();
if (ObjectUtil.isNull(currTaskIns)) {
throw new RuntimeException("当前任务不存在,无法执行撤回操作");
}
// 获取 bpmn 模型
BpmnModel bpmnModel = repositoryService.getBpmnModel(currTaskIns.getProcessDefinitionId());
UserTask currUserTask = ModelUtils.getUserTaskByKey(bpmnModel, currTaskIns.getTaskDefinitionKey());
// 查找下一级用户任务列表
List<UserTask> nextUserTaskList = ModelUtils.findNextUserTasks(currUserTask);
List<String> nextUserTaskKeys = nextUserTaskList.stream().map(UserTask::getId).collect(Collectors.toList());
// 获取当前节点之后已完成的流程历史节点
List<HistoricTaskInstance> finishedTaskInsList = historyService.createHistoricTaskInstanceQuery()
.processInstanceId(procInsId)
.taskCreatedAfter(currTaskIns.getEndTime())
.finished()
.list();
for (HistoricTaskInstance finishedTaskInstance : finishedTaskInsList) {
// 检查已完成流程历史节点是否存在下一级中
if (CollUtil.contains(nextUserTaskKeys, finishedTaskInstance.getTaskDefinitionKey())) {
throw new RuntimeException("下一流程已处理,无法执行撤回操作");
}
}
// 获取所有激活的任务节点,找到需要撤回的任务
List<Task> activateTaskList = taskService.createTaskQuery().processInstanceId(procInsId).list();
List<String> revokeExecutionIds = new ArrayList<>();
identityService.setAuthenticatedUserId(TaskUtils.getUserId());
for (Task task : activateTaskList) {
// 检查激活的任务节点是否存在下一级中,如果存在,则加入到需要撤回的节点
if (CollUtil.contains(nextUserTaskKeys, task.getTaskDefinitionKey())) {
// 添加撤回审批信息
taskService.setAssignee(task.getId(), TaskUtils.getUserId());
taskService.addComment(task.getId(), task.getProcessInstanceId(), FlowComment.REVOKE.getType(), LoginHelper.getNickName() + "撤回流程审批");
revokeExecutionIds.add(task.getExecutionId());
}
}
try {
runtimeService.createChangeActivityStateBuilder()
.processInstanceId(procInsId)
.moveExecutionsToSingleActivityId(revokeExecutionIds, currTaskIns.getTaskDefinitionKey()).changeState();
} catch (FlowableObjectNotFoundException e) {
throw new RuntimeException("未找到流程实例,流程可能已发生变化");
} catch (FlowableException e) {
throw new RuntimeException("执行撤回操作失败");
}
}
/**
* 获取流程过程图
*
* @param processId
* @return
*/
@Override
public InputStream diagram(String processId) {
String processDefinitionId;
// 获取当前的流程实例
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
// 如果流程已经结束,则得到结束节点
if (Objects.isNull(processInstance)) {
HistoricProcessInstance pi = historyService.createHistoricProcessInstanceQuery().processInstanceId(processId).singleResult();
processDefinitionId = pi.getProcessDefinitionId();
} else {// 如果流程没有结束,则取当前活动节点
// 根据流程实例ID获得当前处于活动状态的ActivityId合集
ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
processDefinitionId = pi.getProcessDefinitionId();
}
// 获得活动的节点
List<HistoricActivityInstance> highLightedFlowList = historyService.createHistoricActivityInstanceQuery()
.processInstanceId(processId).orderByHistoricActivityInstanceStartTime().asc().list();
List<String> highLightedFlows = new ArrayList<>();
List<String> highLightedNodes = new ArrayList<>();
//高亮线
for (HistoricActivityInstance tempActivity : highLightedFlowList) {
if ("sequenceFlow".equals(tempActivity.getActivityType())) {
//高亮线
highLightedFlows.add(tempActivity.getActivityId());
} else {
//高亮节点
highLightedNodes.add(tempActivity.getActivityId());
}
}
//获取流程图
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
ProcessEngineConfiguration configuration = processEngine.getProcessEngineConfiguration();
//获取自定义图片生成器
ProcessDiagramGenerator diagramGenerator = new CustomProcessDiagramGenerator();
return diagramGenerator.generateDiagram(bpmnModel, "png", highLightedNodes, highLightedFlows, configuration.getActivityFontName(),
configuration.getLabelFontName(), configuration.getAnnotationFontName(), configuration.getClassLoader(), 1.0, true);
}
/**
* 获取流程变量
*
* @param taskId 任务ID
* @return 流程变量
*/
@Override
public Map<String, Object> getProcessVariables(String taskId) {
HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery()
.includeProcessVariables()
.finished()
.taskId(taskId)
.singleResult();
if (Objects.nonNull(historicTaskInstance)) {
return historicTaskInstance.getProcessVariables();
}
return taskService.getVariables(taskId);
}
/**
* 启动第一个任务
* @param processInstance 流程实例
* @param variables 流程参数
*/
@Override
public void startFirstTask(ProcessInstance processInstance, Map<String, Object> variables) {
// 若第一个用户任务为发起人,则自动完成任务
List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).list();
if (CollUtil.isNotEmpty(tasks)) {
String userIdStr = (String) variables.get(TaskConstants.PROCESS_INITIATOR);
identityService.setAuthenticatedUserId(TaskUtils.getUserId());
for (Task task : tasks) {
if (StrUtil.equals(task.getAssignee(), userIdStr)) {
taskService.addComment(task.getId(), processInstance.getProcessInstanceId(), FlowComment.NORMAL.getType(), LoginHelper.getNickName() + "发起流程申请");
taskService.complete(task.getId(), variables);
}
}
}
}
/**
* 指派下一任务审批人
* @param bpmnModel bpmn模型
* @param processInsId 流程实例id
* @param userIds 用户ids
*/
private void assignNextUsers(BpmnModel bpmnModel, String processInsId, String userIds) {
// 获取所有节点信息
List<Task> list = taskService.createTaskQuery()
.processInstanceId(processInsId)
.list();
if (list.size() == 0) {
return;
}
Queue<String> assignIds = CollUtil.newLinkedList(userIds.split(","));
if (list.size() == assignIds.size()) {
for (Task task : list) {
taskService.setAssignee(task.getId(), assignIds.poll());
}
return;
}
// 优先处理非多实例任务
Iterator<Task> iterator = list.iterator();
while (iterator.hasNext()) {
Task task = iterator.next();
if (!ModelUtils.isMultiInstance(bpmnModel, task.getTaskDefinitionKey())) {
if (!assignIds.isEmpty()) {
taskService.setAssignee(task.getId(), assignIds.poll());
}
iterator.remove();
}
}
// 若存在多实例任务,则进行动态加减签
if (CollUtil.isNotEmpty(list)) {
if (assignIds.isEmpty()) {
// 动态减签
for (Task task : list) {
runtimeService.deleteMultiInstanceExecution(task.getExecutionId(), true);
}
} else {
// 动态加签
for (String assignId : assignIds) {
Map<String, Object> assignVariables = Collections.singletonMap(BpmnXMLConstants.ATTRIBUTE_TASK_USER_ASSIGNEE, assignId);
runtimeService.addMultiInstanceExecution(list.get(0).getTaskDefinitionKey(), list.get(0).getProcessInstanceId(), assignVariables);
}
}
}
}
}

View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.klp.workflow.mapper.WfCategoryMapper">
<resultMap type="com.klp.workflow.domain.WfCategory" id="FlowCategoryResult">
<result property="categoryId" column="category_id"/>
<result property="categoryName" column="category_name"/>
<result property="code" column="code"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<result property="remark" column="remark"/>
<result property="delFlag" column="del_flag"/>
</resultMap>
</mapper>

View File

@@ -1,23 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.klp.workflow.mapper.WfCopyMapper">
<resultMap type="com.klp.workflow.domain.WfCopy" id="WfCopyResult">
<result property="copyId" column="copy_id"/>
<result property="title" column="title"/>
<result property="processId" column="process_id"/>
<result property="processName" column="process_name"/>
<result property="categoryId" column="category_id"/>
<result property="taskId" column="taskId"/>
<result property="userId" column="user_id"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<result property="delFlag" column="del_flag"/>
</resultMap>
</mapper>

View File

@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.klp.workflow.mapper.WfDeployFormMapper">
<resultMap type="com.klp.workflow.domain.WfDeployForm" id="WfDeployFormResult">
<result property="deployId" column="deploy_id"/>
<result property="formKey" column="form_key"/>
<result property="nodeKey" column="node_key"/>
<result property="nodeName" column="node_name"/>
<result property="content" column="content"/>
</resultMap>
</mapper>

View File

@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.klp.workflow.mapper.WfFormMapper">
<resultMap type="com.klp.workflow.domain.WfForm" id="WfFormResult">
<result property="formId" column="form_id"/>
<result property="formName" column="form_name"/>
<result property="content" column="content"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
<result property="createBy" column="create_by"/>
<result property="updateBy" column="update_by"/>
<result property="remark" column="remark"/>
</resultMap>
<select id="selectFormVoList" resultType="com.klp.workflow.domain.vo.WfFormVo">
SELECT
t1.form_id AS formId,
t1.form_name AS formName,
t1.content AS content
FROM wf_form t1
LEFT JOIN wf_deploy_form t2 ON t1.form_id = t2.form_id
${ew.getCustomSqlSegment}
</select>
</mapper>