feat: initial iShare project code

This commit is contained in:
purovps
2026-02-16 23:20:59 +08:00
parent 8c83a6fd46
commit 6f270a972e
1910 changed files with 218015 additions and 0 deletions

View File

@@ -0,0 +1,18 @@
FROM pig4cloud/java:8-jre
MAINTAINER wangiegie@gmail.com
ENV TZ=Asia/Shanghai
ENV JAVA_OPTS="-Xms512m -Xmx1024m -Djava.security.egd=file:/dev/./urandom"
RUN ln -sf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN mkdir -p /pigx-flow-task
WORKDIR /pigx-flow-task
EXPOSE 9030
ADD ./target/pigx-flow-task-biz.jar ./
CMD sleep 60;java $JAVA_OPTS -jar pigx-flow-task-biz.jar

View File

@@ -0,0 +1,118 @@
<?xml version="1.0"?>
<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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-flow-task</artifactId>
<version>5.2.0</version>
</parent>
<artifactId>pigx-flow-task-biz</artifactId>
<dependencies>
<!--必备: undertow容器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<!--必备: spring boot web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--必备: 注册中心客户端-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--必备: 配置中心客户端-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--必备: 操作数据源相关-->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-data</artifactId>
</dependency>
<!--选配: 发号器-->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-sequence</artifactId>
</dependency>
<!--必备pigx安全模块-->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-security</artifactId>
</dependency>
<!--必备xss 过滤模块-->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-xss</artifactId>
</dependency>
<!--必备: sentinel 依赖-->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-sentinel</artifactId>
</dependency>
<!--必备: feign 依赖-->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-feign</artifactId>
</dependency>
<!--必备: 依赖api模块-->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-flow-task-api</artifactId>
</dependency>
<!--必备: log 依赖-->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-log</artifactId>
</dependency>
<!--选配: mybatis 依赖 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!--选配: druid 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!--选配: mysql 数据库驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<!--选配: swagger文档-->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-swagger</artifactId>
</dependency>
<!--测试: spring boot test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>com.dameng</groupId>
<artifactId>DmJdbcDriver18</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,26 @@
package com.pig4cloud.pigx.flow.task;
import com.pig4cloud.pigx.common.feign.annotation.EnablePigxFeignClients;
import com.pig4cloud.pigx.common.security.annotation.EnablePigxResourceServer;
import com.pig4cloud.pigx.common.swagger.annotation.EnableOpenApi;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* @author pigx archetype
* <p>
* 项目启动类
*/
@EnableOpenApi("task")
@EnablePigxFeignClients
@EnableDiscoveryClient
@EnablePigxResourceServer
@SpringBootApplication
public class PigxFlowTaskApplication {
public static void main(String[] args) {
SpringApplication.run(PigxFlowTaskApplication.class, args);
}
}

View File

@@ -0,0 +1,36 @@
package com.pig4cloud.pigx.flow.task.config;
import cn.hutool.core.date.DateUtil;
import com.pig4cloud.pigx.common.data.tenant.TenantContextHolder;
import com.pig4cloud.pigx.common.sequence.builder.DbSeqBuilder;
import com.pig4cloud.pigx.common.sequence.properties.SequenceDbProperties;
import com.pig4cloud.pigx.common.sequence.sequence.Sequence;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
/**
* @author lengleng
* @date 2023-07-19
* <p>
* 设置发号器生成规则
*/
@Configuration
public class SequenceConfiguration {
/**
* 工作流发号器
* @param dataSource
* @param properties
* @return
*/
@Bean
public Sequence flowSequence(DataSource dataSource, SequenceDbProperties properties) {
return DbSeqBuilder.create()
.bizName(() -> String.format("flow_%s_%s", TenantContextHolder.getTenantId(), DateUtil.today()))
.dataSource(dataSource).step(properties.getStep()).retryTimes(properties.getRetryTimes())
.tableName(properties.getTableName()).build();
}
}

View File

@@ -0,0 +1,39 @@
package com.pig4cloud.pigx.flow.task.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.flow.task.service.ICombinationGroupService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 组聚合接口控制器
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/combination/group")
public class CombinationGroupController {
private final ICombinationGroupService combinationGroupService;
/**
* 查询表单组包含流程
* @return 表单组数据
*/
@GetMapping("listGroupWithProcess")
public R listGroupWithProcess(Page page, Long groupId) {
return combinationGroupService.listGroupWithProcess(page, groupId);
}
/**
* 查询所有我可以发起的表单组
* @return
*/
@GetMapping("listCurrentUserStartGroup")
public R listCurrentUserStartGroup() {
return combinationGroupService.listCurrentUserStartGroup();
}
}

View File

@@ -0,0 +1,44 @@
package com.pig4cloud.pigx.flow.task.controller;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.flow.task.service.IOrgService;
import lombok.RequiredArgsConstructor;
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;
/**
* @author : willian fu
* @date : 2022/6/27
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/org")
public class OrgController {
private final IOrgService orgService;
/**
* 查询组织架构树
* @param deptId 部门id
* @param showLeave 是否显示离职员工
* @return 组织架构树数据
*/
@GetMapping("tree")
public R getOrgTreeData(@RequestParam(defaultValue = "0") Long deptId, String type,
@RequestParam(defaultValue = "false") Boolean showLeave) {
return orgService.getOrgTreeData(deptId, type, showLeave);
}
/**
* 模糊搜索用户
* @param userName 用户名/拼音/首字母
* @return 匹配到的用户
*/
@GetMapping("tree/user/search")
public R getOrgTreeUser(@RequestParam String userName) {
return orgService.getOrgTreeUser(userName.trim());
}
}

View File

@@ -0,0 +1,49 @@
package com.pig4cloud.pigx.flow.task.controller;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.flow.task.entity.Process;
import com.pig4cloud.pigx.flow.task.service.IProcessService;
import com.pig4cloud.pigx.flow.task.vo.ProcessVO;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
@RestController
@RequiredArgsConstructor
@RequestMapping("/process")
public class ProcessController {
private final IProcessService processService;
/**
* 获取详细数据
* @param flowId
* @return
*/
@GetMapping("getDetail")
public R<ProcessVO> getDetail(String flowId) {
return processService.getDetail(flowId);
}
/**
* 创建流程
* @param process
* @return
*/
@PostMapping("create")
public R create(@RequestBody Process process) {
return processService.create(process);
}
/**
* 编辑表单
* @param flowId 摸板ID
* @param type 类型 stop using delete
* @return 操作结果
*/
@PutMapping("update/{flowId}")
public R update(@PathVariable String flowId, @RequestParam String type,
@RequestParam(required = false) Long groupId) {
return processService.update(flowId, type, groupId);
}
}

View File

@@ -0,0 +1,35 @@
package com.pig4cloud.pigx.flow.task.controller;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.flow.task.service.IProcessCopyService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 流程抄送数据 前端控制器
* </p>
*
* @author Vincent
* @since 2023-05-20
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/processCopy")
public class ProcessCopyController {
private final IProcessCopyService processCopyService;
/**
* 查询单个抄送详细信息
* @param id
* @return
*/
@GetMapping("querySingleDetail")
public R querySingleDetail(long id) {
return processCopyService.querySingleDetail(id);
}
}

View File

@@ -0,0 +1,47 @@
package com.pig4cloud.pigx.flow.task.controller;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.flow.task.entity.ProcessGroup;
import com.pig4cloud.pigx.flow.task.service.IProcessGroupService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequiredArgsConstructor
@RequestMapping("processGroup")
public class ProcessGroupController {
private final IProcessGroupService processGroupService;
/**
* 组列表
* @return
*/
@GetMapping("list")
public R<List<ProcessGroup>> queryList() {
return processGroupService.queryList();
}
/**
* 新增流程分组
* @param processGroup 分组名
* @return 添加结果
*/
@PostMapping("create")
public R create(@RequestBody ProcessGroup processGroup) {
return processGroupService.create(processGroup);
}
/**
* 删除分组
* @param id
* @return
*/
@DeleteMapping("delete/{id}")
public R delete(@PathVariable long id) {
return processGroupService.delete(id);
}
}

View File

@@ -0,0 +1,97 @@
package com.pig4cloud.pigx.flow.task.controller;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.flow.task.dto.ProcessInstanceParamDto;
import com.pig4cloud.pigx.flow.task.dto.TaskQueryParamDto;
import com.pig4cloud.pigx.flow.task.service.IProcessInstanceService;
import com.pig4cloud.pigx.flow.task.vo.NodeFormatParamVo;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.web.bind.annotation.*;
/**
* 流程实例
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/process-instance")
public class ProcessInstanceController {
private final IProcessInstanceService processInstanceService;
/**
* 启动流程
* @param processInstanceParamDto
* @return
*/
@SneakyThrows
@PostMapping("startProcessInstance")
public R startProcessInstance(@RequestBody ProcessInstanceParamDto processInstanceParamDto) {
return processInstanceService.startProcessInstance(processInstanceParamDto);
}
/**
* 查询当前登录用户的待办任务
* @param pageDto
* @return
*/
@SneakyThrows
@PostMapping("queryMineTask")
public R queryMineTask(@RequestBody TaskQueryParamDto queryParamDto) {
return processInstanceService.queryMineTask(queryParamDto);
}
/**
* 查询当前登录用户已办任务
* @param taskQueryParamDto
* @return
*/
@SneakyThrows
@PostMapping("queryMineEndTask")
public R queryMineEndTask(@RequestBody TaskQueryParamDto taskQueryParamDto) {
return processInstanceService.queryMineEndTask(taskQueryParamDto);
}
/**
* 查询我发起的
* @param pageDto
* @return
*/
@SneakyThrows
@PostMapping("queryMineStarted")
public R queryMineStarted(@RequestBody TaskQueryParamDto taskQueryParamDto) {
return processInstanceService.queryMineStarted(taskQueryParamDto);
}
/**
* 查询抄送我的
* @param pageDto
* @return
*/
@SneakyThrows
@PostMapping("queryMineCC")
public R queryMineCC(@RequestBody TaskQueryParamDto taskQueryParamDto) {
return processInstanceService.queryMineCC(taskQueryParamDto);
}
/**
* 格式化流程显示
* @param nodeFormatParamVo
* @return
*/
@PostMapping("formatStartNodeShow")
public R formatStartNodeShow(@RequestBody NodeFormatParamVo nodeFormatParamVo) {
return processInstanceService.formatStartNodeShow(nodeFormatParamVo);
}
/**
* 流程详情
* @param processInstanceId
* @return
*/
@GetMapping("detail")
public R detail(String processInstanceId) {
return processInstanceService.detail(processInstanceId);
}
}

View File

@@ -0,0 +1,46 @@
package com.pig4cloud.pigx.flow.task.controller;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.flow.task.dto.Node;
import com.pig4cloud.pigx.flow.task.dto.ProcessNodeDataDto;
import com.pig4cloud.pigx.flow.task.service.IProcessNodeDataService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
/**
* <p>
* 流程节点数据 前端控制器
* </p>
*
* @author Vincent
* @since 2023-05-07
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/processNodeData")
public class ProcessNodeDataController {
private final IProcessNodeDataService processNodeDataService;
/**
* 保存节点数据
* @param processNodeDataDto
* @return
*/
@PostMapping("saveNodeData")
public R saveNodeData(@RequestBody ProcessNodeDataDto processNodeDataDto) {
return processNodeDataService.saveNodeData(processNodeDataDto);
}
/**
* 获取节点数据
* @param flowId
* @param nodeId
* @return
*/
@GetMapping("getNodeData")
public R<Node> getNodeData(String flowId, String nodeId) {
return processNodeDataService.getNodeData(flowId, nodeId);
}
}

View File

@@ -0,0 +1,152 @@
package com.pig4cloud.pigx.flow.task.controller;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.flow.task.dto.*;
import com.pig4cloud.pigx.flow.task.service.IRemoteService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
* 远程请求控制器
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/remote")
public class RemoteController {
private final IRemoteService remoteService;
/**
* 根据角色id集合查询用户id集合
* @param roleIdList
* @return
*/
@PostMapping("queryUserIdListByRoleIdList")
public R<List<Long>> queryUserIdListByRoleIdList(@RequestBody List<Long> roleIdList) {
return remoteService.queryUserIdListByRoleIdList(roleIdList);
}
/**
* 保存抄送
* @param copyDto
* @return
*/
@PostMapping("savecc")
public R saveCC(@RequestBody ProcessCopyDto copyDto) {
return remoteService.saveCC(copyDto);
}
/**
* 检查是否是所有的父级
* @param checkParentDto
* @return
*/
@PostMapping("checkIsAllParent")
public R<Boolean> checkIsAllParent(@RequestBody CheckParentDto checkParentDto) {
return remoteService.checkIsAllParent(checkParentDto);
}
/**
* 根据部门id集合查询用户id集合
* @param depIdList
* @return
*/
@PostMapping("queryUserIdListByDepIdList")
public R<List<Long>> queryUserIdListByDepIdList(@RequestBody List<Long> depIdList) {
return remoteService.queryUserIdListByDepIdList(depIdList);
}
/**
* 检查是否是所有的子级
* @param checkChildDto
* @return
*/
@PostMapping("checkIsAllChild")
public R<Boolean> checkIsAllChild(@RequestBody CheckChildDto checkChildDto) {
return remoteService.checkIsAllChild(checkChildDto);
}
/**
* 获取用户的信息-包括扩展字段
* @param userId
* @return
*/
@GetMapping("queryUserAllInfo")
public R<Map<String, Object>> queryUserAllInfo(long userId) {
return remoteService.queryUserAllInfo(userId);
}
/**
* 开始节点事件
* @param recordParamDto
* @return
*/
@PostMapping("startNodeEvent")
public R startNodeEvent(@RequestBody ProcessNodeRecordParamDto recordParamDto) {
return remoteService.startNodeEvent(recordParamDto);
}
/**
* 流程创建了
* @param processInstanceRecordParamDto
* @return
*/
@PostMapping("createProcessEvent")
public R createProcessEvent(@RequestBody ProcessInstanceRecordParamDto processInstanceRecordParamDto) {
return remoteService.createProcessEvent(processInstanceRecordParamDto);
}
/**
* 结束节点事件
* @param recordParamDto
* @return
*/
@PostMapping("endNodeEvent")
public R endNodeEvent(@RequestBody ProcessNodeRecordParamDto recordParamDto) {
return remoteService.endNodeEvent(recordParamDto);
}
/**
* 开始设置执行人
* @param processNodeRecordAssignUserParamDto
* @return
*/
@PostMapping("startAssignUser")
public R startAssignUser(@RequestBody ProcessNodeRecordAssignUserParamDto processNodeRecordAssignUserParamDto) {
return remoteService.startAssignUser(processNodeRecordAssignUserParamDto);
}
/**
* 任务结束事件
* @param processNodeRecordAssignUserParamDto
* @return
*/
@PostMapping("taskEndEvent")
public R taskEndEvent(@RequestBody ProcessNodeRecordAssignUserParamDto processNodeRecordAssignUserParamDto) {
return remoteService.taskEndEvent(processNodeRecordAssignUserParamDto);
}
/**
* 实例结束
* @param processInstanceParamDto
* @return
*/
@PostMapping("endProcess")
public R endProcess(@RequestBody ProcessInstanceParamDto processInstanceParamDto) {
return remoteService.endProcess(processInstanceParamDto.getProcessInstanceId());
}
/**
* 查询流程管理员
* @param flowId
* @return
*/
@GetMapping("queryProcessAdmin")
public R<Long> queryProcessAdmin(String flowId) {
return remoteService.queryProcessAdmin(flowId);
}
}

