Commit db3c713122a71e992460cf8345ceee116d7e188c

Authored by YunaiV
1 parent aac6cc7b

1. 修改流程的表单定义,支持业务表单。

2. 流程提交时,记录表单值
Showing 15 changed files with 190 additions and 107 deletions
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/BpmProcessDefinitionController.java
@@ -32,6 +32,8 @@ public class BpmProcessDefinitionController { @@ -32,6 +32,8 @@ public class BpmProcessDefinitionController {
32 @Resource 32 @Resource
33 private BpmProcessDefinitionService bpmDefinitionService; 33 private BpmProcessDefinitionService bpmDefinitionService;
34 34
  35 + // TODO 芋艿:权限相关
  36 +
35 @GetMapping ("/page") 37 @GetMapping ("/page")
36 @ApiOperation(value = "获得流程定义分页") 38 @ApiOperation(value = "获得流程定义分页")
37 @PreAuthorize("@ss.hasPermission('bpm:model:query')") // 暂时使用 model 的权限标识 39 @PreAuthorize("@ss.hasPermission('bpm:model:query')") // 暂时使用 model 的权限标识
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/form/BpmFormRespVO.java
@@ -18,6 +18,7 @@ public class BpmFormRespVO extends BpmFormBaseVO { @@ -18,6 +18,7 @@ public class BpmFormRespVO extends BpmFormBaseVO {
18 18
19 @ApiModelProperty(value = "表单编号", required = true, example = "1024") 19 @ApiModelProperty(value = "表单编号", required = true, example = "1024")
20 private Long id; 20 private Long id;
  21 +
21 @ApiModelProperty(value = "表单的配置", required = true, notes = "JSON 字符串") 22 @ApiModelProperty(value = "表单的配置", required = true, notes = "JSON 字符串")
22 @NotNull(message = "表单的配置不能为空") 23 @NotNull(message = "表单的配置不能为空")
23 private String conf; 24 private String conf;
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/process/BpmProcessDefinitionRespVO.java
@@ -5,6 +5,8 @@ import io.swagger.annotations.ApiModelProperty; @@ -5,6 +5,8 @@ import io.swagger.annotations.ApiModelProperty;
5 import lombok.Data; 5 import lombok.Data;
6 6
7 import javax.validation.constraints.NotEmpty; 7 import javax.validation.constraints.NotEmpty;
  8 +import javax.validation.constraints.NotNull;
  9 +import java.util.List;
8 10
9 @ApiModel("流程定义 Response VO") 11 @ApiModel("流程定义 Response VO")
10 @Data 12 @Data
@@ -27,8 +29,22 @@ public class BpmProcessDefinitionRespVO { @@ -27,8 +29,22 @@ public class BpmProcessDefinitionRespVO {
27 @NotEmpty(message = "流程分类不能为空") 29 @NotEmpty(message = "流程分类不能为空")
28 private String category; 30 private String category;
29 31
30 - @ApiModelProperty(value = "表单编号", example = "1024") 32 + @ApiModelProperty(value = "表单类型", notes = "参见 bpm_model_form_type 数据字典", example = "1")
  33 + private Integer formType;
  34 + @ApiModelProperty(value = "表单编号", example = "1024", notes = "在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时,必须非空")
31 private Long formId; 35 private Long formId;
  36 + @ApiModelProperty(value = "表单的配置", required = true,
  37 + notes = "JSON 字符串。在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时,必须非空")
  38 + private String formConf;
  39 + @ApiModelProperty(value = "表单项的数组", required = true,
  40 + notes = "JSON 字符串的数组。在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时,必须非空")
  41 + private List<String> formFields;
  42 + @ApiModelProperty(value = "自定义表单的提交路径,使用 Vue 的路由地址", example = "/bpm/oa/leave/create",
  43 + notes = "在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时,必须非空")
  44 + private String formCustomCreatePath;
  45 + @ApiModelProperty(value = "自定义表单的查看路径,使用 Vue 的路由地址", example = "/bpm/oa/leave/view",
  46 + notes = "在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时,必须非空")
  47 + private String formCustomViewPath;
32 48
33 @ApiModelProperty(value = "中断状态", required = true, example = "1", notes = "参见 SuspensionState 枚举") 49 @ApiModelProperty(value = "中断状态", required = true, example = "1", notes = "参见 SuspensionState 枚举")
34 private Integer suspensionState; 50 private Integer suspensionState;
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmModelConvert.java
@@ -83,7 +83,7 @@ public interface BpmModelConvert { @@ -83,7 +83,7 @@ public interface BpmModelConvert {
83 83
84 void copyTo(BpmModelMetaInfoRespDTO from, @MappingTarget BpmModelBaseVO to); 84 void copyTo(BpmModelMetaInfoRespDTO from, @MappingTarget BpmModelBaseVO to);
85 85
86 - default BpmDefinitionCreateReqDTO convert2(Model model) { 86 + default BpmDefinitionCreateReqDTO convert2(Model model, BpmFormDO form) {
87 BpmDefinitionCreateReqDTO createReqDTO = new BpmDefinitionCreateReqDTO(); 87 BpmDefinitionCreateReqDTO createReqDTO = new BpmDefinitionCreateReqDTO();
88 createReqDTO.setModelId(model.getId()); 88 createReqDTO.setModelId(model.getId());
89 createReqDTO.setName(model.getName()); 89 createReqDTO.setName(model.getName());
@@ -92,6 +92,11 @@ public interface BpmModelConvert { @@ -92,6 +92,11 @@ public interface BpmModelConvert {
92 BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class); 92 BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class);
93 // metaInfo 93 // metaInfo
94 copyTo(metaInfo, createReqDTO); 94 copyTo(metaInfo, createReqDTO);
  95 + // form
  96 + if (form != null) {
  97 + createReqDTO.setFormConf(form.getConf());
  98 + createReqDTO.setFormFields(form.getFields());
  99 + }
95 return createReqDTO; 100 return createReqDTO;
96 } 101 }
97 102
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmProcessDefinitionConvert.java
@@ -11,6 +11,7 @@ import org.activiti.engine.repository.Deployment; @@ -11,6 +11,7 @@ import org.activiti.engine.repository.Deployment;
11 import org.activiti.engine.repository.ProcessDefinition; 11 import org.activiti.engine.repository.ProcessDefinition;
12 import org.mapstruct.Mapper; 12 import org.mapstruct.Mapper;
13 import org.mapstruct.Mapping; 13 import org.mapstruct.Mapping;
  14 +import org.mapstruct.MappingTarget;
14 import org.mapstruct.Named; 15 import org.mapstruct.Named;
15 import org.mapstruct.factory.Mappers; 16 import org.mapstruct.factory.Mappers;
16 17
@@ -38,19 +39,17 @@ public interface BpmProcessDefinitionConvert { @@ -38,19 +39,17 @@ public interface BpmProcessDefinitionConvert {
38 } 39 }
39 40
40 default BpmProcessDefinitionPageItemRespVO convert(ProcessDefinition bean, Deployment deployment, 41 default BpmProcessDefinitionPageItemRespVO convert(ProcessDefinition bean, Deployment deployment,
41 - BpmProcessDefinitionExtDO processDefinitionDO, BpmFormDO form) { 42 + BpmProcessDefinitionExtDO processDefinitionExtDO, BpmFormDO form) {
42 BpmProcessDefinitionPageItemRespVO respVO = convert(bean); 43 BpmProcessDefinitionPageItemRespVO respVO = convert(bean);
43 respVO.setSuspensionState(bean.isSuspended() ? SuspensionState.SUSPENDED.getStateCode() : SuspensionState.ACTIVE.getStateCode()); 44 respVO.setSuspensionState(bean.isSuspended() ? SuspensionState.SUSPENDED.getStateCode() : SuspensionState.ACTIVE.getStateCode());
44 if (deployment != null) { 45 if (deployment != null) {
45 respVO.setDeploymentTime(deployment.getDeploymentTime()); 46 respVO.setDeploymentTime(deployment.getDeploymentTime());
46 } 47 }
47 if (form != null) { 48 if (form != null) {
48 - respVO.setFormId(form.getId());  
49 respVO.setFormName(form.getName()); 49 respVO.setFormName(form.getName());
50 } 50 }
51 - if (processDefinitionDO != null) {  
52 - respVO.setDescription(processDefinitionDO.getDescription());  
53 - } 51 + // 复制通用属性
  52 + copyTo(processDefinitionExtDO, respVO);
54 return respVO; 53 return respVO;
55 } 54 }
56 55
@@ -63,9 +62,8 @@ public interface BpmProcessDefinitionConvert { @@ -63,9 +62,8 @@ public interface BpmProcessDefinitionConvert {
63 return CollectionUtils.convertList(list, processDefinition -> { 62 return CollectionUtils.convertList(list, processDefinition -> {
64 BpmProcessDefinitionRespVO respVO = convert3(processDefinition); 63 BpmProcessDefinitionRespVO respVO = convert3(processDefinition);
65 BpmProcessDefinitionExtDO processDefinitionExtDO = processDefinitionDOMap.get(processDefinition.getId()); 64 BpmProcessDefinitionExtDO processDefinitionExtDO = processDefinitionDOMap.get(processDefinition.getId());
66 - if (processDefinitionExtDO != null) {  
67 - respVO.setFormId(processDefinitionExtDO.getFormId());  
68 - } 65 + // 复制通用属性
  66 + copyTo(processDefinitionExtDO, respVO);
69 return respVO; 67 return respVO;
70 }); 68 });
71 } 69 }
@@ -79,4 +77,7 @@ public interface BpmProcessDefinitionConvert { @@ -79,4 +77,7 @@ public interface BpmProcessDefinitionConvert {
79 SuspensionState.ACTIVE.getStateCode(); 77 SuspensionState.ACTIVE.getStateCode();
80 } 78 }
81 79
  80 + @Mapping(source = "from.id", target = "to.id", ignore = true)
  81 + void copyTo(BpmProcessDefinitionExtDO from, @MappingTarget BpmProcessDefinitionRespVO to);
  82 +
82 } 83 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/definition/BpmFormDataDO.java deleted
1 -package cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition;  
2 -  
3 -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;  
4 -import com.baomidou.mybatisplus.annotation.TableField;  
5 -import com.baomidou.mybatisplus.annotation.TableName;  
6 -import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;  
7 -import lombok.*;  
8 -  
9 -import java.util.List;  
10 -import java.util.Map;  
11 -  
12 -/**  
13 - * 工作流的表单结果  
14 - * 用户每次填写工作流的申请表单时,会保存一条记录到该表】  
15 - *  
16 - * @author 芋道源码  
17 - */  
18 -@TableName(value = "bpm_form_data", autoResultMap = true)  
19 -@Data  
20 -@EqualsAndHashCode(callSuper = true)  
21 -@ToString(callSuper = true)  
22 -@Builder  
23 -@NoArgsConstructor  
24 -@AllArgsConstructor  
25 -public class BpmFormDataDO extends BaseDO {  
26 -  
27 - /**  
28 - * 编号  
29 - */  
30 - private Long id;  
31 - /**  
32 - * 表单编号  
33 - *  
34 - * 关联 {@link BpmFormDO#getId()}  
35 - */  
36 - private Long formId;  
37 - /**  
38 - * 状态  
39 - */  
40 - private Integer status;  
41 - /**  
42 - * 表单配置  
43 - *  
44 - * 冗余 {@link BpmFormDO#getFields()}  
45 - * 主要考虑,表单是可以修改的  
46 - */  
47 - @TableField(typeHandler = JacksonTypeHandler.class)  
48 - private List<String> fields;  
49 - /**  
50 - * 表单值  
51 - */  
52 - @TableField(typeHandler = JacksonTypeHandler.class)  
53 - private Map<String, Object> values;  
54 -  
55 -}  
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/definition/BpmProcessDefinitionExtDO.java
1 package cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition; 1 package cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition;
2 2
  3 +import cn.iocoder.yudao.adminserver.modules.bpm.enums.definition.BpmModelFormTypeEnum;
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  5 +import com.baomidou.mybatisplus.annotation.TableField;
4 import com.baomidou.mybatisplus.annotation.TableId; 6 import com.baomidou.mybatisplus.annotation.TableId;
5 import com.baomidou.mybatisplus.annotation.TableName; 7 import com.baomidou.mybatisplus.annotation.TableName;
  8 +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
6 import lombok.*; 9 import lombok.*;
7 import org.activiti.engine.repository.Model; 10 import org.activiti.engine.repository.Model;
8 import org.activiti.engine.repository.ProcessDefinition; 11 import org.activiti.engine.repository.ProcessDefinition;
9 12
  13 +import java.util.List;
  14 +
10 /** 15 /**
11 * Bpm 流程定义的拓展表 16 * Bpm 流程定义的拓展表
12 * 主要解决 Activiti {@link ProcessDefinition} 不支持拓展字段,所以新建拓展表 17 * 主要解决 Activiti {@link ProcessDefinition} 不支持拓展字段,所以新建拓展表
@@ -43,11 +48,45 @@ public class BpmProcessDefinitionExtDO extends BaseDO { @@ -43,11 +48,45 @@ public class BpmProcessDefinitionExtDO extends BaseDO {
43 * 描述 48 * 描述
44 */ 49 */
45 private String description; 50 private String description;
  51 +
  52 + /**
  53 + * 表单类型
  54 + *
  55 + * 关联 {@link BpmModelFormTypeEnum}
  56 + */
  57 + private Integer formType;
46 /** 58 /**
47 - * 表单编号 59 + * 动态表单编号
  60 + * 在表单类型为 {@link BpmModelFormTypeEnum#NORMAL} 时
48 * 61 *
49 * 关联 {@link BpmFormDO#getId()} 62 * 关联 {@link BpmFormDO#getId()}
50 */ 63 */
51 private Long formId; 64 private Long formId;
  65 + /**
  66 + * 表单的配置
  67 + * 在表单类型为 {@link BpmModelFormTypeEnum#NORMAL} 时
  68 + *
  69 + * 冗余 {@link BpmFormDO#getConf()}
  70 + */
  71 + private String formConf;
  72 + /**
  73 + * 表单项的数组
  74 + * 在表单类型为 {@link BpmModelFormTypeEnum#NORMAL} 时
  75 + *
  76 + * 冗余 {@link BpmFormDO#getFields()} ()}
  77 + */
  78 + @TableField(typeHandler = JacksonTypeHandler.class)
  79 + private List<String> formFields;
  80 + /**
  81 + * 自定义表单的提交路径,使用 Vue 的路由地址
  82 + * 在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时
  83 + */
  84 + private String formCustomCreatePath;
  85 + /**
  86 + * 自定义表单的查看路径,使用 Vue 的路由地址
  87 + * 在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时
  88 + */
  89 + private String formCustomViewPath;
  90 +
52 91
53 } 92 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/task/BpmProcessInstanceExtDO.java
@@ -3,7 +3,9 @@ package cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task; @@ -3,7 +3,9 @@ package cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task;
3 import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceResultEnum; 3 import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceResultEnum;
4 import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceStatusEnum; 4 import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceStatusEnum;
5 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 5 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  6 +import com.baomidou.mybatisplus.annotation.TableField;
6 import com.baomidou.mybatisplus.annotation.TableName; 7 import com.baomidou.mybatisplus.annotation.TableName;
  8 +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
7 import lombok.Data; 9 import lombok.Data;
8 import lombok.EqualsAndHashCode; 10 import lombok.EqualsAndHashCode;
9 import lombok.ToString; 11 import lombok.ToString;
@@ -12,6 +14,7 @@ import org.activiti.engine.repository.ProcessDefinition; @@ -12,6 +14,7 @@ import org.activiti.engine.repository.ProcessDefinition;
12 import org.activiti.engine.runtime.ProcessInstance; 14 import org.activiti.engine.runtime.ProcessInstance;
13 15
14 import java.util.Date; 16 import java.util.Date;
  17 +import java.util.Map;
15 18
16 /** 19 /**
17 * Bpm 流程实例的拓展表 20 * Bpm 流程实例的拓展表
@@ -78,4 +81,10 @@ public class BpmProcessInstanceExtDO extends BaseDO { @@ -78,4 +81,10 @@ public class BpmProcessInstanceExtDO extends BaseDO {
78 */ 81 */
79 private Date endTime; 82 private Date endTime;
80 83
  84 + /**
  85 + * 表单值
  86 + */
  87 + @TableField(typeHandler = JacksonTypeHandler.class)
  88 + private Map<String, Object> formVariables;
  89 +
81 } 90 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/dto/BpmDefinitionCreateReqDTO.java
1 package cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto; 1 package cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.StrUtil;
  5 +import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmFormDO;
3 import cn.iocoder.yudao.adminserver.modules.bpm.enums.definition.BpmModelFormTypeEnum; 6 import cn.iocoder.yudao.adminserver.modules.bpm.enums.definition.BpmModelFormTypeEnum;
  7 +import com.baomidou.mybatisplus.annotation.TableField;
  8 +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
4 import lombok.Data; 9 import lombok.Data;
5 10
  11 +import javax.validation.constraints.AssertTrue;
6 import javax.validation.constraints.NotEmpty; 12 import javax.validation.constraints.NotEmpty;
7 import javax.validation.constraints.NotNull; 13 import javax.validation.constraints.NotNull;
  14 +import java.util.List;
  15 +import java.util.Objects;
8 16
9 /** 17 /**
10 * 流程定义创建 Request DTO 18 * 流程定义创建 Request DTO
@@ -58,6 +66,16 @@ public class BpmDefinitionCreateReqDTO { @@ -58,6 +66,16 @@ public class BpmDefinitionCreateReqDTO {
58 */ 66 */
59 private Long formId; 67 private Long formId;
60 /** 68 /**
  69 + * 表单的配置
  70 + * 在表单类型为 {@link BpmModelFormTypeEnum#NORMAL} 时
  71 + */
  72 + private String formConf;
  73 + /**
  74 + * 表单项的数组
  75 + * 在表单类型为 {@link BpmModelFormTypeEnum#NORMAL} 时
  76 + */
  77 + private List<String> formFields;
  78 + /**
61 * 自定义表单的提交路径,使用 Vue 的路由地址 79 * 自定义表单的提交路径,使用 Vue 的路由地址
62 * 在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时 80 * 在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时
63 */ 81 */
@@ -68,6 +86,22 @@ public class BpmDefinitionCreateReqDTO { @@ -68,6 +86,22 @@ public class BpmDefinitionCreateReqDTO {
68 */ 86 */
69 private String formCustomViewPath; 87 private String formCustomViewPath;
70 88
  89 + @AssertTrue(message = "流程表单信息不全")
  90 + public boolean isNormalFormTypeValid() {
  91 + // 如果非业务表单,则直接通过
  92 + if (!Objects.equals(formType, BpmModelFormTypeEnum.NORMAL.getType())) {
  93 + return true;
  94 + }
  95 + return formId != null && StrUtil.isNotEmpty(formConf) && CollUtil.isNotEmpty(formFields);
  96 + }
71 97
  98 + @AssertTrue(message = "业务表单信息不全")
  99 + public boolean isNormalCustomTypeValid() {
  100 + // 如果非业务表单,则直接通过
  101 + if (!Objects.equals(formType, BpmModelFormTypeEnum.CUSTOM.getType())) {
  102 + return true;
  103 + }
  104 + return StrUtil.isNotEmpty(formCustomCreatePath) && StrUtil.isNotEmpty(formCustomViewPath);
  105 + }
72 106
73 } 107 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmModelServiceImpl.java
@@ -7,6 +7,7 @@ import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.model.* @@ -7,6 +7,7 @@ import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.model.*
7 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.rule.BpmTaskAssignRuleRespVO; 7 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.rule.BpmTaskAssignRuleRespVO;
8 import cn.iocoder.yudao.adminserver.modules.bpm.convert.definition.BpmModelConvert; 8 import cn.iocoder.yudao.adminserver.modules.bpm.convert.definition.BpmModelConvert;
9 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmFormDO; 9 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmFormDO;
  10 +import cn.iocoder.yudao.adminserver.modules.bpm.enums.definition.BpmModelFormTypeEnum;
10 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService; 11 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService;
11 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmTaskAssignRuleService; 12 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmTaskAssignRuleService;
12 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmDefinitionCreateReqDTO; 13 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmDefinitionCreateReqDTO;
@@ -36,10 +37,7 @@ import org.springframework.util.ObjectUtils; @@ -36,10 +37,7 @@ import org.springframework.util.ObjectUtils;
36 import org.springframework.validation.annotation.Validated; 37 import org.springframework.validation.annotation.Validated;
37 38
38 import javax.annotation.Resource; 39 import javax.annotation.Resource;
39 -import java.util.HashSet;  
40 -import java.util.List;  
41 -import java.util.Map;  
42 -import java.util.Set; 40 +import java.util.*;
43 import java.util.function.Consumer; 41 import java.util.function.Consumer;
44 42
45 import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.*; 43 import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.*;
@@ -177,15 +175,13 @@ public class BpmModelServiceImpl implements BpmModelService { @@ -177,15 +175,13 @@ public class BpmModelServiceImpl implements BpmModelService {
177 } 175 }
178 // TODO 芋艿:校验流程图的有效性;例如说,是否有开始的元素,是否有结束的元素; 176 // TODO 芋艿:校验流程图的有效性;例如说,是否有开始的元素,是否有结束的元素;
179 // 校验表单已配 177 // 校验表单已配
180 - BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class);  
181 - if (metaInfo == null || metaInfo.getFormType() == null) {  
182 - throw exception(MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG);  
183 - } 178 + // 校验表单存在
  179 + BpmFormDO form = checkFormConfig(model);
184 // 校验任务分配规则已配置 180 // 校验任务分配规则已配置
185 checkTaskAssignRuleAllConfig(id); 181 checkTaskAssignRuleAllConfig(id);
186 182
187 // 创建流程定义 183 // 创建流程定义
188 - BpmDefinitionCreateReqDTO definitionCreateReqDTO = BpmModelConvert.INSTANCE.convert2(model) 184 + BpmDefinitionCreateReqDTO definitionCreateReqDTO = BpmModelConvert.INSTANCE.convert2(model, form)
189 .setBpmnXml(StrUtil.utf8Str(bpmnBytes)); 185 .setBpmnXml(StrUtil.utf8Str(bpmnBytes));
190 String definitionId = processDefinitionService.createProcessDefinition(definitionCreateReqDTO); 186 String definitionId = processDefinitionService.createProcessDefinition(definitionCreateReqDTO);
191 187
@@ -221,6 +217,28 @@ public class BpmModelServiceImpl implements BpmModelService { @@ -221,6 +217,28 @@ public class BpmModelServiceImpl implements BpmModelService {
221 }); 217 });
222 } 218 }
223 219
  220 + /**
  221 + * 校验流程表单已配置
  222 + *
  223 + * @param model 流程模型
  224 + * @return 流程表单
  225 + */
  226 + private BpmFormDO checkFormConfig(Model model) {
  227 + BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class);
  228 + if (metaInfo == null || metaInfo.getFormType() == null) {
  229 + throw exception(MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG);
  230 + }
  231 + // 校验表单存在
  232 + if (Objects.equals(metaInfo.getFormType(), BpmModelFormTypeEnum.NORMAL.getType())) {
  233 + BpmFormDO form = formService.getForm(metaInfo.getFormId());
  234 + if (form == null) {
  235 + throw exception(FORM_NOT_EXISTS);
  236 + }
  237 + return form;
  238 + }
  239 + return null;
  240 + }
  241 +
