From 00e445c80de89ff971fb27f7b2f8fab8362348bf Mon Sep 17 00:00:00 2001 From: chenbowen Date: Sun, 28 Sep 2025 00:08:55 +0800 Subject: [PATCH] =?UTF-8?q?1.=20=E5=8D=87=E7=BA=A7=203.0.40=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=20bpm=20api=20=E6=96=B0=E5=A2=9E=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E5=8C=BA=E5=88=86=E5=86=85=E5=A4=96=E9=83=A8?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E4=BB=A5=E5=8F=8A=20e=20=E5=8A=9E=E7=BB=9F?= =?UTF-8?q?=E4=B8=80=E8=AE=A4=E8=AF=81=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bpm/api/task/BpmProcessInstanceApi.java | 42 +++++-- .../api/task/dto/BpmApprovalDetailReqDTO.java | 40 +++++++ .../task/dto/BpmApprovalDetailRespDTO.java | 110 ++++++++++++++++++ .../task/dto/BpmProcessDefinitionRespDTO.java | 55 +++++++++ ...pmProcessInstanceBpmnModelViewRespDTO.java | 41 +++++++ .../dto/BpmProcessInstanceCancelReqDTO.java | 19 +++ .../dto/BpmProcessInstancePageReqDTO.java | 13 +++ .../task/dto/BpmProcessInstanceRespDTO.java | 56 ++++++++- .../api/task/dto/BpmSimpleModelNodeDTO.java | 31 +++++ .../api/task/BpmProcessInstanceApiImpl.java | 110 ++++++++++++++++-- .../task/BpmProcessInstanceDTOConvert.java | 67 +++++++++++ 11 files changed, 564 insertions(+), 20 deletions(-) create mode 100644 zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmApprovalDetailReqDTO.java create mode 100644 zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmApprovalDetailRespDTO.java create mode 100644 zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmProcessDefinitionRespDTO.java create mode 100644 zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmProcessInstanceBpmnModelViewRespDTO.java create mode 100644 zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmProcessInstanceCancelReqDTO.java create mode 100644 zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmSimpleModelNodeDTO.java create mode 100644 zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/convert/task/BpmProcessInstanceDTOConvert.java diff --git a/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/BpmProcessInstanceApi.java b/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/BpmProcessInstanceApi.java index baf8f52..89839e8 100644 --- a/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/BpmProcessInstanceApi.java +++ b/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/BpmProcessInstanceApi.java @@ -1,19 +1,16 @@ package com.zt.plat.module.bpm.api.task; import com.zt.plat.framework.common.pojo.CommonResult; -import com.zt.plat.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; -import com.zt.plat.module.bpm.api.task.dto.BpmTaskApproveReqDTO; -import com.zt.plat.module.bpm.api.task.dto.BpmTaskRejectReqDTO; +import com.zt.plat.module.bpm.api.task.dto.*; import com.zt.plat.module.bpm.enums.ApiConstants; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.*; + +import java.util.List; @FeignClient(name = ApiConstants.NAME) // TODO 芋艿:fallbackFactory = @Tag(name = "RPC 服务 - 流程实例") @@ -27,6 +24,37 @@ public interface BpmProcessInstanceApi { CommonResult createProcessInstance(@RequestParam("userId") Long userId, @Valid @RequestBody BpmProcessInstanceCreateReqDTO reqDTO); + @GetMapping(PREFIX + "/get") + @Operation(summary = "获得指定流程实例", description = "在【流程详细】界面中,进行调用") + @Parameter(name = "id", description = "流程实例的编号", required = true) + CommonResult getProcessInstance(@RequestParam("id") String id); + + @DeleteMapping(PREFIX + "/cancel-by-start-user") + @Operation(summary = "用户取消流程实例", description = "取消发起的流程") + CommonResult cancelProcessInstanceByStartUser( + @RequestParam("userId") Long userId, + @Valid @RequestBody BpmProcessInstanceCancelReqDTO cancelReqDTO); + + @DeleteMapping(PREFIX + "/cancel-by-admin") + @Operation(summary = "管理员取消流程实例", description = "管理员撤回流程") + CommonResult cancelProcessInstanceByAdmin( + @RequestParam("userId") Long userId, + @Valid @RequestBody BpmProcessInstanceCancelReqDTO cancelReqDTO); + + @PostMapping(PREFIX + "/get-approval-detail") + @Operation(summary = "获得审批详情") + CommonResult getApprovalDetail(@RequestParam("userId") Long userId, + @Valid BpmApprovalDetailReqDTO reqDTO); + + @PostMapping(PREFIX + "/get-next-approval-nodes") + @Operation(summary = "获取下一个执行的流程节点") + CommonResult> getNextApprovalNodes(@RequestParam("userId") Long userId, + @Valid BpmApprovalDetailReqDTO reqDTO); + + @PostMapping(PREFIX + "/get-bpmn-model-view") + @Operation(summary = "获取流程实例的 BPMN 模型视图", description = "在【流程详细】界面中,进行调用") + @Parameter(name = "id", description = "流程实例的编号", required = true) + CommonResult getProcessInstanceBpmnModelView(@RequestParam(value = "id") String id); @PutMapping(PREFIX + "/approveTask") @Operation(summary = "通过任务") diff --git a/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmApprovalDetailReqDTO.java b/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmApprovalDetailReqDTO.java new file mode 100644 index 0000000..4794386 --- /dev/null +++ b/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmApprovalDetailReqDTO.java @@ -0,0 +1,40 @@ +package com.zt.plat.module.bpm.api.task.dto; + +import cn.hutool.core.util.StrUtil; +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.AssertTrue; +import lombok.Data; + +import java.util.Map; + +@Schema(description = "RPC 服务 - 审批详情 Request DTO") +@Data +public class BpmApprovalDetailReqDTO { + + @Schema(description = "流程定义的编号", example = "1024") + private String processDefinitionId; // 使用场景:发起流程时,传流程定义 ID + + @Schema(description = "流程变量") + private Map processVariables; // 使用场景:同 processDefinitionId,用于流程预测 + + @Schema(description = "流程变量") + private String processVariablesStr; // 解决 GET 无法传递对象的问题,最终转换成 processVariables 变量 + + @Schema(description = "流程实例的编号", example = "1024") + private String processInstanceId; // 使用场景:流程已发起时候传流程实例 ID + + // TODO @芋艿:如果未来 BPMN 增加流程图,它没有发起人节点,会有问题。 + @Schema(description = "流程活动编号", example = "StartUserNode") + private String activityId; // 用于获取表单权限。1)发起流程时,传"发起人节点" activityId 可获取发起人的表单权限;2)从抄送列表界面进来时,传抄送的 activityId 可获取抄送人的表单权限; + + @Schema(description = "流程任务编号", example = "95f2f08b-621b-11ef-bf39-00ff4722db8b") + private String taskId; // 用于获取表单权限。1)从待审批/已审批界面进来时,传递 taskId 任务编号,可获取任务节点的变得权限 + + @AssertTrue(message = "流程定义的编号和流程实例的编号不能同时为空") + @JsonIgnore + public boolean isValidProcessParam() { + return StrUtil.isNotEmpty(processDefinitionId) || StrUtil.isNotEmpty(processInstanceId); + } + +} \ No newline at end of file diff --git a/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmApprovalDetailRespDTO.java b/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmApprovalDetailRespDTO.java new file mode 100644 index 0000000..3183561 --- /dev/null +++ b/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmApprovalDetailRespDTO.java @@ -0,0 +1,110 @@ +package com.zt.plat.module.bpm.api.task.dto; + +import com.zt.plat.module.bpm.api.task.dto.BpmTaskRespDTO; +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; + + +@Schema(description = "RPC 服务 - 审批详情 Response DTO") +@Data +public class BpmApprovalDetailRespDTO { + + @Schema(description = "流程实例的状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer status; // 参见 BpmProcessInstanceStatusEnum 枚举 + + @Schema(description = "活动节点列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List activityNodes; + + @Schema(description = "表单字段权限") + private Map formFieldsPermission; + + @Schema(description = "待办任务") + private BpmTaskRespDTO todoTask; + + /** + * 所属流程定义信息 + */ + private BpmProcessDefinitionRespDTO processDefinition; + + /** + * 所属流程实例信息 + */ + private BpmProcessInstanceRespDTO processInstance; + + @Schema(description = "活动节点信息") + @Data + public static class ActivityNode { + + @Schema(description = "节点编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "StartUserNode") + private String id; + + @Schema(description = "节点名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "发起人") + private String name; + + @Schema(description = "节点类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer nodeType; // 参见 BpmSimpleModelNodeType 枚举 + + @Schema(description = "节点状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + private Integer status; // 参见 BpmTaskStatusEnum 枚举 + + @Schema(description = "节点的开始时间") + private LocalDateTime startTime; + @Schema(description = "节点的结束时间") + private LocalDateTime endTime; + + @Schema(description = "审批节点的任务信息") + private List tasks; + + @Schema(description = "候选人策略", example = "35") + private Integer candidateStrategy; // 参见 BpmTaskCandidateStrategyEnum 枚举。主要用于发起时,审批节点、抄送节点自选 + + @Schema(description = "候选人用户 ID 列表", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1818") + @JsonIgnore // 不返回,只是方便后续读取,赋值给 candidateUsers + private List candidateUserIds; + + @Schema(description = "候选人用户列表") + private List candidateUsers; // 只包含未生成 ApprovalTaskInfo 的用户列表 + + @Schema(description = "流程编号", example = "8761d8e0-0922-11f0-bd37-00ff1db677bf") + private String processInstanceId; // 当且仅当,该节点是子流程节点时,才会有值(CallActivity 的 processInstanceId 字段) + + } + + @Schema(description = "活动节点的任务信息") + @Data + public static class ActivityNodeTask { + + @Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private String id; + + @Schema(description = "任务所属人编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1818") + @JsonIgnore // 不返回,只是方便后续读取,赋值给 ownerUser + private Long owner; + + @Schema(description = "任务所属人", example = "1024") + private UserSimpleDTO ownerUser; + + @Schema(description = "任务分配人编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "2048") + @JsonIgnore // 不返回,只是方便后续读取,赋值给 assigneeUser + private Long assignee; + + @Schema(description = "任务分配人", example = "2048") + private UserSimpleDTO assigneeUser; + + @Schema(description = "任务状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer status; // 参见 BpmTaskStatusEnum 枚举 + + @Schema(description = "审批意见", example = "同意") + private String reason; + + @Schema(description = "签名", example = "https://www.iocoder.cn/sign.png") + private String signPicUrl; + + } + +} \ No newline at end of file diff --git a/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmProcessDefinitionRespDTO.java b/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmProcessDefinitionRespDTO.java new file mode 100644 index 0000000..81aec42 --- /dev/null +++ b/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmProcessDefinitionRespDTO.java @@ -0,0 +1,55 @@ +package com.zt.plat.module.bpm.api.task.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "RPC 服务 - 流程定义 Response DTO") +@Data +public class BpmProcessDefinitionRespDTO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private String id; + + @Schema(description = "流程标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "process_order") + private String key; + + @Schema(description = "流程名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "请假流程") + private String name; + + @Schema(description = "流程描述", example = "请假流程描述") + private String description; + + @Schema(description = "流程分类", requiredMode = Schema.RequiredMode.REQUIRED, example = "oa") + private String category; + + @Schema(description = "表单类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer formType; + + @Schema(description = "表单编号", example = "1024") + private Long formId; + + @Schema(description = "表单的配置", requiredMode = Schema.RequiredMode.REQUIRED) + private String formConf; + + @Schema(description = "表单项的数组", requiredMode = Schema.RequiredMode.REQUIRED) + private List formFields; + + @Schema(description = "表单项的 JSON 数组字符串", requiredMode = Schema.RequiredMode.REQUIRED) + private String formFieldsStr; + + @Schema(description = "BPMN XML", requiredMode = Schema.RequiredMode.REQUIRED) + private String bpmnXml; + + @Schema(description = "版本", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer version; + + @Schema(description = "是否挂起", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + private Integer suspensionState; + + @Schema(description = "部署时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime deploymentTime; + +} \ No newline at end of file diff --git a/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmProcessInstanceBpmnModelViewRespDTO.java b/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmProcessInstanceBpmnModelViewRespDTO.java new file mode 100644 index 0000000..9b1f2c3 --- /dev/null +++ b/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmProcessInstanceBpmnModelViewRespDTO.java @@ -0,0 +1,41 @@ +package com.zt.plat.module.bpm.api.task.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; +import java.util.Set; + +@Schema(description = "RPC 服务 - 流程示例的 BPMN 视图 Response DTO") +@Data +public class BpmProcessInstanceBpmnModelViewRespDTO { + + // ========== 基本信息 ========== + + @Schema(description = "流程实例信息", requiredMode = Schema.RequiredMode.REQUIRED) + private BpmProcessInstanceRespDTO processInstance; + + @Schema(description = "任务列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List tasks; + + @Schema(description = "BPMN XML", requiredMode = Schema.RequiredMode.REQUIRED) + private String bpmnXml; + + @Schema(description = "SIMPLE 模型") + private BpmSimpleModelNodeDTO simpleModel; + + // ========== 进度信息 ========== + + @Schema(description = "进行中的活动节点编号集合", requiredMode = Schema.RequiredMode.REQUIRED) + private Set unfinishedTaskActivityIds; // 只包括 UserTask + + @Schema(description = "已经完成的活动节点编号集合", requiredMode = Schema.RequiredMode.REQUIRED) + private Set finishedTaskActivityIds; // 包括 UserTask、Gateway 等,不包括 SequenceFlow + + @Schema(description = "已经完成的连线节点编号集合", requiredMode = Schema.RequiredMode.REQUIRED) + private Set finishedSequenceFlowActivityIds; // 只包括 SequenceFlow + + @Schema(description = "已经拒绝的活动节点编号集合", requiredMode = Schema.RequiredMode.REQUIRED) + private Set rejectedTaskActivityIds; // 只包括 UserTask + +} \ No newline at end of file diff --git a/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmProcessInstanceCancelReqDTO.java b/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmProcessInstanceCancelReqDTO.java new file mode 100644 index 0000000..15316d0 --- /dev/null +++ b/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmProcessInstanceCancelReqDTO.java @@ -0,0 +1,19 @@ +package com.zt.plat.module.bpm.api.task.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; + +@Schema(description = "RPC 服务 - 流程实例的取消 Request DTO") +@Data +public class BpmProcessInstanceCancelReqDTO { + + @Schema(description = "流程实例的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotEmpty(message = "流程实例的编号不能为空") + private String id; + + @Schema(description = "取消原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "不请假了!") + @NotEmpty(message = "取消原因不能为空") + private String reason; + +} \ No newline at end of file diff --git a/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmProcessInstancePageReqDTO.java b/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmProcessInstancePageReqDTO.java index b041098..ce6c38c 100644 --- a/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmProcessInstancePageReqDTO.java +++ b/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmProcessInstancePageReqDTO.java @@ -22,6 +22,9 @@ public class BpmProcessInstancePageReqDTO extends PageParam { @Schema(description = "流程定义的编号", example = "2048") private String processDefinitionId; + @Schema(description = "流程定义的标识", example = "2048") + private String processDefinitionKey; // 精准匹配 + @Schema(description = "流程分类", example = "1") private String category; @@ -35,4 +38,14 @@ public class BpmProcessInstancePageReqDTO extends PageParam { @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime[] createTime; + @Schema(description = "结束时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] endTime; + + @Schema(description = "发起用户编号", example = "1024") + private Long startUserId; // 注意,只有在【流程实例】菜单,才使用该参数 + + @Schema(description = "动态表单字段查询 JSON Str", example = "{}") + private String formFieldsParams; // SpringMVC 在 get 请求下,无法方便的定义 Map 类型的参数,所以通过 String 接收后,逻辑里面转换 + } \ No newline at end of file diff --git a/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmProcessInstanceRespDTO.java b/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmProcessInstanceRespDTO.java index 1138169..48c779c 100644 --- a/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmProcessInstanceRespDTO.java +++ b/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmProcessInstanceRespDTO.java @@ -1,9 +1,12 @@ package com.zt.plat.module.bpm.api.task.dto; +import com.zt.plat.framework.common.core.KeyValue; +import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.time.LocalDateTime; +import java.util.List; import java.util.Map; @Schema(description = "RPC 服务 - 流程实例 Response DTO") @@ -16,23 +19,26 @@ public class BpmProcessInstanceRespDTO { @Schema(description = "流程实例的名字", example = "芋艿") private String name; + @Schema(description = "流程摘要") + private List> summary; // 只有流程表单,才有摘要! + @Schema(description = "流程定义的编号", example = "2048") private String processDefinitionId; @Schema(description = "流程分类", example = "1") private String category; + @Schema(description = "流程分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "请假") + private String categoryName; + @Schema(description = "流程实例的状态", example = "1") private Integer status; @Schema(description = "流程实例的结果", example = "1") private Integer result; - @Schema(description = "提交的表单值", example = "{\"name\": \"芋艿\"}") - private Map formVariables; - - @Schema(description = "业务的唯一标识", example = "1") - private String businessKey; + @Schema(description = "发起时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime startTime; @Schema(description = "创建时间") private LocalDateTime createTime; @@ -43,4 +49,44 @@ public class BpmProcessInstanceRespDTO { @Schema(description = "持续时间", example = "1000") private Long durationInMillis; + @Schema(description = "提交的表单值", example = "{\"name\": \"芋艿\"}") + private Map formVariables; + + @Schema(description = "业务的唯一标识", example = "1") + private String businessKey; + + /** + * 发起流程的用户 + */ + private UserSimpleDTO startUser; + + /** + * 流程定义 + */ + private BpmProcessDefinitionRespDTO processDefinition; + + /** + * 当前审批中的任务 + */ + private List tasks; // 仅在流程实例分页才返回 + + @Schema(description = "流程任务") + @Data + public static class Task { + + @Schema(description = "流程任务的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private String id; + + @Schema(description = "任务名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道") + private String name; + + @Schema(description = "任务分配人编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "2048") + @JsonIgnore // 不返回,只是方便后续读取,赋值给 assigneeUser + private Long assignee; + + @Schema(description = "任务分配人", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "2048") + private UserSimpleDTO assigneeUser; + + } + } \ No newline at end of file diff --git a/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmSimpleModelNodeDTO.java b/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmSimpleModelNodeDTO.java new file mode 100644 index 0000000..a01c60d --- /dev/null +++ b/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/BpmSimpleModelNodeDTO.java @@ -0,0 +1,31 @@ +package com.zt.plat.module.bpm.api.task.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; +import java.util.Map; + +@Schema(description = "RPC 服务 - 简单模型节点 DTO") +@Data +public class BpmSimpleModelNodeDTO { + + @Schema(description = "节点编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "StartNode") + private String id; + + @Schema(description = "节点名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "开始节点") + private String name; + + @Schema(description = "节点类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer type; + + @Schema(description = "节点属性") + private Map attributes; + + @Schema(description = "子节点列表") + private List childNode; + + @Schema(description = "条件节点列表") + private List conditionNodes; + +} \ No newline at end of file diff --git a/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/api/task/BpmProcessInstanceApiImpl.java b/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/api/task/BpmProcessInstanceApiImpl.java index 9b84efe..b3d1e79 100644 --- a/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/api/task/BpmProcessInstanceApiImpl.java +++ b/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/api/task/BpmProcessInstanceApiImpl.java @@ -1,21 +1,34 @@ package com.zt.plat.module.bpm.api.task; +import cn.hutool.core.util.StrUtil; +import com.zt.plat.framework.business.core.util.DeptUtil; import com.zt.plat.framework.common.pojo.CommonResult; +import com.zt.plat.framework.common.util.json.JsonUtils; +import com.zt.plat.framework.common.util.number.NumberUtils; import com.zt.plat.framework.common.util.object.BeanUtils; -import com.zt.plat.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; -import com.zt.plat.module.bpm.api.task.dto.BpmTaskApproveReqDTO; -import com.zt.plat.module.bpm.api.task.dto.BpmTaskRejectReqDTO; +import com.zt.plat.module.bpm.api.task.dto.*; +import com.zt.plat.module.bpm.controller.admin.task.vo.instance.*; import com.zt.plat.module.bpm.controller.admin.task.vo.task.BpmTaskApproveReqVO; import com.zt.plat.module.bpm.controller.admin.task.vo.task.BpmTaskRejectReqVO; +import com.zt.plat.module.bpm.convert.task.BpmProcessInstanceConvert; +import com.zt.plat.module.bpm.convert.task.BpmProcessInstanceDTOConvert; +import com.zt.plat.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO; +import com.zt.plat.module.bpm.service.definition.BpmProcessDefinitionService; import com.zt.plat.module.bpm.service.task.BpmProcessInstanceService; import com.zt.plat.module.bpm.service.task.BpmTaskService; +import com.zt.plat.module.system.api.dept.DeptApi; +import com.zt.plat.module.system.api.dept.dto.DeptRespDTO; +import com.zt.plat.module.system.api.user.AdminUserApi; +import com.zt.plat.module.system.api.user.dto.AdminUserRespDTO; import jakarta.annotation.Resource; import jakarta.validation.Valid; -import org.springframework.validation.annotation.Validated; +import org.flowable.engine.history.HistoricProcessInstance; +import org.flowable.engine.repository.ProcessDefinition; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; +import java.util.List; +import java.util.Map; import static com.zt.plat.framework.common.pojo.CommonResult.success; import static com.zt.plat.framework.web.core.util.WebFrameworkUtils.getLoginUserId; @@ -27,7 +40,7 @@ import static com.zt.plat.framework.web.core.util.WebFrameworkUtils.getLoginUser * @author jason */ @RestController -@Validated +@Valid public class BpmProcessInstanceApiImpl implements BpmProcessInstanceApi { @Resource @@ -36,11 +49,92 @@ public class BpmProcessInstanceApiImpl implements BpmProcessInstanceApi { @Resource private BpmTaskService taskService; + @Resource + private BpmProcessDefinitionService processDefinitionService; + + @Resource + private AdminUserApi adminUserApi; + + @Resource + private DeptApi deptApi; + @Override - public CommonResult createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO reqDTO) { + public CommonResult createProcessInstance(Long userId, @Valid @RequestBody BpmProcessInstanceCreateReqDTO reqDTO) { return success(processInstanceService.createProcessInstance(userId, reqDTO)); } + + @Override + public CommonResult getProcessInstance(String id) { + HistoricProcessInstance processInstance = processInstanceService.getHistoricProcessInstance(id); + if (processInstance == null) { + return success(null); + } + + // 拼接返回 + ProcessDefinition processDefinition = processDefinitionService.getProcessDefinition( + processInstance.getProcessDefinitionId()); + BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.getProcessDefinitionInfo( + processInstance.getProcessDefinitionId()); + AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId())).getCheckedData(); + DeptRespDTO dept = null; + if (startUser != null) { + Long deptId = DeptUtil.getDeptId(startUser); + if (deptId > 0) { + dept = deptApi.getDept(deptId).getCheckedData(); + } + } + BpmProcessInstanceRespVO vo = BpmProcessInstanceConvert.INSTANCE.buildProcessInstance(processInstance, + processDefinition, processDefinitionInfo, startUser, dept); + return success(BpmProcessInstanceDTOConvert.INSTANCE.convert(vo)); + } + + @Override + public CommonResult cancelProcessInstanceByStartUser( + Long userId, @Valid @RequestBody BpmProcessInstanceCancelReqDTO cancelReqDTO) { + BpmProcessInstanceCancelReqVO cancelReqVO = BpmProcessInstanceDTOConvert.INSTANCE.convertVO(cancelReqDTO); + processInstanceService.cancelProcessInstanceByStartUser(userId, cancelReqVO); + return success(true); + } + + @Override + public CommonResult cancelProcessInstanceByAdmin( + Long userId, @Valid @RequestBody BpmProcessInstanceCancelReqDTO cancelReqDTO) { + BpmProcessInstanceCancelReqVO cancelReqVO = BpmProcessInstanceDTOConvert.INSTANCE.convertVO(cancelReqDTO); + processInstanceService.cancelProcessInstanceByAdmin(userId, cancelReqVO); + return success(true); + } + + @Override + @SuppressWarnings("unchecked") + public CommonResult getApprovalDetail(Long userId, + @Valid @RequestBody BpmApprovalDetailReqDTO reqDTO) { + BpmApprovalDetailReqVO reqVO = BpmProcessInstanceDTOConvert.INSTANCE.convertVO(reqDTO); + if (StrUtil.isNotEmpty(reqDTO.getProcessVariablesStr())) { + reqVO.setProcessVariables(JsonUtils.parseObject(reqDTO.getProcessVariablesStr(), Map.class)); + } + BpmApprovalDetailRespVO respVO = processInstanceService.getApprovalDetail(userId, reqVO); + return success(BpmProcessInstanceDTOConvert.INSTANCE.convert(respVO)); + } + + @Override + @SuppressWarnings("unchecked") + public CommonResult> getNextApprovalNodes(Long userId, + @Valid @RequestBody BpmApprovalDetailReqDTO reqDTO) { + BpmApprovalDetailReqVO reqVO = BpmProcessInstanceDTOConvert.INSTANCE.convertVO(reqDTO); + if (StrUtil.isNotEmpty(reqDTO.getProcessVariablesStr())) { + reqVO.setProcessVariables(JsonUtils.parseObject(reqDTO.getProcessVariablesStr(), Map.class)); + } + List nodes = processInstanceService.getNextApprovalNodes(userId, reqVO); + return success(BpmProcessInstanceDTOConvert.INSTANCE.convertActivityNodes(nodes)); + } + + @Override + public CommonResult getProcessInstanceBpmnModelView(String id) { + BpmProcessInstanceBpmnModelViewRespVO respVO = processInstanceService.getProcessInstanceBpmnModelView(id); + return success(BpmProcessInstanceDTOConvert.INSTANCE.convert(respVO)); + } + @Override public CommonResult approveTask(BpmTaskApproveReqDTO reqVO) { taskService.approveTask(getLoginUserId(), BeanUtils.toBean(reqVO, BpmTaskApproveReqVO.class)); diff --git a/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/convert/task/BpmProcessInstanceDTOConvert.java b/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/convert/task/BpmProcessInstanceDTOConvert.java new file mode 100644 index 0000000..8d0a6ff --- /dev/null +++ b/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/convert/task/BpmProcessInstanceDTOConvert.java @@ -0,0 +1,67 @@ +package com.zt.plat.module.bpm.convert.task; + +import com.zt.plat.framework.common.pojo.PageResult; +import com.zt.plat.framework.common.util.object.BeanUtils; +import com.zt.plat.module.bpm.api.task.dto.*; +import com.zt.plat.module.bpm.controller.admin.task.vo.instance.*; +import com.zt.plat.module.bpm.controller.admin.base.user.UserSimpleBaseVO; +import com.zt.plat.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO; +import com.zt.plat.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Named; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 流程实例 DTO 转换器 + * + * @author ZT + */ +@Mapper +public interface BpmProcessInstanceDTOConvert { + + BpmProcessInstanceDTOConvert INSTANCE = Mappers.getMapper(BpmProcessInstanceDTOConvert.class); + + // VO to DTO + BpmProcessInstancePageReqDTO convert(BpmProcessInstancePageReqVO bean); + BpmProcessInstanceCancelReqDTO convert(BpmProcessInstanceCancelReqVO bean); + BpmApprovalDetailReqDTO convert(BpmApprovalDetailReqVO bean); + + // DTO to VO + BpmProcessInstancePageReqVO convertVO(BpmProcessInstancePageReqDTO bean); + BpmProcessInstanceCancelReqVO convertVO(BpmProcessInstanceCancelReqDTO bean); + BpmApprovalDetailReqVO convertVO(BpmApprovalDetailReqDTO bean); + + PageResult convertPage(PageResult pageResult); + BpmProcessInstanceRespDTO convert(BpmProcessInstanceRespVO bean); + BpmApprovalDetailRespDTO convert(BpmApprovalDetailRespVO bean); + BpmProcessInstanceBpmnModelViewRespDTO convert(BpmProcessInstanceBpmnModelViewRespVO bean); + + List convertActivityNodes(List nodes); + + // 内部类转换 + BpmProcessInstanceRespDTO.Task convert(BpmProcessInstanceRespVO.Task task); + BpmApprovalDetailRespDTO.ActivityNode convert(BpmApprovalDetailRespVO.ActivityNode node); + BpmApprovalDetailRespDTO.ActivityNodeTask convert(BpmApprovalDetailRespVO.ActivityNodeTask task); + + // 用户信息转换 + UserSimpleDTO convertUser(UserSimpleBaseVO user); + BpmProcessDefinitionRespDTO convert(BpmProcessDefinitionRespVO definition); + + @Mapping(target = "childNode", source = "childNode", qualifiedByName = "mapChildNode") + BpmSimpleModelNodeDTO convert(BpmSimpleModelNodeVO simpleModel); + + /** + * 将BpmSimpleModelNodeVO的childNode转换为List + */ + @Named("mapChildNode") + default List mapChildNode(BpmSimpleModelNodeVO childNode) { + if (childNode == null) { + return null; + } + return List.of(convert(childNode)); + } + +} \ No newline at end of file