View File

@@ -0,0 +1,118 @@
package com.pig4cloud.pigx.flow.task.controller;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.flow.task.dto.TaskParamDto;
import com.pig4cloud.pigx.flow.task.service.ITaskService;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.web.bind.annotation.*;
/**
* 任务实例
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/task")
public class TaskController {
private final ITaskService taskService;
/**
* 查询首页数据看板
* @return
*/
@SneakyThrows
@GetMapping("queryTaskData")
public R queryTaskData() {
return taskService.queryTaskData();
}
/**
* 查询任务
* @param taskId
* @return
*/
@SneakyThrows
@GetMapping("queryTask")
public R queryTask(String taskId, boolean view) {
return taskService.queryTask(taskId, view);
}
/**
* 完成任务
* @param completeParamDto
* @return
*/
@SneakyThrows
@PostMapping("completeTask")
public R completeTask(@RequestBody TaskParamDto completeParamDto) {
return taskService.completeTask(completeParamDto);
}
/**
* 前加签
* @param completeParamDto
* @return
*/
@SneakyThrows
@PostMapping("delegateTask")
public R delegateTask(@RequestBody TaskParamDto completeParamDto) {
return taskService.delegateTask(completeParamDto);
}
/**
* 加签完成任务
* @param completeParamDto
* @return
*/
@SneakyThrows
@PostMapping("resolveTask")
public R resolveTask(@RequestBody TaskParamDto completeParamDto) {
return taskService.resolveTask(completeParamDto);
}
/**
* 设置执行人
* @param completeParamDto
* @return
*/
@SneakyThrows
@PostMapping("setAssignee")
public R setAssignee(@RequestBody TaskParamDto completeParamDto) {
return taskService.setAssignee(completeParamDto);
}
/**
* 结束流程
* @param completeParamDto
* @return
*/
@SneakyThrows
@PostMapping("stopProcessInstance")
public R stopProcessInstance(@RequestBody TaskParamDto completeParamDto) {
return taskService.stopProcessInstance(completeParamDto);
}
/**
* 退回
* @param taskParamDto
* @return
*/
@PostMapping("back")
public R back(@RequestBody TaskParamDto taskParamDto) {
return taskService.back(taskParamDto);
}
}

View File

@@ -0,0 +1,18 @@
package com.pig4cloud.pigx.flow.task.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.pig4cloud.pigx.flow.task.entity.ProcessCopy;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 流程抄送数据 Mapper 接口
* </p>
*
* @author Vincent
* @since 2023-05-20
*/
@Mapper
public interface ProcessCopyMapper extends BaseMapper<ProcessCopy> {
}

View File

@@ -0,0 +1,18 @@
package com.pig4cloud.pigx.flow.task.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.pig4cloud.pigx.flow.task.entity.ProcessGroup;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author Vincent
* @since 2023-05-25
*/
@Mapper
public interface ProcessGroupMapper extends BaseMapper<ProcessGroup> {
}

View File

@@ -0,0 +1,18 @@
package com.pig4cloud.pigx.flow.task.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.pig4cloud.pigx.flow.task.entity.ProcessInstanceRecord;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 流程记录 Mapper 接口
* </p>
*
* @author Vincent
* @since 2023-05-07
*/
@Mapper
public interface ProcessInstanceRecordMapper extends BaseMapper<ProcessInstanceRecord> {
}

View File

@@ -0,0 +1,18 @@
package com.pig4cloud.pigx.flow.task.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.pig4cloud.pigx.flow.task.entity.Process;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author cxygzl
* @since 2023-05-25
*/
@Mapper
public interface ProcessMapper extends BaseMapper<Process> {
}

View File

@@ -0,0 +1,18 @@
package com.pig4cloud.pigx.flow.task.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.pig4cloud.pigx.flow.task.entity.ProcessNodeData;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 流程节点数据 Mapper 接口
* </p>
*
* @author Vincent
* @since 2023-05-07
*/
@Mapper
public interface ProcessNodeDataMapper extends BaseMapper<ProcessNodeData> {
}

View File

@@ -0,0 +1,18 @@
package com.pig4cloud.pigx.flow.task.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.pig4cloud.pigx.flow.task.entity.ProcessNodeRecordAssignUser;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 流程节点记录-执行人 Mapper 接口
* </p>
*
* @author cxygzl
* @since 2023-05-10
*/
@Mapper
public interface ProcessNodeRecordAssignUserMapper extends BaseMapper<ProcessNodeRecordAssignUser> {
}

View File

@@ -0,0 +1,18 @@
package com.pig4cloud.pigx.flow.task.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.pig4cloud.pigx.flow.task.entity.ProcessNodeRecord;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 流程节点记录 Mapper 接口
* </p>
*
* @author cxygzl
* @since 2023-05-10
*/
@Mapper
public interface ProcessNodeRecordMapper extends BaseMapper<ProcessNodeRecord> {
}

View File

@@ -0,0 +1,18 @@
package com.pig4cloud.pigx.flow.task.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.pig4cloud.pigx.flow.task.entity.ProcessStarter;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 流程发起人 Mapper 接口
* </p>
*
* @author Vincent
* @since 2023-05-30
*/
@Mapper
public interface ProcessStarterMapper extends BaseMapper<ProcessStarter> {
}

View File

@@ -0,0 +1,24 @@
package com.pig4cloud.pigx.flow.task.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pigx.common.core.util.R;
/**
* 聚合接口
*/
public interface ICombinationGroupService {
/**
* 查询表单组包含流程
* @param groupId 表单ID
* @return 表单组数据
*/
R listGroupWithProcess(Page page, Long groupId);
/**
* 查询所有我可以发起的表单组
* @return
*/
R listCurrentUserStartGroup();
}

View File

@@ -0,0 +1,27 @@
package com.pig4cloud.pigx.flow.task.service;
import com.pig4cloud.pigx.common.core.util.R;
/**
* @author : willian fu
* @version : 1.0
*/
public interface IOrgService {
/**
* 查询组织架构树
* @param deptId 部门id
* @param type 只查询部门架构
* @param showLeave 是否显示离职员工
* @return 组织架构树数据
*/
R getOrgTreeData(Long deptId, String type, Boolean showLeave);
/**
* 模糊搜索用户
* @param userName 用户名/拼音/首字母
* @return 匹配到的用户
*/
R getOrgTreeUser(String userName);
}

View File

@@ -0,0 +1,24 @@
package com.pig4cloud.pigx.flow.task.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.flow.task.entity.ProcessCopy;
/**
* <p>
* 流程抄送数据 服务类
* </p>
*
* @author Vincent
* @since 2023-05-20
*/
public interface IProcessCopyService extends IService<ProcessCopy> {
/**
* 查询单个抄送详细信息
* @param id
* @return
*/
R querySingleDetail(long id);
}

View File

@@ -0,0 +1,39 @@
package com.pig4cloud.pigx.flow.task.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.flow.task.entity.ProcessGroup;
import java.util.List;
/**
* <p>
* 服务类
* </p>
*
* @author Vincent
* @since 2023-05-25
*/
public interface IProcessGroupService extends IService<ProcessGroup> {
/**
* 组列表
* @return
*/
R<List<ProcessGroup>> queryList();
/**
* 新增流程分组
* @param processGroup 分组名
* @return 添加结果
*/
R create(ProcessGroup processGroup);
/**
* 删除分组
* @param id
* @return
*/
R delete(long id);
}

View File

@@ -0,0 +1,16 @@
package com.pig4cloud.pigx.flow.task.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.pig4cloud.pigx.flow.task.entity.ProcessInstanceRecord;
/**
* <p>
* 流程记录 服务类
* </p>
*
* @author Vincent
* @since 2023-05-07
*/
public interface IProcessInstanceRecordService extends IService<ProcessInstanceRecord> {
}

View File

@@ -0,0 +1,69 @@
package com.pig4cloud.pigx.flow.task.service;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.flow.task.dto.ProcessInstanceParamDto;
import com.pig4cloud.pigx.flow.task.dto.TaskQueryParamDto;
import com.pig4cloud.pigx.flow.task.vo.NodeFormatParamVo;
/**
* 流程实例进程
*/
public interface IProcessInstanceService {
/**
* 启动流程
* @param processInstanceParamDto
* @return
*/
R startProcessInstance(ProcessInstanceParamDto processInstanceParamDto);
/**
* 查询当前登录用户的待办任务
* @param taskQueryParamDto taskQueryParamDto
* @return
*/
R queryMineTask(TaskQueryParamDto taskQueryParamDto);
/**
* 查询已办任务
* @param taskQueryParamDto
* @return
*/
R queryMineEndTask(TaskQueryParamDto taskQueryParamDto);
/**
* 流程结束
* @param processsInstanceId
* @return
*/
R end(String processsInstanceId);
/**
* 查询我发起的
* @param taskQueryParamDto
* @return
*/
R queryMineStarted(TaskQueryParamDto taskQueryParamDto);
/**
* 查询抄送给我的
* @param taskQueryParamDto
* @return
*/
R queryMineCC(TaskQueryParamDto taskQueryParamDto);
/**
* 格式化流程显示
* @param nodeFormatParamVo
* @return
*/
R formatStartNodeShow(NodeFormatParamVo nodeFormatParamVo);
/**
* 流程详情
* @param processInstanceId
* @return
*/
R detail(String processInstanceId);
}

View File

@@ -0,0 +1,34 @@
package com.pig4cloud.pigx.flow.task.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.flow.task.dto.Node;
import com.pig4cloud.pigx.flow.task.dto.ProcessNodeDataDto;
import com.pig4cloud.pigx.flow.task.entity.ProcessNodeData;
/**
* <p>
* 流程节点数据 服务类
* </p>
*
* @author Vincent
* @since 2023-05-07
*/
public interface IProcessNodeDataService extends IService<ProcessNodeData> {
/**
* 保存流程节点数据
* @param processNodeDataDto
* @return
*/
R saveNodeData(ProcessNodeDataDto processNodeDataDto);
/***
* 获取节点数据
* @param flowId
* @param nodeId
* @return
*/
R<Node> getNodeData(String flowId, String nodeId);
}

View File

@@ -0,0 +1,32 @@
package com.pig4cloud.pigx.flow.task.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.flow.task.dto.ProcessNodeRecordAssignUserParamDto;
import com.pig4cloud.pigx.flow.task.entity.ProcessNodeRecordAssignUser;
/**
* <p>
* 流程节点记录-执行人 服务类
* </p>
*
* @author cxygzl
* @since 2023-05-10
*/
public interface IProcessNodeRecordAssignUserService extends IService<ProcessNodeRecordAssignUser> {
/**
* 设置执行人
* @param processNodeRecordAssignUserParamDto
* @return
*/
R addAssignUser(ProcessNodeRecordAssignUserParamDto processNodeRecordAssignUserParamDto);
/**
* 任务完成通知
* @param processNodeRecordAssignUserParamDto
* @return
*/
R completeTaskEvent(ProcessNodeRecordAssignUserParamDto processNodeRecordAssignUserParamDto);
}

View File

@@ -0,0 +1,32 @@
package com.pig4cloud.pigx.flow.task.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.flow.task.dto.ProcessNodeRecordParamDto;
import com.pig4cloud.pigx.flow.task.entity.ProcessNodeRecord;
/**
* <p>
* 流程节点记录 服务类
* </p>
*
* @author cxygzl
* @since 2023-05-10
*/
public interface IProcessNodeRecordService extends IService<ProcessNodeRecord> {
/**
* 节点开始
* @param processNodeRecordParamDto
* @return
*/
R start(ProcessNodeRecordParamDto processNodeRecordParamDto);
/**
* 节点结束
* @param processNodeRecordParamDto
* @return
*/
R complete(ProcessNodeRecordParamDto processNodeRecordParamDto);
}

View File

