微服务版后端初始化
This commit is contained in:
16
xjrsoft-service/xjrsoft-service-workflow/Dockerfile
Normal file
16
xjrsoft-service/xjrsoft-service-workflow/Dockerfile
Normal file
@ -0,0 +1,16 @@
|
||||
# 基础镜像
|
||||
FROM nexus.gdyditc.com:8082/openjdk:11-arm64
|
||||
# author
|
||||
MAINTAINER xjrsoft
|
||||
|
||||
# 挂载目录
|
||||
VOLUME /home/xjrsoft
|
||||
# 创建目录
|
||||
RUN mkdir -p /home/xjrsoft
|
||||
# 指定路径
|
||||
WORKDIR /home/xjrsoft
|
||||
# 复制jar文件到路径
|
||||
RUN ls
|
||||
COPY ./target/xjrsoft-service-workflow.jar /home/xjrsoft/xjrsoft-service-workflow.jar
|
||||
# 启动认证服务
|
||||
ENTRYPOINT ["java","-Dfile.encoding=utf-8","--add-opens","java.base/java.lang.reflect=ALL-UNNAMED","-jar","xjrsoft-service-workflow.jar"]
|
||||
119
xjrsoft-service/xjrsoft-service-workflow/pom.xml
Normal file
119
xjrsoft-service/xjrsoft-service-workflow/pom.xml
Normal file
@ -0,0 +1,119 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>xjrsoft-service</artifactId>
|
||||
<groupId>com.xjrsoft</groupId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>xjrsoft-service-workflow</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.xjrsoft</groupId>
|
||||
<artifactId>xjrsoft-service-workflow-api</artifactId>
|
||||
<version>${xjrsoft.framework.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.xjrsoft</groupId>
|
||||
<artifactId>xjrsoft-common-core</artifactId>
|
||||
<version>${xjrsoft.framework.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.xjrsoft</groupId>
|
||||
<artifactId>xjrsoft-common-mybatis</artifactId>
|
||||
<version>${xjrsoft.framework.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.xjrsoft</groupId>
|
||||
<artifactId>xjrsoft-service-form-api</artifactId>
|
||||
<version>${xjrsoft.framework.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>com.xjrsoft</groupId>-->
|
||||
<!-- <artifactId>xjrsoft-service-organization-api</artifactId>-->
|
||||
<!-- <version>${xjrsoft.framework.version}</version>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>com.xjrsoft</groupId>-->
|
||||
<!-- <artifactId>xjrsoft-service-system-api</artifactId>-->
|
||||
<!-- <version>${xjrsoft.framework.version}</version>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
<dependency>
|
||||
<groupId>com.xjrsoft</groupId>
|
||||
<artifactId>xjrsoft-service-app-api</artifactId>
|
||||
<version>${xjrsoft.framework.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>com.xjrsoft</groupId>-->
|
||||
<!-- <artifactId>xjrsoft-service-magicapi-api</artifactId>-->
|
||||
<!-- <version>${xjrsoft.framework.version}</version>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-loadbalancer</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.camunda.bpm.springboot</groupId>
|
||||
<artifactId>camunda-bpm-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.ssssssss</groupId>-->
|
||||
<!-- <artifactId>magic-api-spring-boot-starter</artifactId>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@ -0,0 +1,23 @@
|
||||
package com.xjrsoft.workflow;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
/**
|
||||
* @Author: tzx
|
||||
* @Date: 2023/10/18 10:38
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@EnableDiscoveryClient
|
||||
@EnableFeignClients(basePackages = "com.xjrsoft")
|
||||
@MapperScan(value = "com.xjrsoft.**.mapper")
|
||||
@ComponentScan(value = "com.xjrsoft")
|
||||
public class WorkflowApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(WorkflowApplication.class, args);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
package com.xjrsoft.workflow.client;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.xjrsoft.common.core.constant.GlobalConstant;
|
||||
import com.xjrsoft.workflow.vo.HistoryProcessInstanceVo;
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.camunda.bpm.engine.HistoryService;
|
||||
import org.camunda.bpm.engine.history.HistoricProcessInstance;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @Author: tzx
|
||||
* @Date: 2023/10/28 20:08
|
||||
*/
|
||||
@Hidden
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class HistoryClient implements IHistoryClient {
|
||||
|
||||
private final HistoryService historyService;
|
||||
|
||||
|
||||
@Override
|
||||
@GetMapping(GlobalConstant.CLIENT_API_PRE + GlobalConstant.MODULE_WORKFLOW_NAME + "/getProcessInstanceListFeign")
|
||||
public List<HistoryProcessInstanceVo> getProcessInstanceListFeign(Set<String> processIds) {
|
||||
|
||||
List<HistoricProcessInstance> processInstanceList;
|
||||
if (processIds.size() == 0) {
|
||||
processInstanceList = new ArrayList<>();
|
||||
} else {
|
||||
processInstanceList = historyService.createHistoricProcessInstanceQuery().processInstanceIds(processIds).list();
|
||||
}
|
||||
|
||||
return BeanUtil.copyToList(processInstanceList, HistoryProcessInstanceVo.class);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
package com.xjrsoft.workflow.client;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.xjrsoft.common.core.constant.GlobalConstant;
|
||||
import com.xjrsoft.common.core.enums.WorkflowIsRecycleType;
|
||||
import com.xjrsoft.common.core.enums.YesOrNoEnum;
|
||||
import com.xjrsoft.workflow.constant.WorkflowConstant;
|
||||
import com.xjrsoft.workflow.vo.TaskInstanceVo;
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.camunda.bpm.engine.TaskService;
|
||||
import org.camunda.bpm.engine.task.Task;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author: tzx
|
||||
* @Date: 2023/10/28 20:24
|
||||
*/
|
||||
@Hidden
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class TaskClient implements ITaskClient {
|
||||
|
||||
private final TaskService taskService;
|
||||
|
||||
@Override
|
||||
@GetMapping(GlobalConstant.CLIENT_API_PRE + GlobalConstant.MODULE_WORKFLOW_NAME + "/getActiveTaskInstanceListFeign")
|
||||
public List<TaskInstanceVo> getActiveTaskInstanceListFeign(String[] processIdArrays) {
|
||||
|
||||
List<Task> taskList;
|
||||
if (processIdArrays.length > 0) {
|
||||
taskList = taskService.createTaskQuery()
|
||||
.active()
|
||||
.processInstanceIdIn(processIdArrays)
|
||||
.taskVariableValueEquals(WorkflowConstant.TASK_IS_APPOINT_APPROVE, YesOrNoEnum.NO.getCode())
|
||||
.processVariableValueEquals(WorkflowConstant.PROCESS_ISRECYCLE_FLAG_KEY, WorkflowIsRecycleType.NO.getCode())
|
||||
.taskVariableValueLike(WorkflowConstant.TASK_ASSIGNEE_VAR_KEY, StringPool.PERCENT + StpUtil.getLoginIdAsString() + StringPool.PERCENT)
|
||||
.list();
|
||||
} else {
|
||||
taskList = new ArrayList<>();
|
||||
}
|
||||
|
||||
|
||||
return BeanUtil.copyToList(taskList, TaskInstanceVo.class);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package com.xjrsoft.workflow.client;
|
||||
|
||||
import com.xjrsoft.workflow.dto.PendingTaskDto;
|
||||
import com.xjrsoft.workflow.service.IWorkflowExecuteService;
|
||||
import com.xjrsoft.workflow.vo.HistoryProcessInstanceVo;
|
||||
import com.xjrsoft.workflow.vo.PendingTaskVo;
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yjw
|
||||
* @createDate 2024-07-10
|
||||
*/
|
||||
@Hidden
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class WorkflowExecuteClient implements IWorkflowExecuteClient{
|
||||
|
||||
private final IWorkflowExecuteService workflowExecuteService;
|
||||
|
||||
@Override
|
||||
public List<PendingTaskVo> getPendingListFeign(PendingTaskDto pendingTaskDto) {
|
||||
return workflowExecuteService.pending(pendingTaskDto);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
package com.xjrsoft.workflow.client;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.xjrsoft.common.core.constant.GlobalConstant;
|
||||
import com.xjrsoft.workflow.entity.WorkflowFormRelation;
|
||||
import com.xjrsoft.workflow.service.IWorkflowFormRelationService;
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author: tzx
|
||||
* @Date: 2023/10/19 16:18
|
||||
*/
|
||||
@Hidden
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class WorkflowFormRelationClient implements IWorkflowFormRelationClient {
|
||||
|
||||
private final IWorkflowFormRelationService workflowFormRelationService;
|
||||
|
||||
/**
|
||||
* 表单id 获取工作流关联
|
||||
* @param formId
|
||||
* @param formKeyValue
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(GlobalConstant.CLIENT_API_PRE + GlobalConstant.MODULE_WORKFLOW_NAME + "/getWorkflowFormRelationFeign")
|
||||
@Override
|
||||
public List<WorkflowFormRelation> getWorkflowFormRelationFeign(Long formId, String formKeyValue) {
|
||||
|
||||
|
||||
return workflowFormRelationService.list(Wrappers.lambdaQuery(WorkflowFormRelation.class)
|
||||
.eq(WorkflowFormRelation::getFormId, formId).eq(WorkflowFormRelation::getFormKeyValue, formKeyValue));
|
||||
}
|
||||
|
||||
@Override
|
||||
@GetMapping(GlobalConstant.CLIENT_API_PRE + GlobalConstant.MODULE_WORKFLOW_NAME + "/getWorkflowFormRelationBatchFeign")
|
||||
public List<WorkflowFormRelation> getWorkflowFormRelationBatchFeign(Long formId, List<Object> formKeyValues) {
|
||||
|
||||
|
||||
return workflowFormRelationService.list(Wrappers.lambdaQuery(WorkflowFormRelation.class).eq(WorkflowFormRelation::getFormId, formId).in(WorkflowFormRelation::getFormKeyValue, formKeyValues).select(WorkflowFormRelation::getProcessId, WorkflowFormRelation::getFormKeyValue));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package com.xjrsoft.workflow.client;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.xjrsoft.common.core.constant.GlobalConstant;
|
||||
import com.xjrsoft.workflow.entity.WorkflowSchema;
|
||||
import com.xjrsoft.workflow.service.IWorkflowSchemaService;
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @Author: tzx
|
||||
* @Date: 2023/10/28 19:59
|
||||
*/
|
||||
@Hidden
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class WorkflowSchemaClient implements IWorkflowSchemaClient {
|
||||
|
||||
private final IWorkflowSchemaService workflowSchemaService;
|
||||
|
||||
@Override
|
||||
@GetMapping(GlobalConstant.CLIENT_API_PRE + GlobalConstant.MODULE_WORKFLOW_NAME + "/getWorkflowSchemaByFormIdFeign")
|
||||
public WorkflowSchema getWorkflowSchemaByFormIdFeign(Long formId) {
|
||||
return workflowSchemaService.getOne(Wrappers.lambdaQuery(WorkflowSchema.class).eq(WorkflowSchema::getFormId, formId).select(WorkflowSchema::getId));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package com.xjrsoft.workflow.controller;
|
||||
|
||||
import com.xjrsoft.common.core.constant.GlobalConstant;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2023-02-10
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping(GlobalConstant.WORKFLOW_MODULE_PREFIX + "/workflowApproveRecord")
|
||||
public class WorkflowApproveRecordController {
|
||||
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package com.xjrsoft.workflow.controller;
|
||||
|
||||
import com.xjrsoft.common.core.constant.GlobalConstant;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 流程传阅信息表 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2023-02-09
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping(GlobalConstant.WORKFLOW_MODULE_PREFIX + "/workflowCirculated")
|
||||
public class WorkflowCirculatedController {
|
||||
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
package com.xjrsoft.workflow.controller;
|
||||
|
||||
import com.xjrsoft.common.core.constant.GlobalConstant;
|
||||
import com.xjrsoft.common.core.domain.result.R;
|
||||
import com.xjrsoft.workflow.dto.AddDelegateDto;
|
||||
import com.xjrsoft.workflow.dto.DelegatePageDto;
|
||||
import com.xjrsoft.workflow.dto.UpdateDelegateDto;
|
||||
import com.xjrsoft.workflow.service.IWorkflowDelegateService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 流程委托 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2022-11-05
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(GlobalConstant.WORKFLOW_MODULE_PREFIX + "/delegate")
|
||||
@Tag(name = GlobalConstant.WORKFLOW_MODULE_PREFIX + "/delegate", description = "流程委托接口")
|
||||
@AllArgsConstructor
|
||||
public class WorkflowDelegateController {
|
||||
|
||||
private final IWorkflowDelegateService workflowDelegateService;
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "流程委托(分页)")
|
||||
public R page(@Valid DelegatePageDto dto) {
|
||||
return R.ok(workflowDelegateService.page(dto));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "新增流程委托")
|
||||
public R add(@Valid @RequestBody AddDelegateDto dto){
|
||||
return R.ok(workflowDelegateService.add(dto));
|
||||
}
|
||||
|
||||
@PutMapping
|
||||
@Operation(summary = "修改流程委托")
|
||||
public R update(@Valid @RequestBody UpdateDelegateDto dto){
|
||||
return R.ok(workflowDelegateService.update(dto));
|
||||
}
|
||||
|
||||
|
||||
@DeleteMapping
|
||||
@Operation(summary = "删除流程委托")
|
||||
public R delete(@Valid @RequestBody List<Long> ids){
|
||||
return R.ok(workflowDelegateService.delete(ids));
|
||||
}
|
||||
|
||||
@GetMapping("/info")
|
||||
@Operation(summary = "获取流程委托信息")
|
||||
public R info(@RequestParam Long id){
|
||||
return R.ok(workflowDelegateService.getById(id));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,338 @@
|
||||
package com.xjrsoft.workflow.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.xjrsoft.common.core.constant.GlobalConstant;
|
||||
import com.xjrsoft.common.core.domain.result.R;
|
||||
import com.xjrsoft.workflow.dto.*;
|
||||
import com.xjrsoft.workflow.service.IWorkflowExecuteService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 工作流操作接口
|
||||
*
|
||||
* @Author: tzx
|
||||
* @Date: 2022/9/8 14:15
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(GlobalConstant.WORKFLOW_MODULE_PREFIX + "/execute")
|
||||
@Tag(name = GlobalConstant.WORKFLOW_MODULE_PREFIX + "/execute", description = "工作流操作接口")
|
||||
@AllArgsConstructor
|
||||
public class WorkflowExecuteController {
|
||||
|
||||
private final IWorkflowExecuteService workflowExecuteService;
|
||||
|
||||
@PostMapping("/deploy")
|
||||
@Operation(summary = "部署流程")
|
||||
public R deploy(@Valid @RequestBody DeployDto dto) {
|
||||
return R.ok(workflowExecuteService.deploy(dto));
|
||||
}
|
||||
|
||||
@GetMapping("/preview")
|
||||
@Operation(summary = "预览流程")
|
||||
public R preview(@RequestParam Long schemaId) {
|
||||
return R.ok(workflowExecuteService.preview(schemaId));
|
||||
}
|
||||
|
||||
@GetMapping("/start-process-info")
|
||||
@Operation(summary = "发起流程所需要的信息")
|
||||
public R startProcessInfo(@RequestParam Long schemaId) {
|
||||
return R.ok(workflowExecuteService.getStartProcessInfo(schemaId));
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/approve-process-info")
|
||||
@Operation(summary = "审批流程所需要的信息")
|
||||
public R approveProcessInfo(@RequestParam String taskId) {
|
||||
return R.ok(workflowExecuteService.getApproveProcessInfo(taskId));
|
||||
}
|
||||
|
||||
@GetMapping("/view-process-info")
|
||||
@Operation(summary = "查看流程所需要的信息(processId获取)")
|
||||
public R approveProcessInfoByProcessId(@RequestParam String processId) {
|
||||
return R.ok(workflowExecuteService.getApproveProcessInfoByProcessId(processId));
|
||||
}
|
||||
|
||||
@GetMapping("/process/all-record")
|
||||
@Operation(summary = "查看流程所需要的所有流转信息(processId获取,包括父子流程)")
|
||||
public R allRecordInfoByProcessId(@RequestParam String processId,@RequestParam(required = false,defaultValue = "1") Integer onlySelf) {
|
||||
return R.ok(workflowExecuteService.getAllRecordInfoByProcessId(processId,onlySelf));
|
||||
}
|
||||
|
||||
@GetMapping("/recycle-process-info")
|
||||
@Operation(summary = "获取回收站的数据流程数据")
|
||||
public R recycleProcessInfo(@RequestParam String processId) {
|
||||
return R.ok(workflowExecuteService.getRecycleProcessInfo(processId));
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/new-launch")
|
||||
@Operation(summary = "重构后发起流程")
|
||||
public R newLaunch(@Valid @RequestBody LaunchDto dto) {
|
||||
return R.ok(workflowExecuteService.newLaunch(dto));
|
||||
}
|
||||
|
||||
@PostMapping("/relaunch")
|
||||
@Operation(summary = "重新发起")
|
||||
public R reLaunch(@Valid @RequestBody ReLaunchDto dto) {
|
||||
return R.ok(workflowExecuteService.reLaunch(dto));
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/pending")
|
||||
@Operation(summary = "待办任务")
|
||||
public R pending(@Valid PendingTaskPageDto dto) {
|
||||
return R.ok(workflowExecuteService.pending(dto));
|
||||
}
|
||||
|
||||
@GetMapping("/task-info")
|
||||
@Operation(summary = "查询任务详情")
|
||||
public R taskInfo(@RequestParam String taskId) {
|
||||
return R.ok(workflowExecuteService.getTaskInfo(taskId));
|
||||
}
|
||||
|
||||
@GetMapping("/process-info")
|
||||
@Operation(summary = "查询流程详情")
|
||||
public R processInfo(@RequestParam String processId) {
|
||||
return R.ok(workflowExecuteService.getProcessInfo(processId));
|
||||
}
|
||||
|
||||
@GetMapping("/circulated-task-info")
|
||||
@Operation(summary = "查询传阅任务详情")
|
||||
public R circulatedTaskInfo(@RequestParam String taskId) {
|
||||
return R.ok(workflowExecuteService.getCirculatedTaskInfo(taskId));
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/process/finished-task")
|
||||
@Operation(summary = "查询当前流程已完成的任务")
|
||||
public R finishedTask(@RequestParam String processInstanceId){
|
||||
return R.ok(workflowExecuteService.getFinishedTask(processInstanceId));
|
||||
}
|
||||
|
||||
@GetMapping("/process/record")
|
||||
@Operation(summary = "查询当前流程所有流转记录")
|
||||
public R processRecord(@RequestParam String processInstanceId){
|
||||
return R.ok(workflowExecuteService.getProcessRecord(processInstanceId));
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/new-approve")
|
||||
@Operation(summary = "重构后发审批")
|
||||
public R newApprove(@Valid @RequestBody ApproveDto dto) {
|
||||
return R.ok(workflowExecuteService.newApprove(dto));
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/approve/multi-info")
|
||||
@Operation(summary = "批量审批获取流程信息")
|
||||
public R approveMultiInfo(@Valid ApproveMultiInfoDto dto) {
|
||||
return R.ok(workflowExecuteService.approveMultiInfo(dto));
|
||||
}
|
||||
@PostMapping("/approve/multi")
|
||||
@Operation(summary = "批量审批")
|
||||
public R approveMulti(@Valid @RequestBody ApproveMultiDto dto) {
|
||||
return R.ok(workflowExecuteService.approveMulti(dto));
|
||||
}
|
||||
|
||||
@PostMapping("/getNextTaskMaybeArrival/{taskId}")
|
||||
@Operation(summary = "获取下一步可能到达的任务节点,包括节点可选人")
|
||||
@SneakyThrows
|
||||
public R getNextTaskMaybeArrival(@PathVariable String taskId,@RequestBody JSONObject parameter){
|
||||
Set<HashMap<String, Object>> result = workflowExecuteService.getNextUserTaskNodeMaybeArrival(taskId, parameter);
|
||||
return R.ok(result);
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/set-approve")
|
||||
@Operation(summary = "指定下一节点审批人(覆盖)")
|
||||
public R setApproveUser(@Valid @RequestBody ApproveUserDto dto) {
|
||||
return R.ok(workflowExecuteService.setApproveUser(dto));
|
||||
}
|
||||
|
||||
@PostMapping("/set-approve-multi")
|
||||
@Operation(summary = "指定下一节点审批人(批量覆盖)")
|
||||
public R setApproveUserMulti(@Valid @RequestBody ApproveUserMultiDto dto) {
|
||||
return R.ok(workflowExecuteService.setApproveUserMulti(dto));
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/relation-task/page")
|
||||
@Operation(summary = "查询流程模板关联的任务分页")
|
||||
public R relationTaskPage(@Valid RelationTaskPageDto dto) {
|
||||
return R.ok(workflowExecuteService.getRelationTaskPage(dto));
|
||||
}
|
||||
|
||||
@GetMapping("/relation-task/info")
|
||||
@Operation(summary = "查询流程模板关联的任务 详情")
|
||||
public R relationTaskPage(@Valid RelationTaskInfoDto dto) {
|
||||
return R.ok(workflowExecuteService.getRelationTaskInfo(dto));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@GetMapping("/circulated/page")
|
||||
@Operation(summary = "查询我的传阅")
|
||||
public R circulatedTaskPage(@Valid CirculatedTaskPageDto dto) {
|
||||
return R.ok(workflowExecuteService.getCirculatedTaskPage(dto));
|
||||
}
|
||||
|
||||
@GetMapping("/finished/page")
|
||||
@Operation(summary = "查询我的已办任务分页")
|
||||
public R finishedTaskPage(@Valid FinishedTaskPageDto dto) {
|
||||
return R.ok(workflowExecuteService.getFinishedTaskPage(dto));
|
||||
}
|
||||
|
||||
@GetMapping("/my-process/page")
|
||||
@Operation(summary = "查询我的流程")
|
||||
public R myProcessPage(@Valid MyProcessPageDto dto) {
|
||||
return R.ok(workflowExecuteService.getMyProcessPage(dto));
|
||||
}
|
||||
|
||||
@PostMapping("/my-process/move-recycle")
|
||||
@Operation(summary = "我的流程 移入回收站")
|
||||
public R moveRecycle(@Valid @RequestBody MoveRecycleDto dto) {
|
||||
return R.ok(workflowExecuteService.moveRecycle(dto));
|
||||
}
|
||||
|
||||
@GetMapping("/my-process/recycle/page")
|
||||
@Operation(summary = "回收站列表")
|
||||
public R recycleProcessPage(@Valid RecycleProcessPageDto dto) {
|
||||
return R.ok(workflowExecuteService.getRecycleProcessPage(dto));
|
||||
}
|
||||
|
||||
@DeleteMapping("/my-process/recycle")
|
||||
@Operation(summary = "回收站 删除")
|
||||
public R recycleDelete(@Valid @RequestBody RecycleDeleteDto dto) {
|
||||
return R.ok(workflowExecuteService.recycleDelete(dto));
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/my-process/recycle/restart")
|
||||
@Operation(summary = "回收站 重新发起")
|
||||
public R restart(@Valid @RequestBody RestartDto dto) {
|
||||
return R.ok(workflowExecuteService.restart(dto));
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/my-task/history-task")
|
||||
@Operation(summary = "我的流程 已经完成的任务(不包括 外部流程 子流程 会签流程)")
|
||||
public R historyTask(@RequestParam String schemaId, @RequestParam String processInstanceId) {
|
||||
return R.ok(workflowExecuteService.getHistoryTask(schemaId, processInstanceId));
|
||||
}
|
||||
|
||||
@PostMapping("/my-task/withdraw")
|
||||
@Operation(summary = "我的流程 撤回")
|
||||
public R withdraw(@Valid @RequestBody WithdrawDto dto) {
|
||||
return R.ok(workflowExecuteService.withdraw(dto));
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/draft")
|
||||
@Operation(summary = "保存草稿")
|
||||
public R addDraft(@Valid @RequestBody SaveDraftDto dto) throws JsonProcessingException {
|
||||
return R.ok(workflowExecuteService.saveDraft(dto));
|
||||
}
|
||||
|
||||
@PutMapping("/draft")
|
||||
@Operation(summary = "修改草稿")
|
||||
public R updateDraft(@Valid @RequestBody UpdateDraftDto dto) {
|
||||
return R.ok(workflowExecuteService.updateDraft(dto));
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/draft/page")
|
||||
@Operation(summary = "查询草稿列表分页")
|
||||
public R draftPage(@Valid DraftPageDto dto) {
|
||||
return R.ok(workflowExecuteService.draftPage(dto));
|
||||
}
|
||||
|
||||
@GetMapping("/draft/info")
|
||||
@Operation(summary = "查询草稿详情")
|
||||
public R draftInfo(@RequestParam Long id) {
|
||||
return R.ok(workflowExecuteService.draftInfo(id));
|
||||
}
|
||||
|
||||
@DeleteMapping("/draft")
|
||||
@Operation(summary = "删除草稿")
|
||||
public R deleteDraft(@RequestBody List<Long> ids) {
|
||||
return R.ok(workflowExecuteService.deleteDraft(ids));
|
||||
}
|
||||
|
||||
@GetMapping("/process-monitor/page")
|
||||
@Operation(summary = "流程监控分页列表")
|
||||
public R processMonitorPage(@Valid MonitorPageDto dto) {
|
||||
return R.ok(workflowExecuteService.getProcessMonitorPage(dto));
|
||||
}
|
||||
|
||||
@DeleteMapping("/process-monitor/delete")
|
||||
@Operation(summary = "删除流程(流程监控使用)")
|
||||
public R deleteProcessMonitor(@RequestBody DeleteMonitorDto dto) {
|
||||
return R.ok(workflowExecuteService.deleteProcessMonitor(dto));
|
||||
}
|
||||
@PostMapping("/set-assignee")
|
||||
@Operation(summary = "指派审核人(给任务添加审批人)")
|
||||
public R setAssignee(@Valid @RequestBody SetAssigneeDto dto) {
|
||||
return R.ok(workflowExecuteService.setAssignee(dto));
|
||||
}
|
||||
|
||||
@PostMapping("/set-suspended")
|
||||
@Operation(summary = "将流程挂起")
|
||||
public R setSuspended(@Valid @RequestBody SetSuspendedDto dto) {
|
||||
return R.ok(workflowExecuteService.setSuspended(dto));
|
||||
}
|
||||
|
||||
@GetMapping("/approve-user")
|
||||
@Operation(summary = "获取节点审批人(获取下一节点审批人也是这个接口)")
|
||||
public R getAssignee(@Valid GetAssigneeDto dto){
|
||||
return R.ok(workflowExecuteService.getAssignee(dto));
|
||||
}
|
||||
|
||||
@PostMapping("/set-sign")
|
||||
@Operation(summary = "加签/减签")
|
||||
public R addOrSubSign(@Valid @RequestBody AddOrSubSignDto dto) {
|
||||
return R.ok(workflowExecuteService.addOrSubSign(dto));
|
||||
}
|
||||
|
||||
@GetMapping("/reject-node")
|
||||
@Operation(summary = "获取可以驳回的节点")
|
||||
public R rejectNode(@Valid RejectNodeDto dto){
|
||||
return R.ok(workflowExecuteService.getRejectNode(dto));
|
||||
}
|
||||
@GetMapping("/withdraw-node")
|
||||
@Operation(summary = "获取可以撤回的节点")
|
||||
public R withdrawNode(@Valid WithdrawNodeDto dto){
|
||||
return R.ok(workflowExecuteService.getProcessTaskCanWithdraw(dto));
|
||||
}
|
||||
|
||||
@PostMapping("/transfer")
|
||||
@Operation(summary = "转办")
|
||||
public R transfer(@Valid @RequestBody TransferDto dto){
|
||||
return R.ok(workflowExecuteService.transfer(dto));
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/process/form-finished-task")
|
||||
@Operation(summary = "根据formId 查询流程图 以及 当前流程已完成的任务")
|
||||
public R formFinishedTask(FormFinishedTaskDto dto){
|
||||
return R.ok(workflowExecuteService.getFormFinishedTask(dto));
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/count")
|
||||
@Operation(summary = "合计")
|
||||
public R count() {
|
||||
return R.ok(workflowExecuteService.getCount());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package com.xjrsoft.workflow.controller;
|
||||
|
||||
import com.xjrsoft.common.core.constant.GlobalConstant;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2022-10-13
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping(GlobalConstant.WORKFLOW_MODULE_PREFIX + "/workflowExtra")
|
||||
public class WorkflowExtraController {
|
||||
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package com.xjrsoft.workflow.controller;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 工作流 流程 与 表单关联表 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2023-03-27
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/workflow/workflowFormRelation")
|
||||
public class WorkflowFormRelationController {
|
||||
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
package com.xjrsoft.workflow.controller;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.xjrsoft.common.core.constant.GlobalConstant;
|
||||
import com.xjrsoft.common.core.domain.result.R;
|
||||
import com.xjrsoft.workflow.entity.WorkflowRecord;
|
||||
import com.xjrsoft.workflow.service.IWorkflowRecordService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.camunda.bpm.engine.HistoryService;
|
||||
import org.camunda.bpm.engine.history.HistoricProcessInstance;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 流程记录前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2022-10-13
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(GlobalConstant.WORKFLOW_MODULE_PREFIX + "/record")
|
||||
@Tag(name = GlobalConstant.WORKFLOW_MODULE_PREFIX + "/record", description = "流程记录接口")
|
||||
@AllArgsConstructor
|
||||
public class WorkflowRecordController {
|
||||
|
||||
private final IWorkflowRecordService workflowRecordService;
|
||||
|
||||
private final HistoryService historyService;
|
||||
|
||||
/**
|
||||
* 数据库存储xml字段的后缀
|
||||
*/
|
||||
private static final String DB_FIELD_XML_PREFIX = "xml";
|
||||
|
||||
@GetMapping("/list")
|
||||
@Operation(summary = "查询整个流程的流程记录")
|
||||
public R list(@RequestParam String processInstanceId){
|
||||
|
||||
List<HistoricProcessInstance> subProcess = historyService.createHistoricProcessInstanceQuery()
|
||||
.superProcessInstanceId(processInstanceId).list();
|
||||
|
||||
List<String> subProcessIds = subProcess.stream().map(HistoricProcessInstance::getId).collect(Collectors.toList());
|
||||
|
||||
subProcessIds.add(processInstanceId);
|
||||
|
||||
LambdaQueryWrapper<WorkflowRecord> queryWrapper = Wrappers.lambdaQuery(WorkflowRecord.class).in(WorkflowRecord::getProcessId, subProcessIds).orderByDesc(WorkflowRecord::getId);
|
||||
|
||||
return R.ok(workflowRecordService.list(queryWrapper));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package com.xjrsoft.workflow.controller;
|
||||
|
||||
import com.xjrsoft.common.core.constant.GlobalConstant;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 流程模板权限 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author zwq
|
||||
* @since 2022-07-04
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(GlobalConstant.WORKFLOW_MODULE_PREFIX + "/schema-auth")
|
||||
@Tag(name = GlobalConstant.WORKFLOW_MODULE_PREFIX + "/schema-auth", description = "流程模板权限")
|
||||
@AllArgsConstructor
|
||||
public class WorkflowSchemaAuthController {
|
||||
|
||||
}
|
||||
@ -0,0 +1,144 @@
|
||||
package com.xjrsoft.workflow.controller;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.xjrsoft.common.core.constant.GlobalConstant;
|
||||
import com.xjrsoft.common.core.domain.result.R;
|
||||
import com.xjrsoft.common.core.enums.EnabledMark;
|
||||
import com.xjrsoft.workflow.dto.*;
|
||||
import com.xjrsoft.workflow.entity.WorkflowSchema;
|
||||
import com.xjrsoft.workflow.model.WorkflowSchemaConfig;
|
||||
import com.xjrsoft.workflow.service.IWorkflowSchemaService;
|
||||
import com.xjrsoft.workflow.vo.WorkflowSchemaInfoVo;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 流程模板表 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author zwq
|
||||
* @since 2022-07-04
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(GlobalConstant.WORKFLOW_MODULE_PREFIX + "/schema")
|
||||
@Tag(name = GlobalConstant.WORKFLOW_MODULE_PREFIX + "/schema", description = "流程模板")
|
||||
@AllArgsConstructor
|
||||
public class WorkflowSchemaController {
|
||||
|
||||
private final IWorkflowSchemaService workflowSchemaService;
|
||||
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "流程列表(分页)")
|
||||
public R page(@Valid WorkflowSchemaPageDto dto) {
|
||||
return R.ok(workflowSchemaService.getPage(dto));
|
||||
}
|
||||
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "新增流程模板")
|
||||
public R add(@Valid @RequestBody AddWorkflowSchemaDto dto) {
|
||||
return R.ok(workflowSchemaService.add(dto));
|
||||
}
|
||||
|
||||
@PostMapping("/draft")
|
||||
@Operation(summary = "新增流程模板草稿")
|
||||
public R draft(@Valid @RequestBody AddWorkflowSchemaDraftDto dto) {
|
||||
return R.ok(workflowSchemaService.addDraft(dto));
|
||||
}
|
||||
|
||||
@GetMapping("/draft")
|
||||
@Operation(summary = "流程模板草稿")
|
||||
public R draftPage(@Valid WorkflowSchemaDraftPageDto dto) {
|
||||
return R.ok(workflowSchemaService.getDraftPage(dto));
|
||||
}
|
||||
|
||||
|
||||
@PutMapping
|
||||
@Operation(summary = "修改流程模板")
|
||||
public R update(@Valid @RequestBody UpdateWorkflowSchemaDto dto) {
|
||||
return R.ok(workflowSchemaService.update(dto));
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/info")
|
||||
@Operation(summary = "获取流程详细信息")
|
||||
public R info(@RequestParam Long id) {
|
||||
WorkflowSchema workflowSchema = workflowSchemaService.getById(id);
|
||||
if (workflowSchema == null) {
|
||||
return R.error("找不到此模板信息!");
|
||||
}
|
||||
return R.ok(BeanUtil.toBean(workflowSchema, WorkflowSchemaInfoVo.class));
|
||||
}
|
||||
|
||||
@GetMapping("/multi/info")
|
||||
@Operation(summary = "获取批量流程详细信息")
|
||||
public R multiInfo(@RequestParam String ids) {
|
||||
List<String> idList = Arrays.stream(ids.split(StringPool.COMMA)).collect(Collectors.toList());
|
||||
|
||||
List<WorkflowSchema> workflowSchemas = workflowSchemaService.listByIds(idList);
|
||||
|
||||
return R.ok(BeanUtil.copyToList(workflowSchemas, WorkflowSchemaInfoVo.class));
|
||||
}
|
||||
|
||||
|
||||
@DeleteMapping
|
||||
@Operation(summary = "删除模板(可批量)")
|
||||
public R delete(@RequestBody List<Long> ids) {
|
||||
|
||||
return R.ok(workflowSchemaService.delete(ids));
|
||||
}
|
||||
|
||||
@PutMapping("/enabled")
|
||||
@Operation(summary = "流程启用")
|
||||
public R enabled(@Valid @RequestBody EnabledDto dto) {
|
||||
WorkflowSchema schema = new WorkflowSchema();
|
||||
schema.setId(dto.getSchemaId());
|
||||
schema.setEnabledMark(EnabledMark.ENABLED.getCode());
|
||||
return R.ok(workflowSchemaService.updateById(schema));
|
||||
}
|
||||
|
||||
@PutMapping("/disabled")
|
||||
@Operation(summary = "流程禁用")
|
||||
public R disabled(@Valid @RequestBody EnabledDto dto) {
|
||||
WorkflowSchema schema = new WorkflowSchema();
|
||||
schema.setId(dto.getSchemaId());
|
||||
schema.setEnabledMark(EnabledMark.DISABLED.getCode());
|
||||
return R.ok(workflowSchemaService.updateById(schema));
|
||||
}
|
||||
|
||||
@GetMapping("/export")
|
||||
@Operation(summary = "导出流程")
|
||||
@SneakyThrows
|
||||
public R export(@RequestParam Long id) {
|
||||
WorkflowSchema workflowSchema = workflowSchemaService.getById(id);
|
||||
if (workflowSchema == null) {
|
||||
return R.error("找不到此模板信息!");
|
||||
}
|
||||
WorkflowSchemaConfig workflowSchemaConfig = JSONUtil.toBean(workflowSchema.getJsonContent(), WorkflowSchemaConfig.class);
|
||||
workflowSchemaConfig.getProcessConfig().setXmlContent(workflowSchema.getXmlContent());
|
||||
|
||||
return R.ok(JSONUtil.toJsonStr(workflowSchemaConfig));
|
||||
}
|
||||
|
||||
@PostMapping("/import")
|
||||
@Operation(summary = "导入流程")
|
||||
@SneakyThrows
|
||||
public R importSchema(@RequestParam(value = "file") MultipartFile multipartFile) {
|
||||
return R.ok(workflowSchemaService.importSchema(multipartFile));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,75 @@
|
||||
package com.xjrsoft.workflow.controller;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.github.yulichang.toolkit.MPJWrappers;
|
||||
import com.xjrsoft.common.core.constant.GlobalConstant;
|
||||
import com.xjrsoft.common.core.domain.result.R;
|
||||
import com.xjrsoft.common.core.uitls.VoToColumnUtil;
|
||||
import com.xjrsoft.organization.entity.User;
|
||||
import com.xjrsoft.workflow.dto.HistoryChangeDto;
|
||||
import com.xjrsoft.workflow.entity.WorkflowSchemaHistory;
|
||||
import com.xjrsoft.workflow.service.IWorkflowSchemaHistoryService;
|
||||
import com.xjrsoft.workflow.vo.SchemaHistoryListVo;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 流程模板历史记录表 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2022-11-16
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(GlobalConstant.WORKFLOW_MODULE_PREFIX + "/schema-history")
|
||||
@Tag(name = GlobalConstant.WORKFLOW_MODULE_PREFIX + "/schema-history", description = "流程模板历史记录接口")
|
||||
@AllArgsConstructor
|
||||
public class WorkflowSchemaHistoryController {
|
||||
|
||||
private final IWorkflowSchemaHistoryService workflowSchemaHistoryService;
|
||||
|
||||
|
||||
@GetMapping("/list")
|
||||
@Operation(summary = "流程列表(分页)")
|
||||
public R list(@RequestParam Long schemaId) {
|
||||
List<SchemaHistoryListVo> schemaHistoryListVos = workflowSchemaHistoryService.selectJoinList(SchemaHistoryListVo.class,
|
||||
MPJWrappers.<WorkflowSchemaHistory>lambdaJoin()
|
||||
.eq(WorkflowSchemaHistory::getSchemaId, schemaId)
|
||||
.select(WorkflowSchemaHistory::getId)
|
||||
.select(WorkflowSchemaHistory.class, x -> VoToColumnUtil.fieldsToColumns(SchemaHistoryListVo.class).contains(x.getProperty()))
|
||||
.selectAs(User::getName, SchemaHistoryListVo::getCreateUserName)
|
||||
.leftJoin(User.class, User::getId, WorkflowSchemaHistory::getCreateUserId)
|
||||
.orderByAsc(WorkflowSchemaHistory::getVersion)
|
||||
);
|
||||
|
||||
List<SchemaHistoryListVo> listVos = BeanUtil.copyToList(schemaHistoryListVos, SchemaHistoryListVo.class);
|
||||
return R.ok(listVos);
|
||||
}
|
||||
|
||||
@PutMapping("/set-current")
|
||||
@Operation(summary = "更新到此版本")
|
||||
public R change(@Valid @RequestBody HistoryChangeDto dto) {
|
||||
|
||||
return R.ok(workflowSchemaHistoryService.change(dto));
|
||||
}
|
||||
|
||||
@PutMapping("/processChanges")
|
||||
@Operation(summary = "新流程变更")
|
||||
public R processChanges(@Valid @RequestBody HistoryChangeDto dto) {
|
||||
return R.ok(workflowSchemaHistoryService.change(dto));
|
||||
}
|
||||
|
||||
@GetMapping("/preview")
|
||||
@Operation(summary = "历史记录的xml")
|
||||
public R preview(@RequestParam String historyId){
|
||||
WorkflowSchemaHistory history = workflowSchemaHistoryService.getById(historyId);
|
||||
return R.ok(history.getXmlContent());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,96 @@
|
||||
package com.xjrsoft.workflow.controller;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.github.yulichang.toolkit.MPJWrappers;
|
||||
import com.xjrsoft.common.core.constant.GlobalConstant;
|
||||
import com.xjrsoft.common.core.domain.page.PageOutput;
|
||||
import com.xjrsoft.common.core.domain.result.R;
|
||||
import com.xjrsoft.common.core.uitls.VoToColumnUtil;
|
||||
import com.xjrsoft.common.mybatis.utils.ConventPage;
|
||||
import com.xjrsoft.system.entity.Menu;
|
||||
import com.xjrsoft.workflow.dto.AddSpecialMenuDto;
|
||||
import com.xjrsoft.workflow.dto.SpecialMenuPageDto;
|
||||
import com.xjrsoft.workflow.dto.UpdateSpecialMenuDto;
|
||||
import com.xjrsoft.workflow.entity.WorkflowSpecialMenu;
|
||||
import com.xjrsoft.workflow.service.IWorkflowSpecialMenuService;
|
||||
import com.xjrsoft.workflow.vo.SpecialMenuPageVo;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 专项菜单表 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2023-03-20
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(GlobalConstant.WORKFLOW_MODULE_PREFIX + "/special-menu")
|
||||
@Tag(name = GlobalConstant.WORKFLOW_MODULE_PREFIX + "/special-menu", description = "流程专项菜单接口")
|
||||
@AllArgsConstructor
|
||||
public class WorkflowSpecialMenuController {
|
||||
|
||||
private final IWorkflowSpecialMenuService specialMenuService;
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "专项菜单(分页)")
|
||||
public R page(SpecialMenuPageDto dto){
|
||||
//因为多表关联 会有多个表都使用了id字段, 所以必须专门指定主表的Id
|
||||
IPage<SpecialMenuPageVo> page = specialMenuService.selectJoinListPage(ConventPage.getPage(dto), SpecialMenuPageVo.class,
|
||||
MPJWrappers.<WorkflowSpecialMenu>lambdaJoin()
|
||||
.orderByDesc(WorkflowSpecialMenu::getId)
|
||||
.like(StrUtil.isNotBlank(dto.getKeyword()), SpecialMenuPageVo::getName, dto.getKeyword())
|
||||
.or()
|
||||
.like(StrUtil.isNotBlank(dto.getKeyword()), SpecialMenuPageVo::getCode, dto.getKeyword())
|
||||
.or()
|
||||
.like(StrUtil.isNotBlank(dto.getKeyword()), SpecialMenuPageVo::getMenuCode, dto.getKeyword())
|
||||
.or()
|
||||
.like(StrUtil.isNotBlank(dto.getKeyword()), SpecialMenuPageVo::getMenuName, dto.getKeyword())
|
||||
.select(WorkflowSpecialMenu::getId)
|
||||
.select(WorkflowSpecialMenu.class, x -> VoToColumnUtil.fieldsToColumns(SpecialMenuPageVo.class).contains(x.getProperty()))
|
||||
.selectAs(Menu::getName, SpecialMenuPageVo::getMenuName)
|
||||
.selectAs(Menu::getCode, SpecialMenuPageVo::getMenuCode)
|
||||
.leftJoin(Menu.class, Menu::getId, WorkflowSpecialMenu::getMenuId));
|
||||
|
||||
PageOutput<SpecialMenuPageVo> pageOutput = ConventPage.getPageOutput(page);
|
||||
return R.ok(pageOutput);
|
||||
}
|
||||
|
||||
@GetMapping("/info")
|
||||
@Operation(summary = "查询单个详情")
|
||||
public R info(@RequestParam Long id) {
|
||||
return R.ok(specialMenuService.info(id));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "新增专项菜单")
|
||||
public R add(@Valid @RequestBody AddSpecialMenuDto dto) {
|
||||
return R.ok(specialMenuService.add(dto));
|
||||
}
|
||||
|
||||
@PutMapping
|
||||
@Operation(summary = "修改专项菜单")
|
||||
public R update(@Valid @RequestBody UpdateSpecialMenuDto dto) {
|
||||
return R.ok(specialMenuService.update(dto));
|
||||
}
|
||||
|
||||
@DeleteMapping
|
||||
@Operation(summary = "删除专项菜单(可批量)")
|
||||
public R delete(@RequestBody List<Long> ids) {
|
||||
return R.ok(specialMenuService.delete(ids));
|
||||
}
|
||||
|
||||
@GetMapping("/pending")
|
||||
@Operation(summary = "待办任务")
|
||||
public R pending(Map<String,Object> param) {
|
||||
return R.ok(specialMenuService.pending(param));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,481 @@
|
||||
/*
|
||||
* Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
|
||||
* under one or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information regarding copyright
|
||||
* ownership. Camunda licenses this file to you under the Apache License,
|
||||
* Version 2.0; you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.camunda.bpm.engine.history;
|
||||
|
||||
import org.camunda.bpm.engine.ProcessEngineException;
|
||||
import org.camunda.bpm.engine.query.Query;
|
||||
import org.camunda.bpm.engine.task.Task;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* Allows programmatic querying for {@link HistoricTaskInstance}s.
|
||||
*
|
||||
* @author Tom Baeyens
|
||||
*/
|
||||
public interface HistoricTaskInstanceQuery extends Query<HistoricTaskInstanceQuery, HistoricTaskInstance> {
|
||||
|
||||
/** Only select historic task instances for the given task id. */
|
||||
HistoricTaskInstanceQuery taskId(String taskId);
|
||||
|
||||
/** Only select historic task instances for the given process instance. */
|
||||
HistoricTaskInstanceQuery processInstanceId(String processInstanceId);
|
||||
|
||||
/** Only select historic tasks for the given process instance business key */
|
||||
HistoricTaskInstanceQuery processInstanceBusinessKey(String processInstanceBusinessKey);
|
||||
|
||||
/**
|
||||
* Only select historic tasks for any of the given the given process instance business keys.
|
||||
*/
|
||||
HistoricTaskInstanceQuery processInstanceBusinessKeyIn(String... processInstanceBusinessKeys);
|
||||
|
||||
/** Only select historic tasks matching the given process instance business key.
|
||||
* The syntax is that of SQL: for example usage: nameLike(%camunda%)*/
|
||||
HistoricTaskInstanceQuery processInstanceBusinessKeyLike(String processInstanceBusinessKey);
|
||||
|
||||
/** Only select historic task instances for the given execution. */
|
||||
HistoricTaskInstanceQuery executionId(String executionId);
|
||||
|
||||
/** Only select historic task instances which have one of the given activity instance ids. **/
|
||||
HistoricTaskInstanceQuery activityInstanceIdIn(String... activityInstanceIds);
|
||||
|
||||
/** Only select historic task instances for the given process definition. */
|
||||
HistoricTaskInstanceQuery processDefinitionId(String processDefinitionId);
|
||||
|
||||
/**
|
||||
* Only select historic task instances which are part of a (historic) process instance
|
||||
* which has the given process definition key.
|
||||
*/
|
||||
HistoricTaskInstanceQuery processDefinitionKey(String processDefinitionKey);
|
||||
|
||||
/**
|
||||
* Only select historic task instances which are part of a (historic) process instance
|
||||
* which has the given definition name.
|
||||
*/
|
||||
HistoricTaskInstanceQuery processDefinitionName(String processDefinitionName);
|
||||
|
||||
/** Only select historic task instances for the given case definition. */
|
||||
HistoricTaskInstanceQuery caseDefinitionId(String caseDefinitionId);
|
||||
|
||||
/**
|
||||
* Only select historic task instances which are part of a case instance
|
||||
* which has the given case definition key.
|
||||
*/
|
||||
HistoricTaskInstanceQuery caseDefinitionKey(String caseDefinitionKey);
|
||||
|
||||
/**
|
||||
* Only select historic task instances which are part of a (historic) case instance
|
||||
* which has the given case definition name.
|
||||
*/
|
||||
HistoricTaskInstanceQuery caseDefinitionName(String caseDefinitionName);
|
||||
|
||||
/**
|
||||
* Only select historic task instances for the given case instance.
|
||||
*/
|
||||
HistoricTaskInstanceQuery caseInstanceId(String caseInstanceId);
|
||||
|
||||
/**
|
||||
* Only select historic task instances for the given case execution id.
|
||||
*/
|
||||
HistoricTaskInstanceQuery caseExecutionId(String caseExecutionId);
|
||||
|
||||
/**
|
||||
* Only select historic task instances with the given task name.
|
||||
* This is the last name given to the task.
|
||||
* The query will match the names of historic task instances in a case-insensitive way.
|
||||
*/
|
||||
HistoricTaskInstanceQuery taskName(String taskName);
|
||||
|
||||
/**
|
||||
* Only select historic task instances with a task name like the given value.
|
||||
* This is the last name given to the task.
|
||||
* The syntax that should be used is the same as in SQL, eg. %activiti%.
|
||||
* The query will match the names of historic task instances in a case-insensitive way.
|
||||
*/
|
||||
HistoricTaskInstanceQuery taskNameLike(String taskNameLike);
|
||||
|
||||
/**
|
||||
* Only select historic task instances with the given task description.
|
||||
* This is the last description given to the task.
|
||||
* The query will match the descriptions of historic task instances in a case-insensitive way.
|
||||
*/
|
||||
HistoricTaskInstanceQuery taskDescription(String taskDescription);
|
||||
|
||||
/**
|
||||
* Only select historic task instances with a task description like the given value.
|
||||
* This is the last description given to the task.
|
||||
* The syntax that should be used is the same as in SQL, eg. %activiti%.
|
||||
* The query will match the descriptions of historice task instances in a case-insensitive way.
|
||||
*/
|
||||
HistoricTaskInstanceQuery taskDescriptionLike(String taskDescriptionLike);
|
||||
|
||||
/**
|
||||
* Only select historic task instances with the given task definition key.
|
||||
* @see Task#getTaskDefinitionKey()
|
||||
*/
|
||||
HistoricTaskInstanceQuery taskDefinitionKey(String taskDefinitionKey);
|
||||
|
||||
/**
|
||||
* Only select historic task instances with one of the given task definition keys.
|
||||
* @see Task#getTaskDefinitionKey()
|
||||
*/
|
||||
HistoricTaskInstanceQuery taskDefinitionKeyIn(String... taskDefinitionKeys);
|
||||
|
||||
/** Only select historic task instances with the given task delete reason. */
|
||||
HistoricTaskInstanceQuery taskDeleteReason(String taskDeleteReason);
|
||||
|
||||
/**
|
||||
* Only select historic task instances with a task description like the given value.
|
||||
* The syntax that should be used is the same as in SQL, eg. %activiti%.
|
||||
*/
|
||||
HistoricTaskInstanceQuery taskDeleteReasonLike(String taskDeleteReasonLike);
|
||||
|
||||
/** Only select historic task instances with an assignee. */
|
||||
HistoricTaskInstanceQuery taskAssigned();
|
||||
|
||||
/** Only select historic task instances without an assignee. */
|
||||
HistoricTaskInstanceQuery taskUnassigned();
|
||||
|
||||
/**
|
||||
* Only select historic task instances which were last taskAssigned to the given assignee.
|
||||
*/
|
||||
HistoricTaskInstanceQuery taskAssignee(String taskAssignee);
|
||||
|
||||
/**
|
||||
* Only select historic task instances which were last taskAssigned to an assignee like
|
||||
* the given value.
|
||||
* The syntax that should be used is the same as in SQL, eg. %activiti%.
|
||||
*/
|
||||
HistoricTaskInstanceQuery taskAssigneeLike(String taskAssigneeLike);
|
||||
|
||||
/**
|
||||
* Only select historic task instances which have the given owner.
|
||||
*/
|
||||
HistoricTaskInstanceQuery taskOwner(String taskOwner);
|
||||
|
||||
/**
|
||||
* Only select historic task instances which have an owner like the one specified.
|
||||
* The syntax that should be used is the same as in SQL, eg. %activiti%.
|
||||
*/
|
||||
HistoricTaskInstanceQuery taskOwnerLike(String taskOwnerLike);
|
||||
|
||||
/**
|
||||
* Only select historic task instances with the given priority.
|
||||
*/
|
||||
HistoricTaskInstanceQuery taskPriority(Integer taskPriority);
|
||||
|
||||
/**
|
||||
* Only select historic task instances which are finished.
|
||||
*/
|
||||
HistoricTaskInstanceQuery finished();
|
||||
|
||||
/**
|
||||
* Only select historic task instances which aren't finished yet.
|
||||
*/
|
||||
HistoricTaskInstanceQuery unfinished();
|
||||
|
||||
/**
|
||||
* Only select historic task instances which are part of a process
|
||||
* instance which is already finished.
|
||||
*/
|
||||
HistoricTaskInstanceQuery processFinished();
|
||||
|
||||
/**
|
||||
* Only select historic task instances which are part of a process
|
||||
* instance which is not finished yet.
|
||||
*/
|
||||
HistoricTaskInstanceQuery processUnfinished();
|
||||
|
||||
/**
|
||||
* Only select historic task instances which have mapping
|
||||
* with Historic identity links based on user id
|
||||
*
|
||||
* @since 7.5
|
||||
*/
|
||||
HistoricTaskInstanceQuery taskInvolvedUser(String involvedUser);
|
||||
|
||||
/**
|
||||
* Only select historic task instances which have mapping
|
||||
* with Historic identity links based on group id
|
||||
*
|
||||
* @since 7.5
|
||||
*/
|
||||
HistoricTaskInstanceQuery taskInvolvedGroup(String involvedGroup);
|
||||
|
||||
/**
|
||||
* Only select historic task instances which have mapping
|
||||
* with Historic identity links with the condition of user being a candidate
|
||||
*
|
||||
* @since 7.5
|
||||
*/
|
||||
HistoricTaskInstanceQuery taskHadCandidateUser(String candidateUser);
|
||||
|
||||
/**
|
||||
* Only select historic task instances which have mapping
|
||||
* with Historic identity links with the condition of group being a candidate
|
||||
*
|
||||
* @since 7.5
|
||||
*/
|
||||
HistoricTaskInstanceQuery taskHadCandidateGroup(String candidateGroup);
|
||||
|
||||
/** Only select historic task instances which have a candidate group */
|
||||
HistoricTaskInstanceQuery withCandidateGroups();
|
||||
|
||||
/** Only select historic task instances which have no candidate group */
|
||||
HistoricTaskInstanceQuery withoutCandidateGroups();
|
||||
|
||||
/**
|
||||
* The query will match the names of task and process variables in a case-insensitive way.
|
||||
*/
|
||||
HistoricTaskInstanceQuery matchVariableNamesIgnoreCase();
|
||||
|
||||
/**
|
||||
* The query will match the values of task and process variables in a case-insensitive way.
|
||||
*/
|
||||
HistoricTaskInstanceQuery matchVariableValuesIgnoreCase();
|
||||
|
||||
/**
|
||||
* Only select historic task instances which have a local task variable with the
|
||||
* given name set to the given value. Make sure history-level is configured
|
||||
* >= AUDIT when this feature is used.
|
||||
*/
|
||||
HistoricTaskInstanceQuery taskVariableValueEquals(String variableName, Object variableValue);
|
||||
|
||||
/**
|
||||
* Only select historic task instances which have a local task variable with the
|
||||
* given name set to the given value. Make sure history-level is configured
|
||||
* >= AUDIT when this feature is used.
|
||||
*/
|
||||
HistoricTaskInstanceQuery taskVariableValueLike(String variableName, Object variableValue);
|
||||
|
||||
/** Only select subtasks of the given parent task */
|
||||
HistoricTaskInstanceQuery taskParentTaskId(String parentTaskId);
|
||||
|
||||
/**
|
||||
* Only select historic task instances which are part of a process instance which have a variable
|
||||
* with the given name set to the given value. The last variable value in the variable updates
|
||||
* ({@link HistoricDetail}) will be used, so make sure history-level is configured
|
||||
* >= AUDIT when this feature is used.
|
||||
*/
|
||||
HistoricTaskInstanceQuery processVariableValueEquals(String variableName, Object variableValue);
|
||||
|
||||
/**
|
||||
* Only select historic task instances which have a variable with the given name, but
|
||||
* with a different value than the passed value.
|
||||
* Byte-arrays and {@link Serializable} objects (which are not primitive type wrappers)
|
||||
* are not supported.
|
||||
*/
|
||||
HistoricTaskInstanceQuery processVariableValueNotEquals(String variableName, Object variableValue);
|
||||
|
||||
/**
|
||||
* Only select historic task instances which are part of a process that have a variable
|
||||
* with the given name and matching the given value.
|
||||
* The syntax is that of SQL: for example usage: valueLike(%value%)
|
||||
* */
|
||||
HistoricTaskInstanceQuery processVariableValueLike(String variableName, Object variableValue);
|
||||
|
||||
/**
|
||||
* Only select historic task instances which are part of a process that have a variable
|
||||
* with the given name and not matching the given value.
|
||||
* The syntax is that of SQL: for example usage: valueNotLike(%value%)
|
||||
* */
|
||||
HistoricTaskInstanceQuery processVariableValueNotLike(String variableName, Object variableValue);
|
||||
|
||||
/**
|
||||
* Only select historic task instances which are part of a process that have a variable
|
||||
* with the given name and a value greater than the given one.
|
||||
*/
|
||||
HistoricTaskInstanceQuery processVariableValueGreaterThan(String variableName, Object variableValue);
|
||||
|
||||
/**
|
||||
* Only select historic task instances which are part of a process that have a variable
|
||||
* with the given name and a value greater than or equal to the given one.
|
||||
*/
|
||||
HistoricTaskInstanceQuery processVariableValueGreaterThanOrEquals(String variableName, Object variableValue);
|
||||
|
||||
/**
|
||||
* Only select historic task instances which are part of a process that have a variable
|
||||
* with the given name and a value less than the given one.
|
||||
*/
|
||||
HistoricTaskInstanceQuery processVariableValueLessThan(String variableName, Object variableValue);
|
||||
|
||||
/**
|
||||
* Only select historic task instances which are part of a process that have a variable
|
||||
* with the given name and a value less than or equal to the given one.
|
||||
*/
|
||||
HistoricTaskInstanceQuery processVariableValueLessThanOrEquals(String variableName, Object variableValue);
|
||||
|
||||
/**
|
||||
* Only select select historic task instances with the given due date.
|
||||
*/
|
||||
HistoricTaskInstanceQuery taskDueDate(Date dueDate);
|
||||
|
||||
/**
|
||||
* Only select select historic task instances which have a due date before the given date.
|
||||
*/
|
||||
HistoricTaskInstanceQuery taskDueBefore(Date dueDate);
|
||||
|
||||
/**
|
||||
* Only select select historic task instances which have a due date after the given date.
|
||||
*/
|
||||
HistoricTaskInstanceQuery taskDueAfter(Date dueDate);
|
||||
|
||||
/**
|
||||
* Only select select historic task instances that have no due date.
|
||||
*/
|
||||
HistoricTaskInstanceQuery withoutTaskDueDate();
|
||||
|
||||
/**
|
||||
* Only select select historic task instances with the given follow-up date.
|
||||
*/
|
||||
HistoricTaskInstanceQuery taskFollowUpDate(Date followUpDate);
|
||||
|
||||
/**
|
||||
* Only select select historic task instances which have a follow-up date before the given date.
|
||||
*/
|
||||
HistoricTaskInstanceQuery taskFollowUpBefore(Date followUpDate);
|
||||
|
||||
/**
|
||||
* Only select select historic task instances which have a follow-up date after the given date.
|
||||
*/
|
||||
HistoricTaskInstanceQuery taskFollowUpAfter(Date followUpDate);
|
||||
|
||||
/** Only select historic task instances with one of the given tenant ids. */
|
||||
HistoricTaskInstanceQuery tenantIdIn(String... tenantIds);
|
||||
|
||||
/** Only selects historic task instances that have no tenant id. */
|
||||
HistoricTaskInstanceQuery withoutTenantId();
|
||||
|
||||
/**
|
||||
* Only select tasks where end time is after given date
|
||||
*/
|
||||
HistoricTaskInstanceQuery finishedAfter(Date date);
|
||||
|
||||
/**
|
||||
* Only select tasks where end time is before given date
|
||||
*/
|
||||
HistoricTaskInstanceQuery finishedBefore(Date date);
|
||||
|
||||
/**
|
||||
* Only select tasks where started after given date
|
||||
*/
|
||||
HistoricTaskInstanceQuery startedAfter(Date date);
|
||||
|
||||
/**
|
||||
* Only select tasks where started before given date
|
||||
*/
|
||||
HistoricTaskInstanceQuery startedBefore(Date date);
|
||||
|
||||
/**
|
||||
* Order by tenant id (needs to be followed by {@link #asc()} or {@link #desc()}).
|
||||
* Note that the ordering of historic task instances without tenant id is database-specific.
|
||||
*/
|
||||
HistoricTaskInstanceQuery orderByTenantId();
|
||||
|
||||
/** Order by task id (needs to be followed by {@link #asc()} or {@link #desc()}). */
|
||||
HistoricTaskInstanceQuery orderByTaskId();
|
||||
|
||||
/**
|
||||
* Order by the historic activity instance id this task was used in
|
||||
* (needs to be followed by {@link #asc()} or {@link #desc()}).
|
||||
*/
|
||||
HistoricTaskInstanceQuery orderByHistoricActivityInstanceId();
|
||||
|
||||
/** Order by process definition id (needs to be followed by {@link #asc()} or {@link #desc()}). */
|
||||
HistoricTaskInstanceQuery orderByProcessDefinitionId();
|
||||
|
||||
/** Order by process instance id (needs to be followed by {@link #asc()} or {@link #desc()}). */
|
||||
HistoricTaskInstanceQuery orderByProcessInstanceId();
|
||||
|
||||
/** Order by execution id (needs to be followed by {@link #asc()} or {@link #desc()}). */
|
||||
HistoricTaskInstanceQuery orderByExecutionId();
|
||||
|
||||
/** Order by duration (needs to be followed by {@link #asc()} or {@link #desc()}). */
|
||||
HistoricTaskInstanceQuery orderByHistoricTaskInstanceDuration();
|
||||
|
||||
/** Order by end time (needs to be followed by {@link #asc()} or {@link #desc()}). */
|
||||
HistoricTaskInstanceQuery orderByHistoricTaskInstanceEndTime();
|
||||
|
||||
/** Order by start time (needs to be followed by {@link #asc()} or {@link #desc()}). */
|
||||
HistoricTaskInstanceQuery orderByHistoricActivityInstanceStartTime();
|
||||
|
||||
/** Order by task name (needs to be followed by {@link #asc()} or {@link #desc()}). */
|
||||
HistoricTaskInstanceQuery orderByTaskName();
|
||||
|
||||
/** Order by task description (needs to be followed by {@link #asc()} or {@link #desc()}). */
|
||||
HistoricTaskInstanceQuery orderByTaskDescription();
|
||||
|
||||
/** Order by task assignee (needs to be followed by {@link #asc()} or {@link #desc()}). */
|
||||
HistoricTaskInstanceQuery orderByTaskAssignee();
|
||||
|
||||
/** Order by task owner (needs to be followed by {@link #asc()} or {@link #desc()}). */
|
||||
HistoricTaskInstanceQuery orderByTaskOwner();
|
||||
|
||||
/** Order by task due date (needs to be followed by {@link #asc()} or {@link #desc()}). */
|
||||
HistoricTaskInstanceQuery orderByTaskDueDate();
|
||||
|
||||
/** Order by task follow-up date (needs to be followed by {@link #asc()} or {@link #desc()}). */
|
||||
HistoricTaskInstanceQuery orderByTaskFollowUpDate();
|
||||
|
||||
/** Order by task delete reason (needs to be followed by {@link #asc()} or {@link #desc()}). */
|
||||
HistoricTaskInstanceQuery orderByDeleteReason();
|
||||
|
||||
/** Order by task definition key (needs to be followed by {@link #asc()} or {@link #desc()}). */
|
||||
HistoricTaskInstanceQuery orderByTaskDefinitionKey();
|
||||
|
||||
/** Order by task priority key (needs to be followed by {@link #asc()} or {@link #desc()}). */
|
||||
HistoricTaskInstanceQuery orderByTaskPriority();
|
||||
|
||||
/** Order by case definition id (needs to be followed by {@link #asc()} or {@link #desc()}). */
|
||||
HistoricTaskInstanceQuery orderByCaseDefinitionId();
|
||||
|
||||
/** Order by case instance id (needs to be followed by {@link #asc()} or {@link #desc()}). */
|
||||
HistoricTaskInstanceQuery orderByCaseInstanceId();
|
||||
|
||||
/** Order by case execution id (needs to be followed by {@link #asc()} or {@link #desc()}). */
|
||||
HistoricTaskInstanceQuery orderByCaseExecutionId();
|
||||
|
||||
/**
|
||||
* <p>After calling or(), a chain of several filter criteria could follow. Each filter criterion that follows or()
|
||||
* will be linked together with an OR expression until the OR query is terminated. To terminate the OR query right
|
||||
* after the last filter criterion was applied, {@link #endOr()} must be invoked.</p>
|
||||
*
|
||||
* @return an object of the type {@link HistoricTaskInstanceQuery} on which an arbitrary amount of filter criteria could be applied.
|
||||
* The several filter criteria will be linked together by an OR expression.
|
||||
*
|
||||
* @throws ProcessEngineException when or() has been invoked directly after or() or after or() and trailing filter
|
||||
* criteria. To prevent throwing this exception, {@link #endOr()} must be invoked after a chain of filter criteria to
|
||||
* mark the end of the OR query.
|
||||
* */
|
||||
HistoricTaskInstanceQuery or();
|
||||
|
||||
/**
|
||||
* <p>endOr() terminates an OR query on which an arbitrary amount of filter criteria were applied. To terminate the
|
||||
* OR query which has been started by invoking {@link #or()}, endOr() must be invoked. Filter criteria which are
|
||||
* applied after calling endOr() are linked together by an AND expression.</p>
|
||||
*
|
||||
* @return an object of the type {@link HistoricTaskInstanceQuery} on which an arbitrary amount of filter criteria could be applied.
|
||||
* The filter criteria will be linked together by an AND expression.
|
||||
*
|
||||
* @throws ProcessEngineException when endOr() has been invoked before {@link #or()} was invoked. To prevent throwing
|
||||
* this exception, {@link #or()} must be invoked first.
|
||||
* */
|
||||
HistoricTaskInstanceQuery endOr();
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,33 @@
|
||||
package com.xjrsoft.workflow.listener;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.camunda.bpm.engine.impl.bpmn.parser.BpmnParseListener;
|
||||
import org.camunda.bpm.engine.impl.cfg.AbstractProcessEnginePlugin;
|
||||
import org.camunda.bpm.engine.impl.cfg.ProcessEngineConfigurationImpl;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author: tzx
|
||||
* @Date: 2022/10/11 14:27
|
||||
*/
|
||||
@Component
|
||||
@AllArgsConstructor
|
||||
public class CamundaGlobalPlugin extends AbstractProcessEnginePlugin {
|
||||
|
||||
private final NewListener newListener;
|
||||
|
||||
@Override
|
||||
public void preInit(ProcessEngineConfigurationImpl processEngineConfiguration) {
|
||||
List<BpmnParseListener> listeners = processEngineConfiguration.getCustomPreBPMNParseListeners();
|
||||
if(listeners == null){
|
||||
listeners = new ArrayList<>();
|
||||
processEngineConfiguration.setCustomPreBPMNParseListeners(listeners);
|
||||
}
|
||||
// listeners.add(new CamundaGlobalListener());
|
||||
listeners.add(newListener);
|
||||
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,286 @@
|
||||
package com.xjrsoft.workflow.listener;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.camunda.bpm.engine.delegate.ExecutionListener;
|
||||
import org.camunda.bpm.engine.delegate.TaskListener;
|
||||
import org.camunda.bpm.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
|
||||
import org.camunda.bpm.engine.impl.bpmn.parser.AbstractBpmnParseListener;
|
||||
import org.camunda.bpm.engine.impl.persistence.entity.ProcessDefinitionEntity;
|
||||
import org.camunda.bpm.engine.impl.pvm.process.ActivityImpl;
|
||||
import org.camunda.bpm.engine.impl.pvm.process.ScopeImpl;
|
||||
import org.camunda.bpm.engine.impl.pvm.process.TransitionImpl;
|
||||
import org.camunda.bpm.engine.impl.task.TaskDefinition;
|
||||
import org.camunda.bpm.engine.impl.util.xml.Element;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author: tzx
|
||||
* @Date: 2022/12/7 16:24
|
||||
*/
|
||||
@Component
|
||||
@AllArgsConstructor
|
||||
public class NewListener extends AbstractBpmnParseListener {
|
||||
|
||||
private final ExecutionDelegate EXECUTION_LISTENER;
|
||||
|
||||
private final TaskDelegate TASK_LISTENER;
|
||||
|
||||
|
||||
// public final static ExecutionListener EXECUTION_LISTENER = new ExecutionDelegate();
|
||||
// public final static TaskListener TASK_LISTENER = new TaskDelegate();
|
||||
|
||||
protected void addEndEventListener(ScopeImpl activity) {
|
||||
activity.addListener(ExecutionListener.EVENTNAME_END, EXECUTION_LISTENER);
|
||||
}
|
||||
|
||||
protected void addStartEventListener(ScopeImpl activity) {
|
||||
activity.addListener(ExecutionListener.EVENTNAME_START, EXECUTION_LISTENER);
|
||||
}
|
||||
|
||||
|
||||
protected void addTakeEventListener(TransitionImpl transition) {
|
||||
transition.addListener(ExecutionListener.EVENTNAME_TAKE, EXECUTION_LISTENER);
|
||||
|
||||
}
|
||||
|
||||
protected void addTransitionStartEventListener(TransitionImpl transition) {
|
||||
transition.addListener(ExecutionListener.EVENTNAME_START, EXECUTION_LISTENER);
|
||||
|
||||
}
|
||||
|
||||
protected void addTransitionEndEventListener(TransitionImpl transition) {
|
||||
transition.addListener(ExecutionListener.EVENTNAME_END, EXECUTION_LISTENER);
|
||||
|
||||
}
|
||||
|
||||
protected void addTaskAssignmentListeners(TaskDefinition taskDefinition) {
|
||||
taskDefinition.addTaskListener(TaskListener.EVENTNAME_ASSIGNMENT, TASK_LISTENER);
|
||||
}
|
||||
|
||||
protected void addTaskCreateListeners(TaskDefinition taskDefinition) {
|
||||
taskDefinition.addTaskListener(TaskListener.EVENTNAME_CREATE, TASK_LISTENER);
|
||||
}
|
||||
|
||||
protected void addTaskCompleteListeners(TaskDefinition taskDefinition) {
|
||||
taskDefinition.addTaskListener(TaskListener.EVENTNAME_COMPLETE, TASK_LISTENER);
|
||||
}
|
||||
|
||||
protected void addTaskUpdateListeners(TaskDefinition taskDefinition) {
|
||||
taskDefinition.addTaskListener(TaskListener.EVENTNAME_UPDATE, TASK_LISTENER);
|
||||
}
|
||||
|
||||
protected void addTaskDeleteListeners(TaskDefinition taskDefinition) {
|
||||
taskDefinition.addTaskListener(TaskListener.EVENTNAME_DELETE, TASK_LISTENER);
|
||||
}
|
||||
|
||||
// BpmnParseListener implementation
|
||||
// /
|
||||
|
||||
@Override
|
||||
public void parseProcess(Element processElement, ProcessDefinitionEntity processDefinition) {
|
||||
addStartEventListener(processDefinition);
|
||||
addEndEventListener(processDefinition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseStartEvent(Element startEventElement, ScopeImpl scope, ActivityImpl startEventActivity) {
|
||||
addStartEventListener(startEventActivity);
|
||||
addEndEventListener(startEventActivity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseExclusiveGateway(Element exclusiveGwElement, ScopeImpl scope, ActivityImpl activity) {
|
||||
addStartEventListener(activity);
|
||||
addEndEventListener(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseInclusiveGateway(Element inclusiveGwElement, ScopeImpl scope, ActivityImpl activity) {
|
||||
addStartEventListener(activity);
|
||||
addEndEventListener(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseParallelGateway(Element parallelGwElement, ScopeImpl scope, ActivityImpl activity) {
|
||||
addStartEventListener(activity);
|
||||
addEndEventListener(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseScriptTask(Element scriptTaskElement, ScopeImpl scope, ActivityImpl activity) {
|
||||
addStartEventListener(activity);
|
||||
addEndEventListener(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseServiceTask(Element serviceTaskElement, ScopeImpl scope, ActivityImpl activity) {
|
||||
addStartEventListener(activity);
|
||||
addEndEventListener(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseBusinessRuleTask(Element businessRuleTaskElement, ScopeImpl scope, ActivityImpl activity) {
|
||||
addStartEventListener(activity);
|
||||
addEndEventListener(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseTask(Element taskElement, ScopeImpl scope, ActivityImpl activity) {
|
||||
addStartEventListener(activity);
|
||||
addEndEventListener(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseManualTask(Element manualTaskElement, ScopeImpl scope, ActivityImpl activity) {
|
||||
addStartEventListener(activity);
|
||||
addEndEventListener(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseUserTask(Element userTaskElement, ScopeImpl scope, ActivityImpl activity) {
|
||||
addStartEventListener(activity);
|
||||
addEndEventListener(activity);
|
||||
UserTaskActivityBehavior activityBehavior = (UserTaskActivityBehavior) activity.getActivityBehavior();
|
||||
TaskDefinition taskDefinition = activityBehavior.getTaskDefinition();
|
||||
addTaskCreateListeners(taskDefinition);
|
||||
addTaskAssignmentListeners(taskDefinition);
|
||||
addTaskCompleteListeners(taskDefinition);
|
||||
addTaskUpdateListeners(taskDefinition);
|
||||
addTaskDeleteListeners(taskDefinition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseEndEvent(Element endEventElement, ScopeImpl scope, ActivityImpl activity) {
|
||||
addStartEventListener(activity);
|
||||
addEndEventListener(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseBoundaryTimerEventDefinition(Element timerEventDefinition, boolean interrupting, ActivityImpl timerActivity) {
|
||||
// start and end event listener are set by parseBoundaryEvent()
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseBoundaryErrorEventDefinition(Element errorEventDefinition, boolean interrupting, ActivityImpl activity, ActivityImpl nestedErrorEventActivity) {
|
||||
// start and end event listener are set by parseBoundaryEvent()
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseSubProcess(Element subProcessElement, ScopeImpl scope, ActivityImpl activity) {
|
||||
addStartEventListener(activity);
|
||||
addEndEventListener(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseCallActivity(Element callActivityElement, ScopeImpl scope, ActivityImpl activity) {
|
||||
addStartEventListener(activity);
|
||||
addEndEventListener(activity);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void parseSequenceFlow(Element sequenceFlowElement, ScopeImpl scopeElement, TransitionImpl transition) {
|
||||
addTakeEventListener(transition);
|
||||
addTransitionStartEventListener(transition);
|
||||
addTransitionEndEventListener(transition);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void parseSendTask(Element sendTaskElement, ScopeImpl scope, ActivityImpl activity) {
|
||||
addStartEventListener(activity);
|
||||
addEndEventListener(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseMultiInstanceLoopCharacteristics(Element activityElement, Element multiInstanceLoopCharacteristicsElement, ActivityImpl activity) {
|
||||
addStartEventListener(activity);
|
||||
addEndEventListener(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseRootElement(Element rootElement, List<ProcessDefinitionEntity> processDefinitions) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseIntermediateTimerEventDefinition(Element timerEventDefinition, ActivityImpl timerActivity) {
|
||||
// start and end event listener are set by parseIntermediateCatchEvent()
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseReceiveTask(Element receiveTaskElement, ScopeImpl scope, ActivityImpl activity) {
|
||||
addStartEventListener(activity);
|
||||
addEndEventListener(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseIntermediateSignalCatchEventDefinition(Element signalEventDefinition, ActivityImpl signalActivity) {
|
||||
// start and end event listener are set by parseIntermediateCatchEvent()
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseBoundarySignalEventDefinition(Element signalEventDefinition, boolean interrupting, ActivityImpl signalActivity) {
|
||||
// start and end event listener are set by parseBoundaryEvent()
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseEventBasedGateway(Element eventBasedGwElement, ScopeImpl scope, ActivityImpl activity) {
|
||||
addStartEventListener(activity);
|
||||
addEndEventListener(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseTransaction(Element transactionElement, ScopeImpl scope, ActivityImpl activity) {
|
||||
addStartEventListener(activity);
|
||||
addEndEventListener(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseCompensateEventDefinition(Element compensateEventDefinition, ActivityImpl compensationActivity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseIntermediateThrowEvent(Element intermediateEventElement, ScopeImpl scope, ActivityImpl activity) {
|
||||
addStartEventListener(activity);
|
||||
addEndEventListener(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseIntermediateCatchEvent(Element intermediateEventElement, ScopeImpl scope, ActivityImpl activity) {
|
||||
addStartEventListener(activity);
|
||||
addEndEventListener(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseBoundaryEvent(Element boundaryEventElement, ScopeImpl scopeElement, ActivityImpl activity) {
|
||||
addStartEventListener(activity);
|
||||
addEndEventListener(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseIntermediateMessageCatchEventDefinition(Element messageEventDefinition, ActivityImpl nestedActivity) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseBoundaryMessageEventDefinition(Element element, boolean interrupting, ActivityImpl messageActivity) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseBoundaryEscalationEventDefinition(Element escalationEventDefinition, boolean interrupting, ActivityImpl boundaryEventActivity) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseBoundaryConditionalEventDefinition(Element element, boolean interrupting, ActivityImpl conditionalActivity) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseIntermediateConditionalEventDefinition(Element conditionalEventDefinition, ActivityImpl conditionalActivity) {
|
||||
}
|
||||
|
||||
public void parseConditionalStartEventForEventSubprocess(Element element, ActivityImpl conditionalActivity, boolean interrupting) {
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,540 @@
|
||||
package com.xjrsoft.workflow.listener;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.lang.TypeReference;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.xjrsoft.common.core.constant.GlobalConstant;
|
||||
import com.xjrsoft.common.core.enums.*;
|
||||
import com.xjrsoft.common.redis.service.RedisUtil;
|
||||
import com.xjrsoft.organization.client.IUserClient;
|
||||
import com.xjrsoft.organization.entity.User;
|
||||
import com.xjrsoft.organization.entity.UserRoleRelation;
|
||||
import com.xjrsoft.workflow.constant.WorkflowConstant;
|
||||
import com.xjrsoft.workflow.entity.*;
|
||||
import com.xjrsoft.workflow.model.NoticePolicyParam;
|
||||
import com.xjrsoft.workflow.model.TimeoutRemidConfig;
|
||||
import com.xjrsoft.workflow.model.UserTaskConfig;
|
||||
import com.xjrsoft.workflow.model.WorkflowSchemaConfig;
|
||||
import com.xjrsoft.workflow.service.*;
|
||||
import com.xjrsoft.workflow.utils.WorkFlowUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.camunda.bpm.engine.RuntimeService;
|
||||
import org.camunda.bpm.engine.TaskService;
|
||||
import org.camunda.bpm.engine.delegate.DelegateTask;
|
||||
import org.camunda.bpm.engine.delegate.TaskListener;
|
||||
import org.camunda.bpm.engine.task.Task;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 任务监听器
|
||||
*
|
||||
* @Author: tzx
|
||||
* @Date: 2022/12/7 16:28
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
public class TaskDelegate implements TaskListener {
|
||||
|
||||
private final RedisUtil redisUtil;
|
||||
|
||||
private final IWorkflowDelegateService workflowDelegateService;
|
||||
|
||||
private final IWorkflowCirculatedService circulatedService;
|
||||
|
||||
private final IUserClient userClient;
|
||||
|
||||
private Map<String,ScriptEngine> scriptEngineMap;
|
||||
|
||||
|
||||
// private final IWorkflowSchemaService workflowSchemaService;
|
||||
|
||||
@Override
|
||||
public void notify(DelegateTask delegateTask) {
|
||||
//判断事件类型 如果是创建 (如果是单元测试代码 需要注释此代码)
|
||||
if (delegateTask.getEventName().equals(EVENTNAME_CREATE)) {
|
||||
log.info("[用户任务监听器] 事件: {}", delegateTask.getEventName());
|
||||
|
||||
List<String> variableNames = ListUtil.toList(
|
||||
WorkflowConstant.PROCESS_SCHEMA_ID_KEY,
|
||||
WorkflowConstant.PROCESS_SCHEMA_NAME_KEY,
|
||||
WorkflowConstant.PROCESS_START_USER_ID_KEY,
|
||||
WorkflowConstant.PROCESS_START_USER_NAME_KEY,
|
||||
WorkflowConstant.PROCESS_SERIAL_NUMBER_KEY,
|
||||
WorkflowConstant.PROCESS_NAME);
|
||||
|
||||
RuntimeService runtimeService = delegateTask.getProcessEngine().getRuntimeService();
|
||||
|
||||
Map<String, Object> variableMaps = runtimeService.getVariables(delegateTask.getProcessInstanceId(), variableNames);
|
||||
|
||||
IWorkflowSchemaService workflowSchemaService = SpringUtil.getBean(IWorkflowSchemaService.class);
|
||||
WorkflowSchema workflowSchema = workflowSchemaService.getOne(Wrappers.lambdaQuery(WorkflowSchema.class).eq(WorkflowSchema::getId, MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_SCHEMA_ID_KEY)));
|
||||
// WorkflowSchema workflowSchema = redisUtil.get(WorkflowConstant.SCHEMA_CACHE_PREFIX + MapUtil.getStr(variableMaps, WorkflowConstant.PROCESS_SCHEMA_ID_KEY), WorkflowSchema.class);
|
||||
|
||||
if (workflowSchema == null) {
|
||||
workflowSchema = workflowSchemaService.getById(MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_SCHEMA_ID_KEY));
|
||||
}
|
||||
WorkflowSchemaConfig workflowSchemaConfig = JSONUtil.toBean(workflowSchema.getJsonContent(), WorkflowSchemaConfig.class);
|
||||
|
||||
Optional<Map<String, Object>> userTaskConfigOp = workflowSchemaConfig.getChildNodeConfig().stream().filter(c -> c.containsValue(delegateTask.getTaskDefinitionKey())).findFirst();
|
||||
|
||||
if (!userTaskConfigOp.isPresent()) {
|
||||
return;
|
||||
}
|
||||
//将map 转为 java类
|
||||
UserTaskConfig userTaskConfig = Convert.convert(UserTaskConfig.class, userTaskConfigOp.get());
|
||||
|
||||
//设置超时提醒
|
||||
setTimeoutRemid(delegateTask, workflowSchemaConfig, userTaskConfig);
|
||||
|
||||
//多实例任务 会在 流程线 执行监听器 就设置了人员List 会自动生成审批人变量
|
||||
initApproveUser(delegateTask, workflowSchemaConfig, userTaskConfig, variableMaps);
|
||||
|
||||
//设置自定义任务名称规则
|
||||
setProcessExtra(delegateTask, variableMaps, workflowSchema, workflowSchemaConfig, userTaskConfig);
|
||||
|
||||
|
||||
}
|
||||
|
||||
//如果是审批事件 判断当前任务 是否有按钮事件
|
||||
if(delegateTask.getEventName().equals(EVENTNAME_COMPLETE)){
|
||||
|
||||
if(redisUtil.containsKey(WorkflowConstant.BUTTON_EVENT_CACHE_PRE + delegateTask.getId())){
|
||||
Map<String, Object> map = redisUtil.get(WorkflowConstant.BUTTON_EVENT_CACHE_PRE + delegateTask.getId(), new TypeReference<Map<String, Object>>() {
|
||||
});
|
||||
Integer language = MapUtil.get(map, "language", Integer.class);
|
||||
String content = MapUtil.get(map, "content", String.class);
|
||||
|
||||
String scriptvar = "execution";
|
||||
|
||||
ScriptEngine scriptEngine;
|
||||
|
||||
if (ObjectUtil.isNotEmpty(language) && StrUtil.isNotBlank(content)){
|
||||
if(language == 0){
|
||||
String JAVA_SCRIPT = "js";
|
||||
if(scriptEngineMap.containsKey(JAVA_SCRIPT)){
|
||||
scriptEngine = scriptEngineMap.get(JAVA_SCRIPT);
|
||||
}
|
||||
else {
|
||||
scriptEngine = new ScriptEngineManager().getEngineByName(JAVA_SCRIPT);
|
||||
scriptEngineMap.put(JAVA_SCRIPT,scriptEngine);
|
||||
}
|
||||
}
|
||||
else{
|
||||
String GROOVY = "groovy";
|
||||
if(scriptEngineMap.containsKey(GROOVY)){
|
||||
scriptEngine = scriptEngineMap.get(GROOVY);
|
||||
}
|
||||
else {
|
||||
scriptEngine = new ScriptEngineManager().getEngineByName(GROOVY);
|
||||
scriptEngineMap.put(GROOVY,scriptEngine);
|
||||
}
|
||||
}
|
||||
|
||||
// 方式一,默认设置变量
|
||||
scriptEngine.put(scriptvar, delegateTask);
|
||||
|
||||
try {
|
||||
|
||||
redisUtil.delete(WorkflowConstant.BUTTON_EVENT_CACHE_PRE + delegateTask.getId());
|
||||
scriptEngine.eval(content);
|
||||
|
||||
}
|
||||
catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
else {
|
||||
redisUtil.delete(WorkflowConstant.BUTTON_EVENT_CACHE_PRE + delegateTask.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置用户传阅人
|
||||
*
|
||||
* @param delegateTask
|
||||
* @param variableMaps
|
||||
* @param workflowSchemaConfig
|
||||
* @param userTaskConfig
|
||||
*/
|
||||
private void initCirculatedUser(DelegateTask delegateTask, Map<String, Object> variableMaps, WorkflowSchemaConfig workflowSchemaConfig, UserTaskConfig userTaskConfig, Long id) {
|
||||
if (userTaskConfig.getCirculateConfigs() == null) {
|
||||
return;
|
||||
}
|
||||
//获取到用户节点的传阅人
|
||||
List<Long> nextUserTaskCirculated = WorkFlowUtil.getUserIdsByMemberConfig(userTaskConfig.getCirculateConfigs(), workflowSchemaConfig.getChildNodeConfig(),delegateTask.getProcessInstanceId());
|
||||
|
||||
//多实例流程不记录传阅人消息
|
||||
if (userTaskConfig.getCountersignConfig().getMultipleInstancesType() == WorkflowMultiInstanceType.NONE.getCode()) {
|
||||
List<WorkflowCirculated> circulatedList = new ArrayList<>();
|
||||
for (Long userId : nextUserTaskCirculated) {
|
||||
WorkflowCirculated workflowCirculated = new WorkflowCirculated();
|
||||
workflowCirculated.setProcessId(delegateTask.getProcessInstanceId());
|
||||
workflowCirculated.setCreateTime(DateUtil.toLocalDateTime(delegateTask.getCreateTime()));
|
||||
workflowCirculated.setTaskId(delegateTask.getId());
|
||||
workflowCirculated.setCurrentProgress(userTaskConfig.getCurrentProgress());
|
||||
workflowCirculated.setTaskName(delegateTask.getName());
|
||||
workflowCirculated.setIsRead(YesOrNoEnum.NO.getCode());
|
||||
workflowCirculated.setProcessName(MapUtil.getStr(variableMaps, WorkflowConstant.PROCESS_NAME));
|
||||
workflowCirculated.setSchemaId(MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_SCHEMA_ID_KEY));
|
||||
workflowCirculated.setCirculatedUserId(userId);
|
||||
workflowCirculated.setStartUserId(MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_START_USER_ID_KEY));
|
||||
workflowCirculated.setSerialNumber(MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_SERIAL_NUMBER_KEY));
|
||||
circulatedList.add(workflowCirculated);
|
||||
|
||||
}
|
||||
|
||||
NoticePolicyParam param = new NoticePolicyParam();
|
||||
param.setNoticeUserIds(nextUserTaskCirculated);
|
||||
param.setTaskId(delegateTask.getId());
|
||||
param.setTaskName(delegateTask.getName());
|
||||
param.setProcessId(delegateTask.getProcessInstanceId());
|
||||
param.setTaskName(delegateTask.getName());
|
||||
param.setSchemaId(MapUtil.get(variableMaps, WorkflowConstant.PROCESS_SCHEMA_ID_KEY, Long.class));
|
||||
param.setSchemaName(MapUtil.get(variableMaps, WorkflowConstant.PROCESS_SCHEMA_NAME_KEY, String.class));
|
||||
param.setStartUserName(MapUtil.get(variableMaps, WorkflowConstant.PROCESS_START_USER_NAME_KEY, String.class));
|
||||
param.setNoticePolicyConfigs(userTaskConfig.getNoticePolicyConfigs());
|
||||
WorkFlowUtil.sendCirculatedNoticePolicy(param,delegateTask.getName());
|
||||
|
||||
circulatedService.saveBatch(circulatedList);
|
||||
}
|
||||
//当前传阅人[所有传阅人名称]
|
||||
String circulatedName = WorkFlowUtil.getAllUserNamesByIds(nextUserTaskCirculated);
|
||||
//如果当前传阅人不为空,就给上面那条准备审批信息中间加上传阅人信息
|
||||
if (StrUtil.isNotBlank(circulatedName)) {
|
||||
IWorkflowRecordService workflowRecordService = SpringUtil.getBean(IWorkflowRecordService.class);
|
||||
WorkflowRecord record = new WorkflowRecord();
|
||||
record.setId(id);
|
||||
record.setCirculateMessage("当前传阅人【" + circulatedName + "】");
|
||||
workflowRecordService.updateById(record);
|
||||
}
|
||||
// addProcessRecord(delegateTask, MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_SCHEMA_ID_KEY), "当前传阅人【"+circulatedName+"】");
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置审批人
|
||||
* 然后 判断是否自动通过
|
||||
* 新增 流程记录
|
||||
*
|
||||
* @param delegateTask
|
||||
* @param workflowSchemaConfig
|
||||
* @param userTaskConfig
|
||||
* @return 是否指定审批人
|
||||
*/
|
||||
private void initApproveUser(DelegateTask delegateTask, WorkflowSchemaConfig workflowSchemaConfig, UserTaskConfig userTaskConfig, Map<String, Object> variableMaps) {
|
||||
TaskService taskService = delegateTask.getProcessEngine().getTaskService();
|
||||
taskService.setVariableLocal(delegateTask.getId(), WorkflowConstant.TASK_IS_APPOINT_APPROVE, YesOrNoEnum.NO.getCode());
|
||||
|
||||
|
||||
Long schemaId = MapUtil.get(variableMaps, WorkflowConstant.PROCESS_SCHEMA_ID_KEY, Long.class);
|
||||
|
||||
List<Long> approveUserIds = new ArrayList<>();
|
||||
|
||||
// 如果是单实例
|
||||
if (userTaskConfig.getCountersignConfig().getMultipleInstancesType() == WorkflowMultiInstanceType.NONE.getCode()) {
|
||||
|
||||
//获取到所有审批人
|
||||
approveUserIds = WorkFlowUtil.getUserIdsByMemberConfig(userTaskConfig.getApproverConfigs(), workflowSchemaConfig.getChildNodeConfig(),delegateTask.getProcessInstanceId());
|
||||
|
||||
//如果节点设置了指定审批人 就不再走无对应处理人逻辑
|
||||
if (userTaskConfig.getIsPrevChooseNext() == WorkflowIsPrevChooseNextType.PREV.getCode()) {
|
||||
taskService.setVariableLocal(delegateTask.getId(), WorkflowConstant.TASK_ASSIGNEE_VAR_KEY, StrUtil.join(StringPool.COMMA, approveUserIds));
|
||||
return;
|
||||
}
|
||||
|
||||
//如果全局设置了指定审批人 就不再走无对应处理人逻辑
|
||||
if (workflowSchemaConfig.getProcessConfig().getIsPrevChooseNext() == WorkflowIsPrevChooseNextType.PREV.getCode()) {
|
||||
taskService.setVariableLocal(delegateTask.getId(), WorkflowConstant.TASK_ASSIGNEE_VAR_KEY, StrUtil.join(StringPool.COMMA, approveUserIds));
|
||||
return;
|
||||
}
|
||||
|
||||
//无对应处理人
|
||||
if (userTaskConfig.getApproverConfigs().size() == 0 || approveUserIds.size() == 0) {
|
||||
|
||||
//如果节点配置了 无对应处理人 为admin 默认覆盖 全局设置
|
||||
if (userTaskConfig.getNoHandler() == WorkflowNoHandlerType.ADMIN.getCode()) {
|
||||
List<UserRoleRelation> userRoleRelations = redisUtil.get(GlobalConstant.USER_ROLE_RELATION_CACHE_KEY, new TypeReference<List<UserRoleRelation>>() {
|
||||
});
|
||||
//获取超级管理员成员
|
||||
List<Long> adminUserIds = userRoleRelations.stream().filter(x -> x.getRoleId().equals(GlobalConstant.SUPER_ADMIN_ROLE_ID)).map(UserRoleRelation::getUserId).collect(Collectors.toList());
|
||||
//根据用户id获取对应的用户名,并进行拼接输出(张三、李四这种)
|
||||
approveUserIds = adminUserIds;
|
||||
taskService.setVariableLocal(delegateTask.getId(), WorkflowConstant.TASK_ASSIGNEE_VAR_KEY, StrUtil.join(StringPool.COMMA, adminUserIds));
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
//根据所选审批人 找到审批人 新增到 所选审批人中。
|
||||
setUserDelegate(delegateTask, schemaId, approveUserIds);
|
||||
taskService.setVariableLocal(delegateTask.getId(), WorkflowConstant.TASK_ASSIGNEE_VAR_KEY, StrUtil.join(StringPool.COMMA, approveUserIds));
|
||||
|
||||
}
|
||||
}
|
||||
//多实例 不可能没有处理人 因为多实例如果不设置处理人 不会生成task 但是会需要判断是否自动同意
|
||||
else {
|
||||
|
||||
//如果有这个key 就是代表 会签节点有设置过审批人id
|
||||
if(redisUtil.containsKey(WorkflowConstant.MULTI_ASSIGNEE_CACHE_PREFIX + delegateTask.getExecutionId())){
|
||||
String approveId = redisUtil.get(WorkflowConstant.MULTI_ASSIGNEE_CACHE_PREFIX + delegateTask.getExecutionId());
|
||||
approveUserIds.add(Convert.toLong(approveId));
|
||||
taskService.setVariableLocal(delegateTask.getId(), WorkflowConstant.TASK_ASSIGNEE_VAR_KEY, approveId);
|
||||
redisUtil.delete(delegateTask.getExecutionId());
|
||||
}
|
||||
}
|
||||
String approveName = WorkFlowUtil.getAllUserNamesByIds(approveUserIds);
|
||||
Long recordId = addProcessRecord(delegateTask, schemaId, "【" + approveName + "】" + "准备审批");
|
||||
//设置用户传阅人
|
||||
initCirculatedUser(delegateTask, variableMaps, workflowSchemaConfig, userTaskConfig, recordId);
|
||||
//默认所有任务不需要指定审批人 如果需要指定审批人 会在 launch 和 approve 接口 处理。
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据所选审批人 找到委托人 新增到 所选审批人中。
|
||||
*
|
||||
* @param schemaId
|
||||
* @param approveUserIds
|
||||
*/
|
||||
private void setUserDelegate(DelegateTask delegateTask, Long schemaId, List<Long> approveUserIds) {
|
||||
//查询下一个节点审批人 委托 数据 将被委托人加入到 审批人数据中
|
||||
LambdaQueryWrapper<WorkflowDelegate> wrapper = Wrappers.lambdaQuery(WorkflowDelegate.class)
|
||||
.in(WorkflowDelegate::getUserId, approveUserIds)
|
||||
.lt(WorkflowDelegate::getStartTime, DateUtil.parse(DateUtil.now()).toJdkDate())
|
||||
.gt(WorkflowDelegate::getEndTime, DateUtil.parse(DateUtil.now()).toJdkDate())
|
||||
.like(WorkflowDelegate::getSchemaIds, schemaId)
|
||||
.select(WorkflowDelegate::getDelegateUserIds);
|
||||
List<WorkflowDelegate> workflowDelegates = workflowDelegateService.list(wrapper);
|
||||
|
||||
if (workflowDelegates.size() > 0) {
|
||||
|
||||
List<String> allDelegateStr = workflowDelegates.stream().map(WorkflowDelegate::getDelegateUserIds).collect(Collectors.toList());
|
||||
|
||||
List<Long> allDelegateUserIds = Arrays.stream(StrUtil.join(StringPool.COMMA, allDelegateStr).split(StringPool.COMMA)).map(Convert::toLong).collect(Collectors.toList());
|
||||
approveUserIds.addAll(allDelegateUserIds);
|
||||
|
||||
//新增流程发起流程记录
|
||||
//获取当前用户的信息
|
||||
User user = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_INFO_KEY, new User());
|
||||
//根据用户id获取对应的用户名,并进行拼接输出
|
||||
String allDelegateUserNames = WorkFlowUtil.getAllUserNamesByIds(allDelegateUserIds);
|
||||
//[操作人名称]通过[流程委托]委托[被委托人名称]作为审批人
|
||||
String message = "【" + user.getName() + "】通过【流程委托】委托【" + allDelegateUserNames + "】作为审批人";
|
||||
addProcessRecord(delegateTask, schemaId, message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否自动同意
|
||||
*
|
||||
* @param delegateTask
|
||||
*/
|
||||
private void setAutoAgree(DelegateTask delegateTask, WorkflowSchemaConfig workflowSchemaConfig, Long schemaId, List<Long> approveUserIds) {
|
||||
|
||||
List<Integer> autoAgreeRule = workflowSchemaConfig.getProcessConfig().getAutoAgreeRule();
|
||||
|
||||
TaskService taskService = delegateTask.getProcessEngine().getTaskService();
|
||||
//如果没有配置过 默认跳过
|
||||
if (autoAgreeRule != null && autoAgreeRule.size() > 0) {
|
||||
|
||||
User user = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_INFO_KEY, new User());
|
||||
|
||||
//新增流程发起流程记录
|
||||
String opinion = StringPool.EMPTY;
|
||||
|
||||
//候选审批人包含流程任务发起人
|
||||
if (autoAgreeRule.contains(WorkflowAutoAgreeType.APPROVED_INCLUDE_INITIATOR.getCode())) {
|
||||
//模板id
|
||||
Object startUserId = delegateTask.getVariable(WorkflowConstant.PROCESS_START_USER_ID_KEY);
|
||||
if (approveUserIds.contains(Convert.toLong(startUserId))) {
|
||||
|
||||
taskService.createComment(delegateTask.getId(), delegateTask.getProcessInstanceId(), "候选审批人包含流程任务发起人---自动同意");
|
||||
taskService.complete(delegateTask.getId());
|
||||
|
||||
opinion = "候选审批人包含流程任务发起人";
|
||||
}
|
||||
}
|
||||
//候选审批人包含上一节点审批人
|
||||
if (autoAgreeRule.contains(WorkflowAutoAgreeType.APPROVED_INCLUDE_PREV.getCode())) {
|
||||
//当前操作人 就是上一结点审批人
|
||||
if (approveUserIds.contains(StpUtil.getLoginIdAsLong())) {
|
||||
taskService.createComment(delegateTask.getId(), delegateTask.getProcessInstanceId(), "候选审批人包含上一节点审批人---自动同意");
|
||||
taskService.complete(delegateTask.getId());
|
||||
|
||||
opinion = "候选审批人包含上一节点审批人";
|
||||
}
|
||||
}
|
||||
//候选审批人在此流程中审批过
|
||||
if (autoAgreeRule.contains(WorkflowAutoAgreeType.APPROVED_IN_PROCESS.getCode())) {
|
||||
//模板id
|
||||
Object startUserId = delegateTask.getVariable(WorkflowConstant.PROCESS_START_USER_ID_KEY);
|
||||
|
||||
|
||||
if (approveUserIds.contains(Convert.toLong(startUserId))) {
|
||||
taskService.createComment(delegateTask.getId(), delegateTask.getProcessInstanceId(), "候选审批人在此流程中审批过---自动同意");
|
||||
taskService.complete(delegateTask.getId());
|
||||
} else {
|
||||
if (redisUtil.containsKey(WorkflowConstant.TASK_ASSIGNEE_RECORD_VAR_KEY)) {
|
||||
Map<String, List<Long>> taskAssigneeRecordMap = redisUtil.get(WorkflowConstant.TASK_ASSIGNEE_RECORD_VAR_KEY, new TypeReference<Map<String, List<Long>>>() {
|
||||
});
|
||||
|
||||
for (String taskId : taskAssigneeRecordMap.keySet()) {
|
||||
List<Long> userIds = taskAssigneeRecordMap.get(taskId);
|
||||
|
||||
if (userIds.retainAll(approveUserIds)) {
|
||||
taskService.createComment(delegateTask.getId(), delegateTask.getProcessInstanceId(), "候选审批人在此流程中审批过---自动同意");
|
||||
taskService.complete(delegateTask.getId());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
opinion = "候选审批人在此流程中审批过";
|
||||
}
|
||||
|
||||
//缓存 自动通过 记录
|
||||
WorkFlowUtil.cacheTaskAssigneeRecord(delegateTask.getProcessInstanceId(), delegateTask.getId(), StpUtil.getLoginIdAsLong());
|
||||
|
||||
List<Task> list = taskService.createTaskQuery().processInstanceId(delegateTask.getProcessInstanceId()).list();
|
||||
//如果找不到任务了 默认流程已经结束
|
||||
if (list.size() > 0) {
|
||||
|
||||
String allNextTaskName = StrUtil.join(StringPool.SPACE, list.parallelStream().map(t -> "【" + t.getName() + "】").collect(Collectors.toList()));
|
||||
|
||||
String message = "【" + user.getName() + "】【自动同意】 审批, 审批意见为:“【" + opinion + "】”,由【" + delegateTask.getName() + "】流转到 " + allNextTaskName;
|
||||
addProcessRecord(delegateTask, schemaId, message);
|
||||
} else {
|
||||
String message = "【" + user.getName() + "】【自动同意】 审批, 审批意见为:“【" + opinion + "】”,由【" + delegateTask.getName() + "】流转到 结束节点";
|
||||
addProcessRecord(delegateTask, schemaId, message);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加流程记录
|
||||
*/
|
||||
private Long addProcessRecord(DelegateTask delegateTask, Long schemaId, String message) {
|
||||
|
||||
IWorkflowRecordService workflowRecordService = SpringUtil.getBean(IWorkflowRecordService.class);
|
||||
//新增流程发起流程记录
|
||||
WorkflowRecord record = new WorkflowRecord();
|
||||
record.setNodeId(delegateTask.getId());
|
||||
record.setNodeName(delegateTask.getName());
|
||||
record.setNodeType(WorkflowConstant.START_EVENT_TYPE_NAME);
|
||||
record.setProcessId(delegateTask.getProcessInstanceId());
|
||||
record.setSchemaId(schemaId);
|
||||
record.setNodeMultiType(WorkflowMultiInstanceType.NONE.getCode());
|
||||
record.setRecordTime(LocalDateTime.now());
|
||||
|
||||
record.setMessage(message);
|
||||
|
||||
workflowRecordService.save(record);
|
||||
|
||||
return record.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置根据命名规则 设置任务名字
|
||||
*
|
||||
* @param delegateTask
|
||||
*/
|
||||
private void setProcessExtra(DelegateTask delegateTask, Map<String, Object> variableMaps, WorkflowSchema workflowSchema, WorkflowSchemaConfig workflowSchemaConfig, UserTaskConfig userTaskConfig) {
|
||||
|
||||
WorkflowExtra extra = new WorkflowExtra();
|
||||
extra.setProcessId(delegateTask.getProcessInstanceId());
|
||||
extra.setTaskId(delegateTask.getId());
|
||||
extra.setTaskKey(delegateTask.getTaskDefinitionKey());
|
||||
extra.setStartUserId(MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_START_USER_ID_KEY));
|
||||
extra.setStartUserName(MapUtil.getStr(variableMaps, WorkflowConstant.PROCESS_START_USER_NAME_KEY));
|
||||
extra.setProcessName(MapUtil.getStr(variableMaps, WorkflowConstant.PROCESS_NAME));
|
||||
extra.setSchemaId(MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_SCHEMA_ID_KEY));
|
||||
extra.setSchemaName(MapUtil.getStr(variableMaps, WorkflowConstant.PROCESS_SCHEMA_NAME_KEY));
|
||||
extra.setSerialNumber(MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_SERIAL_NUMBER_KEY));
|
||||
extra.setStartTime(LocalDateTime.now());
|
||||
extra.setLaunchTime(DateUtil.toLocalDateTime(delegateTask.getCreateTime()));
|
||||
extra.setCurrentProgress(userTaskConfig.getCurrentProgress());
|
||||
|
||||
TaskService taskService = delegateTask.getProcessEngine().getTaskService();
|
||||
|
||||
Object variable = taskService.getVariable(delegateTask.getId(), WorkflowConstant.TASK_ASSIGNEE_VAR_KEY);
|
||||
extra.setApproveUserIds(Convert.toStr(variable));
|
||||
|
||||
extra.setTaskName(delegateTask.getName());
|
||||
|
||||
|
||||
IWorkflowExtraService workflowExtraService = SpringUtil.getBean(IWorkflowExtraService.class);
|
||||
workflowExtraService.save(extra);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置超时提醒定时任务
|
||||
*/
|
||||
private void setTimeoutRemid(DelegateTask delegateTask, WorkflowSchemaConfig
|
||||
workflowSchemaConfig, UserTaskConfig userTaskConfig) {
|
||||
|
||||
if (workflowSchemaConfig.getProcessConfig().getTimeoutRemidConfig() == null) return;
|
||||
|
||||
TimeoutRemidConfig timeoutRemidConfig = workflowSchemaConfig.getProcessConfig().getTimeoutRemidConfig();
|
||||
|
||||
if (timeoutRemidConfig.getEnabled()) {
|
||||
//获取到所有需要提示的人员
|
||||
List<Long> userIdsByMemberConfig = WorkFlowUtil.getUserIdsByMemberConfig(timeoutRemidConfig.getPushMemberConfigs(), workflowSchemaConfig.getChildNodeConfig(),delegateTask.getProcessInstanceId());
|
||||
List<Long> approveUserIds = WorkFlowUtil.getUserIdsByMemberConfig(userTaskConfig.getApproverConfigs(), workflowSchemaConfig.getChildNodeConfig(), delegateTask.getProcessInstanceId());
|
||||
|
||||
userIdsByMemberConfig.addAll(approveUserIds);
|
||||
List<Integer> noticePolicyConfig = userTaskConfig.getNoticePolicyConfigs();
|
||||
|
||||
if (noticePolicyConfig.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
String noticePolicyConfigString = StrUtil.join(StringPool.UNDERSCORE, noticePolicyConfig);
|
||||
|
||||
RedisUtil redisUtil = SpringUtil.getBean(RedisUtil.class);
|
||||
//推送次数设定为几次 就设置几个key值 然后计算过期时间
|
||||
for (Integer i = 0; i < timeoutRemidConfig.getPushHits(); i++) {
|
||||
|
||||
|
||||
// 公式为 (超时时间 + (间隔 * 第几次提醒)) * 3600秒
|
||||
// 第一次提醒 直接使用超时时间 所以 i == 0
|
||||
int expire = (timeoutRemidConfig.getHour() + (timeoutRemidConfig.getInterval() * i)) * 3600;
|
||||
|
||||
// 格式为 timeout:{taskId}:{hit}:{noticePolicyConfigString}
|
||||
// taskId为任务id hit为次数 noticePolicyConfigString为通知策略使用下划线隔开
|
||||
// 存储数据为所有需要推送的人员
|
||||
// expire 为过期时间
|
||||
redisUtil.set(WorkflowConstant.TIMEOUT_REMID_KEY + delegateTask.getId() + StringPool.COLON + (i + 1) + StringPool.COLON + noticePolicyConfigString, userIdsByMemberConfig, expire);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,208 @@
|
||||
package com.xjrsoft.workflow.listener;
|
||||
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.xjrsoft.common.core.enums.WorkflowNoticePolicyType;
|
||||
import com.xjrsoft.common.core.enums.YesOrNoEnum;
|
||||
import com.xjrsoft.system.client.IMessageClient;
|
||||
import com.xjrsoft.system.model.MessageNoticePolicyParam;
|
||||
import com.xjrsoft.workflow.constant.WorkflowConstant;
|
||||
import com.xjrsoft.workflow.entity.WorkflowSchema;
|
||||
import com.xjrsoft.workflow.model.MemberConfig;
|
||||
import com.xjrsoft.workflow.model.NoticePolicyParam;
|
||||
import com.xjrsoft.workflow.model.UserTaskConfig;
|
||||
import com.xjrsoft.workflow.model.WorkflowSchemaConfig;
|
||||
import com.xjrsoft.workflow.service.IWorkflowSchemaService;
|
||||
import com.xjrsoft.workflow.utils.WorkFlowUtil;
|
||||
import org.camunda.bpm.engine.ProcessEngines;
|
||||
import org.camunda.bpm.engine.TaskService;
|
||||
import org.camunda.bpm.engine.task.Task;
|
||||
import org.springframework.data.redis.connection.Message;
|
||||
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
|
||||
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 超时提醒 监听器
|
||||
* 监听redis key 过期
|
||||
*
|
||||
* @Author: tzx
|
||||
* @Date: 2022/10/26 14:46
|
||||
*/
|
||||
@Component
|
||||
public class TaskTimeoutListener extends KeyExpirationEventMessageListener {
|
||||
|
||||
public TaskTimeoutListener(RedisMessageListenerContainer listenerContainer) {
|
||||
super(listenerContainer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(Message message, byte[] pattern) {
|
||||
String expiredKey = message.toString();
|
||||
|
||||
TaskService taskService = ProcessEngines.getDefaultProcessEngine().getTaskService();
|
||||
|
||||
//如果是指定审批人 key 失效
|
||||
if (expiredKey.contains(WorkflowConstant.TASK_IS_APPOINT_APPROVE)) {
|
||||
String[] split = expiredKey.split(StringPool.UNDERSCORE);
|
||||
String taskId = split[0];
|
||||
|
||||
//获取到审批人 发送消息
|
||||
Object approvedIds = taskService.getVariableLocal(taskId, WorkflowConstant.TASK_ASSIGNEE_VAR_KEY);
|
||||
|
||||
List<String> variableNames = ListUtil.toList(
|
||||
WorkflowConstant.PROCESS_SCHEMA_ID_KEY,
|
||||
WorkflowConstant.PROCESS_SCHEMA_NAME_KEY,
|
||||
WorkflowConstant.PROCESS_START_USER_NAME_KEY);
|
||||
|
||||
Map<String, Object> variables = taskService.getVariables(taskId, variableNames);
|
||||
|
||||
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
|
||||
|
||||
Long schemaId = Convert.toLong(taskService.getVariable(task.getId(), WorkflowConstant.PROCESS_SCHEMA_ID_KEY));
|
||||
|
||||
IWorkflowSchemaService workflowSchemaService = SpringUtil.getBean(IWorkflowSchemaService.class);
|
||||
WorkflowSchema workflowSchema = workflowSchemaService.getOne(Wrappers.lambdaQuery(WorkflowSchema.class).eq(WorkflowSchema::getId, schemaId).select(WorkflowSchema::getJsonContent));
|
||||
|
||||
WorkflowSchemaConfig workflowSchemaConfig = JSONUtil.toBean(workflowSchema.getJsonContent(), WorkflowSchemaConfig.class);
|
||||
|
||||
Map<String, Object> userTaskConfigMap = workflowSchemaConfig.getChildNodeConfig().stream().filter(x -> x.containsValue(task.getTaskDefinitionKey())).findFirst().orElse(new HashMap<>());
|
||||
UserTaskConfig userTaskConfig = Convert.convert(UserTaskConfig.class, userTaskConfigMap);
|
||||
|
||||
|
||||
List<String> approveIds = ListUtil.toList(Convert.toStr(approvedIds).split(StringPool.COMMA));
|
||||
|
||||
NoticePolicyParam param = new NoticePolicyParam();
|
||||
param.setNoticeUserIds(Convert.toList(Long.class, approveIds));
|
||||
param.setTaskId(task.getId());
|
||||
param.setTaskName(task.getName());
|
||||
param.setProcessId(task.getProcessInstanceId());
|
||||
param.setTaskName(task.getName());
|
||||
param.setSchemaId(MapUtil.get(variables, WorkflowConstant.PROCESS_SCHEMA_ID_KEY, Long.class));
|
||||
param.setSchemaName(MapUtil.get(variables, WorkflowConstant.PROCESS_SCHEMA_NAME_KEY, String.class));
|
||||
param.setStartUserName(MapUtil.get(variables, WorkflowConstant.PROCESS_START_USER_NAME_KEY, String.class));
|
||||
param.setNoticePolicyConfigs(userTaskConfig.getNoticePolicyConfigs());
|
||||
//发送消息
|
||||
WorkFlowUtil.sendApproveNoticePolicy(param,task.getName());
|
||||
|
||||
//到期未指定的任务 将变量设置为不需要指定
|
||||
taskService.setVariableLocal(task.getId(), WorkflowConstant.TASK_IS_APPOINT_APPROVE, YesOrNoEnum.NO.getCode());
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//如果key 不包含此前缀 不再执行此逻辑
|
||||
if (!expiredKey.contains(WorkflowConstant.TIMEOUT_REMID_KEY)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// 将过期key使用冒号 切割
|
||||
String[] expiredKeyArr = expiredKey.split(StringPool.COLON);
|
||||
|
||||
//获取到任务id
|
||||
String taskId = expiredKeyArr[1];
|
||||
|
||||
//获取到次数
|
||||
// String hit = expiredKeyArr[2];
|
||||
|
||||
//获取到通知策略
|
||||
String noticePolicyConfigString = expiredKeyArr[3];
|
||||
String[] noticePolicyTypeList = noticePolicyConfigString.split(StringPool.UNDERSCORE);
|
||||
|
||||
|
||||
//根据taskid 获取发起人 以及 模板名称
|
||||
Map<String, Object> variables = taskService.getVariables(taskId, ListUtil.toList(WorkflowConstant.PROCESS_START_USER_NAME_KEY, WorkflowConstant.PROCESS_SCHEMA_NAME_KEY));
|
||||
|
||||
String starter = StrUtil.toString(variables.get(WorkflowConstant.PROCESS_START_USER_NAME_KEY));
|
||||
String schemaName = StrUtil.toString(variables.get(WorkflowConstant.PROCESS_SCHEMA_NAME_KEY));
|
||||
|
||||
//获取到需要提醒的人员(过期key 无法获取到value 需要数据库取审批人)
|
||||
Object assignee = taskService.getVariableLocal(taskId, WorkflowConstant.TASK_ASSIGNEE_VAR_KEY);
|
||||
|
||||
List<String> approveIds = ListUtil.toList(Convert.toStr(assignee).split(StringPool.COMMA));
|
||||
List<Long> ids = Convert.toList(Long.class, approveIds);
|
||||
//获取任务信息
|
||||
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
|
||||
Long schemaId = Convert.toLong(taskService.getVariable(task.getId(), WorkflowConstant.PROCESS_SCHEMA_ID_KEY));
|
||||
|
||||
IWorkflowSchemaService workflowSchemaService = SpringUtil.getBean(IWorkflowSchemaService.class);
|
||||
WorkflowSchema workflowSchema = workflowSchemaService.getOne(Wrappers.lambdaQuery(WorkflowSchema.class).eq(WorkflowSchema::getId, schemaId).select(WorkflowSchema::getJsonContent));
|
||||
|
||||
WorkflowSchemaConfig workflowSchemaConfig = JSONUtil.toBean(workflowSchema.getJsonContent(), WorkflowSchemaConfig.class);
|
||||
|
||||
//找到当前用户任务节点的配置信息
|
||||
List<MemberConfig> pushMemberConfigs = workflowSchemaConfig.getProcessConfig().getTimeoutRemidConfig().getPushMemberConfigs();
|
||||
|
||||
if (pushMemberConfigs.size() > 0) {
|
||||
List<Long> userIdsByMemberConfig = WorkFlowUtil.getUserIdsByMemberConfig(pushMemberConfigs, workflowSchemaConfig.getChildNodeConfig(), task.getProcessInstanceId());
|
||||
ids.addAll(userIdsByMemberConfig);
|
||||
|
||||
}
|
||||
List<Long> allPushUserIds = ids.stream().distinct().collect(Collectors.toList());
|
||||
//遍历所有设定的通知策略
|
||||
// 暂时这样写 后续可以改成 策略模式 或者 工厂模式
|
||||
//TODO sendMessageUtil 改成与 oss 一样的工厂
|
||||
|
||||
MessageNoticePolicyParam param = new MessageNoticePolicyParam();
|
||||
param.setNoticeUserIds(Convert.toList(Long.class, allPushUserIds));
|
||||
param.setTaskId(task.getId());
|
||||
param.setTaskName(task.getName());
|
||||
param.setProcessId(task.getProcessInstanceId());
|
||||
param.setTaskName(task.getName());
|
||||
param.setSchemaId(schemaId);
|
||||
param.setSchemaName(schemaName);
|
||||
param.setStartUserName(starter);
|
||||
|
||||
IMessageClient messageClient = SpringUtil.getBean(IMessageClient.class);
|
||||
for (String type : noticePolicyTypeList) {
|
||||
//如果包含系统消息推送
|
||||
if (Convert.toInt(type) == WorkflowNoticePolicyType.SYSTEM.getCode()) {
|
||||
CompletableFuture.runAsync(() -> {
|
||||
messageClient.sendWorkflowTimeoutMessageFeign(param);
|
||||
});
|
||||
|
||||
}
|
||||
//短信发送
|
||||
if (Convert.toInt(type) == WorkflowNoticePolicyType.SMS.getCode()) {
|
||||
//TODO 短信发送代码
|
||||
CompletableFuture.runAsync(() -> {
|
||||
messageClient.sendWorkflowTimeoutMessageFeign(param);
|
||||
});
|
||||
}
|
||||
|
||||
//企业微信
|
||||
if (Convert.toInt(type) == WorkflowNoticePolicyType.WECHAT.getCode()) {
|
||||
//TODO 企业微信发送代码
|
||||
}
|
||||
|
||||
//钉钉
|
||||
if (Convert.toInt(type) == WorkflowNoticePolicyType.DING.getCode()) {
|
||||
//TODO 钉钉发送代码
|
||||
}
|
||||
|
||||
//邮箱
|
||||
if (Convert.toInt(type) == WorkflowNoticePolicyType.EMAIL.getCode()) {
|
||||
//TODO 邮箱发送
|
||||
CompletableFuture.runAsync(() -> {
|
||||
messageClient.sendWorkflowTimeoutMessageFeign(param);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
package com.xjrsoft.workflow.runner;
|
||||
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.xjrsoft.common.redis.service.RedisUtil;
|
||||
import com.xjrsoft.workflow.entity.WorkflowSchema;
|
||||
import com.xjrsoft.workflow.model.WorkflowSchemaConfig;
|
||||
import com.xjrsoft.workflow.service.IWorkflowSchemaService;
|
||||
import com.xjrsoft.workflow.utils.WorkFlowUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* @Description 加载数据权限 缓存
|
||||
* @Author: tzx
|
||||
* @Date: 2023/2/28 14:49
|
||||
*/
|
||||
@Component
|
||||
@AllArgsConstructor
|
||||
@Slf4j
|
||||
public class WorkflowRunner implements CommandLineRunner {
|
||||
|
||||
private IWorkflowSchemaService workflowSchemaService;
|
||||
|
||||
@Override
|
||||
public void run(String... args) {
|
||||
loadEventCache();
|
||||
}
|
||||
|
||||
@Async
|
||||
void loadEventCache() {
|
||||
log.info("ITC-FRAMEWORK: 加载所有工作流模板开始与结束事件缓存开始");
|
||||
List<WorkflowSchema> list = workflowSchemaService.list();
|
||||
for (WorkflowSchema workflowSchema : list) {
|
||||
//获取到整个流程模板的配置
|
||||
WorkflowSchemaConfig workflowSchemaConfig = JSONUtil.toBean(workflowSchema.getJsonContent(), WorkflowSchemaConfig.class);
|
||||
CompletableFuture.runAsync(() -> {
|
||||
//先删除,后新增
|
||||
WorkFlowUtil.removeNodeListener(workflowSchema.getDeploymentId());
|
||||
WorkFlowUtil.cacheNodeListener(workflowSchema.getDeploymentId(), workflowSchemaConfig.getChildNodeConfig());
|
||||
});
|
||||
}
|
||||
log.info("ITC-FRAMEWORK: 加载所有工作流模板开始与结束事件缓存结束");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,183 @@
|
||||
package com.xjrsoft.workflow.service;
|
||||
|
||||
import cn.hutool.db.Entity;
|
||||
import cn.hutool.db.Session;
|
||||
import com.xjrsoft.common.core.domain.page.PageOutput;
|
||||
import com.xjrsoft.common.generate.model.QueryConfig;
|
||||
import com.xjrsoft.desktop.dto.*;
|
||||
import com.xjrsoft.form.dto.*;
|
||||
import com.xjrsoft.form.vo.DeskFormReleaseVo;
|
||||
import com.xjrsoft.form.vo.DeskTableInfoVo;
|
||||
import org.apache.commons.lang3.tuple.Triple;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Author: tzx
|
||||
* @Date: 2022/5/11 14:57
|
||||
*/
|
||||
public interface IFormExecuteService {
|
||||
/**
|
||||
* 获取自定义表单不分页列表数据
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
List<Entity> list(FormExecuteListDto dto);
|
||||
|
||||
/**
|
||||
* App 获取自定义表单不分页列表数据
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
List<Entity> appList(AppFormExecuteListDto dto);
|
||||
|
||||
/**
|
||||
* 获取自定义表单分页列表数据
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
PageOutput<Entity> page(FormExecutePageDto dto);
|
||||
|
||||
/**
|
||||
* App 获取自定义表单分页列表数据
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
PageOutput<Entity> appPage(AppFormExecutePageDto dto);
|
||||
|
||||
/**
|
||||
* 获取自定义表单 表单数据
|
||||
* @return
|
||||
*/
|
||||
Object info(FormExecuteInfoDto dto);
|
||||
|
||||
/**
|
||||
* App 获取自定义表单 表单数据
|
||||
* @return
|
||||
*/
|
||||
Object appInfo(AppFormExecuteInfoDto dto);
|
||||
|
||||
/**
|
||||
* 自定义表单 新增
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
Boolean add(FormExecuteAddOrUpdateDto dto);
|
||||
|
||||
/**
|
||||
* App 自定义表单 新增
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
Boolean appAdd(AppFormExecuteAddOrUpdateDto dto);
|
||||
|
||||
/**
|
||||
* 自定义表单 修改
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
Boolean update(FormExecuteAddOrUpdateDto dto);
|
||||
|
||||
/**
|
||||
* app 自定义表单 修改
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
Boolean appUpdate(AppFormExecuteAddOrUpdateDto dto);
|
||||
|
||||
/**
|
||||
* 自定义表单 删除
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
Boolean delete(FormExecuteDeleteDto dto);
|
||||
|
||||
/**
|
||||
* app 自定义表单 删除
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
Boolean appDelete(AppFormExecuteDeleteDto dto);
|
||||
|
||||
/**
|
||||
* 工作流调用 自定义表单 新增
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
Triple<Session, Long, Long> workflowAdd(FormExecuteWorkflowAddDto dto);
|
||||
|
||||
|
||||
/**
|
||||
* 工作流调用 自定义表单 修改
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
Triple<Session, Long, Long> workflowUpdate(FormExecuteWorkflowUpdateDto dto);
|
||||
|
||||
/**
|
||||
* 工作流调用 自定义表单 新增或者修改
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
Triple<Session, Boolean, Long> workflowAddOrUpdate(FormExecuteWorkflowUpdateDto dto);
|
||||
|
||||
/**
|
||||
* 获取自定义表单 表单数据
|
||||
* @return
|
||||
*/
|
||||
Object workFlowInfo(FormExecuteWorkflowInfoDto dto);
|
||||
|
||||
/**
|
||||
* 批量新增主表数据
|
||||
* @return
|
||||
*/
|
||||
Boolean saveMainBatch(Long formTemplateId, List<Map<String, Object>> dataList);
|
||||
|
||||
/**
|
||||
* 桌面设计调用新增
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
boolean complexAdd(AddDeskComplexDto dto);
|
||||
|
||||
|
||||
/**
|
||||
* 桌面设计调用编辑
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
boolean complexUpdate(UpdateDeskComplexDto dto);
|
||||
|
||||
/**
|
||||
* 桌面设计调用删除
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
boolean complexDelete(DeleteDeskComplexDto dto);
|
||||
|
||||
/**
|
||||
* 桌面设计调用删除
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
Object complexInfo(DeskComplexInfoDto dto);
|
||||
|
||||
/**
|
||||
* 桌面设计调用自定义表单获取发布id
|
||||
* @param formId
|
||||
* @return
|
||||
*/
|
||||
List<DeskFormReleaseVo> getReleaseInfo(Long formId);
|
||||
|
||||
List<QueryConfig> complexQuery(ComplexQueryDto dto);
|
||||
|
||||
/**
|
||||
* 桌面设计-复杂列表页-获取列表数据 分页
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
PageOutput<Entity> complexPage(ComplexPageDto dto);
|
||||
|
||||
DeskTableInfoVo getTableInfo(Long formId);
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.xjrsoft.workflow.service;
|
||||
|
||||
import com.github.yulichang.base.MPJBaseService;
|
||||
import com.xjrsoft.workflow.entity.WorkflowApproveRecord;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2023-02-10
|
||||
*/
|
||||
public interface IWorkflowApproveRecordService extends MPJBaseService<WorkflowApproveRecord> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.xjrsoft.workflow.service;
|
||||
|
||||
import com.github.yulichang.base.MPJBaseService;
|
||||
import com.xjrsoft.workflow.entity.WorkflowCirculated;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 流程传阅信息表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2023-02-09
|
||||
*/
|
||||
public interface IWorkflowCirculatedService extends MPJBaseService<WorkflowCirculated> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
package com.xjrsoft.workflow.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.xjrsoft.common.core.domain.page.PageOutput;
|
||||
import com.xjrsoft.workflow.dto.AddDelegateDto;
|
||||
import com.xjrsoft.workflow.dto.DelegatePageDto;
|
||||
import com.xjrsoft.workflow.dto.UpdateDelegateDto;
|
||||
import com.xjrsoft.workflow.entity.WorkflowDelegate;
|
||||
import com.xjrsoft.workflow.vo.DelegatePageVo;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 流程委托 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2022-11-05
|
||||
*/
|
||||
@Service
|
||||
public interface IWorkflowDelegateService extends IService<WorkflowDelegate> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
PageOutput<DelegatePageVo> page(DelegatePageDto dto);
|
||||
|
||||
/**
|
||||
* 新增
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
boolean add(AddDelegateDto dto);
|
||||
|
||||
|
||||
/**
|
||||
* 修改
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
boolean update(UpdateDelegateDto dto);
|
||||
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
boolean delete(List<Long> ids);
|
||||
}
|
||||
@ -0,0 +1,413 @@
|
||||
package com.xjrsoft.workflow.service;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.xjrsoft.common.core.domain.page.PageOutput;
|
||||
import com.xjrsoft.workflow.dto.*;
|
||||
import com.xjrsoft.workflow.vo.*;
|
||||
import org.camunda.bpm.model.bpmn.instance.SequenceFlow;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @Author: tzx
|
||||
* @Date: 2022/9/8 14:22
|
||||
*/
|
||||
public interface IWorkflowExecuteService {
|
||||
|
||||
/**
|
||||
* 部署
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
boolean deploy(DeployDto dto);
|
||||
|
||||
/**
|
||||
* 部署
|
||||
*
|
||||
* @param schemaId
|
||||
* @return
|
||||
*/
|
||||
String preview(Long schemaId);
|
||||
|
||||
/**
|
||||
* 发起流程前 所需要获取的流程信息数据
|
||||
* @param schemaId
|
||||
* @return
|
||||
*/
|
||||
StartProcessInfoVo getStartProcessInfo(Long schemaId);
|
||||
|
||||
|
||||
/**
|
||||
* 审批流程前 需要获取的流程信息数据
|
||||
* @param taskId
|
||||
* @return
|
||||
*/
|
||||
UserTaskInfoVo getApproveProcessInfo(String taskId);
|
||||
|
||||
/**
|
||||
* 审批流程前 需要获取的流程信息数据
|
||||
* @param processId
|
||||
* @return
|
||||
*/
|
||||
UserTaskInfoVo getApproveProcessInfoByProcessId(String processId);
|
||||
|
||||
/**
|
||||
* 获取当前流程所有的流转记录
|
||||
* @param processId
|
||||
* @return
|
||||
*/
|
||||
AllRecordListVo getAllRecordInfoByProcessId(String processId,Integer onlySelf);
|
||||
|
||||
/**
|
||||
* 审批流程所需要的信息 需要获取的流程信息数据
|
||||
* @param processId
|
||||
* @return
|
||||
*/
|
||||
RecycleProcessInfoVo getRecycleProcessInfo(String processId);
|
||||
|
||||
|
||||
/**
|
||||
* 发起流程
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
List<LaunchAndApproveVo> newLaunch(LaunchDto dto);
|
||||
|
||||
|
||||
/**
|
||||
* 发起流程
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
List<LaunchAndApproveVo> reLaunch(ReLaunchDto dto);
|
||||
|
||||
|
||||
/**
|
||||
* 当前人员待处理
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
PageOutput<PendingTaskVo> pending(PendingTaskPageDto dto);
|
||||
|
||||
|
||||
/**
|
||||
* 当前人员待处理
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
List<PendingTaskVo> pending(PendingTaskDto dto);
|
||||
|
||||
/**
|
||||
* 审批
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
List<LaunchAndApproveVo> newApprove(ApproveDto dto);
|
||||
|
||||
|
||||
List<ApproveMultiVo> approveMulti(ApproveMultiDto dto);
|
||||
|
||||
ApproveMultiInfoVo approveMultiInfo(ApproveMultiInfoDto dto);
|
||||
|
||||
/**
|
||||
* 获取当前用户任务的下一节点审批人
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
boolean setApproveUser(ApproveUserDto dto);
|
||||
|
||||
/**
|
||||
* 获取当前用户任务的下一节点审批人
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
boolean setApproveUserMulti(ApproveUserMultiDto dto);
|
||||
|
||||
Set<HashMap<String, Object>> getNextUserTaskNodeMaybeArrival(String taskId, JSONObject paramsMap) throws Exception;
|
||||
JSONArray getUserInfoForNextUserTaskNodeMaybeArrival(Set<Long> assigns)throws Exception;
|
||||
Set<HashMap<String, Object>> getNextUserTaskNodeMaybeArrival(SequenceFlow flow, Map<String,Object> variableMap) throws Exception;
|
||||
Boolean checkFlowRuleEl(String el, Map<String,Object> variableMap)throws Exception;
|
||||
|
||||
|
||||
/**
|
||||
* 获取关联任务
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
PageOutput<RelationTaskPageVo> getRelationTaskPage(RelationTaskPageDto dto);
|
||||
|
||||
/**
|
||||
* 查询关联任务详情
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
RelationTaskInfoVo getRelationTaskInfo(RelationTaskInfoDto dto);
|
||||
|
||||
/**
|
||||
* 查询任务详情
|
||||
*
|
||||
* @param taskId
|
||||
* @return
|
||||
*/
|
||||
TaskInfoVo getTaskInfo(String taskId);
|
||||
|
||||
/**
|
||||
* 获取流程详情信息
|
||||
*
|
||||
* @param processId
|
||||
* @return
|
||||
*/
|
||||
ProcessInfoVo getProcessInfo(String processId);
|
||||
|
||||
|
||||
/**
|
||||
* 查询任务详情
|
||||
*
|
||||
* @param taskId
|
||||
* @return
|
||||
*/
|
||||
TaskInfoVo getCirculatedTaskInfo(String taskId);
|
||||
|
||||
|
||||
/**
|
||||
* 查询流程已完成任务
|
||||
* @param processInstanceId 流程id
|
||||
* @return
|
||||
*/
|
||||
FinishedTaskVo getFinishedTask(String processInstanceId);
|
||||
|
||||
|
||||
/**
|
||||
* 根据formId 查询流程图 以及 当前流程已完成的任务
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
FormFinishedTaskVo getFormFinishedTask(FormFinishedTaskDto dto);
|
||||
|
||||
|
||||
/**
|
||||
* 查询流程流转记录
|
||||
* @param processInstanceId 流程id
|
||||
* @return
|
||||
*/
|
||||
List<ProcessRecordListVo> getProcessRecord(String processInstanceId);
|
||||
|
||||
/**
|
||||
* 获取传阅分页列表
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
PageOutput<CirculatedTaskPageVo> getCirculatedTaskPage(CirculatedTaskPageDto dto);
|
||||
|
||||
|
||||
/**
|
||||
* 获取已办分页列表
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
PageOutput<FinishedTaskPageVo> getFinishedTaskPage(FinishedTaskPageDto dto);
|
||||
|
||||
|
||||
/**
|
||||
* 获取我所有发起的流程
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
PageOutput<MyProcessPageVo> getMyProcessPage(MyProcessPageDto dto);
|
||||
|
||||
/**
|
||||
* 流程移入回收站
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
boolean moveRecycle(MoveRecycleDto dto);
|
||||
|
||||
/**
|
||||
* 流程移入回收站
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
PageOutput<RecycleProcessPageVo> getRecycleProcessPage(RecycleProcessPageDto dto);
|
||||
|
||||
|
||||
/**
|
||||
* 回收站流程 重新发起
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
RestartVo restart(RestartDto dto);
|
||||
|
||||
/**
|
||||
* 回收站删除
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
Boolean recycleDelete(RecycleDeleteDto dto);
|
||||
|
||||
/**
|
||||
* 获取当前流程已经审批过的节点
|
||||
* @param schemaId 流程实例id
|
||||
* @param processInstanceId 流程实例id
|
||||
* @return
|
||||
*/
|
||||
List<HistoryTaskVo> getHistoryTask(String schemaId, String processInstanceId);
|
||||
|
||||
|
||||
/**
|
||||
* 撤回
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
boolean withdraw(WithdrawDto dto);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 保存流程草稿
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
boolean saveDraft(SaveDraftDto dto);
|
||||
|
||||
/**
|
||||
* 修改流程草稿
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
boolean updateDraft(UpdateDraftDto dto);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 保存流程草稿
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
PageOutput<DraftPageVo> draftPage(DraftPageDto dto);
|
||||
|
||||
|
||||
/**
|
||||
* 删除草稿
|
||||
*
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
boolean deleteDraft(List<Long> ids);
|
||||
|
||||
/**
|
||||
* 查询草稿详情
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
DraftInfoVo draftInfo(Long id);
|
||||
|
||||
/**
|
||||
* 查询流程监控
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
PageOutput<MonitorPageVo> getProcessMonitorPage(MonitorPageDto dto);
|
||||
|
||||
/**
|
||||
* 删除流程监控
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
boolean deleteProcessMonitor(DeleteMonitorDto dto);
|
||||
|
||||
/**
|
||||
* 设置审批人
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
boolean setAssignee(SetAssigneeDto dto);
|
||||
|
||||
|
||||
/**
|
||||
* 流程挂起
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
boolean setSuspended(SetSuspendedDto dto);
|
||||
|
||||
/**
|
||||
* 获取节点审批人
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
List<GetAssigneeVo> getAssignee(GetAssigneeDto dto);
|
||||
|
||||
/**
|
||||
* 从流程未结束的任务获取流程当前审批人(还未审批的人)
|
||||
* @param dto
|
||||
* @return 按taskDefKey-taskList-taskAssigneeList组织数据
|
||||
*/
|
||||
Map<String,List<GetTaskAssigneeVo>> getCurrentAssignee(GetCurrentAssigneeDto dto);
|
||||
|
||||
/**
|
||||
* 加签/减签
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
boolean addOrSubSign(AddOrSubSignDto dto);
|
||||
|
||||
|
||||
/**
|
||||
* 获取到可以驳回的节点
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
List<RejectNodeVo> getRejectNode(RejectNodeDto dto);
|
||||
|
||||
/**
|
||||
* 获取可以撤回的节点
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
List<WithdrawNodeVo> getProcessTaskCanWithdraw(WithdrawNodeDto dto);
|
||||
|
||||
Boolean transfer(TransferDto dto);
|
||||
|
||||
/**
|
||||
* 获取总和
|
||||
*
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
GetCountVo getCount();
|
||||
|
||||
Boolean dealTimeoutTask(Integer handleType,String taskId);
|
||||
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.xjrsoft.workflow.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.xjrsoft.workflow.entity.WorkflowExtra;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2022-10-11
|
||||
*/
|
||||
public interface IWorkflowExtraService extends IService<WorkflowExtra> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.xjrsoft.workflow.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.xjrsoft.workflow.entity.WorkflowFormRelation;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 工作流 流程 与 表单关联表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2023-03-27
|
||||
*/
|
||||
public interface IWorkflowFormRelationService extends IService<WorkflowFormRelation> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.xjrsoft.workflow.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.xjrsoft.workflow.entity.WorkflowRecord;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 工作流 流转记录信息 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2022-11-10
|
||||
*/
|
||||
public interface IWorkflowRecordService extends IService<WorkflowRecord> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.xjrsoft.workflow.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.xjrsoft.workflow.entity.WorkflowSchemaAuth;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 流程模板权限 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2022-07-04
|
||||
*/
|
||||
public interface IWorkflowSchemaAuthService extends IService<WorkflowSchemaAuth> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package com.xjrsoft.workflow.service;
|
||||
|
||||
import com.github.yulichang.base.MPJBaseService;
|
||||
import com.xjrsoft.workflow.dto.HistoryChangeDto;
|
||||
import com.xjrsoft.workflow.entity.WorkflowSchemaHistory;
|
||||
import com.xjrsoft.workflow.vo.ProcessChangeVo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 流程模板历史记录表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2022-11-16
|
||||
*/
|
||||
public interface IWorkflowSchemaHistoryService extends MPJBaseService<WorkflowSchemaHistory> {
|
||||
|
||||
/**
|
||||
* 设置为当前版本
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
List<ProcessChangeVo> change(HistoryChangeDto dto);
|
||||
|
||||
/**
|
||||
* 流程变更
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
List<ProcessChangeVo> processChanges(HistoryChangeDto dto);
|
||||
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
package com.xjrsoft.workflow.service;
|
||||
|
||||
import com.github.yulichang.base.MPJBaseService;
|
||||
import com.xjrsoft.common.core.domain.page.PageOutput;
|
||||
import com.xjrsoft.workflow.dto.*;
|
||||
import com.xjrsoft.workflow.entity.WorkflowSchema;
|
||||
import com.xjrsoft.workflow.vo.WorkflowSchemaDraftPageVo;
|
||||
import com.xjrsoft.workflow.vo.WorkflowSchemaPageVo;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 流程模板表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2022-07-04
|
||||
*/
|
||||
public interface IWorkflowSchemaService extends MPJBaseService<WorkflowSchema> {
|
||||
|
||||
/**
|
||||
* 新增流程模板草稿
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
PageOutput<WorkflowSchemaPageVo> getPage(WorkflowSchemaPageDto dto);
|
||||
/**
|
||||
* 新增流程模板设计
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
boolean add(AddWorkflowSchemaDto dto);
|
||||
|
||||
/**
|
||||
* 新增流程模板草稿
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
boolean addDraft(AddWorkflowSchemaDraftDto dto);
|
||||
|
||||
|
||||
/**
|
||||
* 新增流程模板草稿
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
PageOutput<WorkflowSchemaDraftPageVo> getDraftPage(WorkflowSchemaDraftPageDto dto);
|
||||
|
||||
|
||||
/**
|
||||
* 修改流程模板设计
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
boolean update(UpdateWorkflowSchemaDto dto);
|
||||
|
||||
|
||||
/**
|
||||
* 删除流程模板设计
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
boolean delete(List<Long> ids);
|
||||
|
||||
|
||||
/**
|
||||
* 删除流程模板设计
|
||||
* @param multipartFile
|
||||
* @return
|
||||
*/
|
||||
boolean importSchema(MultipartFile multipartFile);
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
package com.xjrsoft.workflow.service;
|
||||
|
||||
import com.github.yulichang.base.MPJBaseService;
|
||||
import com.xjrsoft.workflow.dto.AddSpecialMenuDto;
|
||||
import com.xjrsoft.workflow.dto.UpdateSpecialMenuDto;
|
||||
import com.xjrsoft.workflow.entity.WorkflowSpecialMenu;
|
||||
import com.xjrsoft.workflow.vo.SpecialMenuInfoVo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 专项菜单表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2023-03-20
|
||||
*/
|
||||
public interface IWorkflowSpecialMenuService extends MPJBaseService<WorkflowSpecialMenu> {
|
||||
|
||||
/**
|
||||
* 新增专项菜单
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
boolean add(AddSpecialMenuDto dto);
|
||||
|
||||
/**
|
||||
* 修改专项菜单
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
boolean update(UpdateSpecialMenuDto dto);
|
||||
|
||||
/**
|
||||
* 删除专项菜单
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
boolean delete(List<Long> ids);
|
||||
|
||||
/**
|
||||
* 获取详情
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
SpecialMenuInfoVo info(Long id);
|
||||
|
||||
/**
|
||||
* 专项菜单查询列表
|
||||
* @param param
|
||||
* @return
|
||||
*/
|
||||
List<Map<String,Object>> pending(Map<String,Object> param);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,20 @@
|
||||
package com.xjrsoft.workflow.service.impl;
|
||||
|
||||
import com.github.yulichang.base.MPJBaseServiceImpl;
|
||||
import com.xjrsoft.workflow.entity.WorkflowApproveRecord;
|
||||
import com.xjrsoft.workflow.mapper.WorkflowApproveRecordMapper;
|
||||
import com.xjrsoft.workflow.service.IWorkflowApproveRecordService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2023-02-10
|
||||
*/
|
||||
@Service
|
||||
public class WorkflowApproveRecordServiceImpl extends MPJBaseServiceImpl<WorkflowApproveRecordMapper, WorkflowApproveRecord> implements IWorkflowApproveRecordService {
|
||||
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package com.xjrsoft.workflow.service.impl;
|
||||
|
||||
import com.github.yulichang.base.MPJBaseServiceImpl;
|
||||
import com.xjrsoft.workflow.entity.WorkflowCirculated;
|
||||
import com.xjrsoft.workflow.mapper.WorkflowCirculatedMapper;
|
||||
import com.xjrsoft.workflow.service.IWorkflowCirculatedService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 流程传阅信息表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2023-02-09
|
||||
*/
|
||||
@Service
|
||||
public class WorkflowCirculatedServiceImpl extends MPJBaseServiceImpl<WorkflowCirculatedMapper, WorkflowCirculated> implements IWorkflowCirculatedService {
|
||||
|
||||
}
|
||||
@ -0,0 +1,109 @@
|
||||
package com.xjrsoft.workflow.service.impl;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.lang.TypeReference;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.xjrsoft.common.core.constant.GlobalConstant;
|
||||
import com.xjrsoft.common.core.domain.page.PageOutput;
|
||||
import com.xjrsoft.common.mybatis.utils.ConventPage;
|
||||
import com.xjrsoft.common.redis.service.RedisUtil;
|
||||
import com.xjrsoft.organization.entity.User;
|
||||
import com.xjrsoft.workflow.dto.AddDelegateDto;
|
||||
import com.xjrsoft.workflow.dto.DelegatePageDto;
|
||||
import com.xjrsoft.workflow.dto.UpdateDelegateDto;
|
||||
import com.xjrsoft.workflow.entity.WorkflowDelegate;
|
||||
import com.xjrsoft.workflow.mapper.WorkflowDelegateMapper;
|
||||
import com.xjrsoft.workflow.service.IWorkflowDelegateService;
|
||||
import com.xjrsoft.workflow.vo.DelegatePageVo;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 流程委托 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2022-11-05
|
||||
*/
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class WorkflowDelegateServiceImpl extends ServiceImpl<WorkflowDelegateMapper, WorkflowDelegate> implements IWorkflowDelegateService {
|
||||
|
||||
private final RedisUtil redisUtil;
|
||||
@Override
|
||||
public PageOutput<DelegatePageVo> page(DelegatePageDto dto) {
|
||||
//用户只能看到自己的流程委托信息
|
||||
LambdaQueryWrapper<WorkflowDelegate> eq = Wrappers.lambdaQuery(WorkflowDelegate.class)
|
||||
.eq(WorkflowDelegate::getUserId,StpUtil.getLoginIdAsLong())
|
||||
.like(StrUtil.isNotBlank(dto.getKeyword()), WorkflowDelegate::getRemark, dto.getKeyword())
|
||||
.or(StrUtil.isNotBlank(dto.getKeyword()))
|
||||
.like(StrUtil.isNotBlank(dto.getKeyword()), WorkflowDelegate::getDelegateUserNames, dto.getKeyword());
|
||||
IPage<WorkflowDelegate> page = page(ConventPage.getPage(dto), eq);
|
||||
|
||||
PageOutput<DelegatePageVo> pageOutput = ConventPage.getPageOutput(page, DelegatePageVo.class);
|
||||
|
||||
User user = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_INFO_KEY, new User());
|
||||
|
||||
for (DelegatePageVo delegatePageVo : pageOutput.getList()) {
|
||||
delegatePageVo.setDelegator(user.getName());
|
||||
|
||||
}
|
||||
|
||||
return pageOutput;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean add(AddDelegateDto dto) {
|
||||
|
||||
WorkflowDelegate delegate = BeanUtil.toBean(dto, WorkflowDelegate.class);
|
||||
delegate.setUserId(StpUtil.getLoginIdAsLong());
|
||||
|
||||
List<User> allUser = redisUtil.get(GlobalConstant.USER_CACHE_KEY, new TypeReference<List<User>>() {
|
||||
});
|
||||
String allUserIdStr = StrUtil.join(StringPool.COMMA, dto.getDelegateUserIds());
|
||||
List<Long> ids = Arrays.stream(allUserIdStr.split(StringPool.COMMA)).map(Convert::toLong).collect(Collectors.toList());
|
||||
List<String> names = allUser.stream().filter(x -> ids.contains(x.getId())).map(User::getName).collect(Collectors.toList());
|
||||
delegate.setDelegateUserNames(StrUtil.join(StringPool.COMMA,names));
|
||||
|
||||
return save(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean update(UpdateDelegateDto dto) {
|
||||
|
||||
WorkflowDelegate delegate = BeanUtil.toBean(dto, WorkflowDelegate.class);
|
||||
delegate.setUserId(StpUtil.getLoginIdAsLong());
|
||||
|
||||
List<User> allUser = redisUtil.get(GlobalConstant.USER_CACHE_KEY, new TypeReference<List<User>>() {
|
||||
});
|
||||
String allUserIdStr = StrUtil.join(StringPool.COMMA, dto.getDelegateUserIds());
|
||||
List<Long> ids = Arrays.stream(allUserIdStr.split(StringPool.COMMA)).map(Convert::toLong).collect(Collectors.toList());
|
||||
List<String> names = allUser.stream().filter(x -> ids.contains(x.getId())).map(User::getName).collect(Collectors.toList());
|
||||
delegate.setDelegateUserNames(StrUtil.join(StringPool.COMMA,names));
|
||||
|
||||
return updateById(delegate);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean delete(List<Long> ids){
|
||||
|
||||
return removeBatchByIds(ids);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,20 @@
|
||||
package com.xjrsoft.workflow.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.xjrsoft.workflow.entity.WorkflowExtra;
|
||||
import com.xjrsoft.workflow.mapper.WorkflowExtraMapper;
|
||||
import com.xjrsoft.workflow.service.IWorkflowExtraService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2022-10-11
|
||||
*/
|
||||
@Service
|
||||
public class WorkflowExtraServiceImpl extends ServiceImpl<WorkflowExtraMapper, WorkflowExtra> implements IWorkflowExtraService {
|
||||
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package com.xjrsoft.workflow.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.xjrsoft.workflow.entity.WorkflowFormRelation;
|
||||
import com.xjrsoft.workflow.mapper.WorkflowFormRelationMapper;
|
||||
import com.xjrsoft.workflow.service.IWorkflowFormRelationService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 工作流 流程 与 表单关联表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2023-03-27
|
||||
*/
|
||||
@Service
|
||||
public class WorkflowFormRelationServiceImpl extends ServiceImpl<WorkflowFormRelationMapper, WorkflowFormRelation> implements IWorkflowFormRelationService {
|
||||
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package com.xjrsoft.workflow.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.xjrsoft.workflow.entity.WorkflowRecord;
|
||||
import com.xjrsoft.workflow.mapper.WorkflowRecordMapper;
|
||||
import com.xjrsoft.workflow.service.IWorkflowRecordService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 工作流 流转记录信息 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2022-11-10
|
||||
*/
|
||||
@Service
|
||||
public class WorkflowRecordServiceImpl extends ServiceImpl<WorkflowRecordMapper, WorkflowRecord> implements IWorkflowRecordService {
|
||||
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
package com.xjrsoft.workflow.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.xjrsoft.workflow.entity.WorkflowSchemaAuth;
|
||||
import com.xjrsoft.workflow.mapper.WorkflowSchemaAuthMapper;
|
||||
import com.xjrsoft.workflow.service.IWorkflowSchemaAuthService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 流程模板权限 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2022-07-04
|
||||
*/
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class WorkflowSchemaAuthServiceImpl extends ServiceImpl<WorkflowSchemaAuthMapper, WorkflowSchemaAuth> implements IWorkflowSchemaAuthService {
|
||||
|
||||
}
|
||||
@ -0,0 +1,226 @@
|
||||
package com.xjrsoft.workflow.service.impl;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.github.yulichang.base.MPJBaseServiceImpl;
|
||||
import com.xjrsoft.common.core.constant.GlobalConstant;
|
||||
import com.xjrsoft.common.core.enums.EnabledMark;
|
||||
import com.xjrsoft.common.core.enums.WorkflowMultiInstanceType;
|
||||
import com.xjrsoft.common.core.exception.MyException;
|
||||
import com.xjrsoft.organization.entity.User;
|
||||
import com.xjrsoft.workflow.constant.WorkflowConstant;
|
||||
import com.xjrsoft.workflow.dto.HistoryChangeDto;
|
||||
import com.xjrsoft.workflow.entity.WorkflowRecord;
|
||||
import com.xjrsoft.workflow.entity.WorkflowSchema;
|
||||
import com.xjrsoft.workflow.entity.WorkflowSchemaHistory;
|
||||
import com.xjrsoft.workflow.mapper.WorkflowSchemaHistoryMapper;
|
||||
import com.xjrsoft.workflow.mapper.WorkflowSchemaMapper;
|
||||
import com.xjrsoft.workflow.model.WorkflowSchemaConfig;
|
||||
import com.xjrsoft.workflow.service.IWorkflowRecordService;
|
||||
import com.xjrsoft.workflow.service.IWorkflowSchemaHistoryService;
|
||||
import com.xjrsoft.workflow.utils.WorkFlowUtil;
|
||||
import com.xjrsoft.workflow.vo.ProcessChangeVo;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.camunda.bpm.engine.HistoryService;
|
||||
import org.camunda.bpm.engine.RepositoryService;
|
||||
import org.camunda.bpm.engine.RuntimeService;
|
||||
import org.camunda.bpm.engine.TaskService;
|
||||
import org.camunda.bpm.engine.history.HistoricVariableInstance;
|
||||
import org.camunda.bpm.engine.impl.persistence.entity.HistoricVariableInstanceEntity;
|
||||
import org.camunda.bpm.engine.impl.persistence.entity.TaskEntity;
|
||||
import org.camunda.bpm.engine.migration.MigrationPlan;
|
||||
import org.camunda.bpm.engine.migration.MigrationPlanExecutionBuilder;
|
||||
import org.camunda.bpm.engine.repository.Deployment;
|
||||
import org.camunda.bpm.engine.runtime.ProcessInstance;
|
||||
import org.camunda.bpm.engine.spring.SpringProcessEngineConfiguration;
|
||||
import org.camunda.bpm.engine.task.Task;
|
||||
import org.camunda.commons.utils.IoUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 流程模板历史记录表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2022-11-16
|
||||
*/
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class WorkflowSchemaHistoryServiceImpl extends MPJBaseServiceImpl<WorkflowSchemaHistoryMapper, WorkflowSchemaHistory> implements IWorkflowSchemaHistoryService {
|
||||
|
||||
private final WorkflowSchemaHistoryMapper workflowSchemaHistoryMapper;
|
||||
|
||||
private final RepositoryService repositoryService;
|
||||
|
||||
private final WorkflowSchemaMapper workflowSchemaMapper;
|
||||
|
||||
private final HistoryService historyService;
|
||||
|
||||
private final RuntimeService runtimeService;
|
||||
|
||||
private final TaskService taskService;
|
||||
|
||||
private final SpringProcessEngineConfiguration processEngineConfiguration;
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public List<ProcessChangeVo> change(HistoryChangeDto dto) {
|
||||
WorkflowSchema workflowSchema = workflowSchemaMapper.selectById(dto.getSchemaId());
|
||||
|
||||
WorkflowSchemaHistory history = getById(dto.getId());
|
||||
WorkflowSchemaConfig workflowSchemaConfig = JSONUtil.toBean(history.getJsonContent(), WorkflowSchemaConfig.class);
|
||||
|
||||
WorkflowSchema newWorkflowSchema = BeanUtil.toBean(workflowSchemaConfig.getProcessConfig(), WorkflowSchema.class);
|
||||
|
||||
newWorkflowSchema.setId(workflowSchema.getId());
|
||||
newWorkflowSchema.setXmlContent(history.getXmlContent());
|
||||
newWorkflowSchema.setJsonContent(history.getJsonContent());
|
||||
|
||||
//找到历史记录当前活动流程
|
||||
// WorkflowSchemaHistory activeHistory = getOne(Wrappers.lambdaQuery(WorkflowSchemaHistory.class).eq(WorkflowSchemaHistory::getSchemaId, dto.getSchemaId()).eq(WorkflowSchemaHistory::getActivityFlag, YesOrNoEnum.YES.getCode()));
|
||||
|
||||
|
||||
|
||||
//找到所有非当前所选历史记录的所有数据
|
||||
List<WorkflowSchemaHistory> list = list(Wrappers.lambdaQuery(WorkflowSchemaHistory.class).eq(WorkflowSchemaHistory::getSchemaId, dto.getSchemaId()).ne(WorkflowSchemaHistory::getId, dto.getId()).select(WorkflowSchemaHistory::getDefinitionId,WorkflowSchemaHistory::getDefinitionKey));
|
||||
|
||||
|
||||
//将所有历史记录设置为 非活动版本
|
||||
WorkflowSchemaHistory paramObj = new WorkflowSchemaHistory();
|
||||
paramObj.setActivityFlag(EnabledMark.DISABLED.getCode());
|
||||
LambdaQueryWrapper<WorkflowSchemaHistory> wrapper = Wrappers.lambdaQuery(WorkflowSchemaHistory.class).eq(WorkflowSchemaHistory::getSchemaId, dto.getSchemaId());
|
||||
workflowSchemaHistoryMapper.update(paramObj, wrapper);
|
||||
|
||||
//将当前所选history 设置为活动版本
|
||||
wrapper.eq(WorkflowSchemaHistory::getId, dto.getId());
|
||||
paramObj.setActivityFlag(EnabledMark.ENABLED.getCode());
|
||||
workflowSchemaHistoryMapper.update(paramObj, wrapper);
|
||||
|
||||
try {
|
||||
for (WorkflowSchemaHistory workflowSchemaHistory : list) {
|
||||
|
||||
MigrationPlan migrationPlan = runtimeService
|
||||
.createMigrationPlan(workflowSchemaHistory.getDefinitionId(), history.getDefinitionId())
|
||||
.mapEqualActivities()
|
||||
.updateEventTriggers()
|
||||
.build();
|
||||
//找到当前流程模板的正在运行的所有流程
|
||||
List<ProcessInstance> processInstances = runtimeService.createProcessInstanceQuery().processDefinitionId(workflowSchemaHistory.getDefinitionId()).active().list();
|
||||
if (processInstances.size() > 0) {
|
||||
List<String> processInstanceIds = processInstances.stream().map(ProcessInstance::getProcessInstanceId).collect(Collectors.toList());
|
||||
|
||||
MigrationPlanExecutionBuilder migrationPlanExecutionBuilder = runtimeService.newMigration(migrationPlan).processInstanceIds(processInstanceIds)
|
||||
.skipCustomListeners()
|
||||
.skipIoMappings();
|
||||
migrationPlanExecutionBuilder.execute();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception e){
|
||||
throw new MyException("当前流程图过于复杂,并且流程历史记录的模板,有正在进行的流程,不适用于迁移,请等待进行的流程完结!");
|
||||
}
|
||||
|
||||
|
||||
|
||||
List<ProcessInstance> newProcesses = runtimeService.createProcessInstanceQuery().processDefinitionId(history.getDefinitionId()).list();
|
||||
|
||||
|
||||
String[] processIds = newProcesses.stream().map(ProcessInstance::getProcessInstanceId).toArray(String[]::new);
|
||||
|
||||
List<HistoricVariableInstance> variableInstanceList = historyService.createHistoricVariableInstanceQuery().processInstanceIdIn(processIds).variableName(WorkflowConstant.PROCESS_SERIAL_NUMBER_KEY).list();
|
||||
|
||||
List<Task> taskList = taskService.createTaskQuery().processInstanceIdIn(processIds).list();
|
||||
|
||||
List<ProcessChangeVo> voList = new ArrayList<>(newProcesses.size());
|
||||
|
||||
|
||||
for (ProcessInstance newProcess : newProcesses) {
|
||||
ProcessChangeVo vo = new ProcessChangeVo();
|
||||
vo.setName(newWorkflowSchema.getName());
|
||||
|
||||
HistoricVariableInstance historicVariableInstance = variableInstanceList.stream().filter(x -> x.getProcessInstanceId().equals(newProcess.getProcessInstanceId())).findFirst().orElse(new HistoricVariableInstanceEntity());
|
||||
vo.setSerailNumber(Convert.toInt(historicVariableInstance.getValue()));
|
||||
|
||||
vo.setStatus(1);
|
||||
|
||||
Task task = taskList.stream().filter(x -> x.getProcessInstanceId().equals(newProcess.getProcessInstanceId())).findFirst().orElse(new TaskEntity());
|
||||
|
||||
//获取当前用户的信息
|
||||
User user = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_INFO_KEY, new User());
|
||||
Long schemaId = Convert.toLong(taskService.getVariable(task.getId(), WorkflowConstant.PROCESS_SCHEMA_ID_KEY));
|
||||
IWorkflowRecordService workflowRecordService = SpringUtil.getBean(IWorkflowRecordService.class);
|
||||
//新增流程发起流程记录
|
||||
WorkflowRecord record = new WorkflowRecord();
|
||||
record.setNodeId(task.getId());
|
||||
record.setNodeName(task.getName());
|
||||
record.setNodeType(WorkflowConstant.USER_TASK_TYPE_NAME);
|
||||
record.setProcessId(task.getProcessInstanceId());
|
||||
record.setSchemaId(schemaId);
|
||||
record.setNodeMultiType(WorkflowMultiInstanceType.NONE.getCode());
|
||||
record.setRecordTime(LocalDateTime.now());
|
||||
|
||||
//如果当前任务的节点被删除 默认将此任务完成
|
||||
if (workflowSchemaConfig.getChildNodeConfig().stream().noneMatch(x -> x.get(WorkflowConstant.NODE_CONFIG_ID_KEY).equals(task.getTaskDefinitionKey()))) {
|
||||
taskService.complete(task.getId());
|
||||
|
||||
List<Task> nextTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list();
|
||||
List<String> nextTaskNameList = nextTaskList.stream().map(Task::getName).collect(Collectors.toList());
|
||||
vo.setDetail("流程已经变更到" + StrUtil.join(StringPool.COMMA, nextTaskNameList) + "节点");
|
||||
|
||||
//[操作人名称]对流程进行了变更,流程当前节点为[节点名称]。
|
||||
record.setMessage("【" + user.getName() + "】对流程进行了变更,流程当前节点为【" + StrUtil.join("、", nextTaskNameList) + "】");
|
||||
workflowRecordService.save(record);
|
||||
} else {
|
||||
vo.setDetail("流程已经变更到" + task.getName() + "节点");
|
||||
|
||||
//[操作人名称]对流程进行了变更,流程当前节点为[节点名称]。
|
||||
record.setMessage("【" + user.getName() + "】对流程进行了变更,流程当前节点为【" + task.getName() + "】");
|
||||
workflowRecordService.save(record);
|
||||
}
|
||||
|
||||
voList.add(vo);
|
||||
}
|
||||
|
||||
|
||||
//更新的流程重新部署
|
||||
Deployment deploy = repositoryService.createDeployment()
|
||||
.addInputStream(newWorkflowSchema.getName() + StringPool.DOT + WorkflowConstant.WORKFLOW_SUFFIX, IoUtil.stringAsInputStream(newWorkflowSchema.getXmlContent())).name(newWorkflowSchema.getName())
|
||||
.deploy();
|
||||
|
||||
newWorkflowSchema.setDeploymentId(deploy.getId());
|
||||
workflowSchemaMapper.updateById(newWorkflowSchema);
|
||||
|
||||
|
||||
//缓存节点监听器数据
|
||||
CompletableFuture.runAsync(() -> {
|
||||
WorkFlowUtil.removeNodeListener(workflowSchema.getDeploymentId());
|
||||
WorkFlowUtil.cacheNodeListener(deploy.getId(), workflowSchemaConfig.getChildNodeConfig());
|
||||
});
|
||||
|
||||
|
||||
|
||||
return voList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProcessChangeVo> processChanges(HistoryChangeDto dto) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,502 @@
|
||||
package com.xjrsoft.workflow.service.impl;
|
||||
|
||||
import cn.dev33.satoken.session.SaSession;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import com.github.yulichang.base.MPJBaseServiceImpl;
|
||||
import com.github.yulichang.toolkit.MPJWrappers;
|
||||
import com.xjrsoft.common.core.constant.GlobalConstant;
|
||||
import com.xjrsoft.common.core.domain.page.PageOutput;
|
||||
import com.xjrsoft.common.core.enums.EnabledMark;
|
||||
import com.xjrsoft.common.core.enums.YesOrNoEnum;
|
||||
import com.xjrsoft.common.core.exception.MyException;
|
||||
import com.xjrsoft.common.core.uitls.VoToColumnUtil;
|
||||
import com.xjrsoft.common.mybatis.utils.ConventPage;
|
||||
import com.xjrsoft.organization.entity.Post;
|
||||
import com.xjrsoft.system.entity.DictionaryDetail;
|
||||
import com.xjrsoft.workflow.constant.WorkflowConstant;
|
||||
import com.xjrsoft.workflow.dto.*;
|
||||
import com.xjrsoft.workflow.entity.WorkflowSchema;
|
||||
import com.xjrsoft.workflow.entity.WorkflowSchemaAuth;
|
||||
import com.xjrsoft.workflow.entity.WorkflowSchemaDraft;
|
||||
import com.xjrsoft.workflow.entity.WorkflowSchemaHistory;
|
||||
import com.xjrsoft.workflow.mapper.WorkflowSchemaDraftMapper;
|
||||
import com.xjrsoft.workflow.mapper.WorkflowSchemaHistoryMapper;
|
||||
import com.xjrsoft.workflow.mapper.WorkflowSchemaMapper;
|
||||
import com.xjrsoft.workflow.model.AuthConfig;
|
||||
import com.xjrsoft.workflow.model.FormInitConfig;
|
||||
import com.xjrsoft.workflow.model.MemberConfig;
|
||||
import com.xjrsoft.workflow.model.WorkflowSchemaConfig;
|
||||
import com.xjrsoft.workflow.service.IWorkflowSchemaAuthService;
|
||||
import com.xjrsoft.workflow.service.IWorkflowSchemaService;
|
||||
import com.xjrsoft.workflow.utils.WorkFlowUtil;
|
||||
import com.xjrsoft.workflow.vo.WorkflowSchemaDraftPageVo;
|
||||
import com.xjrsoft.workflow.vo.WorkflowSchemaPageVo;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import org.camunda.bpm.engine.RepositoryService;
|
||||
import org.camunda.bpm.engine.TaskService;
|
||||
import org.camunda.bpm.engine.repository.Deployment;
|
||||
import org.camunda.bpm.engine.repository.ProcessDefinition;
|
||||
import org.camunda.bpm.engine.spring.SpringProcessEngineConfiguration;
|
||||
import org.camunda.commons.utils.IoUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 流程模板表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2022-07-04
|
||||
*/
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class WorkflowSchemaServiceImpl extends MPJBaseServiceImpl<WorkflowSchemaMapper, WorkflowSchema> implements IWorkflowSchemaService {
|
||||
|
||||
private final RepositoryService repositoryService;
|
||||
|
||||
private final SpringProcessEngineConfiguration processEngineConfiguration;
|
||||
|
||||
private final WorkflowSchemaDraftMapper workflowSchemaDraftMapper;
|
||||
|
||||
private final WorkflowSchemaHistoryMapper workflowSchemaHistoryMapper;
|
||||
|
||||
private final TaskService taskService;
|
||||
|
||||
private final IWorkflowSchemaAuthService workflowSchemaAuthService;
|
||||
|
||||
@Override
|
||||
public PageOutput<WorkflowSchemaPageVo> getPage(WorkflowSchemaPageDto dto) {
|
||||
|
||||
SaSession tokenSession = StpUtil.getTokenSession();
|
||||
List<Long> roleIds = tokenSession.get(GlobalConstant.LOGIN_USER_ROLE_ID_KEY, new ArrayList<>());
|
||||
Post post = tokenSession.get(GlobalConstant.LOGIN_USER_POST_INFO_KEY, new Post());
|
||||
|
||||
List<Long> allSchemaId = new ArrayList<>();
|
||||
|
||||
//是否需要管控权限
|
||||
if (dto.getIsAuth()) {
|
||||
LambdaQueryWrapper<WorkflowSchemaAuth> query = Wrappers.lambdaQuery(WorkflowSchemaAuth.class)
|
||||
.eq(WorkflowSchemaAuth::getObjType, -1)
|
||||
.or(x -> x.eq(WorkflowSchemaAuth::getObjType, 2).in(WorkflowSchemaAuth::getObjId, post.getId()))
|
||||
.or(x -> x.eq(WorkflowSchemaAuth::getObjType, 1).in(WorkflowSchemaAuth::getObjId, roleIds))
|
||||
.or(x -> x.eq(WorkflowSchemaAuth::getObjType, 0).in(WorkflowSchemaAuth::getObjId, StpUtil.getLoginIdAsLong())
|
||||
);
|
||||
List<WorkflowSchemaAuth> authList = workflowSchemaAuthService.list(query);
|
||||
allSchemaId = authList.stream().map(WorkflowSchemaAuth::getSchemaId).collect(Collectors.toList());
|
||||
|
||||
if (CollectionUtil.isEmpty(allSchemaId)) {
|
||||
//如果权限为空 返回空数组
|
||||
PageOutput<WorkflowSchemaPageVo> pageOutput = new PageOutput<>();
|
||||
pageOutput.setList(new ArrayList<>());
|
||||
pageOutput.setCurrentPage(0);
|
||||
pageOutput.setTotalPage(0);
|
||||
pageOutput.setPageSize(0);
|
||||
return pageOutput;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//因为多表关联 会有多个表都使用了id字段, 所以必须专门指定主表的Id
|
||||
IPage<WorkflowSchemaPageVo> page = selectJoinListPage(ConventPage.getPage(dto), WorkflowSchemaPageVo.class,
|
||||
MPJWrappers.<WorkflowSchema>lambdaJoin()
|
||||
.disableSubLogicDel()
|
||||
.orderByDesc(WorkflowSchema::getId)
|
||||
.eq(ObjectUtil.isNotNull(dto.getEnabledMark()), WorkflowSchema::getEnabledMark, dto.getEnabledMark())
|
||||
.like(StrUtil.isNotBlank(dto.getKeyword()), WorkflowSchema::getName, dto.getKeyword())
|
||||
.like(StrUtil.isNotBlank(dto.getName()), WorkflowSchema::getName, dto.getName())
|
||||
.like(StrUtil.isNotBlank(dto.getCode()), WorkflowSchema::getCode, dto.getCode())
|
||||
.eq(ObjectUtil.isNotNull(dto.getCategory()), WorkflowSchema::getCategory, dto.getCategory())
|
||||
.in(dto.getIsAuth() && CollectionUtil.isNotEmpty(allSchemaId), WorkflowSchema::getId, allSchemaId)
|
||||
.select(WorkflowSchema::getId)
|
||||
.select(WorkflowSchema.class, x -> VoToColumnUtil.fieldsToColumns(WorkflowSchemaPageVo.class).contains(x.getProperty()))
|
||||
.selectAs(DictionaryDetail::getName, WorkflowSchemaPageVo::getCategoryName)
|
||||
.leftJoin(DictionaryDetail.class, DictionaryDetail::getId, WorkflowSchema::getCategory));
|
||||
|
||||
return ConventPage.getPageOutput(page);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@SneakyThrows
|
||||
public boolean add(AddWorkflowSchemaDto dto) {
|
||||
LambdaQueryWrapper<WorkflowSchema> countQuery = Wrappers.lambdaQuery(WorkflowSchema.class).eq(WorkflowSchema::getName, dto.getProcessConfig().getName()).or().eq(WorkflowSchema::getCode, dto.getProcessConfig().getCode());
|
||||
if (count(countQuery) > 0) {
|
||||
throw new MyException("当前模板名称和模板编号重复!");
|
||||
}
|
||||
|
||||
WorkflowSchemaConfig workflowSchemaConfig = BeanUtil.toBean(dto, WorkflowSchemaConfig.class);
|
||||
WorkflowSchema workflowSchema = BeanUtil.toBean(dto.getProcessConfig(), WorkflowSchema.class);
|
||||
|
||||
//表单发起流程
|
||||
FormInitConfig formInitConfig = workflowSchemaConfig.getProcessConfig().getFormInitConfig();
|
||||
if (formInitConfig.getEnabled()) {
|
||||
LambdaQueryWrapper<WorkflowSchema> select = Wrappers.lambdaQuery(WorkflowSchema.class).eq(WorkflowSchema::getFormId, formInitConfig.getFormId()).select(WorkflowSchema::getId);
|
||||
|
||||
if (count(select) > 0) {
|
||||
throw new MyException("当前表单已经绑定过流程,请重新选择!");
|
||||
}
|
||||
workflowSchema.setFormId(formInitConfig.getFormId());
|
||||
}
|
||||
|
||||
Deployment deploy = repositoryService.createDeployment()
|
||||
.addInputStream(workflowSchemaConfig.getProcessConfig().getName() + StringPool.DOT + WorkflowConstant.WORKFLOW_SUFFIX, IoUtil.stringAsInputStream(workflowSchemaConfig.getProcessConfig().getXmlContent())).name(workflowSchemaConfig.getProcessConfig().getName()).deploy();
|
||||
|
||||
//存储流程部署id
|
||||
workflowSchema.setDeploymentId(deploy.getId());
|
||||
|
||||
//获取流程定义id
|
||||
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploy.getId()).singleResult();
|
||||
//存储流程定义key
|
||||
workflowSchema.setDefinitionKey(processDefinition.getKey());
|
||||
|
||||
//存储流程定义id
|
||||
workflowSchema.setDefinitionId(processDefinition.getId());
|
||||
|
||||
//把配置json存储 (清除掉xml)
|
||||
workflowSchemaConfig.getProcessConfig().setXmlContent("");
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
SimpleModule simpleModule = new SimpleModule();
|
||||
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
|
||||
simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
|
||||
mapper.registerModule(simpleModule);
|
||||
|
||||
String jsonContent = mapper.writeValueAsString(workflowSchemaConfig);
|
||||
|
||||
workflowSchema.setJsonContent(jsonContent);
|
||||
|
||||
save(workflowSchema);
|
||||
|
||||
AuthConfig authConfig = workflowSchemaConfig.getProcessConfig().getAuthConfig();
|
||||
|
||||
//如果是指定人员
|
||||
if (authConfig.getAuthType() == 1) {
|
||||
List<WorkflowSchemaAuth> authList = new ArrayList<>();
|
||||
List<MemberConfig> authMemberConfigs = authConfig.getAuthMemberConfigs();
|
||||
for (MemberConfig authMemberConfig : authMemberConfigs) {
|
||||
WorkflowSchemaAuth auth = new WorkflowSchemaAuth();
|
||||
auth.setSchemaId(workflowSchema.getId());
|
||||
auth.setObjId(Long.parseLong(authMemberConfig.getId()));
|
||||
auth.setObjName(authMemberConfig.getName());
|
||||
auth.setObjType(authMemberConfig.getMemberType());
|
||||
authList.add(auth);
|
||||
}
|
||||
workflowSchemaAuthService.saveBatch(authList);
|
||||
}
|
||||
//如果所有人
|
||||
else {
|
||||
WorkflowSchemaAuth auth = new WorkflowSchemaAuth();
|
||||
auth.setSchemaId(workflowSchema.getId());
|
||||
auth.setObjType(-1);
|
||||
workflowSchemaAuthService.save(auth);
|
||||
}
|
||||
|
||||
|
||||
//将新增的数据 记录模板历史记录
|
||||
WorkflowSchemaHistory history = new WorkflowSchemaHistory();
|
||||
history.setSchemaId(workflowSchema.getId());
|
||||
history.setVersion(1);
|
||||
history.setActivityFlag(EnabledMark.ENABLED.getCode());
|
||||
history.setXmlContent(workflowSchema.getXmlContent());
|
||||
history.setJsonContent(workflowSchema.getJsonContent());
|
||||
history.setDefinitionKey(workflowSchema.getDefinitionKey());
|
||||
history.setDeploymentId(workflowSchema.getDeploymentId());
|
||||
history.setDefinitionId(workflowSchema.getDefinitionId());
|
||||
|
||||
|
||||
//缓存节点监听器数据
|
||||
CompletableFuture.runAsync(() -> {
|
||||
WorkFlowUtil.cacheNodeListener(deploy.getId(), workflowSchemaConfig.getChildNodeConfig());
|
||||
});
|
||||
|
||||
|
||||
return workflowSchemaHistoryMapper.insert(history) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addDraft(AddWorkflowSchemaDraftDto dto) {
|
||||
WorkflowSchemaConfig workflowSchemaConfig = BeanUtil.toBean(dto, WorkflowSchemaConfig.class);
|
||||
WorkflowSchemaDraft workflowSchemaDraft = BeanUtil.toBean(dto.getProcessConfig(), WorkflowSchemaDraft.class);
|
||||
|
||||
//把配置json存储
|
||||
workflowSchemaDraft.setJsonContent(JSONUtil.toJsonStr(workflowSchemaConfig));
|
||||
|
||||
return workflowSchemaDraftMapper.insert(workflowSchemaDraft) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageOutput<WorkflowSchemaDraftPageVo> getDraftPage(WorkflowSchemaDraftPageDto dto) {
|
||||
|
||||
LambdaQueryWrapper<WorkflowSchemaDraft> queryWrapper = Wrappers.lambdaQuery(WorkflowSchemaDraft.class)
|
||||
.like(StrUtil.isNotBlank(dto.getKeyword()), WorkflowSchemaDraft::getName, dto.getKeyword())
|
||||
.between(ObjectUtil.isNotNull(dto.getStartTime()) && ObjectUtil.isNotNull(dto.getEndTime()), WorkflowSchemaDraft::getCreateDate, dto.getStartTime(), dto.getEndTime())
|
||||
.select(WorkflowSchemaDraft.class, x -> VoToColumnUtil.fieldsToColumns(WorkflowSchemaPageVo.class).contains(x.getProperty()));
|
||||
|
||||
IPage<WorkflowSchemaDraft> workflowSchemaDraftPage = workflowSchemaDraftMapper.selectPage(ConventPage.getPage(dto), queryWrapper);
|
||||
|
||||
return ConventPage.getPageOutput(workflowSchemaDraftPage, WorkflowSchemaDraftPageVo.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@SneakyThrows
|
||||
public boolean update(UpdateWorkflowSchemaDto dto) {
|
||||
LambdaQueryWrapper<WorkflowSchema> countQuery = Wrappers.lambdaQuery(WorkflowSchema.class).ne(WorkflowSchema::getId, dto.getId()).and(x -> x.eq(WorkflowSchema::getName, dto.getProcessConfig().getName()).or().eq(WorkflowSchema::getCode, dto.getProcessConfig().getCode()));
|
||||
if (count(countQuery) > 0) {
|
||||
throw new MyException("当前模板名称和模板编号重复!");
|
||||
}
|
||||
|
||||
|
||||
WorkflowSchema workflowSchema = getById(dto.getId());
|
||||
|
||||
if (workflowSchema == null) {
|
||||
throw new MyException("找不到此模板!");
|
||||
}
|
||||
|
||||
workflowSchema.setName(dto.getProcessConfig().getName());
|
||||
workflowSchema.setCode(dto.getProcessConfig().getCode());
|
||||
workflowSchema.setRemark(dto.getProcessConfig().getRemark());
|
||||
workflowSchema.setXmlContent(dto.getProcessConfig().getXmlContent());
|
||||
workflowSchema.setWorkflowChat(dto.getProcessConfig().getWorkflowChat());
|
||||
workflowSchema.setCategory(Long.valueOf(dto.getProcessConfig().getCategory()));
|
||||
|
||||
WorkflowSchemaConfig workflowSchemaConfig = BeanUtil.toBean(dto, WorkflowSchemaConfig.class);
|
||||
|
||||
|
||||
//表单发起流程
|
||||
FormInitConfig formInitConfig = workflowSchemaConfig.getProcessConfig().getFormInitConfig();
|
||||
if (formInitConfig.getEnabled()) {
|
||||
LambdaQueryWrapper<WorkflowSchema> select = Wrappers.lambdaQuery(WorkflowSchema.class).ne(WorkflowSchema::getId, dto.getId()).eq(WorkflowSchema::getFormId, formInitConfig.getFormId()).select(WorkflowSchema::getId);
|
||||
|
||||
if (count(select) > 0) {
|
||||
throw new MyException("当前表单已经绑定过流程,请重新选择!");
|
||||
}
|
||||
workflowSchema.setFormId(formInitConfig.getFormId());
|
||||
} else {
|
||||
workflowSchema.setFormId(0L);
|
||||
}
|
||||
|
||||
|
||||
// ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(workflowSchema.getDeploymentId()).singleResult();
|
||||
//
|
||||
//
|
||||
// //如果需要级联删除 把第二个参数设置为true
|
||||
// //级联删除 会删除所有关联数据 包括 历史记录
|
||||
// repositoryService.deleteProcessDefinition(processDefinition.getId());
|
||||
//
|
||||
// //如果需要级联删除 把第二个参数设置为true
|
||||
// //级联删除 会删除所有关联数据 包括 历史记录
|
||||
// repositoryService.deleteDeployment(workflowSchema.getDeploymentId());
|
||||
|
||||
|
||||
//因为流程图会被缓存 如果修改了流程图 缓存会没变。 需要清理本地缓存
|
||||
// processEngineConfiguration.getDeploymentCache().removeDeployment(workflowSchema.getDeploymentId());
|
||||
|
||||
//更新的流程重新部署
|
||||
Deployment deploy = repositoryService.createDeployment()
|
||||
.addInputStream(dto.getProcessConfig().getName() + StringPool.DOT + WorkflowConstant.WORKFLOW_SUFFIX, IoUtil.stringAsInputStream(dto.getProcessConfig().getXmlContent())).name(dto.getProcessConfig().getName()).deploy();
|
||||
|
||||
//获取流程定义id
|
||||
ProcessDefinition newProcessDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploy.getId()).singleResult();
|
||||
//存储流程定义key
|
||||
workflowSchema.setDefinitionKey(newProcessDefinition.getKey());
|
||||
//存储流程定义id
|
||||
workflowSchema.setDefinitionId(newProcessDefinition.getId());
|
||||
workflowSchema.setDeploymentId(deploy.getId());
|
||||
|
||||
AuthConfig authConfig = workflowSchemaConfig.getProcessConfig().getAuthConfig();
|
||||
//如果是指定人员
|
||||
if (authConfig.getAuthType() == 1) {
|
||||
workflowSchemaAuthService.remove(Wrappers.lambdaQuery(WorkflowSchemaAuth.class).eq(WorkflowSchemaAuth::getSchemaId, workflowSchema.getId()));
|
||||
List<WorkflowSchemaAuth> authList = new ArrayList<>();
|
||||
List<MemberConfig> authMemberConfigs = authConfig.getAuthMemberConfigs();
|
||||
for (MemberConfig authMemberConfig : authMemberConfigs) {
|
||||
WorkflowSchemaAuth auth = new WorkflowSchemaAuth();
|
||||
auth.setSchemaId(workflowSchema.getId());
|
||||
auth.setObjId(Long.parseLong(authMemberConfig.getId()));
|
||||
auth.setObjName(authMemberConfig.getName());
|
||||
auth.setObjType(authMemberConfig.getMemberType());
|
||||
authList.add(auth);
|
||||
}
|
||||
workflowSchemaAuthService.saveBatch(authList);
|
||||
}
|
||||
//如果所有人
|
||||
else {
|
||||
workflowSchemaAuthService.remove(Wrappers.lambdaQuery(WorkflowSchemaAuth.class).eq(WorkflowSchemaAuth::getSchemaId, workflowSchema.getId()));
|
||||
WorkflowSchemaAuth auth = new WorkflowSchemaAuth();
|
||||
auth.setSchemaId(workflowSchema.getId());
|
||||
auth.setObjType(-1);
|
||||
workflowSchemaAuthService.save(auth);
|
||||
}
|
||||
|
||||
|
||||
//找到上一个版本号 只需要版本号 以及 id
|
||||
LambdaQueryWrapper<WorkflowSchemaHistory> queryWrapper = Wrappers.lambdaQuery(WorkflowSchemaHistory.class)
|
||||
.eq(WorkflowSchemaHistory::getSchemaId, workflowSchema.getId())
|
||||
.eq(WorkflowSchemaHistory::getActivityFlag, YesOrNoEnum.YES.getCode())
|
||||
.select(WorkflowSchemaHistory::getVersion, WorkflowSchemaHistory::getId)
|
||||
.orderByDesc(WorkflowSchemaHistory::getVersion);
|
||||
WorkflowSchemaHistory oldHistory = workflowSchemaHistoryMapper.selectOne(queryWrapper);
|
||||
Integer version = oldHistory.getVersion();
|
||||
|
||||
//把配置json存储 (清除掉xml)
|
||||
workflowSchemaConfig.getProcessConfig().setXmlContent("");
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
SimpleModule simpleModule = new SimpleModule();
|
||||
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
|
||||
simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
|
||||
mapper.registerModule(simpleModule);
|
||||
|
||||
String jsonContent = mapper.writeValueAsString(workflowSchemaConfig);
|
||||
|
||||
workflowSchema.setJsonContent(jsonContent);
|
||||
|
||||
//将修改后的数据 记录模板历史记录
|
||||
WorkflowSchemaHistory history = new WorkflowSchemaHistory();
|
||||
history.setSchemaId(workflowSchema.getId());
|
||||
history.setVersion(version + 1);
|
||||
history.setActivityFlag(EnabledMark.ENABLED.getCode());
|
||||
history.setXmlContent(workflowSchema.getXmlContent());
|
||||
history.setJsonContent(workflowSchema.getJsonContent());
|
||||
history.setWorkflowChat(workflowSchema.getWorkflowChat());
|
||||
history.setDefinitionId(workflowSchema.getDefinitionId());
|
||||
history.setDefinitionKey(workflowSchema.getDefinitionKey());
|
||||
workflowSchemaHistoryMapper.insert(history);
|
||||
//将上一个版本的 历史数据 flag 改为 非活动版本
|
||||
oldHistory.setActivityFlag(EnabledMark.DISABLED.getCode());
|
||||
workflowSchemaHistoryMapper.updateById(oldHistory);
|
||||
|
||||
//缓存节点监听器数据
|
||||
CompletableFuture.runAsync(() -> {
|
||||
WorkFlowUtil.cacheNodeListener(deploy.getId(), workflowSchemaConfig.getChildNodeConfig());
|
||||
});
|
||||
|
||||
|
||||
return updateById(workflowSchema);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean delete(List<Long> ids) {
|
||||
|
||||
for (Long id : ids) {
|
||||
long count = taskService.createTaskQuery().processVariableValueEquals(WorkflowConstant.PROCESS_SCHEMA_ID_KEY, id).count();
|
||||
if (count > 0) {
|
||||
throw new MyException("有流程正在执行 无法删除!");
|
||||
}
|
||||
}
|
||||
QueryWrapper<WorkflowSchema> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.lambda()
|
||||
.in(WorkflowSchema::getId, ids)
|
||||
.select(WorkflowSchema::getDeploymentId, WorkflowSchema::getDefinitionId);
|
||||
|
||||
List<WorkflowSchema> workflowSchemas = list(queryWrapper);
|
||||
|
||||
//获取到所有流程定义id
|
||||
List<String> definitionIds = workflowSchemas.stream().map(WorkflowSchema::getDefinitionId).collect(Collectors.toList());
|
||||
//获取到所有deployIds
|
||||
List<String> deploymentIds = workflowSchemas.stream().map(WorkflowSchema::getDeploymentId).collect(Collectors.toList());
|
||||
|
||||
try {
|
||||
repositoryService.deleteProcessDefinitions().byIds(StrUtil.join(",", definitionIds)).delete();
|
||||
}catch (Exception e){
|
||||
if (e.getMessage().contains("since there exists")) {
|
||||
throw new MyException("有流程正在执行 无法删除!");//避免有外部任务正在执行的流程删除时,提示引擎删除错误。
|
||||
}
|
||||
}
|
||||
for (String deploymentId : deploymentIds) {
|
||||
repositoryService.deleteDeployment(deploymentId);
|
||||
}
|
||||
|
||||
//缓存节点监听器数据
|
||||
CompletableFuture.runAsync(() -> {
|
||||
for (String deploymentId : deploymentIds) {
|
||||
WorkFlowUtil.removeNodeListener(deploymentId);
|
||||
}
|
||||
});
|
||||
|
||||
return removeBatchByIds(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@SneakyThrows
|
||||
public boolean importSchema(MultipartFile multipartFile) {
|
||||
|
||||
//用流读取文件
|
||||
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(multipartFile.getInputStream()));
|
||||
String line;
|
||||
StringBuilder content = new StringBuilder();
|
||||
// 读取想定文件
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
content.append(line);
|
||||
}
|
||||
|
||||
WorkflowSchemaConfig workflowSchemaConfig = JSONUtil.toBean(content.toString(), WorkflowSchemaConfig.class);
|
||||
|
||||
WorkflowSchema workflowSchema = BeanUtil.toBean(workflowSchemaConfig.getProcessConfig(), WorkflowSchema.class);
|
||||
|
||||
Deployment deploy = repositoryService.createDeployment()
|
||||
.addInputStream(workflowSchemaConfig.getProcessConfig().getName() + StringPool.DOT + WorkflowConstant.WORKFLOW_SUFFIX, IoUtil.stringAsInputStream(workflowSchemaConfig.getProcessConfig().getXmlContent())).name(workflowSchemaConfig.getProcessConfig().getName()).deploy();
|
||||
|
||||
//存储流程部署id
|
||||
workflowSchema.setDeploymentId(deploy.getId());
|
||||
|
||||
//获取流程定义id
|
||||
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploy.getId()).singleResult();
|
||||
//存储流程定义key
|
||||
workflowSchema.setDefinitionKey(processDefinition.getKey());
|
||||
|
||||
//存储流程定义id
|
||||
workflowSchema.setDefinitionId(processDefinition.getId());
|
||||
|
||||
//把配置json存储 (清除掉xml)
|
||||
workflowSchemaConfig.getProcessConfig().setXmlContent("");
|
||||
workflowSchema.setJsonContent(JSONUtil.toJsonStr(workflowSchemaConfig));
|
||||
|
||||
save(workflowSchema);
|
||||
|
||||
//将新增的数据 记录模板历史记录
|
||||
WorkflowSchemaHistory history = new WorkflowSchemaHistory();
|
||||
history.setSchemaId(workflowSchema.getId());
|
||||
history.setVersion(1);
|
||||
history.setActivityFlag(EnabledMark.ENABLED.getCode());
|
||||
history.setXmlContent(workflowSchema.getXmlContent());
|
||||
history.setJsonContent(workflowSchema.getJsonContent());
|
||||
|
||||
//缓存节点监听器数据
|
||||
CompletableFuture.runAsync(() -> {
|
||||
WorkFlowUtil.cacheNodeListener(deploy.getId(), workflowSchemaConfig.getChildNodeConfig());
|
||||
});
|
||||
|
||||
|
||||
return workflowSchemaHistoryMapper.insert(history) > 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,199 @@
|
||||
package com.xjrsoft.workflow.service.impl;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.lang.TypeReference;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.github.yulichang.base.MPJBaseServiceImpl;
|
||||
import com.xjrsoft.common.core.constant.GlobalConstant;
|
||||
import com.xjrsoft.common.core.enums.MenuType;
|
||||
import com.xjrsoft.common.core.enums.WorkflowIsRecycleType;
|
||||
import com.xjrsoft.common.core.enums.YesOrNoEnum;
|
||||
import com.xjrsoft.common.core.exception.MyException;
|
||||
import com.xjrsoft.organization.entity.User;
|
||||
import com.xjrsoft.system.client.IMenuClient;
|
||||
import com.xjrsoft.system.entity.Menu;
|
||||
import com.xjrsoft.system.vo.MenuVo;
|
||||
import com.xjrsoft.workflow.constant.WorkflowConstant;
|
||||
import com.xjrsoft.workflow.dto.AddSpecialMenuDto;
|
||||
import com.xjrsoft.workflow.dto.UpdateSpecialMenuDto;
|
||||
import com.xjrsoft.workflow.entity.WorkflowSpecialMenu;
|
||||
import com.xjrsoft.workflow.mapper.WorkflowSpecialMenuMapper;
|
||||
import com.xjrsoft.workflow.model.SpecialMenuQueryConfig;
|
||||
import com.xjrsoft.workflow.service.IWorkflowSpecialMenuService;
|
||||
import com.xjrsoft.workflow.vo.SpecialMenuInfoVo;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.camunda.bpm.engine.TaskService;
|
||||
import org.camunda.bpm.engine.task.TaskQuery;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 专项菜单表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author tzx
|
||||
* @since 2023-03-20
|
||||
*/
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class WorkflowSpecialMenuServiceImpl extends MPJBaseServiceImpl<WorkflowSpecialMenuMapper, WorkflowSpecialMenu> implements IWorkflowSpecialMenuService {
|
||||
|
||||
private final IMenuClient menuClient;
|
||||
|
||||
private final TaskService taskService;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean add(AddSpecialMenuDto dto) {
|
||||
|
||||
WorkflowSpecialMenu workflowSpecialMenu = BeanUtil.toBean(dto, WorkflowSpecialMenu.class);
|
||||
save(workflowSpecialMenu);
|
||||
|
||||
Menu menu = BeanUtil.toBean(dto.getMenuInfo(), Menu.class);
|
||||
menu.setTitle(dto.getMenuInfo().getName());
|
||||
menu.setMenuType(MenuType.FUNCTION.getCode());
|
||||
menu.setDisplay(YesOrNoEnum.YES.getCode());
|
||||
menu.setAllowDelete(YesOrNoEnum.YES.getCode());
|
||||
menu.setAllowModify(YesOrNoEnum.YES.getCode());
|
||||
menu.setOutLink(YesOrNoEnum.NO.getCode());
|
||||
menu.setKeepAlive(YesOrNoEnum.NO.getCode());
|
||||
menu.setSortCode(dto.getMenuInfo().getSortCode());
|
||||
//固定路径 与前端必须匹配
|
||||
menu.setPath("/special-menu/" + workflowSpecialMenu.getId());
|
||||
menuClient.insertMenuFeign(menu);
|
||||
|
||||
WorkflowSpecialMenu updateSpecialMenu = new WorkflowSpecialMenu();
|
||||
updateSpecialMenu.setId(workflowSpecialMenu.getId());
|
||||
updateSpecialMenu.setMenuId(menu.getId());
|
||||
updateById(updateSpecialMenu);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean update(UpdateSpecialMenuDto dto) {
|
||||
|
||||
WorkflowSpecialMenu workflowSpecialMenu = BeanUtil.toBean(dto, WorkflowSpecialMenu.class);
|
||||
updateById(workflowSpecialMenu);
|
||||
|
||||
Menu menu = BeanUtil.toBean(dto.getMenuInfo(), Menu.class);
|
||||
menuClient.updateMenuFeign(menu);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean delete(List<Long> ids) {
|
||||
|
||||
List<WorkflowSpecialMenu> list = list(Wrappers.lambdaQuery(WorkflowSpecialMenu.class).in(WorkflowSpecialMenu::getId, ids).select(WorkflowSpecialMenu::getMenuId));
|
||||
|
||||
List<Long> allMenuIds = list.stream().map(WorkflowSpecialMenu::getMenuId).collect(Collectors.toList());
|
||||
removeBatchByIds(ids);
|
||||
|
||||
menuClient.deleteMenuBatchFeign(allMenuIds);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpecialMenuInfoVo info(Long id) {
|
||||
|
||||
WorkflowSpecialMenu specialMenu = getById(id);
|
||||
SpecialMenuInfoVo specialMenuInfoVo = BeanUtil.toBean(specialMenu, SpecialMenuInfoVo.class);
|
||||
|
||||
Menu menu = menuClient.getMenuByIdFeign(specialMenu.getMenuId());
|
||||
specialMenuInfoVo.setMenuInfo(BeanUtil.toBean(menu, MenuVo.class));
|
||||
|
||||
return specialMenuInfoVo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Map<String, Object>> pending(Map<String, Object> param) {
|
||||
|
||||
Long specialMenuId = MapUtil.get(param, WorkflowConstant.SPECIAL_MENU_ID_PARAM_NAME, Long.class);
|
||||
WorkflowSpecialMenu specialMenu = getById(specialMenuId);
|
||||
|
||||
//最先判断当前操作人 是否有权限使用 此专项菜单。
|
||||
if (StrUtil.isBlank(specialMenu.getSchemaAuthUserId())) {
|
||||
throw new MyException("当前登陆人无操作权限!");
|
||||
}
|
||||
|
||||
if (StrUtil.isBlank(specialMenu.getSchemaId())) {
|
||||
throw new MyException("当前专项菜单没有绑定模板!");
|
||||
}
|
||||
|
||||
|
||||
String[] userIds = specialMenu.getSchemaAuthUserId().split(StringPool.COMMA);
|
||||
if (Arrays.stream(userIds).noneMatch(u -> u.equals(StpUtil.getLoginIdAsString()))) {
|
||||
throw new MyException("当前登陆人无操作权限!");
|
||||
}
|
||||
|
||||
//判断是多模板 还是单模板
|
||||
String schemaIdsStr = specialMenu.getSchemaId();
|
||||
String[] schemaIds = schemaIdsStr.split(StringPool.COMMA);
|
||||
List<SpecialMenuQueryConfig> specialMenuQueryConfigs = JSONUtil.toBean(specialMenu.getQueryConfig(), new TypeReference<List<SpecialMenuQueryConfig>>() {
|
||||
}, true);
|
||||
|
||||
User user = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_INFO_KEY, new User());
|
||||
TaskQuery taskQuery = taskService.createTaskQuery()
|
||||
.active()
|
||||
.taskVariableValueEquals(WorkflowConstant.TASK_IS_APPOINT_APPROVE, YesOrNoEnum.NO.getCode())
|
||||
.processVariableValueEquals(WorkflowConstant.PROCESS_ISRECYCLE_FLAG_KEY, WorkflowIsRecycleType.NO.getCode())
|
||||
.taskVariableValueLike(WorkflowConstant.TASK_ASSIGNEE_VAR_KEY, StringPool.PERCENT + user.getId() + StringPool.PERCENT);
|
||||
//获取所有查询条件
|
||||
for (SpecialMenuQueryConfig specialMenuQueryConfig : specialMenuQueryConfigs) {
|
||||
if (specialMenuQueryConfig.getFieldName().equals(WorkflowConstant.SPECIAL_MENU_START_TIME_PARAM_NAME)) {
|
||||
Date starTime = MapUtil.get(param, WorkflowConstant.SPECIAL_MENU_START_TIME_PARAM_NAME, Date.class);
|
||||
taskQuery.taskCreatedAfter(starTime);
|
||||
}
|
||||
|
||||
if (specialMenuQueryConfig.getFieldName().equals(WorkflowConstant.SPECIAL_MENU_END_TIME_PARAM_NAME)) {
|
||||
Date endTime = MapUtil.get(param, WorkflowConstant.SPECIAL_MENU_END_TIME_PARAM_NAME, Date.class);
|
||||
taskQuery.taskCreatedBefore(endTime);
|
||||
}
|
||||
|
||||
if (specialMenuQueryConfig.getFieldName().equals(WorkflowConstant.SPECIAL_MENU_SERIAL_NUMBER_PARAM_NAME)) {
|
||||
Integer serialNumber = MapUtil.get(param, WorkflowConstant.SPECIAL_MENU_SERIAL_NUMBER_PARAM_NAME, Integer.class);
|
||||
taskQuery.processVariableValueEquals(WorkflowConstant.PROCESS_SERIAL_NUMBER_KEY, serialNumber);
|
||||
}
|
||||
|
||||
if (specialMenuQueryConfig.getFieldName().equals(WorkflowConstant.SPECIAL_MENU_SCHEMA_NAME_PARAM_NAME)) {
|
||||
String schemaName = MapUtil.get(param, WorkflowConstant.SPECIAL_MENU_SCHEMA_NAME_PARAM_NAME, String.class);
|
||||
taskQuery.processVariableValueLike(WorkflowConstant.PROCESS_SCHEMA_NAME_KEY, StringPool.PERCENT + schemaName + StringPool.PERCENT);
|
||||
}
|
||||
|
||||
if (specialMenuQueryConfig.getFieldName().equals(WorkflowConstant.SPECIAL_MENU_ORIGINATOR_PARAM_NAME)) {
|
||||
String originator = MapUtil.get(param, WorkflowConstant.SPECIAL_MENU_ORIGINATOR_PARAM_NAME, String.class);
|
||||
taskQuery.or()
|
||||
.processVariableValueEquals(WorkflowConstant.PROCESS_START_USER_NAME_KEY, originator)
|
||||
.processVariableValueEquals(WorkflowConstant.PROCESS_START_USER_ID_KEY,originator)
|
||||
.endOr();
|
||||
}
|
||||
|
||||
if (specialMenuQueryConfig.getFieldName().equals(WorkflowConstant.SPECIAL_MENU_TASK_NAME_PARAM_NAME)) {
|
||||
String taskName = MapUtil.get(param, WorkflowConstant.SPECIAL_MENU_TASK_NAME_PARAM_NAME, String.class);
|
||||
taskQuery.taskNameLike(StringPool.PERCENT + taskName + StringPool.PERCENT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,401 @@
|
||||
package com.xjrsoft.workflow.utils;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.lang.TypeReference;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.db.Entity;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
import com.xjrsoft.common.core.constant.GlobalConstant;
|
||||
import com.xjrsoft.common.core.constant.StringPool;
|
||||
import com.xjrsoft.common.core.domain.generator.ComponentConfig;
|
||||
import com.xjrsoft.common.mybatis.model.Department;
|
||||
import com.xjrsoft.common.mybatis.model.User;
|
||||
import com.xjrsoft.common.mybatis.utils.LocalDateTimeUtil;
|
||||
import com.xjrsoft.common.redis.service.RedisUtil;
|
||||
import com.xjrsoft.form.entity.FormDesignConfig;
|
||||
import com.xjrsoft.generate.constant.ComponentTypeConstant;
|
||||
import com.xjrsoft.generate.utils.GeneratorUtil;
|
||||
import com.xjrsoft.magicapi.client.IMagicApiClient;
|
||||
import com.xjrsoft.system.client.IAreaClient;
|
||||
import com.xjrsoft.system.entity.Area;
|
||||
import com.xjrsoft.system.entity.DictionaryDetail;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
import org.ssssssss.magicapi.modules.db.model.PageResult;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author Zexy
|
||||
*/
|
||||
@Slf4j
|
||||
public final class FormDataTransUtil {
|
||||
private FormDataTransUtil(){}
|
||||
|
||||
private static final RedisUtil redisUtil;
|
||||
|
||||
private static final IMagicApiClient magcApiClient;
|
||||
|
||||
private static final IAreaClient areaClient;
|
||||
|
||||
static {
|
||||
redisUtil = SpringUtil.getBean(RedisUtil.class);
|
||||
magcApiClient = SpringUtil.getBean(IMagicApiClient.class);
|
||||
areaClient = SpringUtil.getBean(IAreaClient.class);
|
||||
}
|
||||
|
||||
public static void transData(List<Entity> dataList, FormDesignConfig formDesignConfig) {
|
||||
if (CollectionUtils.isEmpty(dataList)) {
|
||||
return;
|
||||
}
|
||||
List<DictionaryDetail> detailList = null;
|
||||
Map<String, Object> userMap = null;
|
||||
Map<String, Object> deptMap = null;
|
||||
// List<Map<String, Object>> postList = null;
|
||||
Map<String, Object> areaMap = null;
|
||||
Map<String, Map<String, Object>> apiDataMap = new HashMap<>();
|
||||
List<ComponentConfig> componentConfigList = GeneratorUtil.getFormComponentListWithMain(formDesignConfig.getFormJson().getList());
|
||||
Map<String, Map<String, Object>> fieldValuesMap = new HashMap<>(componentConfigList.size());
|
||||
Map<String, Map<String, String>> multiFieldMap = new HashMap<>();
|
||||
Map<String, String> dateFormatMap = new HashMap<>(4);
|
||||
for (ComponentConfig componentConfig : componentConfigList) {
|
||||
String type = componentConfig.getType();
|
||||
String bindField = componentConfig.getBindField();
|
||||
Map<String, Object> options = componentConfig.getOptions();
|
||||
Integer infoType = MapUtils.getInteger(options, "infoType");
|
||||
boolean isCascade = StrUtil.equalsIgnoreCase(ComponentTypeConstant.CASCADE, type);
|
||||
if (StrUtil.equalsIgnoreCase(ComponentTypeConstant.CHECKBOX, type)
|
||||
|| StrUtil.equalsIgnoreCase(ComponentTypeConstant.SELECT, type)
|
||||
|| StrUtil.equalsIgnoreCase(ComponentTypeConstant.ASSOCIATE_SELECT, type)
|
||||
|| StrUtil.equalsIgnoreCase(ComponentTypeConstant.ASSOCIATE_POPUP, type)
|
||||
|| StrUtil.equalsIgnoreCase(ComponentTypeConstant.MULTIPLE_POPUP, type)
|
||||
|| StrUtil.equalsIgnoreCase(ComponentTypeConstant.RADIO, type)
|
||||
|| isCascade) {
|
||||
String datasourceType = MapUtils.getString(options, "datasourceType");
|
||||
if (StrUtil.equalsIgnoreCase(datasourceType, "dic")) {
|
||||
if (detailList == null) {
|
||||
detailList = redisUtil.get(GlobalConstant.DIC_DETAIL_CACHE_KEY, new TypeReference<List<DictionaryDetail>>() {});
|
||||
}
|
||||
Map<String, Object> detailMap = detailList.stream().filter(x -> StrUtil.equalsIgnoreCase(x.getItemId().toString(), MapUtils.getString(options, "itemId"))).collect(Collectors.toMap(DictionaryDetail::getValue, DictionaryDetail::getName, (e1, e2) -> e1));
|
||||
fieldValuesMap.put(bindField, detailMap);
|
||||
} else if (StrUtil.equalsIgnoreCase(datasourceType, "api") || isCascade) {
|
||||
String apiId = MapUtils.getString(MapUtils.getMap(options, "apiConfig"), "apiId");
|
||||
if (apiDataMap.get(apiId) == null) {
|
||||
Object resultApiData = magcApiClient.executeApiFeign(apiId);
|
||||
List<Map<String, Object>> apiDataList = null;
|
||||
if (resultApiData.getClass().getName().contains("PageResult")) {
|
||||
Map<String, Object> map = Convert.toMap(String.class, Object.class, resultApiData);
|
||||
apiDataList = (List<Map<String, Object>>) map.get("list");
|
||||
} else if (resultApiData instanceof List) {
|
||||
apiDataList = (List<Map<String, Object>>) resultApiData;
|
||||
}
|
||||
if (isCascade) {
|
||||
apiDataList = treeToList(apiDataList);
|
||||
}
|
||||
if (apiDataList != null ) {
|
||||
apiDataMap.put(apiId, apiDataList.stream().filter(x -> ObjectUtil.isNotNull(x.get("value"))).collect(Collectors.toMap(data -> data.get("value").toString(), data -> data.get("label"), (e1, e2) -> e1)));
|
||||
}
|
||||
}
|
||||
fieldValuesMap.put(bindField, apiDataMap.get(apiId));
|
||||
}
|
||||
if (StrUtil.equalsIgnoreCase(ComponentTypeConstant.MULTIPLE_POPUP, type)
|
||||
|| StrUtil.equalsIgnoreCase(ComponentTypeConstant.CHECKBOX, type)
|
||||
|| isCascade) {
|
||||
Map<String, String> multiSettingMap = new HashMap<>(4);
|
||||
multiSettingMap.put("separator", MapUtils.getString(options, "separator", StringPool.COMMA));
|
||||
multiSettingMap.put("showFormat", MapUtils.getString(options, "showFormat"));
|
||||
multiFieldMap.put(bindField, multiSettingMap);
|
||||
}
|
||||
} else if (StrUtil.equalsIgnoreCase(ComponentTypeConstant.AREA, type)) {
|
||||
Set<Long> areaValueList = new LinkedHashSet<>();
|
||||
for (Map<String, Object> data : dataList) {
|
||||
String values = MapUtils.getString(data, bindField);
|
||||
if (StrUtil.isEmpty(values)) {
|
||||
continue;
|
||||
}
|
||||
String[] valueArray = values.split(StringPool.COMMA);
|
||||
areaValueList.addAll(Arrays.stream(valueArray).map(NumberUtils::toLong).collect(Collectors.toSet()));
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(areaValueList)) {
|
||||
List<Area> areaList = areaClient.getAreaListFeign(new ArrayList<>(areaValueList));
|
||||
areaMap = areaList.stream().collect(Collectors.toMap(area -> area.getId().toString(), Area::getName, (e1, e2) -> e1));
|
||||
} else {
|
||||
areaMap = new HashMap<>(0);
|
||||
}
|
||||
fieldValuesMap.put(bindField, areaMap);
|
||||
multiFieldMap.put(bindField, null);
|
||||
}else if (StrUtil.equalsIgnoreCase(ComponentTypeConstant.ORGANIZATION, type)
|
||||
|| (StrUtil.equalsIgnoreCase(ComponentTypeConstant.INFO, type) && infoType.equals(1))) {
|
||||
if (deptMap == null) {
|
||||
List<Department> departmentList = redisUtil.get(GlobalConstant.DEP_CACHE_KEY, new TypeReference<List<Department>>() {});
|
||||
deptMap = departmentList.stream().collect(Collectors.toMap(department -> department.getId().toString(), Department::getName, (e1, e2) -> e1));
|
||||
}
|
||||
fieldValuesMap.put(bindField, deptMap);
|
||||
} else if (StrUtil.equalsIgnoreCase(ComponentTypeConstant.USER, type)
|
||||
|| (StrUtil.equalsIgnoreCase(ComponentTypeConstant.INFO, type) && infoType.equals(0))) {
|
||||
if (userMap == null) {
|
||||
List<User> userList = redisUtil.get(GlobalConstant.USER_CACHE_KEY, new TypeReference<List<User>>() {});
|
||||
userMap = userList.stream().collect(Collectors.toMap(user -> user.getId().toString(), User::getName, (e1, e2) -> e1));
|
||||
}
|
||||
if (infoType == null) {
|
||||
multiFieldMap.put(bindField, null);
|
||||
}
|
||||
fieldValuesMap.put(bindField, userMap);
|
||||
} else if (StrUtil.equalsIgnoreCase(ComponentTypeConstant.DATE, type)) {
|
||||
dateFormatMap.put(bindField, LocalDateTimeUtil.convertFontFormat(MapUtils.getString(options, "format")));
|
||||
} else if (StrUtil.equalsIgnoreCase(ComponentTypeConstant.DATE_RANGE, type)) {
|
||||
String format = LocalDateTimeUtil.convertFontFormat(MapUtils.getString(options, "format"));
|
||||
dateFormatMap.put(componentConfig.getBindStartTime(), format);
|
||||
dateFormatMap.put(componentConfig.getBindEndTime(), format);
|
||||
}
|
||||
}
|
||||
|
||||
for (Map<String, Object> data : dataList) {
|
||||
for (Map.Entry<String, Map<String, Object>> entry : fieldValuesMap.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
Object o = data.get(key);
|
||||
if (StrUtil.isEmptyIfStr(o)) {
|
||||
continue;
|
||||
}
|
||||
String value = String.valueOf(o);
|
||||
Map<String, Object> entryValue = entry.getValue();
|
||||
if (multiFieldMap.containsKey(key)) {
|
||||
List<String> values = StrUtil.split(value, StringPool.COMMA);
|
||||
Map<String, String> multiSettingsMap = multiFieldMap.get(key);
|
||||
StringBuilder showValue = new StringBuilder();
|
||||
for (int i = 0; i < values.size(); i++) {
|
||||
String valueStr = values.get(i);
|
||||
String separator = StringPool.COMMA;
|
||||
Object showValueStr = entryValue.get(valueStr);
|
||||
if (StrUtil.isEmptyIfStr(showValueStr)) {
|
||||
continue;
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(multiSettingsMap)) {
|
||||
separator = MapUtils.getString(multiSettingsMap, "separator", StringPool.COMMA);
|
||||
String showFormat = MapUtils.getString(multiSettingsMap, "showFormat");
|
||||
if (StrUtil.equalsIgnoreCase(showFormat, "showMostChildLevel")) {
|
||||
if (i == values.size() - 1) {
|
||||
showValue.append(showValueStr);
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
showValue.append(showValueStr);
|
||||
}
|
||||
} else {
|
||||
showValue.append(showValueStr);
|
||||
}
|
||||
if (i < values.size() - 1) {
|
||||
showValue.append(separator);
|
||||
}
|
||||
}
|
||||
if (showValue.length() > 0) {
|
||||
data.put(key, showValue.toString());
|
||||
}
|
||||
} else {
|
||||
Object obj = entryValue.get(value);
|
||||
if (StrUtil.isEmptyIfStr(obj)) {
|
||||
continue;
|
||||
}
|
||||
data.put(key, obj);
|
||||
}
|
||||
}
|
||||
// 时间格式化处理
|
||||
for (Map.Entry<String, String> entry : dateFormatMap.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
Object value = data.get(key);
|
||||
if (value == null) {
|
||||
continue;
|
||||
}
|
||||
if (value instanceof Timestamp) {
|
||||
Timestamp timestamp = (Timestamp) value;
|
||||
data.put(key, LocalDateTimeUtil.format(timestamp.toLocalDateTime(), entry.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void transDataOver(List<Entity> dataList, FormDesignConfig formDesignConfig) {
|
||||
if (CollectionUtils.isEmpty(dataList)) {
|
||||
return;
|
||||
}
|
||||
List<DictionaryDetail> detailList = null;
|
||||
Map<String, Object> userMap = null;
|
||||
Map<String, Object> deptMap = null;
|
||||
// List<Map<String, Object>> postList = null;
|
||||
Map<String, Object> areaMap = null;
|
||||
Map<String, Map<String, Object>> apiDataMap = new HashMap<>();
|
||||
List<ComponentConfig> componentConfigList = GeneratorUtil.getFormComponentListWithMain(formDesignConfig.getFormJson().getList());
|
||||
Map<String, Map<String, Object>> fieldValuesMap = new HashMap<>(componentConfigList.size());
|
||||
Map<String, Map<String, String>> multiFieldMap = new HashMap<>();
|
||||
Map<String, String> dateFormatMap = new HashMap<>(4);
|
||||
List<String> keyList = new ArrayList<>(dataList.size());
|
||||
for (ComponentConfig componentConfig : componentConfigList) {
|
||||
String type = componentConfig.getType();
|
||||
String bindField = componentConfig.getBindField();
|
||||
keyList.add(bindField);
|
||||
Map<String, Object> options = componentConfig.getOptions();
|
||||
Integer infoType = MapUtils.getInteger(options, "infoType");
|
||||
boolean isCascade = StrUtil.equalsIgnoreCase(ComponentTypeConstant.CASCADE, type);
|
||||
if (StrUtil.equalsIgnoreCase(ComponentTypeConstant.CHECKBOX, type)
|
||||
|| StrUtil.equalsIgnoreCase(ComponentTypeConstant.SELECT, type)
|
||||
|| StrUtil.equalsIgnoreCase(ComponentTypeConstant.ASSOCIATE_SELECT, type)
|
||||
|| StrUtil.equalsIgnoreCase(ComponentTypeConstant.ASSOCIATE_POPUP, type)
|
||||
|| StrUtil.equalsIgnoreCase(ComponentTypeConstant.MULTIPLE_POPUP, type)
|
||||
|| StrUtil.equalsIgnoreCase(ComponentTypeConstant.RADIO, type)
|
||||
|| isCascade) {
|
||||
String datasourceType = MapUtils.getString(options, "datasourceType");
|
||||
if (StrUtil.equalsIgnoreCase(datasourceType, "dic")) {
|
||||
if (detailList == null) {
|
||||
detailList = redisUtil.get(GlobalConstant.DIC_DETAIL_CACHE_KEY, new TypeReference<List<DictionaryDetail>>() {});
|
||||
}
|
||||
Map<String, Object> detailMap = detailList.stream().filter(x -> StrUtil.equalsIgnoreCase(x.getItemId().toString(), MapUtils.getString(options, "itemId"))).collect(Collectors.toMap(DictionaryDetail::getValue, DictionaryDetail::getName, (e1, e2) -> e1));
|
||||
fieldValuesMap.put(bindField, detailMap);
|
||||
} else if (StrUtil.equalsIgnoreCase(datasourceType, "api") || isCascade) {
|
||||
String apiId = MapUtils.getString(MapUtils.getMap(options, "apiConfig"), "apiId");
|
||||
if (apiDataMap.get(apiId) == null) {
|
||||
Object resultApiData = magcApiClient.executeApiFeign(apiId);
|
||||
List<Map<String, Object>> apiDataList = null;
|
||||
if (resultApiData instanceof PageResult) {
|
||||
apiDataList = (List<Map<String, Object>>) ((PageResult) resultApiData).getList();
|
||||
} else if (resultApiData instanceof List) {
|
||||
apiDataList = (List<Map<String, Object>>) resultApiData;
|
||||
}
|
||||
if (isCascade) apiDataList = treeToList(apiDataList);
|
||||
if (apiDataList != null ) apiDataMap.put(apiId, apiDataList.stream().filter(x -> ObjectUtil.isNotNull(x.get("value"))).collect(Collectors.toMap(data -> data.get("value").toString(), data -> data.get("label"), (e1, e2) -> e1)));
|
||||
}
|
||||
fieldValuesMap.put(bindField, apiDataMap.get(apiId));
|
||||
}
|
||||
if (StrUtil.equalsIgnoreCase(ComponentTypeConstant.MULTIPLE_POPUP, type)
|
||||
|| StrUtil.equalsIgnoreCase(ComponentTypeConstant.CHECKBOX, type)
|
||||
|| isCascade) {
|
||||
Map<String, String> multiSettingMap = new HashMap<>(4);
|
||||
multiSettingMap.put("separator", MapUtils.getString(options, "separator", com.baomidou.mybatisplus.core.toolkit.StringPool.COMMA));
|
||||
multiSettingMap.put("showFormat", MapUtils.getString(options, "showFormat"));
|
||||
multiFieldMap.put(bindField, multiSettingMap);
|
||||
}
|
||||
} else if (StrUtil.equalsIgnoreCase(ComponentTypeConstant.AREA, type)) {
|
||||
Set<Long> areaValueList = new LinkedHashSet<>();
|
||||
for (Map<String, Object> data : dataList) {
|
||||
String values = MapUtils.getString(data, bindField);
|
||||
if (StrUtil.isEmpty(values)) continue;
|
||||
String[] valueArray = values.split(com.baomidou.mybatisplus.core.toolkit.StringPool.COMMA);
|
||||
areaValueList.addAll(Arrays.stream(valueArray).map(NumberUtils::toLong).collect(Collectors.toSet()));
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(areaValueList)) {
|
||||
List<Area> areaList = areaClient.getAreaListFeign(new ArrayList<>(areaValueList));
|
||||
areaMap = areaList.stream().collect(Collectors.toMap(area -> area.getId().toString(), Area::getName, (e1, e2) -> e1));
|
||||
} else {
|
||||
areaMap = new HashMap<>(0);
|
||||
}
|
||||
fieldValuesMap.put(bindField, areaMap);
|
||||
multiFieldMap.put(bindField, null);
|
||||
}else if (StrUtil.equalsIgnoreCase(ComponentTypeConstant.ORGANIZATION, type)
|
||||
|| (StrUtil.equalsIgnoreCase(ComponentTypeConstant.INFO, type) && infoType.equals(1))) {
|
||||
if (deptMap == null) {
|
||||
List<Department> departmentList = redisUtil.get(GlobalConstant.DEP_CACHE_KEY, new TypeReference<List<Department>>() {});
|
||||
deptMap = departmentList.stream().collect(Collectors.toMap(department -> department.getId().toString(), Department::getName, (e1, e2) -> e1));
|
||||
}
|
||||
fieldValuesMap.put(bindField, deptMap);
|
||||
} else if (StrUtil.equalsIgnoreCase(ComponentTypeConstant.USER, type)
|
||||
|| (StrUtil.equalsIgnoreCase(ComponentTypeConstant.INFO, type) && infoType.equals(0))) {
|
||||
if (userMap == null) {
|
||||
List<User> userList = redisUtil.get(GlobalConstant.USER_CACHE_KEY, new TypeReference<List<User>>() {});
|
||||
userMap = userList.stream().collect(Collectors.toMap(user -> user.getId().toString(), User::getName, (e1, e2) -> e1));
|
||||
}
|
||||
if (infoType == null) {
|
||||
multiFieldMap.put(bindField, null);
|
||||
}
|
||||
fieldValuesMap.put(bindField, userMap);
|
||||
} else if (StrUtil.equalsIgnoreCase(ComponentTypeConstant.DATE, type)) {
|
||||
dateFormatMap.put(bindField, LocalDateTimeUtil.convertFontFormat(MapUtils.getString(options, "format")));
|
||||
} else if (StrUtil.equalsIgnoreCase(ComponentTypeConstant.DATE_RANGE, type)) {
|
||||
String format = LocalDateTimeUtil.convertFontFormat(MapUtils.getString(options, "format"));
|
||||
dateFormatMap.put(componentConfig.getBindStartTime(), format);
|
||||
dateFormatMap.put(componentConfig.getBindEndTime(), format);
|
||||
}
|
||||
}
|
||||
|
||||
for (Map<String, Object> data : dataList) {
|
||||
for (String key : keyList) {
|
||||
String addKey = key + com.baomidou.mybatisplus.core.toolkit.StringPool.UNDERSCORE + "api";
|
||||
Object o = data.get(key);
|
||||
String value = String.valueOf(o);
|
||||
data.put(addKey,value);
|
||||
}
|
||||
for (Map.Entry<String, Map<String, Object>> entry : fieldValuesMap.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
Object o = data.get(key);
|
||||
if (StrUtil.isEmptyIfStr(o)) {
|
||||
continue;
|
||||
}
|
||||
String value = String.valueOf(o);
|
||||
Map<String, Object> entryValue = entry.getValue();
|
||||
if (multiFieldMap.containsKey(key)) {
|
||||
List<String> values = StrUtil.split(value, com.baomidou.mybatisplus.core.toolkit.StringPool.COMMA);
|
||||
Map<String, String> multiSettingsMap = multiFieldMap.get(key);
|
||||
StringBuilder showValue = new StringBuilder();
|
||||
for (int i = 0; i < values.size(); i++) {
|
||||
String valueStr = values.get(i);
|
||||
String separator = com.baomidou.mybatisplus.core.toolkit.StringPool.COMMA;
|
||||
Object showValueStr = entryValue.get(valueStr);
|
||||
if (StrUtil.isEmptyIfStr(showValueStr)) continue;
|
||||
if (CollectionUtils.isNotEmpty(multiSettingsMap)) {
|
||||
separator = MapUtils.getString(multiSettingsMap, "separator", com.baomidou.mybatisplus.core.toolkit.StringPool.COMMA);
|
||||
String showFormat = MapUtils.getString(multiSettingsMap, "showFormat");
|
||||
if (StrUtil.equalsIgnoreCase(showFormat, "showMostChildLevel")) {
|
||||
if (i == values.size() - 1) {
|
||||
showValue.append(showValueStr);
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
showValue.append(showValueStr);
|
||||
}
|
||||
} else {
|
||||
showValue.append(showValueStr);
|
||||
}
|
||||
if (i < values.size() - 1) {
|
||||
showValue.append(separator);
|
||||
}
|
||||
}
|
||||
if (showValue.length() > 0) data.put(key, showValue.toString());
|
||||
} else {
|
||||
Object obj = entryValue.get(value);
|
||||
if (StrUtil.isEmptyIfStr(obj)) continue;
|
||||
data.put(key, obj);
|
||||
}
|
||||
}
|
||||
// 时间格式化处理
|
||||
for (Map.Entry<String, String> entry : dateFormatMap.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
Object value = data.get(key);
|
||||
if (value == null) {
|
||||
continue;
|
||||
}
|
||||
if (value instanceof Timestamp) {
|
||||
Timestamp timestamp = (Timestamp) value;
|
||||
data.put(key, LocalDateTimeUtil.format(timestamp.toLocalDateTime(), entry.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Map<String, Object>> treeToList(List<Map<String, Object>> treeDataList) {
|
||||
if (CollectionUtils.isEmpty(treeDataList)) {
|
||||
return treeDataList;
|
||||
}
|
||||
List<Map<String, Object>> resultList = new ArrayList<>();
|
||||
for (Map<String, Object> data : treeDataList) {
|
||||
resultList.add(data);
|
||||
Object obj = data.get("children");
|
||||
if (obj instanceof List) {
|
||||
resultList.addAll(treeToList((List<Map<String, Object>>)obj));
|
||||
}
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,610 @@
|
||||
package com.xjrsoft.workflow.utils;
|
||||
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.db.sql.SqlBuilder;
|
||||
import cn.hutool.db.sql.Wrapper;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.xjrsoft.common.core.exception.MyException;
|
||||
import com.xjrsoft.common.core.exception.ValidationException;
|
||||
import com.xjrsoft.magicapi.vo.MagicApiInfoVo;
|
||||
import com.xjrsoft.organization.entity.User;
|
||||
import com.xjrsoft.tenant.util.SecureUtil;
|
||||
import com.xjrsoft.workflow.constant.WorkflowConstant;
|
||||
import com.xjrsoft.workflow.entity.WorkflowApproveRecord;
|
||||
import com.xjrsoft.workflow.entity.WorkflowFormRelation;
|
||||
import com.xjrsoft.workflow.entity.WorkflowSchema;
|
||||
import com.xjrsoft.workflow.model.ApiConfig;
|
||||
import com.xjrsoft.workflow.model.ApiRequestParamsConfig;
|
||||
import com.xjrsoft.workflow.model.UserTaskConfig;
|
||||
import com.xjrsoft.workflow.model.WorkflowSchemaConfig;
|
||||
import com.xjrsoft.workflow.service.IWorkflowApproveRecordService;
|
||||
import com.xjrsoft.workflow.service.IWorkflowExecuteService;
|
||||
import com.xjrsoft.workflow.service.IWorkflowFormRelationService;
|
||||
import com.xjrsoft.workflow.service.IWorkflowSchemaService;
|
||||
import com.xjrsoft.workflow.vo.TaskInfoVo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.ibatis.jdbc.SQL;
|
||||
import org.camunda.bpm.engine.HistoryService;
|
||||
import org.camunda.bpm.engine.RepositoryService;
|
||||
import org.camunda.bpm.engine.RuntimeService;
|
||||
import org.camunda.bpm.engine.TaskService;
|
||||
import org.camunda.bpm.engine.history.HistoricActivityInstance;
|
||||
import org.camunda.bpm.engine.history.HistoricVariableInstance;
|
||||
import org.camunda.bpm.engine.runtime.*;
|
||||
import org.camunda.bpm.engine.task.Task;
|
||||
import org.camunda.bpm.model.bpmn.BpmnModelInstance;
|
||||
import org.camunda.bpm.model.bpmn.instance.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 工作流和业务关联的工具类
|
||||
*/
|
||||
@Slf4j
|
||||
public class WorkflowBusinessUtil {
|
||||
private static final IWorkflowSchemaService workflowSchemaService;
|
||||
private static final IWorkflowFormRelationService workflowFormRelationService;
|
||||
private static final IWorkflowExecuteService workflowExecuteService;
|
||||
private static final HistoryService historyService;
|
||||
private static final RepositoryService repositoryService;
|
||||
private static final TaskService taskService;
|
||||
private static final RuntimeService runtimeService;
|
||||
private static final IWorkflowApproveRecordService workflowApproveRecordService;
|
||||
|
||||
static {
|
||||
workflowSchemaService=SpringUtil.getBean(IWorkflowSchemaService.class);
|
||||
workflowFormRelationService=SpringUtil.getBean(IWorkflowFormRelationService.class);
|
||||
workflowExecuteService=SpringUtil.getBean(IWorkflowExecuteService.class);
|
||||
historyService=SpringUtil.getBean(HistoryService.class);
|
||||
repositoryService=SpringUtil.getBean(RepositoryService.class);
|
||||
taskService=SpringUtil.getBean(TaskService.class);
|
||||
runtimeService=SpringUtil.getBean(RuntimeService.class);
|
||||
workflowApproveRecordService=SpringUtil.getBean(IWorkflowApproveRecordService.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询业务对应流程当前运行中的任务(反映流程状态)
|
||||
*/
|
||||
public static final List<Task>queryTaskListByBusinessId(Long businessId,Long schemaId){
|
||||
List<Task>result=new ArrayList<>();
|
||||
//先用业务id查询有没有关联的流程
|
||||
List<WorkflowFormRelation>formRelationList=workflowFormRelationService.list(Wrappers.lambdaQuery(WorkflowFormRelation.class)
|
||||
.eq(WorkflowFormRelation::getFormKeyValue,businessId)
|
||||
);
|
||||
List<String>processInstIdList=new ArrayList<>();
|
||||
if(ObjectUtil.isNotEmpty(formRelationList)) {
|
||||
processInstIdList.addAll(formRelationList.stream().map(WorkflowFormRelation::getProcessId).collect(Collectors.toList()));
|
||||
//如果有流程配置id,过滤出正确的流程实例
|
||||
if(formRelationList.size()>1&&schemaId!=null){
|
||||
List<HistoricVariableInstance> variableInstanceList = historyService.createHistoricVariableInstanceQuery()
|
||||
.processInstanceIdIn(processInstIdList.toArray(new String[]{}))
|
||||
.variableValueEquals(WorkflowConstant.PROCESS_SCHEMA_ID_KEY,schemaId)
|
||||
.list();
|
||||
if(ObjectUtil.isNotEmpty(variableInstanceList)){
|
||||
processInstIdList=variableInstanceList.stream().map(HistoricVariableInstance::getProcessInstanceId).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ObjectUtil.isNotEmpty(processInstIdList)){
|
||||
//查询运行中的任务
|
||||
result.addAll(taskService.createTaskQuery()
|
||||
.active()
|
||||
.processInstanceIdIn(processInstIdList.toArray(new String[]{}))
|
||||
.list()
|
||||
);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存退回的节点选人,按子流程拆分
|
||||
* @param processInstId
|
||||
* @param nextTaskUserMap
|
||||
* @param isClearFirst
|
||||
* @return 返回按子流程拆分的节点选人(即保存的节点选人)
|
||||
*/
|
||||
public static Map<String,Map<String,String>> saveRejectTaskUser(String processInstId,Map<String,String>nextTaskUserMap,Boolean isClearFirst){
|
||||
//按主流程子流程拆分选人
|
||||
Map<String,Map<String,String>>subProcessMap=new HashMap<>();
|
||||
for(String key:nextTaskUserMap.keySet()){
|
||||
if(StringUtils.isNotBlank(nextTaskUserMap.get(key))){
|
||||
Map<String,Set<String>>tmp=new HashMap<>();
|
||||
Arrays.stream(nextTaskUserMap.get(key).split(StringPool.COMMA)).forEach(user->{
|
||||
String[]str=user.split(WorkflowConstant.SUB_PROCESS_SEPARATOR);
|
||||
String k=str.length==1?WorkflowConstant.MAIN_PROCESS_ID:str[0];
|
||||
String v=str.length==1?str[0]:str[1];
|
||||
//没有带子流程实例id,属于主流程
|
||||
if(tmp.get(k)==null){
|
||||
tmp.put(k,new LinkedHashSet<>());
|
||||
}
|
||||
tmp.get(k).add(v);
|
||||
});
|
||||
for(String subProcessId:tmp.keySet()){
|
||||
if(subProcessMap.get(subProcessId)==null){
|
||||
subProcessMap.put(subProcessId,new HashMap<>());
|
||||
}
|
||||
subProcessMap.get(subProcessId).put(key,StringUtils.join(tmp.get(subProcessId),StringPool.COMMA));
|
||||
}
|
||||
}
|
||||
}
|
||||
for(String subProcessId:subProcessMap.keySet()){
|
||||
saveNextTaskUser(processInstId,WorkflowConstant.MAIN_PROCESS_ID.equals(subProcessId)?null:subProcessId,subProcessMap.get(subProcessId),isClearFirst);
|
||||
}
|
||||
return subProcessMap;
|
||||
}
|
||||
public static void saveNextTaskUser(String processInstId,String subProcessInstId,Map<String,String>nextTaskUserMap,Boolean isClearFirst){
|
||||
saveNextTaskUser(processInstId,subProcessInstId,nextTaskUserMap,isClearFirst,false);
|
||||
}
|
||||
/**
|
||||
* 保存流程下一节点审批人,
|
||||
* 数据存储格式processId,nextTaskUser->Map<taskDefKey(_subProcessInstId),Map<currentUserId,nextTaskUserStr>>
|
||||
* @param processInstId
|
||||
* @param subProcessInstId
|
||||
* @param nextTaskUserMap
|
||||
* @param isClearFirst 是否先清除节点选人
|
||||
* @param isAdd 对用户的选人,追加还是覆盖
|
||||
*/
|
||||
public static void saveNextTaskUser(String processInstId,String subProcessInstId,Map<String,String>nextTaskUserMap,Boolean isClearFirst,Boolean isAdd){
|
||||
if(ObjectUtil.isEmpty(nextTaskUserMap)){
|
||||
throw new ValidationException("审批人不能为空");
|
||||
}
|
||||
String userId= SecureUtil.getCurrentUserId().toString();
|
||||
Object variableMaps=runtimeService.getVariable(processInstId, WorkflowConstant.NEXT_TASK_USER_VAR_FLAG);
|
||||
Map<String,Object>taskUserMap=variableMaps==null?new HashMap<>():(Map<String,Object>)variableMaps;
|
||||
for(String taskDefKey: nextTaskUserMap.keySet()){
|
||||
if(StringUtils.isNotBlank(nextTaskUserMap.get(taskDefKey))){
|
||||
String key=(StringUtils.isNotBlank(subProcessInstId)?(subProcessInstId+WorkflowConstant.SUB_PROCESS_SEPARATOR):"")+taskDefKey;
|
||||
Map<String,String>taskUser=new HashMap<>();
|
||||
if(!isClearFirst) {
|
||||
//兼容旧数据格式
|
||||
if (taskUserMap.get(key) instanceof String) {
|
||||
taskUser.put(userId, (String) taskUserMap.get(key));
|
||||
} else if(taskUserMap.get(key)!=null) {
|
||||
taskUser.putAll((Map<String, String>) taskUserMap.get(key));
|
||||
}
|
||||
}
|
||||
if(isAdd){
|
||||
//解析已选人去重
|
||||
Set<String>set=new LinkedHashSet<>();
|
||||
if(StringUtils.isNotBlank(taskUser.get(userId))){
|
||||
set.addAll(Arrays.asList(taskUser.get(userId).split(StringPool.COMMA)));
|
||||
}
|
||||
set.addAll(Arrays.asList(nextTaskUserMap.get(taskDefKey).split(StringPool.COMMA)));
|
||||
taskUser.put(userId, StringUtils.join(set,StringPool.COMMA));
|
||||
}else{
|
||||
taskUser.put(userId, nextTaskUserMap.get(taskDefKey));
|
||||
}
|
||||
taskUserMap.put(key,taskUser);
|
||||
}
|
||||
}
|
||||
runtimeService.setVariable(processInstId,WorkflowConstant.NEXT_TASK_USER_VAR_FLAG,taskUserMap);
|
||||
}
|
||||
/**
|
||||
* 查询流程节点预审选择的候选人
|
||||
* @param variableMaps
|
||||
* @param processInstId
|
||||
* @param subProcessInstId
|
||||
* @param taskDefKey
|
||||
* @return
|
||||
*/
|
||||
public static final List<Long>queryNextTaskUser(Map<String, Object> variableMaps,String processInstId,String subProcessInstId,String taskDefKey){
|
||||
if(variableMaps==null&&StringUtils.isNotBlank(processInstId)){
|
||||
List<String> variableNames = ListUtil.toList(
|
||||
WorkflowConstant.NEXT_TASK_USER_VAR_FLAG);
|
||||
variableMaps = runtimeService.getVariables(processInstId, variableNames);
|
||||
}
|
||||
Set<Long>nextTaskUserSet=new HashSet<>();
|
||||
if(variableMaps!=null){
|
||||
Map<String,Object> nextTaskUserMap= MapUtil.get(variableMaps,WorkflowConstant.NEXT_TASK_USER_VAR_FLAG,Map.class);
|
||||
if(ObjectUtil.isNotEmpty(nextTaskUserMap)) {
|
||||
String key=(StringUtils.isNotBlank(subProcessInstId) ? (subProcessInstId+WorkflowConstant.SUB_PROCESS_SEPARATOR) : "")+taskDefKey;
|
||||
//兼容旧格式
|
||||
Map<String, String> nextTaskUser = new HashMap<>();
|
||||
if (nextTaskUserMap.get(key) instanceof String) {
|
||||
nextTaskUser.put(SecureUtil.getCurrentUserId().toString(), (String) nextTaskUserMap.get(key));
|
||||
} else if(nextTaskUserMap.get(key)!=null) {
|
||||
nextTaskUser.putAll((Map<String, String>) nextTaskUserMap.get(key));
|
||||
}
|
||||
if (ObjectUtil.isNotEmpty(nextTaskUser)) {
|
||||
for (String userIds : nextTaskUser.values()) {
|
||||
if (StringUtils.isNotBlank(userIds)) {
|
||||
Arrays.stream(userIds.split(StringPool.COMMA)).forEach(s -> nextTaskUserSet.add(Long.parseLong(s)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ArrayList<>(nextTaskUserSet);
|
||||
}
|
||||
public static final List<Long>queryNextTaskUser(Map<String, Object> variableMaps,String processInstId,String taskDefKey){
|
||||
return queryNextTaskUser(variableMaps,processInstId,null,taskDefKey);
|
||||
}
|
||||
/**
|
||||
* 查询流程节点的最终审批人
|
||||
* @param processInstId
|
||||
* @param taskDefKey
|
||||
* @param isOnlyLastOne 只要最后一个审批人
|
||||
* @return
|
||||
*/
|
||||
public static final Map<String,List<Long>>queryAuditPerson(String processInstId,String[] taskDefKey,Boolean isOnlyLastOne){
|
||||
Map<String,List<Long>>result=new HashMap<>();
|
||||
List<WorkflowApproveRecord> list = workflowApproveRecordService.list(Wrappers.lambdaQuery(WorkflowApproveRecord.class)
|
||||
.eq(WorkflowApproveRecord::getProcessId, processInstId)
|
||||
.in(ObjectUtil.isNotEmpty(taskDefKey),WorkflowApproveRecord::getTaskDefinitionKey, taskDefKey)
|
||||
.orderByDesc(WorkflowApproveRecord::getApproveTime)
|
||||
);
|
||||
if(ObjectUtil.isNotEmpty(list)){
|
||||
list.forEach(record->{
|
||||
if(result.get(record.getTaskDefinitionKey())==null){
|
||||
result.put(record.getTaskDefinitionKey(), ListUtil.toList(record.getApproveUserId()));
|
||||
}else if(!isOnlyLastOne){
|
||||
result.get(record.getTaskDefinitionKey()).add(record.getApproveUserId());
|
||||
}
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public static final List<Long>queryTaskAuditPerson(String processInstId,String taskDefKey){
|
||||
return queryAuditPerson(processInstId,new String[]{taskDefKey},false).get(taskDefKey);
|
||||
}
|
||||
|
||||
|
||||
public static final void updateSubProcessInstName(String subProcessInstId,String subProcessInstName){
|
||||
HistoricActivityInstance instance=historyService.createHistoricActivityInstanceQuery().activityInstanceId(subProcessInstId).singleResult();
|
||||
runtimeService.setVariable(instance.getExecutionId(),WorkflowConstant.SUB_PROCESS_INSTANCE_NAME,subProcessInstName);
|
||||
}
|
||||
public static final Map<String,String> querySubProcessInstId(String[]executionIds){
|
||||
Map<String,String> subProcessInstIdMap = historyService.createHistoricVariableInstanceQuery().executionIdIn(executionIds)
|
||||
.variableName(WorkflowConstant.SUB_PROCESS_INSTANCE_ID).list()
|
||||
.stream().collect(Collectors.toMap(HistoricVariableInstance::getExecutionId,item->Convert.toStr(item.getValue())));
|
||||
return subProcessInstIdMap;
|
||||
}
|
||||
public static final Map<String,String> querySubProcessInstName(String[]executionIds){
|
||||
return querySubProcessInstName(executionIds,null);
|
||||
}
|
||||
public static final Map<String,String> querySubProcessInstName(String[]executionIds,Map<String,String> subProcessInstIdMap){
|
||||
if(subProcessInstIdMap==null) {
|
||||
subProcessInstIdMap = querySubProcessInstId(executionIds);
|
||||
}
|
||||
Map<String,String> subProcessInstNameMap = historyService.createHistoricVariableInstanceQuery().executionIdIn(executionIds)
|
||||
.variableName(WorkflowConstant.SUB_PROCESS_INSTANCE_NAME).list()
|
||||
.stream().collect(Collectors.toMap(HistoricVariableInstance::getExecutionId,item->Convert.toStr(item.getValue())));
|
||||
Set<String>actInstIdToQuery=new HashSet<>();
|
||||
for(String key:subProcessInstIdMap.keySet()){
|
||||
if(subProcessInstNameMap.get(key)==null&&subProcessInstIdMap.get(key)!=null){
|
||||
//去子流程实例的activityInst里查
|
||||
actInstIdToQuery.add(subProcessInstIdMap.get(key));
|
||||
}
|
||||
}
|
||||
if(ObjectUtil.isNotEmpty(actInstIdToQuery)) {
|
||||
Wrapper wrapper=new Wrapper();
|
||||
Map<String,String>subProcessActInstExecutionIdMap=historyService.createNativeHistoricActivityInstanceQuery()
|
||||
.sql(SqlBuilder.create(wrapper)
|
||||
.select("id_","execution_id_").from("act_hi_actinst").where("1=1 and ")
|
||||
.in("id_",actInstIdToQuery.stream().map(x->"'"+x+"'").toArray()).build()
|
||||
).list()
|
||||
.stream().collect(Collectors.toMap(HistoricActivityInstance::getId, HistoricActivityInstance::getExecutionId));
|
||||
Map<String,String> subProcessActInstExecutionNameMap = historyService.createHistoricVariableInstanceQuery()
|
||||
.executionIdIn(subProcessActInstExecutionIdMap.values().toArray(new String[]{}))
|
||||
.variableName(WorkflowConstant.SUB_PROCESS_INSTANCE_NAME).list()
|
||||
.stream().collect(Collectors.toMap(HistoricVariableInstance::getExecutionId,item->Convert.toStr(item.getValue())));
|
||||
for(String key:subProcessInstIdMap.keySet()){
|
||||
if(subProcessInstNameMap.get(key)==null&&subProcessInstIdMap.get(key)!=null
|
||||
&&subProcessActInstExecutionIdMap.get(subProcessInstIdMap.get(key))!=null
|
||||
&&subProcessActInstExecutionNameMap.get(subProcessActInstExecutionIdMap.get(subProcessInstIdMap.get(key)))!=null){
|
||||
//赋值子流程实例里的流程名称
|
||||
subProcessInstNameMap.put(key,subProcessActInstExecutionNameMap.get(subProcessActInstExecutionIdMap.get(subProcessInstIdMap.get(key))));
|
||||
}
|
||||
}
|
||||
}
|
||||
return subProcessInstNameMap;
|
||||
}
|
||||
public static final String querySubProcessInstId(String executionId){
|
||||
return querySubProcessInstId(executionId,false);
|
||||
}
|
||||
public static final String querySubProcessInstId(String executionId,Boolean isOriginal){
|
||||
Object subProcessInstIdObj=runtimeService.getVariableLocal(executionId,
|
||||
isOriginal?WorkflowConstant.ORIGINAL_SUB_PROCESS_INSTANCE_ID:WorkflowConstant.SUB_PROCESS_INSTANCE_ID);
|
||||
return subProcessInstIdObj==null?(isOriginal?querySubProcessInstId(executionId):null):String.valueOf(subProcessInstIdObj);
|
||||
}
|
||||
public static final String querySubProcessParentInstId(String executionId){
|
||||
return querySubProcessParentInstId(executionId,false);
|
||||
}
|
||||
public static final String querySubProcessParentInstId(String executionId,Boolean isOriginal){
|
||||
Object subProcessParentInstIdObj=runtimeService.getVariableLocal(executionId,
|
||||
isOriginal?WorkflowConstant.ORIGINAL_SUB_PROCESS_PARENT_INSTANCE_ID:WorkflowConstant.SUB_PROCESS_PARENT_INSTANCE_ID);
|
||||
return subProcessParentInstIdObj==null?(isOriginal?querySubProcessParentInstId(executionId):null):String.valueOf(subProcessParentInstIdObj);
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归查询给定活动实例下的直到活动实例id的活动实例
|
||||
* @param activityInstance
|
||||
* @param activityInstId
|
||||
* @return
|
||||
*/
|
||||
public static final ActivityInstance queryActivityInstByActInstId(ActivityInstance activityInstance,String activityInstId){
|
||||
if(activityInstance==null||activityInstance.getId().equals(activityInstId)){
|
||||
return activityInstance;
|
||||
}
|
||||
if(ObjectUtil.isNotEmpty(activityInstance.getChildActivityInstances())){
|
||||
for(ActivityInstance child:activityInstance.getChildActivityInstances()){
|
||||
child=queryActivityInstByActInstId(child,activityInstId);
|
||||
if(child!=null){
|
||||
return child;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static final Task queryTaskCurrentUserCanApprove(String taskId){
|
||||
Task task = taskService.createTaskQuery().taskId(taskId)
|
||||
//校验当前登录人是审批人
|
||||
.taskVariableValueLike(WorkflowConstant.TASK_ASSIGNEE_VAR_KEY, StringPool.PERCENT+StrUtil.toString(SecureUtil.getCurrentUserId())+StringPool.PERCENT)
|
||||
.active()
|
||||
.singleResult();
|
||||
if(task==null){
|
||||
throw new ValidationException("任务不存在或无审批权限!");
|
||||
}
|
||||
return task;
|
||||
}
|
||||
public static final HistoricActivityInstance queryHistoricActivityInstanceOfTask(Task task){
|
||||
HistoricActivityInstance executionActivityInstance=null;
|
||||
List<HistoricActivityInstance> taskExecutionActivityInstanceList=historyService.createHistoricActivityInstanceQuery()
|
||||
.executionId(task.getExecutionId())
|
||||
.activityId(task.getTaskDefinitionKey())
|
||||
.list();
|
||||
if(ObjectUtil.isNotEmpty(taskExecutionActivityInstanceList)){
|
||||
executionActivityInstance=taskExecutionActivityInstanceList.stream().filter(x->task.getId().equals(x.getTaskId())).findFirst()
|
||||
.orElse(taskExecutionActivityInstanceList.get(0));
|
||||
}
|
||||
return executionActivityInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询流程配置相关的方法
|
||||
*/
|
||||
public static final WorkflowSchema queryWorkflowSchema(String processInstId){
|
||||
HistoricVariableInstance historicVariableInstance = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstId)
|
||||
.variableName(WorkflowConstant.PROCESS_SCHEMA_ID_KEY).singleResult();
|
||||
if(historicVariableInstance==null){
|
||||
log.error("no schemaId found from process variable:"+processInstId);
|
||||
return null;
|
||||
}
|
||||
//排除xml 查出数据
|
||||
WorkflowSchema workflowSchema = workflowSchemaService.getOne(Wrappers.lambdaQuery(WorkflowSchema.class)
|
||||
.eq(WorkflowSchema::getId, historicVariableInstance.getValue()));
|
||||
return workflowSchema;
|
||||
}
|
||||
public static final WorkflowSchema queryWorkflowSchema(Long schemaId){
|
||||
return workflowSchemaService.getById(schemaId);
|
||||
}
|
||||
public static final List<Map<String,Object>>queryNodeConfigList(String processInstId){
|
||||
WorkflowSchema workflowSchema = queryWorkflowSchema(processInstId);
|
||||
//获取到整个流程模板的配置
|
||||
WorkflowSchemaConfig workflowSchemaConfig = JSONUtil.toBean(workflowSchema.getJsonContent(), WorkflowSchemaConfig.class);
|
||||
return workflowSchemaConfig.getChildNodeConfig();
|
||||
}
|
||||
public static final Map<String,Object>queryNodeConfig(String processInstId,String taskDefKey){
|
||||
Optional<Map<String, Object>> configOp = queryNodeConfigList(processInstId).stream().filter(c -> c.containsValue(taskDefKey)).findFirst();
|
||||
if (!configOp.isPresent()) {
|
||||
throw new MyException("找不到当前节点配置!");
|
||||
}
|
||||
return configOp.get();
|
||||
}
|
||||
public static final UserTaskConfig queryUserTaskNodeConfig(String processInstId,String taskDefKey){
|
||||
return Convert.convert(UserTaskConfig.class, queryNodeConfig(processInstId,taskDefKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* 按照执行的层级查询已完成的活动实例
|
||||
* 往上查询父层级和根层级
|
||||
* @param executionActivityInstance
|
||||
* @return
|
||||
*/
|
||||
public static final List<HistoricActivityInstance> queryFinishedActivityByParentLevel(HistoricActivityInstance executionActivityInstance){
|
||||
List<HistoricActivityInstance> list=new ArrayList<>();
|
||||
//从当前任务的executionId所在层级开始,往上查找所有执行过的活动,直到主分支层级
|
||||
//不会进入其他子分支
|
||||
while(executionActivityInstance!=null){
|
||||
list.addAll(historyService.createHistoricActivityInstanceQuery()
|
||||
.processInstanceId(executionActivityInstance.getProcessInstanceId())
|
||||
.executionId(executionActivityInstance.getExecutionId())
|
||||
.activityType(WorkflowConstant.BPMN_USER_TASK_TYPE_NAME)
|
||||
.finished()
|
||||
.orderPartiallyByOccurrence()
|
||||
.desc()
|
||||
.list());
|
||||
if(executionActivityInstance.getParentActivityInstanceId().equals(executionActivityInstance.getProcessInstanceId())){
|
||||
//将要到达顶层或已到达顶层
|
||||
break;
|
||||
}else {
|
||||
//加入上一层
|
||||
executionActivityInstance = historyService.createHistoricActivityInstanceQuery()
|
||||
.activityInstanceId(executionActivityInstance.getParentActivityInstanceId()).singleResult();
|
||||
}
|
||||
}
|
||||
if(executionActivityInstance!=null&&!executionActivityInstance.getExecutionId().equals(executionActivityInstance.getProcessInstanceId())){
|
||||
//将要到达顶层的情况,补充顶层的数据
|
||||
list.addAll(historyService.createHistoricActivityInstanceQuery()
|
||||
.processInstanceId(executionActivityInstance.getProcessInstanceId())
|
||||
.executionId(executionActivityInstance.getProcessInstanceId())
|
||||
.activityType(WorkflowConstant.BPMN_USER_TASK_TYPE_NAME)
|
||||
.finished()
|
||||
.orderPartiallyByOccurrence()
|
||||
.desc()
|
||||
.list());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
/**
|
||||
* 查询子流程中完成的活动,按节点层级倒序排列
|
||||
* @param processInstId
|
||||
* @param subProcessInstId
|
||||
* @param filtrateAfterActInstId 如果有值则按活动实例id过滤,否则按定义id
|
||||
* @param filtrateAfterActId
|
||||
* @param queryIn 是否查询在子流程中
|
||||
* @return
|
||||
*/
|
||||
public static final List<HistoricActivityInstance> queryFinishedActivityInOrNotInSubProcess(String processInstId,String subProcessInstId,String filtrateAfterActInstId,String filtrateAfterActId,Boolean queryIn){
|
||||
List<HistoricActivityInstance> list=historyService.createNativeHistoricActivityInstanceQuery().sql(
|
||||
"SELECT id_, parent_act_inst_id_, proc_def_key_, proc_def_id_, root_proc_inst_id_, proc_inst_id_, execution_id_, act_id_, task_id_, call_proc_inst_id_, call_case_inst_id_, act_name_, act_type_, assignee_, start_time_, end_time_, duration_, act_inst_state_, sequence_counter_, tenant_id_, removal_time_\n" +
|
||||
"FROM act_hi_actinst WHERE proc_inst_id_ ='"+processInstId+"' AND execution_id_ "+(queryIn?"":"not ")+"in(\n" +
|
||||
"SELECT execution_id_ FROM act_hi_varinst arv WHERE proc_inst_id_ ='"+processInstId+"' AND name_='subProcessInstanceId' "+
|
||||
(StringUtils.isNotBlank(subProcessInstId)?("AND text_='"+subProcessInstId+"'"):"")+"\n" +
|
||||
")ORDER BY sequence_counter_ DESC").list();
|
||||
return filtrateAfterActivity(list,filtrateAfterActInstId,filtrateAfterActId,true);
|
||||
}
|
||||
/**
|
||||
* 查询主流程中完成的活动,按节点层级倒序排列
|
||||
* @param processInstId
|
||||
* @param filtrateAfterActInstId
|
||||
* @param filtrateAfterActId
|
||||
* @return
|
||||
*/
|
||||
public static final List<HistoricActivityInstance> queryFinishedActivityInProcess(String processInstId,String filtrateAfterActInstId,String filtrateAfterActId){
|
||||
List<HistoricActivityInstance> list=historyService.createHistoricActivityInstanceQuery()
|
||||
.processInstanceId(processInstId)
|
||||
.finished()
|
||||
.orderPartiallyByOccurrence()
|
||||
.desc()
|
||||
.list();
|
||||
return filtrateAfterActivity(list,filtrateAfterActInstId,filtrateAfterActId,true);
|
||||
}
|
||||
/**
|
||||
* 传入一个按发生时间倒序的列表,从第一个元素开始过滤掉发生在指定节点之后的活动:如果有满足条件的元素,删除直到两个条件之一成立,该模式保留了最多的结果
|
||||
* 可指定为逆序,即从尾部开始,直到满足条件的元素出现后,开始删除后续的元素,该模式保留最少的结果
|
||||
* @param list
|
||||
* @param filtrateAfterActInstId
|
||||
* @param filtrateAfterActId
|
||||
*/
|
||||
public static final List<HistoricActivityInstance> filtrateAfterActivity(List<HistoricActivityInstance>list,String filtrateAfterActInstId,String filtrateAfterActId,Boolean isReversal){
|
||||
if(ObjectUtil.isNotEmpty(list)&&(StringUtils.isNotBlank(filtrateAfterActInstId)||StringUtils.isNotBlank(filtrateAfterActId))
|
||||
&&list.stream().anyMatch(x->x.getId().equals(filtrateAfterActInstId)||x.getActivityId().equals(filtrateAfterActId))){
|
||||
if(isReversal){
|
||||
ListIterator<HistoricActivityInstance>iterator=list.listIterator(list.size());
|
||||
Boolean startRemove=false;
|
||||
while(iterator.hasPrevious()){
|
||||
HistoricActivityInstance item=iterator.previous();
|
||||
if(!startRemove){
|
||||
if(item.getId().equals(filtrateAfterActInstId)||item.getActivityId().equals(filtrateAfterActId)) {
|
||||
startRemove = true;
|
||||
}
|
||||
}else{
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}else{
|
||||
Iterator<HistoricActivityInstance>iterator=list.iterator();
|
||||
while(iterator.hasNext()){
|
||||
HistoricActivityInstance item=iterator.next();
|
||||
if(item.getId().equals(filtrateAfterActInstId)||item.getActivityId().equals(filtrateAfterActId)){
|
||||
break;
|
||||
}else{
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static final Boolean isMultiInstanceNode(FlowNode node){
|
||||
return ((Activity)node).getLoopCharacteristics()!=null;
|
||||
}
|
||||
public static final FlowNode getFlowNode(String processDefId,String nodeDefKey){
|
||||
BpmnModelInstance bpmnModel = repositoryService.getBpmnModelInstance(processDefId);
|
||||
FlowNode flowNode = bpmnModel.getModelElementById(nodeDefKey);
|
||||
return flowNode;
|
||||
}
|
||||
public static final List<String>queryPrevActivityDefKeyInModel(List<SequenceFlow> flows,List<String>includeTypes){
|
||||
return queryPrevActivityDefKeyInModel(flows,includeTypes,null,null);
|
||||
}
|
||||
public static final List<String>queryPrevActivityDefKeyInModel(List<SequenceFlow> flows,List<String>includeTypes,List<String>excludeTypes,List<String>result){
|
||||
if(result==null) {
|
||||
result = new ArrayList<>();
|
||||
}
|
||||
for(SequenceFlow flow:flows){
|
||||
FlowNode node=flow.getSource();
|
||||
if(!result.contains(node.getId())){
|
||||
if((ObjectUtil.isEmpty(includeTypes)||includeTypes.contains(node.getElementType().getTypeName()))
|
||||
&&(ObjectUtil.isEmpty(excludeTypes)||!excludeTypes.contains(node.getElementType().getTypeName()))) {
|
||||
result.add(node.getId());
|
||||
}
|
||||
//如果是子流程,从子流程的结束节点递归
|
||||
if(node instanceof SubProcess){
|
||||
for(FlowNode item:Convert.toList(FlowNode.class,node.getChildElementsByType(EndEvent.class))){
|
||||
queryPrevActivityDefKeyInModel(ListUtil.toList(item.getIncoming()), includeTypes, excludeTypes, result);
|
||||
}
|
||||
}else if(ObjectUtil.isNotEmpty(node.getIncoming())) {
|
||||
queryPrevActivityDefKeyInModel(ListUtil.toList(node.getIncoming()), includeTypes, excludeTypes, result);
|
||||
}else if(node.getParentElement() instanceof FlowNode){
|
||||
queryPrevActivityDefKeyInModel(ListUtil.toList(((FlowNode)node.getParentElement()).getIncoming()), includeTypes, excludeTypes, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*public static final Boolean gotoNode(String processInstId,String subProcessInstId){
|
||||
User operator=SecureUtil.getCurrentUser();
|
||||
//如果是子流程内退回,仅退回该子流程实例,需要查询原始的子流程实例id
|
||||
//子流程外退回,应退回整个流程(会签退回所有工作项,不想退回的话用不同意的百分比处理,不要用退回)
|
||||
//发起退回的节点,源活动
|
||||
String activityInstIdToReject=StringUtils.isNotBlank(subProcessInstId)?
|
||||
WorkflowBusinessUtil.querySubProcessInstId(task.getExecutionId(),true):processInstId;
|
||||
ActivityInstance activityInstanceToReject=WorkflowBusinessUtil.queryActivityInstByActInstId(runtimeService.getActivityInstance(processInstId),activityInstIdToReject);
|
||||
List<String>cancelActInstIdsOfActInstToRejectAtLast=new ArrayList<>();
|
||||
//是否退回到同个子流程中,是则特殊处理
|
||||
Boolean isRejectToCurrentSubProcessInst=!processInstId.equals(activityInstIdToReject)&&ListUtil.toList(rejectToMap.keySet()).contains(activityInstIdToReject);
|
||||
|
||||
ProcessInstanceModificationInstantiationBuilder modifyBuilder= (ProcessInstanceModificationInstantiationBuilder) runtimeService.createProcessInstanceModification(processInstId)
|
||||
.setAnnotation("【审批人:" + operator.getName() + "】 驳回 【任务:" + task.getId() + "】");
|
||||
if(isRejectToCurrentSubProcessInst){
|
||||
//同个子流程内退回的情况,先保留当前子流程实例内的活动实例,在发起新活动实例后,再取消掉这些已有实例
|
||||
cancelActInstIdsOfActInstToRejectAtLast.addAll(Arrays.stream(activityInstanceToReject.getChildActivityInstances()).map(ActivityInstance::getId).collect(Collectors.toList()));
|
||||
//TODO 会签仅退回一个?
|
||||
}else{
|
||||
//如果退回其他(子)流程中,或者是主流程退回,先取消当前(子)流程实例
|
||||
modifyBuilder.cancelActivityInstance(activityInstIdToReject);
|
||||
log.info("stop activityInstId:{} for reject to {} by {}",activityInstIdToReject,dto.getRejectNodeActivityId(),operator.getUserName());
|
||||
}
|
||||
//按主流程子流程执行退回到目标活动
|
||||
for(String rejectToSubProcessId:rejectToMap.keySet()) {
|
||||
//除了退回同子流程用子流程发起目标活动,其他都用主流程发起
|
||||
modifyBuilder.startBeforeActivity(dto.getRejectNodeActivityId(), isRejectToCurrentSubProcessInst?activityInstIdToReject:processInstId);
|
||||
if (!rejectToSubProcessId.equals(activityInstIdToReject)
|
||||
&&!WorkflowConstant.MAIN_PROCESS_ID.equals(rejectToSubProcessId)) {
|
||||
//如果退回到子流程内,重启选人的子流程(重启是发起新的子流程,但是把原子流程的流程变量复制过去)
|
||||
List<HistoricVariableInstance> subProcessVarList = historyService.createHistoricVariableInstanceQuery()
|
||||
.activityInstanceIdIn(rejectToSubProcessId)
|
||||
.variableNameIn(WorkflowConstant.SUB_PROCESS_INSTANCE_ID, WorkflowConstant.SUB_PROCESS_PARENT_INSTANCE_ID)
|
||||
.list();
|
||||
Map<String, Object> subProcessVarMap = subProcessVarList.stream().collect(Collectors.toMap(x->x.getName()+"Force", HistoricVariableInstance::getValue));
|
||||
modifyBuilder.setVariablesLocal(subProcessVarMap);
|
||||
}
|
||||
log.info("restart subProcess:{} by {}",rejectToSubProcessId,operator.getUserName());
|
||||
}
|
||||
//最后才取消的活动实例(退回同子流程的情况,先取消会导致子流程实例被取消,无法发起目标活动实例
|
||||
for(String cancelActInstIdOfActInstToReject:cancelActInstIdsOfActInstToRejectAtLast){
|
||||
modifyBuilder.cancelActivityInstance(cancelActInstIdOfActInstToReject);
|
||||
log.info("stop activityInstId:{} for reject to {} by {}",cancelActInstIdOfActInstToReject,dto.getRejectNodeActivityId(),operator.getUserName());
|
||||
}
|
||||
modifyBuilder.execute();
|
||||
|
||||
return true;
|
||||
}*/
|
||||
}
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
spring:
|
||||
profiles:
|
||||
active: public
|
||||
@ -0,0 +1,79 @@
|
||||
server:
|
||||
port: 3007
|
||||
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: workflow-service
|
||||
main:
|
||||
allow-bean-definition-overriding: true
|
||||
autoconfigure:
|
||||
#自动化配置 例外处理
|
||||
exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
|
||||
datasource:
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
dynamic:
|
||||
primary: master
|
||||
datasource:
|
||||
master:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://new-energy-mysqlt.itc.gdyd.com:3307/fcd2-msat-init?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
|
||||
username: learun4dev
|
||||
password: ABcd1234@
|
||||
|
||||
cloud:
|
||||
nacos: #nacos监控
|
||||
discovery:
|
||||
server-addr: 10.0.252.1:8848
|
||||
namespace: ITC
|
||||
group: DNE
|
||||
username: nacos
|
||||
password: ABcd1234@
|
||||
config:
|
||||
server-addr: 10.0.252.1:8848 # nacos 配置中心地址
|
||||
namespace: ITC
|
||||
group: DNE
|
||||
username: nacos
|
||||
password: ABcd1234@
|
||||
file-extension: yml # 指定格式 xjrsoft-demo-service-dev.yml
|
||||
extension-configs:
|
||||
- data-id: global-config.yml #导入全局配置
|
||||
refresh: true
|
||||
group: DNE
|
||||
- data-id: mybatis-plus-config.yml #导入mybatisplus 配置
|
||||
refresh: true
|
||||
group: DNE
|
||||
- data-id: sa-token-client-config.yml #导入sa-token配置
|
||||
refresh: true
|
||||
group: DNE
|
||||
- data-id: redis-config.yml #导入redis配置
|
||||
refresh: true
|
||||
group: DNE
|
||||
- data-id: seata-config.yml #导入seata配置
|
||||
refresh: true
|
||||
group: DNE
|
||||
- data-id: camunda-config.yml #导入seata配置
|
||||
refresh: true
|
||||
group: DNE
|
||||
sentinel:
|
||||
transport:
|
||||
dashboard: localhost:8080 #sentinel dashboard 地址
|
||||
port: 8719 #默认端口, 如果 被占用,会一直+1 直到未被占用为止
|
||||
|
||||
|
||||
|
||||
|
||||
springdoc:
|
||||
swagger-ui:
|
||||
path: /swagger-ui.html
|
||||
tags-sorter: alpha
|
||||
operations-sorter: alpha
|
||||
show-extensions: true
|
||||
api-docs:
|
||||
path: /workflow/v3/api-docs
|
||||
group-configs:
|
||||
- group: 'default'
|
||||
paths-to-match: '/workflow/**'
|
||||
packages-to-scan: com.xjrsoft.workflow
|
||||
default-flat-param-object: false
|
||||
|
||||
Reference in New Issue
Block a user