224 @Override 242 @Override
225 @Transactional(rollbackFor = Exception.class) 243 @Transactional(rollbackFor = Exception.class)
226 public void deleteModel(String id) { 244 public void deleteModel(String id) {
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmProcessDefinitionServiceImpl.java
@@ -34,7 +34,8 @@ import java.util.*; @@ -34,7 +34,8 @@ import java.util.*;
34 import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.PROCESS_DEFINITION_KEY_NOT_MATCH; 34 import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.PROCESS_DEFINITION_KEY_NOT_MATCH;
35 import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.PROCESS_DEFINITION_NAME_NOT_MATCH; 35 import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.PROCESS_DEFINITION_NAME_NOT_MATCH;
36 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 36 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
37 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; 37 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
  38 +import static java.util.Collections.emptyList;
38 39
39 /** 40 /**
40 * 流程定义实现 41 * 流程定义实现
@@ -70,22 +71,22 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ @@ -70,22 +71,22 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
70 List<ProcessDefinition> processDefinitions = definitionQuery.orderByProcessDefinitionVersion().desc() 71 List<ProcessDefinition> processDefinitions = definitionQuery.orderByProcessDefinitionVersion().desc()
71 .listPage(PageUtils.getStart(pageVO), pageVO.getPageSize()); 72 .listPage(PageUtils.getStart(pageVO), pageVO.getPageSize());
72 if (CollUtil.isEmpty(processDefinitions)) { 73 if (CollUtil.isEmpty(processDefinitions)) {
73 - return new PageResult<>(Collections.emptyList(), definitionQuery.count()); 74 + return new PageResult<>(emptyList(), definitionQuery.count());
74 } 75 }
75 76
76 // 获得 Deployment Map 77 // 获得 Deployment Map
77 Set<String> deploymentIds = new HashSet<>(); 78 Set<String> deploymentIds = new HashSet<>();
78 - processDefinitions.forEach(definition -> CollectionUtils.addIfNotNull(deploymentIds, definition.getDeploymentId())); 79 + processDefinitions.forEach(definition -> addIfNotNull(deploymentIds, definition.getDeploymentId()));
79 Map<String, Deployment> deploymentMap = getDeploymentMap(deploymentIds); 80 Map<String, Deployment> deploymentMap = getDeploymentMap(deploymentIds);
80 81
81 // 获得 BpmProcessDefinitionDO Map 82 // 获得 BpmProcessDefinitionDO Map
82 List<BpmProcessDefinitionExtDO> processDefinitionDOs = processDefinitionMapper.selectListByProcessDefinitionIds( 83 List<BpmProcessDefinitionExtDO> processDefinitionDOs = processDefinitionMapper.selectListByProcessDefinitionIds(
83 convertList(processDefinitions, ProcessDefinition::getId)); 84 convertList(processDefinitions, ProcessDefinition::getId));
84 - Map<String, BpmProcessDefinitionExtDO> processDefinitionDOMap = CollectionUtils.convertMap(processDefinitionDOs, 85 + Map<String, BpmProcessDefinitionExtDO> processDefinitionDOMap = convertMap(processDefinitionDOs,
85 BpmProcessDefinitionExtDO::getProcessDefinitionId); 86 BpmProcessDefinitionExtDO::getProcessDefinitionId);
86 87
87 // 获得 Form Map 88 // 获得 Form Map
88 - Set<Long> formIds = CollectionUtils.convertSet(processDefinitionDOs, BpmProcessDefinitionExtDO::getFormId); 89 + Set<Long> formIds = convertSet(processDefinitionDOs, BpmProcessDefinitionExtDO::getFormId);
89 Map<Long, BpmFormDO> formMap = bpmFormService.getFormMap(formIds); 90 Map<Long, BpmFormDO> formMap = bpmFormService.getFormMap(formIds);
90 91
91 // 拼接结果 92 // 拼接结果
@@ -109,7 +110,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ @@ -109,7 +110,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
109 // 获得 BpmProcessDefinitionDO Map 110 // 获得 BpmProcessDefinitionDO Map
110 List<BpmProcessDefinitionExtDO> processDefinitionDOs = processDefinitionMapper.selectListByProcessDefinitionIds( 111 List<BpmProcessDefinitionExtDO> processDefinitionDOs = processDefinitionMapper.selectListByProcessDefinitionIds(
111 convertList(processDefinitions, ProcessDefinition::getId)); 112 convertList(processDefinitions, ProcessDefinition::getId));
112 - Map<String, BpmProcessDefinitionExtDO> processDefinitionDOMap = CollectionUtils.convertMap(processDefinitionDOs, 113 + Map<String, BpmProcessDefinitionExtDO> processDefinitionDOMap = convertMap(processDefinitionDOs,
113 BpmProcessDefinitionExtDO::getProcessDefinitionId); 114 BpmProcessDefinitionExtDO::getProcessDefinitionId);
114 // 执行查询,并返回 115 // 执行查询,并返回
115 return BpmProcessDefinitionConvert.INSTANCE.convertList3(processDefinitions, processDefinitionDOMap); 116 return BpmProcessDefinitionConvert.INSTANCE.convertList3(processDefinitions, processDefinitionDOMap);
@@ -152,11 +153,11 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ @@ -152,11 +153,11 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
152 @Override 153 @Override
153 public List<Deployment> getDeployments(Set<String> ids) { 154 public List<Deployment> getDeployments(Set<String> ids) {
154 if (CollUtil.isEmpty(ids)) { 155 if (CollUtil.isEmpty(ids)) {
155 - return Collections.emptyList(); 156 + return emptyList();
156 } 157 }
157 List<Deployment> list = new ArrayList<>(ids.size()); 158 List<Deployment> list = new ArrayList<>(ids.size());
158 for (String id : ids) { 159 for (String id : ids) {
159 - CollectionUtils.addIfNotNull(list, getDeployment(id)); 160 + addIfNotNull(list, getDeployment(id));
160 } 161 }
161 return list; 162 return list;
162 } 163 }
@@ -169,7 +170,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ @@ -169,7 +170,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
169 @Override 170 @Override
170 public List<ProcessDefinition> getProcessDefinitionListByDeploymentIds(Set<String> deploymentIds) { 171 public List<ProcessDefinition> getProcessDefinitionListByDeploymentIds(Set<String> deploymentIds) {
171 if (CollUtil.isEmpty(deploymentIds)) { 172 if (CollUtil.isEmpty(deploymentIds)) {
172 - return Collections.emptyList(); 173 + return emptyList();
173 } 174 }
174 return repositoryService.createProcessDefinitionQuery().deploymentIds(deploymentIds).list(); 175 return repositoryService.createProcessDefinitionQuery().deploymentIds(deploymentIds).list();
175 } 176 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmProcessInstanceServiceImpl.java
@@ -86,9 +86,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -86,9 +86,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
86 // 设置流程名字 86 // 设置流程名字
87 runtimeService.setProcessInstanceName(instance.getId(), definition.getName()); 87 runtimeService.setProcessInstanceName(instance.getId(), definition.getName());
88 88
89 - // TODO 芋艿:临时使用, 保证分配  
90 -// List<Task> tasks = taskService.getTasksByProcessInstanceId(instance.getId());  
91 -// tasks.forEach(task -> taskService.updateTaskAssign(task.getId(), userId)); 89 + // 补全流程实例的拓展表
  90 + processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId())
  91 + .setFormVariables(createReqVO.getVariables()));
92 92
93 // 添加初始的评论 TODO 芋艿:在思考下 93 // 添加初始的评论 TODO 芋艿:在思考下
94 // Task task = taskService.createTaskQuery().processInstanceId(instance.getId()).singleResult(); 94 // Task task = taskService.createTaskQuery().processInstanceId(instance.getId()).singleResult();
@@ -98,9 +98,6 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -98,9 +98,6 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
98 // String type = "normal"; 98 // String type = "normal";
99 // taskService.addComment(task.getId(), instance.getProcessInstanceId(), type, 99 // taskService.addComment(task.getId(), instance.getProcessInstanceId(), type,
100 // String.format("%s 发起流程申请", user.getNickname())); 100 // String.format("%s 发起流程申请", user.getNickname()));
101 -// // TODO 芋艿:应该不用下面两个步骤  
102 -//// taskService.setAssignee(task.getId(), String.valueOf(userId));  
103 -//// taskService.complete(task.getId(), variables);  
104 // } 101 // }
105 return instance.getId(); 102 return instance.getId();
106 } 103 }
yudao-admin-server/src/main/resources/processes/leave-update.bpmn_bak renamed to yudao-admin-server/src/main/resources/processes/oa-leave.bpmn_bak
yudao-admin-ui/src/views/bpm/definition/index.vue
@@ -15,11 +15,14 @@ @@ -15,11 +15,14 @@
15 <span>{{ getDictDataLabel(DICT_TYPE.BPM_MODEL_CATEGORY, scope.row.category) }}</span> 15 <span>{{ getDictDataLabel(DICT_TYPE.BPM_MODEL_CATEGORY, scope.row.category) }}</span>
16 </template> 16 </template>
17 </el-table-column> 17 </el-table-column>
18 - <el-table-column label="表单信息" align="center" prop="formId"> 18 + <el-table-column label="表单信息" align="center" prop="formType" width="200">
19 <template slot-scope="scope"> 19 <template slot-scope="scope">
20 <el-button v-if="scope.row.formId" type="text" @click="handleFormDetail(scope.row)"> 20 <el-button v-if="scope.row.formId" type="text" @click="handleFormDetail(scope.row)">
21 <span>{{ scope.row.formName }}</span> 21 <span>{{ scope.row.formName }}</span>
22 </el-button> 22 </el-button>
  23 + <el-button v-else-if="scope.row.formCustomCreatePath" type="text" @click="handleFormDetail(scope.row)">
  24 + <span>{{ scope.row.formCustomCreatePath }}</span>
  25 + </el-button>
23 <label v-else>暂无表单</label> 26 <label v-else>暂无表单</label>
24 </template> 27 </template>
25 </el-table-column> 28 </el-table-column>
@@ -134,16 +137,19 @@ export default { @@ -134,16 +137,19 @@ export default {
134 }, 137 },
135 /** 流程表单的详情按钮操作 */ 138 /** 流程表单的详情按钮操作 */
136 handleFormDetail(row) { 139 handleFormDetail(row) {
137 - getForm(row.formId).then(response => { 140 + // 流程表单
  141 + if (row.formId) {
138 // 设置值 142 // 设置值
139 - const data = response.data  
140 this.detailForm = { 143 this.detailForm = {
141 - ...JSON.parse(data.conf),  
142 - fields: decodeFields(data.fields) 144 + ...JSON.parse(row.formConf),
  145 + fields: decodeFields(row.formFields)
143 } 146 }
144 // 弹窗打开 147 // 弹窗打开
145 this.detailOpen = true 148 this.detailOpen = true
146 - }) 149 + // 业务表单
  150 + } else if (row.formCustomCreatePath) {
  151 + this.$router.push({ path: row.formCustomCreatePath});
  152 + }
147 }, 153 },
148 /** 流程图的详情按钮操作 */ 154 /** 流程图的详情按钮操作 */
149 handleBpmnDetail(row) { 155 handleBpmnDetail(row) {
yudao-admin-ui/src/views/bpm/model/index.vue
@@ -50,11 +50,14 @@ @@ -50,11 +50,14 @@
50 <span>{{ getDictDataLabel(DICT_TYPE.BPM_MODEL_CATEGORY, scope.row.category) }}</span> 50 <span>{{ getDictDataLabel(DICT_TYPE.BPM_MODEL_CATEGORY, scope.row.category) }}</span>
51 </template> 51 </template>
52 </el-table-column> 52 </el-table-column>
53 - <el-table-column label="表单信息" align="center" prop="formId"> 53 + <el-table-column label="表单信息" align="center" prop="formType" width="200">
54 <template slot-scope="scope"> 54 <template slot-scope="scope">
55 <el-button v-if="scope.row.formId" type="text" @click="handleFormDetail(scope.row)"> 55 <el-button v-if="scope.row.formId" type="text" @click="handleFormDetail(scope.row)">
56 <span>{{ scope.row.formName }}</span> 56 <span>{{ scope.row.formName }}</span>
57 </el-button> 57 </el-button>
  58 + <el-button v-else-if="scope.row.formCustomCreatePath" type="text" @click="handleFormDetail(scope.row)">
  59 + <span>{{ scope.row.formCustomCreatePath }}</span>
  60 + </el-button>
58 <label v-else>暂无表单</label> 61 <label v-else>暂无表单</label>
59 </template> 62 </template>
60 </el-table-column> 63 </el-table-column>
@@ -450,16 +453,22 @@ export default { @@ -450,16 +453,22 @@ export default {
450 }, 453 },
451 /** 流程表单的详情按钮操作 */ 454 /** 流程表单的详情按钮操作 */
452 handleFormDetail(row) { 455 handleFormDetail(row) {
453 - getForm(row.formId).then(response => {  
454 - // 设置值  
455 - const data = response.data  
456 - this.detailForm = {  
457 - ...JSON.parse(data.conf),  
458 - fields: decodeFields(data.fields)  
459 - }  
460 - // 弹窗打开  
461 - this.detailOpen = true  
462 - }) 456 + // 流程表单
  457 + if (row.formId) {
  458 + getForm(row.formId).then(response => {
  459 + // 设置值
  460 + const data = response.data
  461 + this.detailForm = {
  462 + ...JSON.parse(data.conf),
  463 + fields: decodeFields(data.fields)
  464 + }
  465 + // 弹窗打开
  466 + this.detailOpen = true
  467 + })
  468 + // 业务表单
  469 + } else if (row.formCustomCreatePath) {
  470 + this.$router.push({ path: row.formCustomCreatePath});
  471 + }
463 }, 472 },
464 /** 流程图的详情按钮操作 */ 473 /** 流程图的详情按钮操作 */
465 handleBpmnDetail(row) { 474 handleBpmnDetail(row) {