@@ -0,0 +1,46 @@
package com.pig4cloud.pigx.flow.task.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.flow.task.entity.Process;
import com.pig4cloud.pigx.flow.task.vo.ProcessVO;
/**
* <p>
* 服务类
* </p>
*
* @author cxygzl
* @since 2023-05-25
*/
public interface IProcessService extends IService<Process> {
/**
* 获取详细数据
* @param flowId
* @return
*/
R<ProcessVO> getDetail(String flowId);
Process getByFlowId(String flowId);
void updateByFlowId(Process process);
void hide(String flowId);
/**
* 创建流程
* @param process
* @return
*/
R create(Process process);
/**
* 编辑表单
* @param flowId 摸板ID
* @param type 类型 stop using delete
* @return 操作结果
*/
R update(String flowId, String type, Long groupId);
}

View File

@@ -0,0 +1,16 @@
package com.pig4cloud.pigx.flow.task.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.pig4cloud.pigx.flow.task.entity.ProcessStarter;
/**
* <p>
* 流程发起人 服务类
* </p>
*
* @author Vincent
* @since 2023-05-30
*/
public interface IProcessStarterService extends IService<ProcessStarter> {
}

View File

@@ -0,0 +1,106 @@
package com.pig4cloud.pigx.flow.task.service;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.flow.task.dto.*;
import java.util.List;
import java.util.Map;
/**
* 远程调用的接口
*/
public interface IRemoteService {
/**
* 根据角色id集合查询用户id集合
* @param roleIdList
* @return
*/
R<List<Long>> queryUserIdListByRoleIdList(List<Long> roleIdList);
/**
* 保存抄送
* @param copyDto
* @return
*/
R saveCC(ProcessCopyDto copyDto);
/**
* 检查是否是所有的父级
* @param checkParentDto
* @return
*/
R<Boolean> checkIsAllParent(CheckParentDto checkParentDto);
/**
* 根据部门id集合查询用户id集合
* @param depIdList
* @return
*/
R<List<Long>> queryUserIdListByDepIdList(List<Long> depIdList);
/**
* 检查是否是所有的子级
* @param checkChildDto
* @return
*/
R<Boolean> checkIsAllChild(CheckChildDto checkChildDto);
/**
* 获取用户的信息-包括扩展字段
* @param userId
* @return
*/
R<Map<String, Object>> queryUserAllInfo(long userId);
/**
* 开始节点事件
* @param recordParamDto
* @return
*/
R startNodeEvent(ProcessNodeRecordParamDto recordParamDto);
/**
* 流程创建了
* @param processInstanceRecordParamDto
* @return
*/
R createProcessEvent(ProcessInstanceRecordParamDto processInstanceRecordParamDto);
/**
* 完成节点事件
* @param recordParamDto
* @return
*/
R endNodeEvent(ProcessNodeRecordParamDto recordParamDto);
/**
* 开始设置执行人
* @param processNodeRecordAssignUserParamDto
* @return
*/
R startAssignUser(ProcessNodeRecordAssignUserParamDto processNodeRecordAssignUserParamDto);
/**
* 任务结束事件
* @param processNodeRecordAssignUserParamDto
* @return
*/
R taskEndEvent(ProcessNodeRecordAssignUserParamDto processNodeRecordAssignUserParamDto);
/**
* 实例结束
* @param processInstanceId
* @return
*/
R endProcess(String processInstanceId);
/**
* 查询流程管理员
* @param flowId
* @return
*/
R<Long> queryProcessAdmin(String flowId);
}

View File

@@ -0,0 +1,67 @@
package com.pig4cloud.pigx.flow.task.service;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.flow.task.dto.TaskParamDto;
/**
* 任务处理
*/
public interface ITaskService {
/**
* 查询任务
* @param taskId
* @param view
* @return
*/
R queryTask(String taskId, boolean view);
/**
* 完成任务
* @param taskParamDto
* @return
*/
R completeTask(TaskParamDto taskParamDto);
/**
* 前加签
* @param taskParamDto
* @return
*/
R delegateTask(TaskParamDto taskParamDto);
/**
* 加签完成任务
* @param taskParamDto
* @return
*/
R resolveTask(TaskParamDto taskParamDto);
/**
* 设置执行人
* @param taskParamDto
* @return
*/
R setAssignee(TaskParamDto taskParamDto);
/**
* 结束流程
* @param taskParamDto
* @return
*/
R stopProcessInstance(TaskParamDto taskParamDto);
/**
* 退回
* @param taskParamDto
* @return
*/
R back(TaskParamDto taskParamDto);
/**
* 查询首页数据看板
* @return
*/
R queryTaskData();
}

View File

@@ -0,0 +1,113 @@
package com.pig4cloud.pigx.flow.task.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.security.service.PigxUser;
import com.pig4cloud.pigx.common.security.util.SecurityUtils;
import com.pig4cloud.pigx.flow.task.constant.NodeUserTypeEnum;
import com.pig4cloud.pigx.flow.task.entity.Process;
import com.pig4cloud.pigx.flow.task.entity.ProcessGroup;
import com.pig4cloud.pigx.flow.task.entity.ProcessStarter;
import com.pig4cloud.pigx.flow.task.service.ICombinationGroupService;
import com.pig4cloud.pigx.flow.task.service.IProcessGroupService;
import com.pig4cloud.pigx.flow.task.service.IProcessService;
import com.pig4cloud.pigx.flow.task.service.IProcessStarterService;
import com.pig4cloud.pigx.flow.task.vo.FormGroupVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
@Service
@Slf4j
@RequiredArgsConstructor
public class CombinationGroupServiceImpl implements ICombinationGroupService {
private final IProcessGroupService processGroupService;
private final IProcessService processService;
private final IProcessStarterService processStarterService;
/**
* 查询表单组包含流程
* @param hidden
* @return 表单组数据
*/
@Override
public R listGroupWithProcess(Page page, Long groupId) {
return R.ok(processService.lambdaQuery().eq(Process::getGroupId, groupId).eq(Process::getHidden, false)
.orderByAsc(Process::getSort).orderByDesc(Process::getCreateTime).page(page));
}
/**
* 查询所有我可以发起的表单组
* @return
*/
@Override
public R listCurrentUserStartGroup() {
PigxUser user = SecurityUtils.getUser();
List<FormGroupVo> formGroupVos = new LinkedList<>();
List<ProcessGroup> processGroupList = processGroupService.lambdaQuery().orderByAsc(ProcessGroup::getSort)
.list();
processGroupList.forEach(group -> {
FormGroupVo formGroupVo = FormGroupVo.builder().id(group.getId()).name(group.getGroupName())
.items(new LinkedList<>()).build();
formGroupVos.add(formGroupVo);
List<Process> processList = processService.lambdaQuery().eq(Process::getGroupId, group.getId())
.eq(Process::getHidden, false).eq(Process::getStop, false).orderByAsc(Process::getSort).list();
Map<Long, Boolean> existMap = new HashMap<>();
if (!processList.isEmpty()) {
List<Long> idList = processList.stream().map(Process::getId).collect(Collectors.toList());
// 查询发起人集合
List<ProcessStarter> processStarterList = processStarterService.lambdaQuery()
.in(ProcessStarter::getProcessId, idList).list();
Map<Long, List<ProcessStarter>> groupmap = processStarterList.stream()
.collect(Collectors.groupingBy(ProcessStarter::getProcessId));
for (Process process : processList) {
List<ProcessStarter> processStarters = groupmap.get(process.getId());
if (processStarters == null) {
existMap.put(process.getId(), true);
continue;
}
boolean match = processStarters.stream().anyMatch(w -> w.getTypeId().longValue() == user.getId()
&& w.getType().equals(NodeUserTypeEnum.USER.getKey()));
if (match) {
existMap.put(process.getId(), true);
continue;
}
Set<Long> deptIdSet = processStarters.stream()
.filter(w -> w.getType().equals(NodeUserTypeEnum.DEPT.getKey())).map(w -> w.getTypeId())
.collect(Collectors.toSet());
existMap.put(process.getId(), deptIdSet.contains(user.getDeptId()));
}
}
processList.forEach(process -> {
if (!existMap.get(process.getId())) {
return;
}
formGroupVo.getItems()
.add(FormGroupVo.FlowVo.builder().flowId(process.getFlowId()).name(process.getName())
.logo(process.getLogo()).remark(process.getRemark()).stop(process.getStop())
.updated(process.getUpdateTime()).build());
});
});
return R.ok(formGroupVos);
}
}

View File

@@ -0,0 +1,131 @@
package com.pig4cloud.pigx.flow.task.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil;
import com.pig4cloud.pigx.admin.api.entity.SysDept;
import com.pig4cloud.pigx.admin.api.entity.SysRole;
import com.pig4cloud.pigx.admin.api.entity.SysUser;
import com.pig4cloud.pigx.admin.api.feign.RemoteDeptService;
import com.pig4cloud.pigx.admin.api.feign.RemoteRoleService;
import com.pig4cloud.pigx.admin.api.feign.RemoteUserService;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.core.util.RetOps;
import com.pig4cloud.pigx.flow.task.constant.NodeUserTypeEnum;
import com.pig4cloud.pigx.flow.task.service.IOrgService;
import com.pig4cloud.pigx.flow.task.utils.DataUtil;
import com.pig4cloud.pigx.flow.task.vo.OrgTreeVo;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class OrgServiceImpl implements IOrgService {
private final RemoteUserService remoteUserService;
private final RemoteRoleService remoteRoleService;
private final RemoteDeptService remoteDeptService;
/**
* 查询组织架构树
* @param deptId 部门id
* @param type 只查询部门架构
* @param showLeave 是否显示离职员工
* @return 组织架构树数据
*/
@Override
public R getOrgTreeData(Long deptId, String type, Boolean showLeave) {
List<OrgTreeVo> orgs = new LinkedList<>();
if (StrUtil.equals(type, NodeUserTypeEnum.ROLE.getKey())) {
// 角色
List<SysRole> roleList = remoteRoleService.getAllRole().getData();
for (SysRole role : roleList) {
OrgTreeVo orgTreeVo = new OrgTreeVo();
orgTreeVo.setId(role.getRoleId());
orgTreeVo.setName(role.getRoleName());
orgTreeVo.setType(NodeUserTypeEnum.ROLE.getKey());
orgTreeVo.setSelected(false);
orgs.add(orgTreeVo);
}
Dict dict = Dict.create().set("roleList", orgs).set("childDepartments", orgs).set("employees",
new ArrayList<>());
return R.ok(dict);
}
Dict dict = Dict.create().set("titleDepartments", new ArrayList<>()).set("roleList", new ArrayList<>())
.set("employees", new ArrayList<>());
List<SysDept> deptList = remoteDeptService.getAllDept().getData();
// 查询所有部门及员工
{
List deptVoList = new ArrayList();
for (SysDept dept : deptList) {
OrgTreeVo orgTreeVo = new OrgTreeVo();
orgTreeVo.setId(dept.getDeptId());
orgTreeVo.setName(dept.getName());
orgTreeVo.setType(NodeUserTypeEnum.DEPT.getKey());
orgTreeVo.setSelected(false);
deptVoList.add(orgTreeVo);
}
dict.set("childDepartments", deptVoList);
}
if (!StrUtil.equals(type, NodeUserTypeEnum.DEPT.getKey())) {
List userVoList = new ArrayList();
List<SysUser> userList = remoteUserService.getUserIdListByDeptIdList(CollUtil.toList(deptId)).getData();
for (SysUser user : userList) {
OrgTreeVo orgTreeVo = new OrgTreeVo();
orgTreeVo.setId(user.getUserId());
orgTreeVo.setName(user.getUsername());
orgTreeVo.setType(NodeUserTypeEnum.USER.getKey());
orgTreeVo.setSelected(false);
orgTreeVo.setAvatar(user.getAvatar());
userVoList.add(orgTreeVo);
}
dict.set("employees", userVoList);
}
if (deptId > 0) {
List<SysDept> allDept = remoteDeptService.getAllDept().getData();
List<SysDept> depts = DataUtil.selectParentByDept(deptId, allDept);
dict.set("titleDepartments", CollUtil.reverse(depts));
}
return R.ok(dict);
}
/**
* 模糊搜索用户
* @param userName 用户名/拼音/首字母
* @return 匹配到的用户
*/
@Override
public R getOrgTreeUser(String userName) {
return R.ok(RetOps.of(remoteUserService.getUserListByUserName(userName)).getData().orElseGet(ArrayList::new)
.stream().map(user -> {
OrgTreeVo orgTreeVo = new OrgTreeVo();
orgTreeVo.setId(user.getUserId());
orgTreeVo.setName(user.getUsername());
orgTreeVo.setType(NodeUserTypeEnum.USER.getKey());
orgTreeVo.setSelected(false);
orgTreeVo.setAvatar(user.getAvatar());
return orgTreeVo;
}).collect(Collectors.toList()));
}
}

View File

@@ -0,0 +1,123 @@
package com.pig4cloud.pigx.flow.task.service.impl;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.flow.task.constant.FormTypeEnum;
import com.pig4cloud.pigx.flow.task.constant.ProcessInstanceConstant;
import com.pig4cloud.pigx.flow.task.dto.Node;
import com.pig4cloud.pigx.flow.task.entity.Process;
import com.pig4cloud.pigx.flow.task.entity.ProcessCopy;
import com.pig4cloud.pigx.flow.task.mapper.ProcessCopyMapper;
import com.pig4cloud.pigx.flow.task.service.IProcessCopyService;
import com.pig4cloud.pigx.flow.task.service.IProcessNodeDataService;
import com.pig4cloud.pigx.flow.task.service.IProcessService;
import com.pig4cloud.pigx.flow.task.vo.FormItemVO;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* <p>
* 流程抄送数据 服务实现类
* </p>
*
* @author Vincent
* @since 2023-05-20
*/
@Service
@RequiredArgsConstructor
public class ProcessCopyServiceImpl extends ServiceImpl<ProcessCopyMapper, ProcessCopy> implements IProcessCopyService {
private final ObjectMapper objectMapper;
private final IProcessService processService;
private final IProcessNodeDataService nodeDataService;
/**
* 查询单个抄送详细信息
* @param id
* @return
*/
@SneakyThrows
@Override
public R querySingleDetail(long id) {
ProcessCopy processCopy = this.getById(id);
String flowId = processCopy.getFlowId();
Process oaForms = processService.getByFlowId(flowId);
if (oaForms == null) {
return R.failed("流程不存在");
}
String formData = processCopy.getFormData();
Map<String, Object> variableMap = objectMapper.readValue(formData, new TypeReference<Map<String, Object>>() {
});
String nodeId = processCopy.getNodeId();
Node node = nodeDataService.getNodeData(flowId, nodeId).getData();
Map<String, String> formPerms = node.getFormPerms();
List<FormItemVO> jsonObjectList = objectMapper.readValue(oaForms.getFormItems(),
new TypeReference<List<FormItemVO>>() {
});
for (FormItemVO formItemVO : jsonObjectList) {
String fid = formItemVO.getId();
String perm = formPerms.get(fid);
formItemVO.setPerm(StrUtil.isBlankIfStr(perm) ? ProcessInstanceConstant.FormPermClass.HIDE : perm);
if (formItemVO.getType().equals(FormTypeEnum.LAYOUT.getType())) {
// 明细
List<Map<String, Object>> subParamList = MapUtil.get(variableMap, fid,
new cn.hutool.core.lang.TypeReference<List<Map<String, Object>>>() {
});
Object value = formItemVO.getProps().getValue();
List<List<FormItemVO>> l = new ArrayList<>();
for (Map<String, Object> map : subParamList) {
List<FormItemVO> subItemList = Convert.toList(FormItemVO.class, value);
for (FormItemVO itemVO : subItemList) {
itemVO.getProps().setValue(map.get(itemVO.getId()));
String permSub = formPerms.get(itemVO.getId());
if (StrUtil.isNotBlank(permSub)) {
itemVO.setPerm(ProcessInstanceConstant.FormPermClass.EDIT.equals(permSub)
? ProcessInstanceConstant.FormPermClass.READ : permSub
);
}
else {
itemVO.setPerm(ProcessInstanceConstant.FormPermClass.HIDE);
}
}
l.add(subItemList);
}
formItemVO.getProps().setValue(l);
}
else {
formItemVO.getProps().setValue(variableMap.get(fid));
}
}
Dict set = Dict.create().set("formItems", jsonObjectList);
return R.ok(set);
}
}

View File

@@ -0,0 +1,61 @@
package com.pig4cloud.pigx.flow.task.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.flow.task.entity.ProcessGroup;
import com.pig4cloud.pigx.flow.task.mapper.ProcessGroupMapper;
import com.pig4cloud.pigx.flow.task.service.IProcessGroupService;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* <p>
* 服务实现类
* </p>
*
* @author Vincent
* @since 2023-05-25
*/
@Service
public class ProcessGroupServiceImpl extends ServiceImpl<ProcessGroupMapper, ProcessGroup>
implements IProcessGroupService {
/**
* 组列表
* @return
*/
@Override
public R<List<ProcessGroup>> queryList() {
List<ProcessGroup> processGroupList = this.lambdaQuery().orderByAsc(ProcessGroup::getSort).list();
return R.ok(processGroupList);
}
/**
* 新增表单分组
* @param processGroup 分组名
* @return 添加结果
*/
@Override
public R create(ProcessGroup processGroup) {
ProcessGroup pg = new ProcessGroup();
pg.setSort(0);
pg.setGroupName(processGroup.getGroupName());
this.save(pg);
return R.ok();
}
/**
* 删除分组
* @param id
* @return
*/
@Override
public R delete(long id) {
this.removeById(id);
return R.ok();
}
}

View File

@@ -0,0 +1,21 @@
package com.pig4cloud.pigx.flow.task.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pigx.flow.task.entity.ProcessInstanceRecord;
import com.pig4cloud.pigx.flow.task.mapper.ProcessInstanceRecordMapper;
import com.pig4cloud.pigx.flow.task.service.IProcessInstanceRecordService;
import org.springframework.stereotype.Service;
/**
* <p>
* 流程记录 服务实现类
* </p>
*
* @author Vincent
* @since 2023-05-07
*/
@Service
public class ProcessInstanceRecordServiceImpl extends ServiceImpl<ProcessInstanceRecordMapper, ProcessInstanceRecord>
implements IProcessInstanceRecordService {
}

View File

@@ -0,0 +1,417 @@
package com.pig4cloud.pigx.flow.task.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.pig4cloud.pigx.admin.api.entity.SysUser;
import com.pig4cloud.pigx.admin.api.feign.RemoteUserService;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.security.service.PigxUser;
import com.pig4cloud.pigx.common.security.util.SecurityUtils;
import com.pig4cloud.pigx.flow.task.api.feign.RemoteFlowEngineService;
import com.pig4cloud.pigx.flow.task.constant.FormTypeEnum;
import com.pig4cloud.pigx.flow.task.constant.NodeStatusEnum;
import com.pig4cloud.pigx.flow.task.constant.NodeUserTypeEnum;
import com.pig4cloud.pigx.flow.task.constant.ProcessInstanceConstant;
import com.pig4cloud.pigx.flow.task.dto.*;
import com.pig4cloud.pigx.flow.task.entity.Process;
import com.pig4cloud.pigx.flow.task.entity.*;
import com.pig4cloud.pigx.flow.task.service.*;
import com.pig4cloud.pigx.flow.task.utils.NodeFormatUtil;
import com.pig4cloud.pigx.flow.task.vo.FormItemVO;
import com.pig4cloud.pigx.flow.task.vo.NodeFormatParamVo;
import com.pig4cloud.pigx.flow.task.vo.NodeVo;
import com.pig4cloud.pigx.flow.task.vo.ProcessCopyVo;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
/**
* 实例进程服务
*/
@Service
@Slf4j
@RequiredArgsConstructor
public class ProcessInstanceServiceImpl implements IProcessInstanceService {
private final RemoteFlowEngineService flowEngineService;
private final RemoteUserService userService;
private final IProcessInstanceRecordService processInstanceRecordService;
private final IProcessCopyService processCopyService;
private final IProcessService processService;
private final IProcessNodeRecordService processNodeRecordService;
private final IProcessNodeRecordAssignUserService processNodeRecordAssignUserService;
private final ObjectMapper objectMapper;
/**
* 启动流程
* @param processInstanceParamDto
* @return
*/
@Override
public R startProcessInstance(ProcessInstanceParamDto processInstanceParamDto) {
PigxUser user = SecurityUtils.getUser();
processInstanceParamDto.setStartUserId(String.valueOf(user.getId()));
Map<String, Object> paramMap = processInstanceParamDto.getParamMap();
Dict rootUser = Dict.create().set("id", user.getId()).set("name", user.getUsername()).set("type",
NodeUserTypeEnum.USER.getKey());
paramMap.put("root", CollUtil.newArrayList(rootUser));
return flowEngineService.startProcess(processInstanceParamDto);
}
/**
* 查询当前登录用户的待办任务
* @param pageVO
* @param taskDto
* @return
*/
@Override
public R queryMineTask(TaskQueryParamDto taskQueryParamDto) {
taskQueryParamDto.setAssign(SecurityUtils.getUser().getId().toString());
R<Page<TaskDto>> r = flowEngineService.queryAssignTask(taskQueryParamDto);
if (CollUtil.isEmpty(r.getData().getRecords())) {
return r;
}
Set<String> processInstanceIdSet = r.getData().getRecords().stream().map(TaskDto::getProcessInstanceId)
.collect(Collectors.toSet());
// 流程实例记录
List<ProcessInstanceRecord> processInstanceRecordList = processInstanceRecordService.lambdaQuery()
.in(ProcessInstanceRecord::getProcessInstanceId, processInstanceIdSet).list();
// 发起人
List<SysUser> startUserList = processInstanceRecordList.stream().map(ProcessInstanceRecord::getUserId)
.map(userId -> userService.getUserById(userId).getData()).collect(Collectors.toList());
Page<TaskDto> pageResultDto = r.getData();
List<TaskDto> taskDtoList = new ArrayList<>();
for (TaskDto record : r.getData().getRecords()) {
ProcessInstanceRecord processInstanceRecord = processInstanceRecordList.stream()
.filter(w -> StrUtil.equals(w.getProcessInstanceId(), record.getProcessInstanceId())).findAny()
.orElse(null);
if (processInstanceRecord != null) {
record.setProcessName(processInstanceRecord.getName());
SysUser startUser = startUserList.stream()
.filter(w -> w.getUserId().longValue() == processInstanceRecord.getUserId()).findAny()
.orElse(null);
record.setRootUserId(processInstanceRecord.getUserId());
record.setGroupName(processInstanceRecord.getGroupName());
record.setRootUserName(startUser.getUsername());
record.setRootUserAvatarUrl(startUser.getAvatar());
record.setStartTime(processInstanceRecord.getCreateTime());
taskDtoList.add(record);
}
}
pageResultDto.setRecords(taskDtoList);
return R.ok(pageResultDto);
}
/**
* 查询已办任务
* @param taskQueryParamDto
* @return
*/
@Override
public R queryMineEndTask(TaskQueryParamDto taskQueryParamDto) {
taskQueryParamDto.setAssign(SecurityUtils.getUser().getId().toString());
R<Page<TaskDto>> r = flowEngineService.queryCompletedTask(taskQueryParamDto);
Page<TaskDto> pageResultDto = r.getData();
List<TaskDto> records = pageResultDto.getRecords();
if (CollUtil.isEmpty(records)) {
return R.ok(pageResultDto);
}
Set<String> processInstanceIdSet = records.stream().map(TaskDto::getProcessInstanceId)
.collect(Collectors.toSet());
// 流程实例记录
List<ProcessInstanceRecord> processInstanceRecordList = processInstanceRecordService.lambdaQuery()
.in(ProcessInstanceRecord::getProcessInstanceId, processInstanceIdSet).list();
// 发起人
List<SysUser> startUserList = processInstanceRecordList.stream().map(ProcessInstanceRecord::getUserId)
.map(userId -> userService.getUserById(userId).getData()).collect(Collectors.toList());
List<TaskDto> taskDtoList = new ArrayList<>();
for (TaskDto record : records) {
ProcessInstanceRecord processInstanceRecord = processInstanceRecordList.stream()
.filter(w -> StrUtil.equals(w.getProcessInstanceId(), record.getProcessInstanceId())).findAny()
.orElse(null);
if (processInstanceRecord != null) {
record.setProcessName(processInstanceRecord.getName());
SysUser startUser = startUserList.stream()
.filter(w -> w.getUserId().longValue() == processInstanceRecord.getUserId()).findAny()
.orElse(null);
record.setRootUserId(processInstanceRecord.getUserId());
record.setGroupName(processInstanceRecord.getGroupName());
record.setRootUserName(startUser.getName());
record.setRootUserAvatarUrl(startUser.getAvatar());
record.setTaskId(record.getTaskId());
record.setStartTime(processInstanceRecord.getCreateTime());
taskDtoList.add(record);
}
}
pageResultDto.setRecords(taskDtoList);
return R.ok(pageResultDto);
}
/**
* 流程结束
* @param processsInstanceId
* @return
*/
@Override
public R end(String processsInstanceId) {
processInstanceRecordService.lambdaUpdate().set(ProcessInstanceRecord::getEndTime, new Date())
.set(ProcessInstanceRecord::getStatus, NodeStatusEnum.YJS.getCode())
.eq(ProcessInstanceRecord::getProcessInstanceId, processsInstanceId)
.update(new ProcessInstanceRecord());
return R.ok();
}
/**
* 查询我发起的
* @param pageDto
* @return
*/
@Override
public R queryMineStarted(TaskQueryParamDto taskQueryParamDto) {
long userId = SecurityUtils.getUser().getId();
Page<ProcessInstanceRecord> instanceRecordPage = processInstanceRecordService.lambdaQuery()
.eq(ProcessInstanceRecord::getUserId, userId)
.eq(ProcessInstanceRecord::getStatus, taskQueryParamDto.getStatus())
.between(ArrayUtil.isNotEmpty(taskQueryParamDto.getTaskTime()), ProcessInstanceRecord::getCreateTime,
ArrayUtil.isNotEmpty(taskQueryParamDto.getTaskTime()) ? taskQueryParamDto.getTaskTime()[0]
: null,
ArrayUtil.isNotEmpty(taskQueryParamDto.getTaskTime()) ? taskQueryParamDto.getTaskTime()[1]
: null)
.orderByDesc(ProcessInstanceRecord::getCreateTime)
.page(new Page<>(taskQueryParamDto.getPageNum(), taskQueryParamDto.getPageSize()));
return R.ok(instanceRecordPage);
}
/**
* 查询抄送给我的
* @param pageDto
* @return
*/
@Override
public R queryMineCC(TaskQueryParamDto taskQueryParamDto) {
long userId = SecurityUtils.getUser().getId();
Page<ProcessCopy> page = processCopyService.lambdaQuery().eq(ProcessCopy::getUserId, userId).between(
ArrayUtil.isNotEmpty(taskQueryParamDto.getTaskTime()), ProcessCopy::getCreateTime,
ArrayUtil.isNotEmpty(taskQueryParamDto.getTaskTime()) ? taskQueryParamDto.getTaskTime()[0] : null,
ArrayUtil.isNotEmpty(taskQueryParamDto.getTaskTime()) ? taskQueryParamDto.getTaskTime()[1] : null)
.orderByDesc(ProcessCopy::getNodeTime)
.page(new Page<>(taskQueryParamDto.getPageNum(), taskQueryParamDto.getPageSize()));
List<ProcessCopy> records = page.getRecords();
List<ProcessCopyVo> processCopyVoList = BeanUtil.copyToList(records, ProcessCopyVo.class);
if (CollUtil.isNotEmpty(records)) {
// 发起人
List<SysUser> startUserList = records.stream().map(ProcessCopy::getStartUserId)
.map(id -> userService.getUserById(id).getData()).collect(Collectors.toList());
for (ProcessCopyVo record : processCopyVoList) {
SysUser startUser = startUserList.stream()
.filter(w -> w.getUserId().longValue() == record.getStartUserId()).findAny().orElse(null);
record.setStartUserName(startUser.getUsername());
}
}
Page p = BeanUtil.copyProperties(page, Page.class);
p.setRecords(processCopyVoList);
return R.ok(p);
}
/**
* 格式化流程显示
* @param nodeFormatParamVo
* @return
*/
@SneakyThrows
@Override
public R formatStartNodeShow(NodeFormatParamVo nodeFormatParamVo) {
String flowId = nodeFormatParamVo.getFlowId();
String processInstanceId = nodeFormatParamVo.getProcessInstanceId();
if (StrUtil.isAllBlank(flowId, processInstanceId)) {
return R.ok(new ArrayList<>());
}
if (StrUtil.isBlankIfStr(flowId) && StrUtil.isNotBlank(processInstanceId)) {
ProcessInstanceRecord processInstanceRecord = processInstanceRecordService.lambdaQuery()
.eq(ProcessInstanceRecord::getProcessInstanceId, processInstanceId).one();
flowId = processInstanceRecord.getFlowId();
}
Map<String, Object> paramMap = nodeFormatParamVo.getParamMap();
if (StrUtil.isNotBlank(nodeFormatParamVo.getTaskId())) {
VariableQueryParamDto variableQueryParamDto = new VariableQueryParamDto();
variableQueryParamDto.setTaskId(nodeFormatParamVo.getTaskId());
R<Map<String, Object>> r = flowEngineService.queryTaskVariables(variableQueryParamDto);
if (!r.isOk()) {
ProcessNodeRecordAssignUser processNodeRecordAssignUser = processNodeRecordAssignUserService
.lambdaQuery().eq(ProcessNodeRecordAssignUser::getTaskId, nodeFormatParamVo.getTaskId())
.eq(ProcessNodeRecordAssignUser::getStatus, NodeStatusEnum.YJS.getCode()).last("limit 1")
.orderByDesc(ProcessNodeRecordAssignUser::getEndTime).one();
String data = processNodeRecordAssignUser.getData();
Map<String, Object> variableMap = objectMapper.readValue(data,
new TypeReference<Map<String, Object>>() {
});
variableMap.putAll(paramMap);
paramMap.putAll(variableMap);
}
else {
Map<String, Object> variableMap = r.getData();
variableMap.putAll(paramMap);
paramMap.putAll(variableMap);
}
}
Set<String> completeNodeSet = new HashSet<>();
if (StrUtil.isNotBlank(processInstanceId)) {
List<ProcessNodeRecord> processNodeRecordList = processNodeRecordService.lambdaQuery()
.eq(ProcessNodeRecord::getProcessInstanceId, processInstanceId)
.eq(ProcessNodeRecord::getStatus, NodeStatusEnum.YJS.getCode()).list();
Set<String> collect = processNodeRecordList.stream().map(ProcessNodeRecord::getNodeId)
.collect(Collectors.toSet());
completeNodeSet.addAll(collect);
}
Process oaForms = processService.getByFlowId(flowId);
String process = oaForms.getProcess();
Node nodeDto = objectMapper.readValue(process, new TypeReference<Node>() {
});
List<NodeVo> processNodeShowDtos = NodeFormatUtil.formatProcessNodeShow(nodeDto, completeNodeSet,
new HashSet<>(), processInstanceId, paramMap);
return R.ok(processNodeShowDtos);
}
/**
* 流程详情
* @param processInstanceId
* @return
*/
@SneakyThrows
@Override
public R detail(String processInstanceId) {
ProcessInstanceRecord processInstanceRecord = processInstanceRecordService.lambdaQuery()
.eq(ProcessInstanceRecord::getProcessInstanceId, processInstanceId).one();
Process oaForms = processService.getByFlowId(processInstanceRecord.getFlowId());
if (oaForms == null) {
return R.failed("流程不存在");
}
// 发起人变量数据
String formData = processInstanceRecord.getFormData();
Map<String, Object> variableMap = objectMapper.readValue(formData, new TypeReference<Map<String, Object>>() {
});
// 发起人表单权限
String process = oaForms.getProcess();
Node nodeDto = objectMapper.readValue(process, Node.class);
Map<String, String> formPerms1 = nodeDto.getFormPerms();
List<FormItemVO> jsonObjectList = objectMapper.readValue(oaForms.getFormItems(),
new TypeReference<List<FormItemVO>>() {
});
for (FormItemVO formItemVO : jsonObjectList) {
String id = formItemVO.getId();
String perm = formPerms1.get(id);
formItemVO.setPerm(StrUtil.isBlankIfStr(perm) ? ProcessInstanceConstant.FormPermClass.READ
: (StrUtil.equals(perm, ProcessInstanceConstant.FormPermClass.HIDE) ? perm
: ProcessInstanceConstant.FormPermClass.READ));
if (formItemVO.getType().equals(FormTypeEnum.LAYOUT.getType())) {
// 明细
List<Map<String, Object>> subParamList = MapUtil.get(variableMap, id,
new cn.hutool.core.lang.TypeReference<List<Map<String, Object>>>() {
});
Object value = formItemVO.getProps().getValue();
List<List<FormItemVO>> l = new ArrayList<>();
for (Map<String, Object> map : subParamList) {
List<FormItemVO> subItemList = Convert.toList(FormItemVO.class, value);
for (FormItemVO itemVO : subItemList) {
itemVO.getProps().setValue(map.get(itemVO.getId()));
String permSub = formPerms1.get(itemVO.getId());
itemVO.setPerm(StrUtil.isBlankIfStr(permSub) ? ProcessInstanceConstant.FormPermClass.READ
: (StrUtil.equals(permSub, ProcessInstanceConstant.FormPermClass.HIDE) ? permSub
: ProcessInstanceConstant.FormPermClass.READ));
}
l.add(subItemList);
}
formItemVO.getProps().setValue(l);
}
else {
formItemVO.getProps().setValue(variableMap.get(id));
}
}
Dict set = Dict.create().set("processInstanceId", processInstanceId).set("process", oaForms.getProcess())
.set("formItems", jsonObjectList);
return R.ok(set);
}
}

View File

@@ -0,0 +1,57 @@
package com.pig4cloud.pigx.flow.task.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.flow.task.dto.Node;
import com.pig4cloud.pigx.flow.task.dto.ProcessNodeDataDto;
import com.pig4cloud.pigx.flow.task.entity.ProcessNodeData;
import com.pig4cloud.pigx.flow.task.mapper.ProcessNodeDataMapper;
import com.pig4cloud.pigx.flow.task.service.IProcessNodeDataService;
import org.springframework.stereotype.Service;
import java.util.Optional;
/**
* <p>
* 流程节点数据 服务实现类
* </p>
*
* @author Vincent
* @since 2023-05-07
*/
@Service
public class ProcessNodeDataServiceImpl extends ServiceImpl<ProcessNodeDataMapper, ProcessNodeData>
implements IProcessNodeDataService {
/**
* 保存流程节点数据。
* @param processNodeDataDto 流程节点数据DTO
* @return 保存结果
*/
@Override
public R saveNodeData(ProcessNodeDataDto processNodeDataDto) {
ProcessNodeData processNodeData = BeanUtil.copyProperties(processNodeDataDto, ProcessNodeData.class);
this.save(processNodeData);
return R.ok();
}
/**
* 获取节点数据。
* @param flowId 流程ID
* @param nodeId 节点ID
* @return 节点数据
*/
@Override
public R<Node> getNodeData(String flowId, String nodeId) {
Optional<ProcessNodeData> processNodeDataOptional = this.lambdaQuery().eq(ProcessNodeData::getFlowId, flowId)
.eq(ProcessNodeData::getNodeId, nodeId).oneOpt();
Node node = processNodeDataOptional
.map(processNodeData -> JSONUtil.toBean(processNodeData.getData(), Node.class)).orElse(null);
return R.ok(node);
}
}

View File

@@ -0,0 +1,85 @@
package com.pig4cloud.pigx.flow.task.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.flow.task.constant.NodeStatusEnum;
import com.pig4cloud.pigx.flow.task.dto.ProcessNodeRecordAssignUserParamDto;
import com.pig4cloud.pigx.flow.task.entity.ProcessNodeRecordAssignUser;
import com.pig4cloud.pigx.flow.task.mapper.ProcessNodeRecordAssignUserMapper;
import com.pig4cloud.pigx.flow.task.service.IProcessNodeRecordAssignUserService;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
/**
* <p>
* 流程节点记录-执行人 服务实现类
* </p>
*
* @author cxygzl
* @since 2023-05-10
*/
@Service
public class ProcessNodeRecordAssignUserServiceImpl
extends ServiceImpl<ProcessNodeRecordAssignUserMapper, ProcessNodeRecordAssignUser>
implements IProcessNodeRecordAssignUserService {
/**
* 设置执行人
* @param processNodeRecordAssignUserParamDto
* @return
*/
@Override
public R addAssignUser(ProcessNodeRecordAssignUserParamDto processNodeRecordAssignUserParamDto) {
if (StrUtil.isNotBlank(processNodeRecordAssignUserParamDto.getApproveDesc())) {
ProcessNodeRecordAssignUser processNodeRecordAssignUser = this.lambdaQuery()
.eq(ProcessNodeRecordAssignUser::getTaskId, processNodeRecordAssignUserParamDto.getTaskId())
.orderByDesc(ProcessNodeRecordAssignUser::getId).last("limit 1").one();
if (processNodeRecordAssignUser != null) {
processNodeRecordAssignUser.setApproveDesc(processNodeRecordAssignUserParamDto.getApproveDesc());
processNodeRecordAssignUser.setTaskType(processNodeRecordAssignUserParamDto.getTaskType());
processNodeRecordAssignUser.setStatus(NodeStatusEnum.YJS.getCode());
processNodeRecordAssignUser.setEndTime(LocalDateTime.now());
this.updateById(processNodeRecordAssignUser);
}
}
ProcessNodeRecordAssignUser processNodeRecordAssignUser = BeanUtil
.copyProperties(processNodeRecordAssignUserParamDto, ProcessNodeRecordAssignUser.class);
processNodeRecordAssignUser.setStartTime(LocalDateTime.now());
processNodeRecordAssignUser.setStatus(NodeStatusEnum.JXZ.getCode());
processNodeRecordAssignUser.setApproveDesc("");
processNodeRecordAssignUser.setTaskType("");
this.save(processNodeRecordAssignUser);
return R.ok();
}
/**
* 任务完成通知
* @param processNodeRecordAssignUserParamDto
* @return
*/
@Override
public R completeTaskEvent(ProcessNodeRecordAssignUserParamDto processNodeRecordAssignUserParamDto) {
ProcessNodeRecordAssignUser processNodeRecordAssignUser = this.lambdaQuery()
.eq(ProcessNodeRecordAssignUser::getTaskId, processNodeRecordAssignUserParamDto.getTaskId())
.eq(ProcessNodeRecordAssignUser::getUserId, processNodeRecordAssignUserParamDto.getUserId())
.eq(ProcessNodeRecordAssignUser::getProcessInstanceId,
processNodeRecordAssignUserParamDto.getProcessInstanceId())
.eq(ProcessNodeRecordAssignUser::getStatus, NodeStatusEnum.JXZ.getCode())
.orderByDesc(ProcessNodeRecordAssignUser::getId).last("limit 1").one();
processNodeRecordAssignUser.setStatus(NodeStatusEnum.YJS.getCode());
processNodeRecordAssignUser.setApproveDesc(processNodeRecordAssignUserParamDto.getApproveDesc());
processNodeRecordAssignUser.setEndTime(LocalDateTime.now());
processNodeRecordAssignUser.setData(processNodeRecordAssignUserParamDto.getData());
processNodeRecordAssignUser.setLocalData(processNodeRecordAssignUserParamDto.getLocalData());
processNodeRecordAssignUser.setTaskType("COMPLETE");
this.updateById(processNodeRecordAssignUser);
return R.ok();
}
}

View File

@@ -0,0 +1,65 @@
package com.pig4cloud.pigx.flow.task.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.flow.task.constant.NodeStatusEnum;
import com.pig4cloud.pigx.flow.task.dto.ProcessNodeRecordParamDto;
import com.pig4cloud.pigx.flow.task.entity.ProcessNodeRecord;
import com.pig4cloud.pigx.flow.task.mapper.ProcessNodeRecordMapper;
import com.pig4cloud.pigx.flow.task.service.IProcessNodeRecordService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Date;
/**
* <p>
* 流程节点记录 服务实现类
* </p>
*
* @author cxygzl
* @since 2023-05-10
*/
@Slf4j
@Service
public class ProcessNodeRecordServiceImpl extends ServiceImpl<ProcessNodeRecordMapper, ProcessNodeRecord>
implements IProcessNodeRecordService {
/**
* 节点开始
* @param processNodeRecordParamDto
* @return
*/
@Override
public R start(ProcessNodeRecordParamDto processNodeRecordParamDto) {
ProcessNodeRecord processNodeRecord = BeanUtil.copyProperties(processNodeRecordParamDto,
ProcessNodeRecord.class);
processNodeRecord.setStartTime(new Date());
processNodeRecord.setStatus(NodeStatusEnum.JXZ.getCode());
this.save(processNodeRecord);
return R.ok();
}
/**
* 节点结束
* @param processNodeRecordParamDto
* @return
*/
@Override
public R complete(ProcessNodeRecordParamDto processNodeRecordParamDto) {
log.info("节点结束---{}", processNodeRecordParamDto);
// TODO 完成节点和完成任务要区分下
this.lambdaUpdate().set(ProcessNodeRecord::getStatus, NodeStatusEnum.YJS.getCode())
.set(ProcessNodeRecord::getEndTime, new Date())
.eq(ProcessNodeRecord::getProcessInstanceId, processNodeRecordParamDto.getProcessInstanceId())
.eq(ProcessNodeRecord::getNodeId, processNodeRecordParamDto.getNodeId())
.update(new ProcessNodeRecord());
return R.ok();
}
}

View File

@@ -0,0 +1,254 @@
package com.pig4cloud.pigx.flow.task.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.security.util.SecurityUtils;
import com.pig4cloud.pigx.common.sequence.sequence.Sequence;
import com.pig4cloud.pigx.flow.task.api.feign.RemoteFlowEngineService;
import com.pig4cloud.pigx.flow.task.constant.FormTypeEnum;
import com.pig4cloud.pigx.flow.task.constant.ProcessInstanceConstant;
import com.pig4cloud.pigx.flow.task.dto.Node;
import com.pig4cloud.pigx.flow.task.dto.NodeUser;
import com.pig4cloud.pigx.flow.task.entity.Process;
import com.pig4cloud.pigx.flow.task.entity.ProcessStarter;
import com.pig4cloud.pigx.flow.task.mapper.ProcessMapper;
import com.pig4cloud.pigx.flow.task.service.IProcessService;
import com.pig4cloud.pigx.flow.task.service.IProcessStarterService;
import com.pig4cloud.pigx.flow.task.utils.NodeUtil;
import com.pig4cloud.pigx.flow.task.vo.FormItemVO;
import com.pig4cloud.pigx.flow.task.vo.ProcessVO;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* <p>
* 服务实现类
* </p>
*
* @author cxygzl
* @since 2023-05-25
*/
@Service
@RequiredArgsConstructor
public class ProcessServiceImpl extends ServiceImpl<ProcessMapper, Process> implements IProcessService {
private final IProcessStarterService processStarterService;
private final RemoteFlowEngineService flowEngineService;
private final Sequence flowSequence;
private final ObjectMapper objectMapper;
/**
* 获取详细数据
* @param flowId
* @return
*/
@Override
public R<ProcessVO> getDetail(String flowId) {
// 获取流程详情
ProcessVO processVO = this.getProcessVO(flowId);
return R.ok(processVO);
}
/**
* 根据流程ID获取流程详情
* @param flowId 流程ID
* @return 流程详情
*/
@SneakyThrows
private ProcessVO getProcessVO(String flowId) {
Process oaForms = getByFlowId(flowId);
String process = oaForms.getProcess();
String formItems = oaForms.getFormItems();
Node startNode = objectMapper.readValue(process, new TypeReference<Node>() {
});
Map<String, String> formPerms = startNode.getFormPerms();
List<FormItemVO> formItemVOList = objectMapper.readValue(formItems, new TypeReference<List<FormItemVO>>() {
});
for (FormItemVO formItemVO : formItemVOList) {
String perm = MapUtil.getStr(formPerms, formItemVO.getId(), ProcessInstanceConstant.FormPermClass.EDIT);
formItemVO.setPerm(perm);
// 发号器赋值
if (StrUtil.equals(formItemVO.getType(), FormTypeEnum.SEQUENCE.getType())) {
FormItemVO.Props props = formItemVO.getProps();
String prefix = props.getPrefix();
String nextNo = flowSequence.nextNo();
formItemVO.setPlaceholder(StrUtil.isNotBlank(prefix) ? prefix + nextNo : nextNo);
props.setValue(StrUtil.isNotBlank(prefix) ? prefix + nextNo : nextNo);
formItemVO.setProps(props);
}
if (StrUtil.equals(formItemVO.getType(), FormTypeEnum.LAYOUT.getType())) {
// 明细
Object value = formItemVO.getProps().getValue();
List<FormItemVO> subList = Convert.toList(FormItemVO.class, value);
for (FormItemVO itemVO : subList) {
String perm1 = MapUtil.getStr(formPerms, itemVO.getId(),
ProcessInstanceConstant.FormPermClass.EDIT);
itemVO.setPerm(perm1);
}
formItemVO.getProps().setValue(subList);
formItemVO.getProps();
}
}
oaForms.setFormItems(objectMapper.writeValueAsString(formItemVOList));
List<String> selectUserNodeId = NodeUtil.selectUserNodeId(startNode);
ProcessVO processVO = BeanUtil.copyProperties(oaForms, ProcessVO.class);
processVO.setSelectUserNodeId(selectUserNodeId);
return processVO;
}
/**
* 根据流程ID获取流程
* @param flowId 流程ID
* @return 流程
*/
@Override
public Process getByFlowId(String flowId) {
return this.lambdaQuery().eq(Process::getFlowId, flowId).one();
}
/**
* 更新流程
* @param process 流程
*/
@Override
public void updateByFlowId(Process process) {
this.lambdaUpdate().eq(Process::getFlowId, process.getFlowId()).update(process);
}
/**
* 隐藏流程
* @param flowId 流程ID
*/
@Override
public void hide(String flowId) {
this.lambdaUpdate().set(Process::getHidden, true).eq(Process::getFlowId, flowId).update(new Process());
}
/**
* 创建流程
* @param process 流程
* @return 操作结果
*/
@SneakyThrows
@Override
public R create(Process process) {
Map<String, Object> map = new HashMap<>();
map.put("process", process);
map.put("userId", SecurityUtils.getUser().getId());
R<String> r = flowEngineService.createFlow(map);
if (!r.isOk()) {
return R.failed(r.getMsg());
}
String flowId = r.getData();
NodeUser nodeUser = objectMapper.readValue(process.getAdminList(), new TypeReference<List<NodeUser>>() {
}).get(0);
// 更新流程
if (StrUtil.isNotBlank(process.getFlowId())) {
Process oldProcess = this.getByFlowId(process.getFlowId());
this.hide(process.getFlowId());
// 修改所有的管理员
this.lambdaUpdate().set(Process::getAdminId, nodeUser.getId())
.eq(Process::getUniqueId, oldProcess.getUniqueId()).update(new Process());
}
Node startNode = objectMapper.readValue(process.getProcess(), Node.class);
List<NodeUser> nodeUserList = startNode.getNodeUserList();
StringBuilder stringBuilder = new StringBuilder();
if (CollUtil.isNotEmpty(nodeUserList)) {
int index = 0;
for (NodeUser user : nodeUserList) {
if (index > 0) {
stringBuilder.append(",");
}
stringBuilder.append(user.getName());
index++;
if (index > 5) {
break;
}
}
}
Process p = new Process();
p.setFlowId(flowId);
p.setName(process.getName());
p.setLogo(process.getLogo());
p.setSettings(process.getSettings());
p.setGroupId(process.getGroupId());
p.setFormItems(process.getFormItems());
p.setProcess(process.getProcess());
p.setRemark(process.getRemark());
p.setSort(0);
p.setHidden(false);
p.setStop(false);
p.setAdminId(nodeUser.getId());
p.setUniqueId(IdUtil.fastSimpleUUID());
p.setAdminList(process.getAdminList());
p.setRangeShow(stringBuilder.toString());
this.save(p);
// 保存范围
for (NodeUser nodeUserDto : nodeUserList) {
ProcessStarter processStarter = new ProcessStarter();
processStarter.setProcessId(p.getId());
processStarter.setTypeId(nodeUserDto.getId());
processStarter.setType(nodeUserDto.getType());
processStarterService.save(processStarter);
}
return R.ok();
}
/**
* 编辑表单
* @param flowId 流程ID
* @param type 类型 stop using delete
* @param groupId 分组ID
* @return 操作结果
*/
@Override
public R update(String flowId, String type, Long groupId) {
Process process = new Process();
process.setFlowId(flowId);
process.setStop("stop".equals(type));
process.setHidden("delete".equals(type));
process.setGroupId(groupId);
this.updateByFlowId(process);
return R.ok();
}
}

View File

@@ -0,0 +1,21 @@
package com.pig4cloud.pigx.flow.task.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pigx.flow.task.entity.ProcessStarter;
import com.pig4cloud.pigx.flow.task.mapper.ProcessStarterMapper;
import com.pig4cloud.pigx.flow.task.service.IProcessStarterService;
import org.springframework.stereotype.Service;
/**
* <p>
* 流程发起人 服务实现类
* </p>
*
* @author Vincent
* @since 2023-05-30
*/
@Service
public class ProcessStarterServiceImpl extends ServiceImpl<ProcessStarterMapper, ProcessStarter>
implements IProcessStarterService {
}

View File

@@ -0,0 +1,257 @@
package com.pig4cloud.pigx.flow.task.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ArrayUtil;
import com.pig4cloud.pigx.admin.api.entity.SysDept;
import com.pig4cloud.pigx.admin.api.entity.SysUser;
import com.pig4cloud.pigx.admin.api.feign.RemoteDeptService;
import com.pig4cloud.pigx.admin.api.feign.RemoteUserService;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.flow.task.constant.NodeStatusEnum;
import com.pig4cloud.pigx.flow.task.dto.*;
import com.pig4cloud.pigx.flow.task.entity.Process;
import com.pig4cloud.pigx.flow.task.entity.ProcessCopy;
import com.pig4cloud.pigx.flow.task.entity.ProcessGroup;
import com.pig4cloud.pigx.flow.task.entity.ProcessInstanceRecord;
import com.pig4cloud.pigx.flow.task.service.*;
import com.pig4cloud.pigx.flow.task.utils.DataUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Service
@Slf4j
@RequiredArgsConstructor
public class RemoteServiceImpl implements IRemoteService {
private final IProcessInstanceRecordService processInstanceRecordService;
private final IProcessNodeRecordService processNodeRecordService;
private final IProcessNodeRecordAssignUserService processNodeRecordAssignUserService;
private final IProcessInstanceService processInstanceService;
private final IProcessCopyService processCopyService;
private final IProcessService processService;
private final IProcessGroupService processGroupService;
private final RemoteUserService userService;
private final RemoteDeptService deptService;
/**
* 根据角色id集合查询用户id集合
* @param roleIdList
* @return
*/
@Override
public R<List<Long>> queryUserIdListByRoleIdList(List<Long> roleIdList) {
return userService.getUserIdListByRoleIdList(roleIdList);
}
/**
* 保存抄送
* @param copyDto
* @return
*/
@Override
public R saveCC(ProcessCopyDto copyDto) {
String processInstanceId = copyDto.getProcessInstanceId();
// 如果抄送是第一个节点 会出现查询不到的情况
ThreadUtil.execute(() -> {
try {
ProcessInstanceRecord processInstanceRecord = processInstanceRecordService.lambdaQuery()
.eq(ProcessInstanceRecord::getProcessInstanceId, processInstanceId).one();
int index = 10;
while (index > 0 && processInstanceRecord == null) {
TimeUnit.SECONDS.sleep(5);
processInstanceRecord = processInstanceRecordService.lambdaQuery()
.eq(ProcessInstanceRecord::getProcessInstanceId, processInstanceId).one();
index--;
}
ProcessCopy processCopy = BeanUtil.copyProperties(copyDto, ProcessCopy.class);
processCopy.setGroupId(processInstanceRecord.getGroupId());
processCopy.setGroupName(processInstanceRecord.getGroupName());
processCopy.setProcessName(processInstanceRecord.getName());
processCopy.setStartTime(processInstanceRecord.getCreateTime());
processCopyService.save(processCopy);
}
catch (Exception e) {
log.error("Error:", e);
}
});
return R.ok();
}
/**
* 检查是否是所有的父级
* @param checkParentDto
* @return
*/
@Override
public R<Boolean> checkIsAllParent(CheckParentDto checkParentDto) {
Long parentId = checkParentDto.getParentId();
List<Long> deptIdList = checkParentDto.getDeptIdList();
// 查询子级包括自己
List<SysDept> allDept = deptService.getAllDept().getData();
List<SysDept> childrenDeptList = DataUtil.selectChildrenByDept(parentId, allDept);
List<Long> childrenDeptIdList = childrenDeptList.stream().map(SysDept::getDeptId).collect(Collectors.toList());
childrenDeptIdList.remove(parentId);
List<Long> remainIdList = CollUtil.removeAny(deptIdList, ArrayUtil.toArray(childrenDeptIdList, Long.class));
return R.ok(remainIdList.isEmpty());
}
/**
* 根据部门id集合查询用户id集合
* @param depIdList
* @return
*/
@Override
public R<List<Long>> queryUserIdListByDepIdList(List<Long> depIdList) {
List<Long> list = userService.getUserIdListByDeptIdList(depIdList).getData().stream().map(SysUser::getUserId)
.collect(Collectors.toList());
return R.ok(list);
}
/**
* 检查是否是所有的子级
* @param checkChildDto
* @return
*/
@Override
public R<Boolean> checkIsAllChild(CheckChildDto checkChildDto) {
Long childId = checkChildDto.getChildId();
List<Long> deptIdList = checkChildDto.getDeptIdList();
// 查询父级包括自己
List<SysDept> allDept = deptService.getAllDept().getData();
List<SysDept> parentDeptList = DataUtil.selectParentByDept(childId, allDept);
List<Long> parentDeptIdList = parentDeptList.stream().map(SysDept::getDeptId).collect(Collectors.toList());
parentDeptIdList.remove(childId);
List<Long> remainIdList = CollUtil.removeAny(deptIdList, ArrayUtil.toArray(parentDeptIdList, Long.class));
return R.ok(remainIdList.isEmpty());
}
/**
* 获取用户的信息-包括扩展字段
* @param userId
* @return
*/
@Override
public R<Map<String, Object>> queryUserAllInfo(long userId) {
SysUser sysUser = userService.getUserById(userId).getData();
return R.ok(BeanUtil.beanToMap(sysUser));
}
/**
* 开始节点事件
* @param recordParamDto
* @return
*/
@Override
public R startNodeEvent(ProcessNodeRecordParamDto recordParamDto) {
return processNodeRecordService.start(recordParamDto);
}
/**
* 流程创建了
* @param processInstanceRecordParamDto
* @return
*/
@Override
public R createProcessEvent(ProcessInstanceRecordParamDto processInstanceRecordParamDto) {
ProcessInstanceRecord entity = BeanUtil.copyProperties(processInstanceRecordParamDto,
ProcessInstanceRecord.class);
Process oaForms = processService.getByFlowId(processInstanceRecordParamDto.getFlowId());
ProcessGroup oaFormGroups = processGroupService.getById(oaForms.getGroupId());
entity.setName(oaForms.getName());
entity.setLogo(oaForms.getLogo());
entity.setUserId(processInstanceRecordParamDto.getUserId());
entity.setFlowId(processInstanceRecordParamDto.getFlowId());
entity.setProcessInstanceId(processInstanceRecordParamDto.getProcessInstanceId());
entity.setGroupId(oaFormGroups.getId());
entity.setGroupName(oaFormGroups.getGroupName());
entity.setStatus(NodeStatusEnum.JXZ.getCode());
processInstanceRecordService.save(entity);
return R.ok();
}
/**
* 完成节点事件
* @param recordParamDto
* @return
*/
@Override
public R endNodeEvent(ProcessNodeRecordParamDto recordParamDto) {
return processNodeRecordService.complete(recordParamDto);
}
/**
* 开始设置执行人
* @param processNodeRecordAssignUserParamDto
* @return
*/
@Override
public R startAssignUser(ProcessNodeRecordAssignUserParamDto processNodeRecordAssignUserParamDto) {
return processNodeRecordAssignUserService.addAssignUser(processNodeRecordAssignUserParamDto);
}
/**
* 任务结束事件
* @param processNodeRecordAssignUserParamDto
* @return
*/
@Override
public R taskEndEvent(ProcessNodeRecordAssignUserParamDto processNodeRecordAssignUserParamDto) {
return processNodeRecordAssignUserService.completeTaskEvent(processNodeRecordAssignUserParamDto);
}
/**
* 实例结束
* @param processInstanceId
* @return
*/
@Override
public R endProcess(String processInstanceId) {
return processInstanceService.end(processInstanceId);
}
/**
* 查询流程管理员
* @param flowId
* @return
*/
@Override
public R<Long> queryProcessAdmin(String flowId) {
Process process = processService.getByFlowId(flowId);
return R.ok(process.getAdminId());
}
}

View File

@@ -0,0 +1,334 @@
package com.pig4cloud.pigx.flow.task.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.security.util.SecurityUtils;
import com.pig4cloud.pigx.flow.task.api.feign.RemoteFlowEngineService;
import com.pig4cloud.pigx.flow.task.constant.FormTypeEnum;
import com.pig4cloud.pigx.flow.task.constant.NodeStatusEnum;
import com.pig4cloud.pigx.flow.task.constant.ProcessInstanceConstant;
import com.pig4cloud.pigx.flow.task.dto.IndexPageStatistics;
import com.pig4cloud.pigx.flow.task.dto.Node;
import com.pig4cloud.pigx.flow.task.dto.TaskParamDto;
import com.pig4cloud.pigx.flow.task.dto.TaskResultDto;
import com.pig4cloud.pigx.flow.task.entity.Process;
import com.pig4cloud.pigx.flow.task.entity.ProcessCopy;
import com.pig4cloud.pigx.flow.task.entity.ProcessInstanceRecord;
import com.pig4cloud.pigx.flow.task.entity.ProcessNodeRecordAssignUser;
import com.pig4cloud.pigx.flow.task.service.*;
import com.pig4cloud.pigx.flow.task.vo.FormItemVO;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
@Slf4j
@RequiredArgsConstructor
public class TaskServiceImpl implements ITaskService {
private final RemoteFlowEngineService flowEngineService;
private final IProcessService processService;
private final IProcessCopyService processCopyService;
private final IProcessNodeDataService nodeDataService;
private final IProcessNodeRecordAssignUserService processNodeRecordAssignUserService;
private final IProcessInstanceRecordService processInstanceRecordService;
private final ObjectMapper objectMapper;
/**
* 查询首页数据看板
* @return
*/
@Override
public R queryTaskData() {
R<IndexPageStatistics> indexPageStatisticsR = flowEngineService
.querySimpleData(SecurityUtils.getUser().getId());
// 获取抄送任务
Long copyCount = processCopyService.lambdaQuery().eq(ProcessCopy::getUserId, SecurityUtils.getUser().getId())
.count();
indexPageStatisticsR.getData().setCopyNum(copyCount);
return indexPageStatisticsR;
}
/**
* 查询任务
* @param taskId
* @param view
* @return
*/
@SneakyThrows
@Override
public R queryTask(String taskId, boolean view) {
long userId = SecurityUtils.getUser().getId();
R<TaskResultDto> r = flowEngineService.queryTask(taskId, userId);
if (!r.isOk()) {
return R.failed(r.getMsg());
}
TaskResultDto taskResultDto = r.getData();
// 变量
Map<String, Object> paramMap = taskResultDto.getVariableAll();
// 是否是当前活动任务
Boolean currentTask = taskResultDto.getCurrentTask();
if (!currentTask) {
ProcessNodeRecordAssignUser processNodeRecordAssignUser = processNodeRecordAssignUserService.lambdaQuery()
.eq(ProcessNodeRecordAssignUser::getTaskId, taskId)
.eq(ProcessNodeRecordAssignUser::getUserId, userId)
.eq(ProcessNodeRecordAssignUser::getStatus, NodeStatusEnum.YJS.getCode()).last("limit 1")
.orderByDesc(ProcessNodeRecordAssignUser::getEndTime).one();
if (processNodeRecordAssignUser != null) {
String data = processNodeRecordAssignUser.getData();
if (StrUtil.isNotBlank(data)) {
Map<String, Object> collect = objectMapper.readValue(data,
new TypeReference<Map<String, Object>>() {
});
paramMap.putAll(collect);
}
}
}
// 当前节点数据
Node node = nodeDataService.getNodeData(taskResultDto.getFlowId(), taskResultDto.getNodeId()).getData();
Map<String, String> formPerms = node.getFormPerms();
Process oaForms = processService.getByFlowId(taskResultDto.getFlowId());
if (oaForms == null) {
return R.failed("流程不存在");
}
List<FormItemVO> formItemVOList = JSONUtil.toList(oaForms.getFormItems(), FormItemVO.class);
for (FormItemVO formItemVO : formItemVOList) {
String id = formItemVO.getId();
String perm = formPerms.get(id);
if (StrUtil.isNotBlank(perm)) {
formItemVO.setPerm(view ? (ProcessInstanceConstant.FormPermClass.EDIT.equals(perm)
? ProcessInstanceConstant.FormPermClass.READ : perm) : perm);
}
else {
formItemVO.setPerm(ProcessInstanceConstant.FormPermClass.HIDE);
}
if (formItemVO.getType().equals(FormTypeEnum.LAYOUT.getType())) {
// 明细
List<Map<String, Object>> subParamList = MapUtil.get(paramMap, id,
new cn.hutool.core.lang.TypeReference<List<Map<String, Object>>>() {
});
Object value = formItemVO.getProps().getValue();
List<List<FormItemVO>> l = new ArrayList<>();
for (Map<String, Object> map : subParamList) {
List<FormItemVO> subItemList = Convert.toList(FormItemVO.class, value);
for (FormItemVO itemVO : subItemList) {
itemVO.getProps().setValue(map.get(itemVO.getId()));
String permSub = formPerms.get(itemVO.getId());
if (StrUtil.isNotBlank(permSub)) {
itemVO.setPerm(view ? (ProcessInstanceConstant.FormPermClass.EDIT.equals(permSub)
? ProcessInstanceConstant.FormPermClass.READ : permSub) : permSub);
}
else {
itemVO.setPerm(ProcessInstanceConstant.FormPermClass.HIDE);
}
}
l.add(subItemList);
}
formItemVO.getProps().setValue(l);
{
List<FormItemVO> subItemList = Convert.toList(FormItemVO.class, value);
for (FormItemVO itemVO : subItemList) {
String permSub = formPerms.get(itemVO.getId());
if (StrUtil.isNotBlank(permSub)) {
itemVO.setPerm(permSub);
}
else {
itemVO.setPerm(ProcessInstanceConstant.FormPermClass.HIDE);
}
}
formItemVO.getProps().setOriForm(subItemList);
}
}
else {
formItemVO.getProps().setValue(paramMap.get(id));
}
}
Dict set = Dict.create().set("processInstanceId", taskResultDto.getProcessInstanceId())
.set("node", taskResultDto.getTaskNode()).set("process", oaForms.getProcess())
.set("delegateAgain", taskResultDto.getDelegate())
.set("delegationTask", StrUtil.equals(taskResultDto.getDelegationState(), "PENDING"))
.set("formItems", formItemVOList);
return R.ok(set);
}
/**
* 完成任务
* @param taskParamDto
* @return
*/
@Override
public R completeTask(TaskParamDto taskParamDto) {
long userId = SecurityUtils.getUser().getId();
taskParamDto.setUserId(String.valueOf(userId));
R r = flowEngineService.completeTask(taskParamDto);
if (!r.isOk()) {
return R.failed(r.getMsg());
}
return R.ok();
}
/**
* 前加签
* @param taskParamDto
* @return
*/
@Transactional
@Override
public R delegateTask(TaskParamDto taskParamDto) {
taskParamDto.setUserId(SecurityUtils.getUser().getId().toString());
R r = flowEngineService.delegateTask(taskParamDto);
if (!r.isOk()) {
return R.failed(r.getMsg());
}
return R.ok();
}
/**
* 加签完成任务
* @param taskParamDto
* @return
*/
@Override
public R resolveTask(TaskParamDto taskParamDto) {
R r = flowEngineService.resolveTask(taskParamDto);
if (!r.isOk()) {
return R.failed(r.getMsg());
}
return R.ok();
}
/**
* 设置执行人
* @param taskParamDto
* @return
*/
@Override
public R setAssignee(TaskParamDto taskParamDto) {
taskParamDto.setUserId(SecurityUtils.getUser().getId().toString());
R r = flowEngineService.setAssignee(taskParamDto);
if (!r.isOk()) {
return R.failed(r.getMsg());
}
return R.ok();
}
/**
* 结束流程
* @param taskParamDto
* @return
*/
@Override
public R stopProcessInstance(TaskParamDto taskParamDto) {
String processInstanceId = taskParamDto.getProcessInstanceId();
List<String> allStopProcessInstanceIdList = getAllStopProcessInstanceIdList(processInstanceId);
CollUtil.reverse(allStopProcessInstanceIdList);
allStopProcessInstanceIdList.add(processInstanceId);
taskParamDto.setProcessInstanceIdList(allStopProcessInstanceIdList);
taskParamDto.setUserId(SecurityUtils.getUser().getId().toString());
R r = flowEngineService.stopProcessInstance(taskParamDto);
if (!r.isOk()) {
return R.failed(r.getMsg());
}
return R.ok();
}
/**
* 退回
* @param taskParamDto
* @return
*/
@Override
public R back(TaskParamDto taskParamDto) {
taskParamDto.setUserId(SecurityUtils.getUser().getId().toString());
R r = flowEngineService.back(taskParamDto);
if (!r.isOk()) {
return R.failed(r.getMsg());
}
return R.ok();
}
private List<String> getAllStopProcessInstanceIdList(String processInstanceId) {
List<ProcessInstanceRecord> list = processInstanceRecordService.lambdaQuery()
.eq(ProcessInstanceRecord::getParentProcessInstanceId, processInstanceId).list();
List<String> collect = list.stream().map(w -> w.getProcessInstanceId()).collect(Collectors.toList());
for (ProcessInstanceRecord processInstanceRecord : list) {
List<String> allStopProcessInstanceIdList = getAllStopProcessInstanceIdList(
processInstanceRecord.getProcessInstanceId());
collect.addAll(allStopProcessInstanceIdList);
}
return collect;
}
}

View File

@@ -0,0 +1,79 @@
package com.pig4cloud.pigx.flow.task.utils;
import cn.hutool.core.collection.CollUtil;
import com.pig4cloud.pigx.admin.api.entity.SysDept;
import com.pig4cloud.pigx.admin.api.entity.SysMenu;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class DataUtil {
/**
* 根据当前部门id向上查找所有的部门
* @param deptId
* @param allDeptList
* @return 返回包括自己部门在内的所有父级部门
*/
public static List<SysDept> selectParentByDept(long deptId, List<SysDept> allDeptList) {
List<SysDept> list = new ArrayList<>();
SysDept dept = allDeptList.stream().filter(w -> w.getDeptId() == deptId).findAny().orElse(null);
if (dept == null || dept.getParentId() == null) {
return list;
}
Long parentId = dept.getParentId();
List<SysDept> depts = selectParentByDept(parentId, allDeptList);
list.add(dept);
list.addAll(depts);
return list;
}
/**
* 根据当前部门id向下查找所有的部门
* @param deptId
* @param allDeptList
* @return 返回包括自己部门在内的所有子级部门
*/
public static List<SysDept> selectChildrenByDept(long deptId, List<SysDept> allDeptList) {
List<SysDept> list = new ArrayList<>();
list.add(allDeptList.stream().filter(w -> w.getDeptId() == deptId).findFirst().get());
List<SysDept> collect = allDeptList.stream().filter(w -> w.getParentId() == deptId)
.collect(Collectors.toList());
if (CollUtil.isEmpty(collect)) {
return list;
}
for (SysDept dept : collect) {
List<SysDept> depts = selectChildrenByDept(dept.getDeptId(), allDeptList);
list.addAll(depts);
}
return list;
}
/**
* 根据当前菜单id向下查找所有的菜单
* @param menuId
* @param allMenuList
* @return 返回包括自己在内的所有子级菜单
*/
public static List<SysMenu> selectChildrenByMenu(long menuId, List<SysMenu> allMenuList) {
List<SysMenu> list = new ArrayList<>();
list.add(allMenuList.stream().filter(w -> w.getMenuId() == menuId).findFirst().get());
List<SysMenu> collect = allMenuList.stream().filter(w -> w.getParentId() == menuId)
.collect(Collectors.toList());
if (CollUtil.isEmpty(collect)) {
return list;
}
for (SysMenu dept : collect) {
List<SysMenu> depts = selectChildrenByMenu(dept.getMenuId(), allMenuList);
list.addAll(depts);
}
return list;
}
}

View File

@@ -0,0 +1,296 @@
package com.pig4cloud.pigx.flow.task.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.pig4cloud.pigx.admin.api.entity.SysUser;
import com.pig4cloud.pigx.admin.api.feign.RemoteUserService;
import com.pig4cloud.pigx.common.security.util.SecurityUtils;
import com.pig4cloud.pigx.flow.task.constant.NodeStatusEnum;
import com.pig4cloud.pigx.flow.task.constant.NodeTypeEnum;
import com.pig4cloud.pigx.flow.task.constant.NodeUserTypeEnum;
import com.pig4cloud.pigx.flow.task.constant.ProcessInstanceConstant;
import com.pig4cloud.pigx.flow.task.dto.Node;
import com.pig4cloud.pigx.flow.task.dto.NodeUser;
import com.pig4cloud.pigx.flow.task.entity.ProcessInstanceRecord;
import com.pig4cloud.pigx.flow.task.entity.ProcessNodeRecordAssignUser;
import com.pig4cloud.pigx.flow.task.service.IProcessInstanceRecordService;
import com.pig4cloud.pigx.flow.task.service.IProcessNodeRecordAssignUserService;
import com.pig4cloud.pigx.flow.task.service.IRemoteService;
import com.pig4cloud.pigx.flow.task.vo.NodeVo;
import com.pig4cloud.pigx.flow.task.vo.UserVo;
import lombok.SneakyThrows;
import java.util.*;
import java.util.stream.Collectors;
/**
* 节点格式化显示工具
*/
public class NodeFormatUtil {
/**
* 格式化流程节点显示
* @param node
* @param completeNodeSet
* @param continueNodeSet
* @param processInstanceId
* @param paramMap
*/
@SneakyThrows
public static List<NodeVo> formatProcessNodeShow(Node node, Set<String> completeNodeSet,
Set<String> continueNodeSet, String processInstanceId, Map<String, Object> paramMap) {
List<NodeVo> list = new ArrayList<>();
if (!NodeUtil.isNode(node)) {
return list;
}
String name = node.getName();
Integer type = node.getType();
// SELF_SELECT
NodeVo nodeVo = new NodeVo();
nodeVo.setId(node.getId());
nodeVo.setName(name);
nodeVo.setType(type);
nodeVo.setStatus(NodeStatusEnum.WKS.getCode());
if (completeNodeSet.contains(node.getId())) {
nodeVo.setStatus(NodeStatusEnum.YJS.getCode());
}
if (continueNodeSet.contains(node.getId())) {
nodeVo.setStatus(NodeStatusEnum.JXZ.getCode());
}
{
nodeVo.setPlaceholder(node.getPlaceHolder());
}
List<UserVo> userVoList = new ArrayList<>();
if (type == NodeTypeEnum.APPROVAL.getValue().intValue()) {
Integer assignedType = node.getAssignedType();
boolean selfSelect = assignedType == ProcessInstanceConstant.AssignedTypeClass.SELF_SELECT;
nodeVo.setSelectUser(selfSelect);
if (selfSelect) {
nodeVo.setMultiple(node.getMultiple());
}
// 用户列表
if (StrUtil.isNotBlank(processInstanceId)) {
IProcessNodeRecordAssignUserService processNodeRecordAssignUserService = SpringUtil
.getBean(IProcessNodeRecordAssignUserService.class);
List<ProcessNodeRecordAssignUser> processNodeRecordAssignUserList = processNodeRecordAssignUserService
.lambdaQuery().eq(ProcessNodeRecordAssignUser::getNodeId, node.getId())
.eq(ProcessNodeRecordAssignUser::getProcessInstanceId, processInstanceId)
.orderByAsc(ProcessNodeRecordAssignUser::getCreateTime).list();
Map<String, List<ProcessNodeRecordAssignUser>> map = processNodeRecordAssignUserList.stream()
.collect(Collectors.groupingBy(ProcessNodeRecordAssignUser::getTaskId));
for (Map.Entry<String, List<ProcessNodeRecordAssignUser>> entry : map.entrySet()) {
List<ProcessNodeRecordAssignUser> value = entry.getValue();
List<UserVo> collect = value.stream().map(w -> {
UserVo userVo = buildUser(Long.parseLong(w.getUserId()));
userVo.setShowTime(w.getEndTime());
userVo.setApproveDesc(w.getApproveDesc());
userVo.setStatus(w.getStatus());
userVo.setOperType(w.getTaskType());
return userVo;
}).collect(Collectors.toList());
userVoList.addAll(collect);
}
if (processNodeRecordAssignUserList.isEmpty()) {
if (assignedType == ProcessInstanceConstant.AssignedTypeClass.SELF) {
// 发起人自己
userVoList.addAll(CollUtil.newArrayList(buildRootUser(processInstanceId)));
}
if (assignedType == ProcessInstanceConstant.AssignedTypeClass.SELF_SELECT) {
// 发起人自选
Object variable = paramMap.get(StrUtil.format("{}_assignee_select", node.getId()));
ObjectMapper objectMapper = SpringUtil.getBean(ObjectMapper.class);
List<NodeUser> nodeUserDtos = objectMapper.readValue(objectMapper.writeValueAsString(variable),
new TypeReference<List<NodeUser>>() {
});
List<Long> collect = nodeUserDtos.stream().map(w -> Long.valueOf(w.getId()))
.collect(Collectors.toList());
for (Long aLong : collect) {
UserVo userVo = buildUser(aLong);
userVoList.addAll(CollUtil.newArrayList(userVo));
}
}
}
}
else if (assignedType == ProcessInstanceConstant.AssignedTypeClass.USER) {
// 指定用户
List<NodeUser> nodeUserList = node.getNodeUserList();
List<UserVo> tempList = buildUser(nodeUserList);
userVoList.addAll(tempList);
}
else if (assignedType == ProcessInstanceConstant.AssignedTypeClass.FORM_USER) {
// 表单人员
String formUser = node.getFormUserId();
Object o = paramMap.get(formUser);
if (o != null) {
ObjectMapper objectMapper = SpringUtil.getBean(ObjectMapper.class);
String jsonString = objectMapper.writeValueAsString(o);
if (StrUtil.isNotBlank(jsonString)) {
List<NodeUser> nodeUserDtoList = objectMapper.readValue(jsonString,
new TypeReference<List<NodeUser>>() {
});
List<Long> userIdList = nodeUserDtoList.stream().map(NodeUser::getId)
.collect(Collectors.toList());
for (Long aLong : userIdList) {
userVoList.addAll(CollUtil.newArrayList(buildUser(aLong)));
}
}
}
}
else if (assignedType == ProcessInstanceConstant.AssignedTypeClass.SELF) {
// 发起人自己
userVoList.addAll(CollUtil.newArrayList(buildUser(SecurityUtils.getUser().getId())));
}
}
else if (Objects.equals(node.getType(), NodeTypeEnum.ROOT.getValue())) {
// 发起节点
if (StrUtil.isBlank(processInstanceId)) {
UserVo userVo = buildUser(SecurityUtils.getUser().getId());
userVoList.addAll(CollUtil.newArrayList(userVo));
}
else {
IProcessInstanceRecordService processInstanceRecordService = SpringUtil
.getBean(IProcessInstanceRecordService.class);
ProcessInstanceRecord processInstanceRecord = processInstanceRecordService.lambdaQuery()
.eq(ProcessInstanceRecord::getProcessInstanceId, processInstanceId).one();
UserVo userVo = buildRootUser(processInstanceId);
userVo.setShowTime(processInstanceRecord.getCreateTime());
userVo.setStatus(NodeStatusEnum.YJS.getCode());
userVoList.addAll(CollUtil.newArrayList(userVo));
}
}
else if (node.getType() == NodeTypeEnum.CC.getValue()) {
// 抄送节点
List<NodeUser> nodeUserList = node.getNodeUserList();
List<UserVo> tempList = buildUser(nodeUserList);
userVoList.addAll(tempList);
}
nodeVo.setUserVoList(userVoList);
List<NodeVo> branchList = new ArrayList<>();
if (type == NodeTypeEnum.EXCLUSIVE_GATEWAY.getValue().intValue()
|| type == NodeTypeEnum.PARALLEL_GATEWAY.getValue().intValue()) {
// 条件分支
List<Node> branchs = node.getConditionNodes();
for (Node branch : branchs) {
Node children = branch.getChildren();
List<NodeVo> processNodeShowDtos = formatProcessNodeShow(children, completeNodeSet, continueNodeSet,
processInstanceId, paramMap);
NodeVo p = new NodeVo();
p.setChildren(processNodeShowDtos);
p.setPlaceholder(branch.getPlaceHolder());
branchList.add(p);
}
}
nodeVo.setBranch(branchList);
list.add(nodeVo);
List<NodeVo> next = formatProcessNodeShow(node.getChildren(), completeNodeSet, continueNodeSet,
processInstanceId, paramMap);
list.addAll(next);
return list;
}
/**
* 根据实例id
* @param processInstanceId
* @return
*/
private static UserVo buildRootUser(String processInstanceId) {
IProcessInstanceRecordService processInstanceRecordService = SpringUtil
.getBean(IProcessInstanceRecordService.class);
ProcessInstanceRecord processInstanceRecord = processInstanceRecordService.lambdaQuery()
.eq(ProcessInstanceRecord::getProcessInstanceId, processInstanceId).one();
Long userId = processInstanceRecord.getUserId();
UserVo userVo = buildUser(userId);
return userVo;
}
/**
* 根据用户id
* @param userId
* @return
*/
private static UserVo buildUser(long userId) {
RemoteUserService userService = SpringUtil.getBean(RemoteUserService.class);
SysUser user = userService.getUserById(userId).getData();
if (user == null) {
return null;
}
return UserVo.builder().id(userId).name(user.getName()).avatar(user.getAvatar()).build();
}
private static List<UserVo> buildUser(List<NodeUser> nodeUserList) {
List<UserVo> userVoList = new ArrayList<>();
// 用户id
List<Long> userIdList = nodeUserList.stream()
.filter(w -> StrUtil.equals(w.getType(), NodeUserTypeEnum.USER.getKey()))
.map(w -> Convert.toLong(w.getId())).collect(Collectors.toList());
// 部门id
List<Long> deptIdList = nodeUserList.stream()
.filter(w -> StrUtil.equals(w.getType(), NodeUserTypeEnum.DEPT.getKey()))
.map(w -> Convert.toLong(w.getId())).collect(Collectors.toList());
if (CollUtil.isNotEmpty(deptIdList)) {
IRemoteService iRemoteService = SpringUtil.getBean(IRemoteService.class);
List<Long> data = iRemoteService.queryUserIdListByDepIdList(deptIdList).getData();
if (CollUtil.isNotEmpty(data)) {
for (long datum : data) {
if (!userIdList.contains(datum)) {
userIdList.add(datum);
}
}
}
}
{
for (Long aLong : userIdList) {
userVoList.addAll(CollUtil.newArrayList(buildUser(aLong)));
}
}
return userVoList;
}
}

View File

@@ -0,0 +1,18 @@
server:
port: 9030
spring:
application:
name: @artifactId@
cloud:
nacos:
username: @nacos.username@
password: @nacos.password@
discovery:
server-addr: ${NACOS_HOST:pigx-register}:${NACOS_PORT:8848}
config:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
config:
import:
- optional:nacos:application-@profiles.active@.yml
- optional:nacos:${spring.application.name}-@profiles.active@.yml

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
小技巧: 在根pom里面设置统一存放路径统一管理方便维护
<properties>
<log-path>/Users/lengleng</log-path>
</properties>
1. 其他模块加日志输出直接copy本文件放在resources 目录即可
2. 注意修改 <property name="${log-path}/log.path" value=""/> 的value模块
-->
<configuration debug="false" scan="false">
<property name="log.path" value="logs/${project.artifactId}"/>
<!-- 彩色日志格式 -->
<property name="CONSOLE_LOG_PATTERN"
value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<!-- 彩色日志依赖的渲染类 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<!-- Console log output -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- Log file debug output -->
<appender name="debug" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/debug.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${log.path}/%d{yyyy-MM, aux}/debug.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n</pattern>
</encoder>
</appender>
<!-- Log file error output -->
<appender name="error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/error.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${log.path}/%d{yyyy-MM}/error.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
</appender>
<logger name="org.activiti.engine.impl.db" level="DEBUG">
<appender-ref ref="debug"/>
</logger>
<!--nacos 心跳 INFO 屏蔽-->
<logger name="com.alibaba.nacos" level="OFF">
<appender-ref ref="error"/>
</logger>
<!-- Level: FATAL 0 ERROR 3 WARN 4 INFO 6 DEBUG 7 -->
<root level="INFO">
<appender-ref ref="console"/>
<appender-ref ref="debug"/>
</root>
</configuration>