diff --git a/czsj-flow/src/main/java/com/czsj/flow/adapter/AbstractWarmFlowAdapter.java b/czsj-flow/src/main/java/com/czsj/flow/adapter/AbstractWarmFlowAdapter.java new file mode 100644 index 0000000..3c025c1 --- /dev/null +++ b/czsj-flow/src/main/java/com/czsj/flow/adapter/AbstractWarmFlowAdapter.java @@ -0,0 +1,40 @@ +package com.czsj.flow.adapter; + +import com.czsj.common.core.domain.entity.SysRole; +import com.czsj.common.core.domain.entity.SysUser; +import org.dromara.warm.flow.core.enums.CooperateType; +import org.dromara.warm.flow.core.service.TaskService; +import org.dromara.warm.flow.core.utils.StreamUtils; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +@Service +public abstract class AbstractWarmFlowAdapter { + @Resource + protected TaskService taskService; + + /** + * 获取权限 + * + * @return 权限列表 + */ + protected List permissionList(SysUser sysUser, String userId) { + List roles = sysUser.getRoles(); + List permissionList = StreamUtils.toList(roles, role -> "role:" + role.getRoleId()); + permissionList.add(userId); + permissionList.add("dept:" + sysUser.getDeptId()); + return permissionList; + } + + /** + * 根据类型获取描述 + * + * @param type 流程类型 + * @return value + */ + protected String type(Integer type) { + return CooperateType.getValueByKey(type); + } +} diff --git a/czsj-flow/src/main/java/com/czsj/flow/adapter/AddSignatureAdapter.java b/czsj-flow/src/main/java/com/czsj/flow/adapter/AddSignatureAdapter.java new file mode 100644 index 0000000..081da92 --- /dev/null +++ b/czsj-flow/src/main/java/com/czsj/flow/adapter/AddSignatureAdapter.java @@ -0,0 +1,35 @@ +package com.czsj.flow.adapter; + +import com.czsj.common.core.domain.entity.SysUser; +import com.czsj.common.utils.SecurityUtils; +import com.czsj.common.vo.WarmFlowInteractiveTypeVo; +import org.dromara.warm.flow.core.dto.FlowParams; +import org.dromara.warm.flow.core.enums.CooperateType; +import org.springframework.stereotype.Component; + +import java.util.Objects; + +/** + * 加签适配器 + */ +@Component +public class AddSignatureAdapter extends AbstractWarmFlowAdapter implements WarmFlowAdapter { + @Override + public boolean isAdapter(Integer warmFlowType) { + return Objects.equals(CooperateType.ADD_SIGNATURE.getKey(), warmFlowType); + } + + @Override + public boolean adapter(WarmFlowInteractiveTypeVo obj) { + Long taskId = obj.getTaskId(); + SysUser sysUser = SecurityUtils.getLoginUser().getUser(); + String userId = String.valueOf(sysUser.getUserId()); + FlowParams flowParams = new FlowParams() + .handler(userId) + .permissionFlag(permissionList(sysUser, userId)) + .addHandlers(obj.getAddHandlers()) + .message(this.type(obj.getOperatorType())); + + return super.taskService.addSignature(taskId, flowParams); + } +} diff --git a/czsj-flow/src/main/java/com/czsj/flow/adapter/DeputeAdapter.java b/czsj-flow/src/main/java/com/czsj/flow/adapter/DeputeAdapter.java new file mode 100644 index 0000000..53f9bc6 --- /dev/null +++ b/czsj-flow/src/main/java/com/czsj/flow/adapter/DeputeAdapter.java @@ -0,0 +1,35 @@ +package com.czsj.flow.adapter; + +import com.czsj.common.core.domain.entity.SysUser; +import com.czsj.common.utils.SecurityUtils; +import com.czsj.common.vo.WarmFlowInteractiveTypeVo; +import org.dromara.warm.flow.core.dto.FlowParams; +import org.dromara.warm.flow.core.enums.CooperateType; +import org.springframework.stereotype.Component; + +import java.util.Objects; + +/** + * 委派适配器 + */ +@Component +public class DeputeAdapter extends AbstractWarmFlowAdapter implements WarmFlowAdapter { + @Override + public boolean isAdapter(Integer warmFlowType) { + return Objects.equals(CooperateType.DEPUTE.getKey(), warmFlowType); + } + + @Override + public boolean adapter(WarmFlowInteractiveTypeVo obj) { + Long taskId = obj.getTaskId(); + SysUser sysUser = SecurityUtils.getLoginUser().getUser(); + String userId = String.valueOf(sysUser.getUserId()); + FlowParams flowParams = new FlowParams() + .handler(userId) + .permissionFlag(permissionList(sysUser, userId)) + .addHandlers(obj.getAddHandlers()) + .message(this.type(obj.getOperatorType())); + + return super.taskService.depute(taskId, flowParams); + } +} diff --git a/czsj-flow/src/main/java/com/czsj/flow/adapter/ReductionSignatureAdapter.java b/czsj-flow/src/main/java/com/czsj/flow/adapter/ReductionSignatureAdapter.java new file mode 100644 index 0000000..7e971bb --- /dev/null +++ b/czsj-flow/src/main/java/com/czsj/flow/adapter/ReductionSignatureAdapter.java @@ -0,0 +1,35 @@ +package com.czsj.flow.adapter; + +import com.czsj.common.core.domain.entity.SysUser; +import com.czsj.common.utils.SecurityUtils; +import com.czsj.common.vo.WarmFlowInteractiveTypeVo; +import org.dromara.warm.flow.core.dto.FlowParams; +import org.dromara.warm.flow.core.enums.CooperateType; +import org.springframework.stereotype.Component; + +import java.util.Objects; + +/** + * 减签适配器 + */ +@Component +public class ReductionSignatureAdapter extends AbstractWarmFlowAdapter implements WarmFlowAdapter { + @Override + public boolean isAdapter(Integer warmFlowType) { + return Objects.equals(CooperateType.REDUCTION_SIGNATURE.getKey(), warmFlowType); + } + + @Override + public boolean adapter(WarmFlowInteractiveTypeVo obj) { + Long taskId = obj.getTaskId(); + SysUser sysUser = SecurityUtils.getLoginUser().getUser(); + String userId = String.valueOf(sysUser.getUserId()); + FlowParams flowParams = new FlowParams() + .handler(userId) + .permissionFlag(permissionList(sysUser, userId)) + .reductionHandlers(obj.getAddHandlers()) + .message(type(obj.getOperatorType())); + + return super.taskService.reductionSignature(taskId, flowParams); + } +} diff --git a/czsj-flow/src/main/java/com/czsj/flow/adapter/TransferAdapter.java b/czsj-flow/src/main/java/com/czsj/flow/adapter/TransferAdapter.java new file mode 100644 index 0000000..859cff6 --- /dev/null +++ b/czsj-flow/src/main/java/com/czsj/flow/adapter/TransferAdapter.java @@ -0,0 +1,35 @@ +package com.czsj.flow.adapter; + +import com.czsj.common.core.domain.entity.SysUser; +import com.czsj.common.utils.SecurityUtils; +import com.czsj.common.vo.WarmFlowInteractiveTypeVo; +import org.dromara.warm.flow.core.dto.FlowParams; +import org.dromara.warm.flow.core.enums.CooperateType; +import org.springframework.stereotype.Component; + +import java.util.Objects; + +/** + * 转办适配器 + */ +@Component +public class TransferAdapter extends AbstractWarmFlowAdapter implements WarmFlowAdapter { + @Override + public boolean isAdapter(Integer warmFlowType) { + return Objects.equals(CooperateType.TRANSFER.getKey(), warmFlowType); + } + + @Override + public boolean adapter(WarmFlowInteractiveTypeVo obj) { + Long taskId = obj.getTaskId(); + SysUser sysUser = SecurityUtils.getLoginUser().getUser(); + String userId = String.valueOf(sysUser.getUserId()); + FlowParams flowParams = new FlowParams() + .handler(userId) + .permissionFlag(permissionList(sysUser, userId)) + .addHandlers(obj.getAddHandlers()) + .message(this.type(obj.getOperatorType())); + + return super.taskService.transfer(taskId, flowParams); + } +} diff --git a/czsj-flow/src/main/java/com/czsj/flow/adapter/WarmFlowAdapter.java b/czsj-flow/src/main/java/com/czsj/flow/adapter/WarmFlowAdapter.java new file mode 100644 index 0000000..cdedd9a --- /dev/null +++ b/czsj-flow/src/main/java/com/czsj/flow/adapter/WarmFlowAdapter.java @@ -0,0 +1,9 @@ +package com.czsj.flow.adapter; + +import com.czsj.common.vo.WarmFlowInteractiveTypeVo; + +public interface WarmFlowAdapter { + boolean isAdapter(Integer warmFlowType); + + boolean adapter(WarmFlowInteractiveTypeVo obj); +} diff --git a/czsj-flow/src/main/java/com/czsj/flow/controller/DefController.java b/czsj-flow/src/main/java/com/czsj/flow/controller/DefController.java new file mode 100644 index 0000000..7656fba --- /dev/null +++ b/czsj-flow/src/main/java/com/czsj/flow/controller/DefController.java @@ -0,0 +1,211 @@ +package com.czsj.flow.controller; + +import com.czsj.common.annotation.Log; +import com.czsj.common.constant.HttpStatus; +import com.czsj.common.core.controller.BaseController; +import com.czsj.common.core.domain.R; +import com.czsj.common.core.page.PageDomain; +import com.czsj.common.core.page.TableDataInfo; +import com.czsj.common.core.page.TableSupport; +import com.czsj.common.enums.BusinessType; +import org.dromara.warm.flow.core.entity.Definition; +import org.dromara.warm.flow.core.service.ChartService; +import org.dromara.warm.flow.core.service.DefService; +import org.dromara.warm.flow.core.utils.page.Page; +import org.dromara.warm.flow.orm.entity.FlowDefinition; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.List; + +/** + * 流程定义Controller + * + * @author hh + * @date 2023-04-11 + */ +@Validated +@RestController +@RequestMapping("/flow/definition") +public class DefController extends BaseController { + @Resource + private DefService defService; + + @Resource + private ChartService chartService; + + /** + * 分页查询流程定义列表 + */ + @GetMapping("/list") + public TableDataInfo list(FlowDefinition flowDefinition) { + // flow组件自带分页功能 + PageDomain pageDomain = TableSupport.buildPageRequest(); + Page page = Page.pageOf(pageDomain.getPageNum(), pageDomain.getPageSize()); + page = defService.orderByCreateTime().desc().page(flowDefinition, page); + TableDataInfo rspData = new TableDataInfo(); + rspData.setCode(HttpStatus.SUCCESS); + rspData.setMsg("查询成功"); + rspData.setRows(page.getList()); + rspData.setTotal(page.getTotal()); + return rspData; + } + + + /** + * 获取流程定义详细信息 + */ + @PreAuthorize("@ss.hasPermi('flow:definition:query')") + @GetMapping(value = "/{id}") + public R getInfo(@PathVariable("id") Long id) { + return R.ok(defService.getById(id)); + } + + /** + * 新增流程定义 + */ + @PreAuthorize("@ss.hasPermi('flow:definition:add')") + @Log(title = "流程定义", businessType = BusinessType.INSERT) + @PostMapping + @Transactional(rollbackFor = Exception.class) + public R add(@RequestBody FlowDefinition flowDefinition) { + return R.ok(defService.saveAndInitNode(flowDefinition)); + } + + /** + * 发布流程定义 + */ + @PreAuthorize("@ss.hasPermi('flow:definition:publish')") + @Log(title = "流程定义", businessType = BusinessType.INSERT) + @GetMapping("/publish/{id}") + @Transactional(rollbackFor = Exception.class) + public R publish(@PathVariable("id") Long id) { + return R.ok(defService.publish(id)); + } + + /** + * 取消发布流程定义 + */ + @PreAuthorize("@ss.hasPermi('flow:definition:publish')") + @Log(title = "流程定义", businessType = BusinessType.INSERT) + @GetMapping("/unPublish/{id}") + @Transactional(rollbackFor = Exception.class) + public R unPublish(@PathVariable("id") Long id) { + defService.unPublish(id); + return R.ok(); + } + + /** + * 修改流程定义 + */ + @PreAuthorize("@ss.hasPermi('flow:definition:edit')") + @Log(title = "流程定义", businessType = BusinessType.UPDATE) + @PutMapping + @Transactional(rollbackFor = Exception.class) + public R edit(@RequestBody FlowDefinition flowDefinition) { + return R.ok(defService.updateById(flowDefinition)); + } + + /** + * 删除流程定义 + */ + @PreAuthorize("@ss.hasPermi('flow:definition:remove')") + @Log(title = "流程定义", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + @Transactional(rollbackFor = Exception.class) + public R remove(@PathVariable List ids) { + return R.ok(defService.removeDef(ids)); + } + + /** + * 复制流程定义 + */ + @PreAuthorize("@ss.hasPermi('flow:definition:publish')") + @Log(title = "流程定义", businessType = BusinessType.INSERT) + @GetMapping("/copyDef/{id}") + @Transactional(rollbackFor = Exception.class) + public R copyDef(@PathVariable("id") Long id) { + return R.ok(defService.copyDef(id)); + } + + @Log(title = "流程定义", businessType = BusinessType.IMPORT) + @PreAuthorize("@ss.hasPermi('flow:definition:importDefinition')") + @PostMapping("/importDefinition") + @Transactional(rollbackFor = Exception.class) + public R importDefinition(MultipartFile file) throws Exception { + defService.importIs(file.getInputStream()); + return R.ok(); + } + + @Log(title = "流程定义", businessType = BusinessType.EXPORT) + @PreAuthorize("@ss.hasPermi('flow:definition:exportDefinition')") + @PostMapping("/exportDefinition/{id}") + public ResponseEntity exportDefinition(@PathVariable("id") Long id) { + // 要导出的字符串 + String content = defService.exportJson(id); + + // 设置响应头 + HttpHeaders headers = new HttpHeaders(); + headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=exported_string.txt"); + + // 返回响应 + return ResponseEntity.ok() + .headers(headers) + .contentType(MediaType.TEXT_PLAIN) + .body(content.getBytes(StandardCharsets.UTF_8)); + } + + /** + * 查询流程图 + * + * @param definitionId + * + * @return + */ + @GetMapping("/chartDef/{definitionId}") + public R chartDef(@PathVariable("definitionId") Long definitionId) { + return R.ok(chartService.chartDef(definitionId)); + } + + /** + * 查询流程图 + * + * @param instanceId + * @return + */ + @GetMapping("/flowChart/{instanceId}") + public R flowChart(@PathVariable("instanceId") Long instanceId) throws IOException { + return R.ok(chartService.chartIns(instanceId)); + } + + /** + * 激活流程 + * + * @param definitionId + * @return + */ + @GetMapping("/active/{definitionId}") + public R active(@PathVariable("definitionId") Long definitionId) { + return R.ok(defService.active(definitionId)); + } + + /** + * 挂起流程 + * + * @param definitionId + * @return + */ + @GetMapping("/unActive/{definitionId}") + public R unActive(@PathVariable("definitionId") Long definitionId) { + return R.ok(defService.unActive(definitionId)); + } +} diff --git a/czsj-flow/src/main/java/com/czsj/flow/controller/ExecuteController.java b/czsj-flow/src/main/java/com/czsj/flow/controller/ExecuteController.java new file mode 100644 index 0000000..68a1ca5 --- /dev/null +++ b/czsj-flow/src/main/java/com/czsj/flow/controller/ExecuteController.java @@ -0,0 +1,366 @@ +package com.czsj.flow.controller; + +import com.czsj.common.core.controller.BaseController; +import com.czsj.common.core.domain.R; +import com.czsj.common.core.domain.entity.SysDept; +import com.czsj.common.core.domain.entity.SysRole; +import com.czsj.common.core.domain.entity.SysUser; +import com.czsj.common.core.page.TableDataInfo; +import com.czsj.common.utils.SecurityUtils; +import com.czsj.common.utils.StringUtils; +import com.czsj.common.vo.WarmFlowInteractiveTypeVo; +import com.czsj.flow.service.ExecuteService; +import com.czsj.flow.service.HhDefService; +import com.czsj.flow.vo.FlowTaskVo; +import com.czsj.system.service.ISysDeptService; +import com.czsj.system.service.ISysRoleService; +import com.czsj.system.service.ISysUserService; +import org.apache.commons.collections4.CollectionUtils; +import org.dromara.warm.flow.core.FlowEngine; +import org.dromara.warm.flow.core.entity.*; +import org.dromara.warm.flow.core.enums.CooperateType; +import org.dromara.warm.flow.core.enums.NodeType; +import org.dromara.warm.flow.core.enums.UserType; +import org.dromara.warm.flow.core.service.*; +import org.dromara.warm.flow.core.utils.StreamUtils; +import org.dromara.warm.flow.orm.entity.FlowHisTask; +import org.dromara.warm.flow.orm.entity.FlowTask; +import org.springframework.beans.BeanUtils; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/**load + * 流程实例Controller + * + * @author hh + * @date 2023-04-18 + */ +@Validated +@RestController +@RequestMapping("/flow/execute") +public class ExecuteController extends BaseController { + @Resource + private ISysUserService userService; + + @Resource + private ISysDeptService deptService; + + @Resource + private ISysRoleService roleService; + + @Resource + private HisTaskService hisTaskService; + + @Resource + private TaskService taskService; + + @Resource + private NodeService nodeService; + + @Resource + private InsService insService; + + @Resource + private UserService flowUserservice; + + @Resource + private ExecuteService executeService; + + @Resource + private HhDefService hhDefService; + + /** + * 分页待办任务列表 + */ + @PreAuthorize("@ss.hasPermi('flow:execute:toDoPage')") + @GetMapping("/toDoPage") + public TableDataInfo toDoPage(FlowTask flowTask) { + SysUser sysUser = SecurityUtils.getLoginUser().getUser(); + List permissionList = permissionList(String.valueOf(sysUser.getUserId()), sysUser.getDeptId(), sysUser); + flowTask.setPermissionList(permissionList); + startPage(); + List list = executeService.toDoPage(flowTask); + List taskIds = StreamUtils.toList(list, FlowTaskVo::getId); + List userList = flowUserservice.getByAssociateds(taskIds); + Map> map = StreamUtils.groupByKey(userList, User::getAssociated); + for (FlowTaskVo taskVo : list) { + if (StringUtils.isNotNull(taskVo)) { + List users = map.get(taskVo.getId()); + if (CollectionUtils.isNotEmpty(users)) { + for (User user : users) { + if (UserType.APPROVAL.getKey().equals(user.getType())) { + if (StringUtils.isEmpty(taskVo.getApprover())) { + taskVo.setApprover(""); + } + String name = getName(user.getProcessedBy()); + if (StringUtils.isNotEmpty(name)) taskVo.setApprover(taskVo.getApprover().concat(name).concat(";")); + } else if (UserType.TRANSFER.getKey().equals(user.getType())) { + if (StringUtils.isEmpty(taskVo.getTransferredBy())) { + taskVo.setTransferredBy(""); + } + String name = getName(user.getProcessedBy()); + if (StringUtils.isNotEmpty(name)) taskVo.setTransferredBy(taskVo.getTransferredBy().concat(name).concat(";")); + } else if (UserType.DEPUTE.getKey().equals(user.getType())) { + if (StringUtils.isEmpty(taskVo.getDelegate())) { + taskVo.setDelegate(""); + } + String name = getName(user.getProcessedBy()); + if (StringUtils.isNotEmpty(name)) taskVo.setDelegate(taskVo.getDelegate().concat(name).concat(";")); + } + } + } + } + } + return getDataTable(list); + } + + /** + * 分页抄送任务列表 + * author:暗影 + */ + @PreAuthorize("@ss.hasPermi('flow:execute:copyPage')") + @GetMapping("/copyPage") + public TableDataInfo copyPage(FlowTask flowTask) { + SysUser sysUser = SecurityUtils.getLoginUser().getUser(); + List permissionList = permissionList(String.valueOf(sysUser.getUserId()), sysUser.getDeptId(), sysUser); + flowTask.setPermissionList(permissionList); + startPage(); + List list = executeService.copyPage(flowTask); + return getDataTable(list); + } + /** + * 分页已办任务列表 + */ + @PreAuthorize("@ss.hasPermi('flow:execute:donePage')") + @GetMapping("/donePage") + public TableDataInfo donePage(FlowHisTask flowHisTask) { + startPage(); + SysUser sysUser = SecurityUtils.getLoginUser().getUser(); + List permissionList = permissionList(String.valueOf(sysUser.getUserId()), sysUser.getDeptId(), sysUser); + flowHisTask.setPermissionList(permissionList); + List list = executeService.donePage(flowHisTask); + Map userMap = StreamUtils.toMap(userService.selectUserList(new SysUser()) + , SysUser::getUserId, SysUser::getNickName); + if (CollectionUtils.isNotEmpty(list)) { + for (FlowHisTask hisTask : list) { + if (StringUtils.isNotEmpty(hisTask.getApprover())) { + String name = getName(hisTask.getApprover()); + hisTask.setApprover(name); + } + if (StringUtils.isNotEmpty(hisTask.getCollaborator())) { + String[] split = hisTask.getCollaborator().split(","); + if (split.length > 1) { + List names = new ArrayList<>(); + for (String s : split) { + names.add(userMap.get(Long.valueOf(s))); + } + hisTask.setCollaborator(StringUtils.join(names, ",")); + } + } + } + } + return getDataTable(list); + } + + private String getName(String id) { + Map userMap = StreamUtils.toMap(userService.selectUserList(new SysUser()) + , SysUser::getUserId, SysUser::getNickName); + Map deptMap = StreamUtils.toMap(deptService.selectDeptList(new SysDept()) + , SysDept::getDeptId, SysDept::getDeptName); + Map roleMap = StreamUtils.toMap(roleService.selectRoleAll() + , SysRole::getRoleId, SysRole::getRoleName); + if (StringUtils.isNotNull(id)) { + if (id.contains("user:")) { + String name = userMap.get(Long.valueOf(id.replace("user:", ""))); + if (StringUtils.isNotEmpty(name)) { + return "用户:" + name; + } + } else if (id.contains("dept:")) { + String name = deptMap.get(Long.valueOf(id.replace("dept:", ""))); + if (StringUtils.isNotEmpty(name)) { + return "部门:" + name; + } + } else if (id.contains("role")) { + String name = roleMap.get(Long.valueOf(id.replace("role:", ""))); + if (StringUtils.isNotEmpty(name)) { + return "角色:" + name; + } + } else { + try { + long parseLong = Long.parseLong(id); + String name = userMap.get(parseLong); + if (StringUtils.isNotEmpty(name)) { + return "用户:" + name; + } + } catch (NumberFormatException e) { + return id; + } + + } + } + return ""; + } + + + /** + * 查询已办任务历史记录 + */ + @PreAuthorize("@ss.hasPermi('flow:execute:doneList')") + @GetMapping("/doneList/{instanceId}") + public R> doneList(@PathVariable("instanceId") Long instanceId) { + List flowHisTasks = hisTaskService.orderById().desc().list(new FlowHisTask().setInstanceId(instanceId)); + Map userMap = StreamUtils.toMap(userService.selectUserList(new SysUser()) + , SysUser::getUserId, SysUser::getNickName); + List flowHisTaskList = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(flowHisTasks)) { + for (HisTask hisTask : flowHisTasks) { + if (StringUtils.isNotEmpty(hisTask.getApprover())) { + String name = getName(hisTask.getApprover()); + hisTask.setApprover(name); + } + if (StringUtils.isNotEmpty(hisTask.getCollaborator())) { + String[] split = hisTask.getCollaborator().split(","); + if (split.length > 1) { + List names = new ArrayList<>(); + for (String s : split) { + names.add(userMap.get(Long.valueOf(s))); + } + hisTask.setCollaborator(StringUtils.join(names, ",")); + } + } + FlowHisTask flowHisTask = new FlowHisTask(); + BeanUtils.copyProperties(hisTask, flowHisTask); + flowHisTaskList.add(flowHisTask); + } + } + return R.ok(flowHisTaskList); + } + + /** + * 根据taskId查询代表任务 + * + * @param taskId + * @return + */ + @GetMapping("/getTaskById/{taskId}") + public R getTaskById(@PathVariable("taskId") Long taskId) { + return R.ok(taskService.getById(taskId)); + } + + /** + * 查询跳转任意节点列表 + */ + @PreAuthorize("@ss.hasPermi('flow:execute:doneList')") + @GetMapping("/anyNodeList/{instanceId}") + public R> anyNodeList(@PathVariable("instanceId") Long instanceId) { + Instance instance = insService.getById(instanceId); + List nodeList = nodeService.list(FlowEngine.newNode().setDefinitionId(instance.getDefinitionId())); + nodeList.removeIf(node -> NodeType.isGateWay(node.getNodeType())); + return R.ok(nodeList); + } + + /** + * 处理非办理的流程交互类型 + * + * @param warmFlowInteractiveTypeVo 要转办用户 + * @return 是否成功 + */ + @PostMapping("/interactiveType") + public R interactiveType(WarmFlowInteractiveTypeVo warmFlowInteractiveTypeVo) { + return R.ok(hhDefService.interactiveType(warmFlowInteractiveTypeVo)); + } + + /** + * 交互类型可以选择的用户 + * + * @param warmFlowInteractiveTypeVo 交互类型请求类 + * @return 是否成功 + */ + @GetMapping("/interactiveTypeSysUser") + public TableDataInfo interactiveTypeSysUser(WarmFlowInteractiveTypeVo warmFlowInteractiveTypeVo) { + startPage(); + SysUser currentUser = SecurityUtils.getLoginUser().getUser(); + Long userId = currentUser.getUserId(); + Integer operatorType = warmFlowInteractiveTypeVo.getOperatorType(); + List list; + Long taskId = warmFlowInteractiveTypeVo.getTaskId(); + List users = flowUserservice.listByAssociatedAndTypes(taskId); + if (!Objects.equals(CooperateType.REDUCTION_SIGNATURE.getKey(), operatorType)) { + List userIds = StreamUtils.toList(users, User::getProcessedBy); + warmFlowInteractiveTypeVo.setUserIds(userIds); + list = userService.selectNotUserList(warmFlowInteractiveTypeVo); + } else { + List userIds = StreamUtils.toList(users, User::getProcessedBy); + warmFlowInteractiveTypeVo.setUserIds(userIds); + list = userService.selectUserList(warmFlowInteractiveTypeVo); + list = StreamUtils.filter(list, sysUser -> !Objects.equals(userId, sysUser.getUserId())); + } + return getDataTable(list); + } + + /** + * 激活流程 + * + * @param instanceId + * @return + */ + @GetMapping("/active/{instanceId}") + public R active(@PathVariable("instanceId") Long instanceId) { + return R.ok(insService.active(instanceId)); + } + + /** + * 挂起流程 + * + * @param instanceId + * @return + */ + @GetMapping("/unActive/{instanceId}") + public R unActive(@PathVariable("instanceId") Long instanceId) { + return R.ok(insService.unActive(instanceId)); + } + + /** + * 获取权限 + * + * @param userId 用户编号 + * @param deptId 部门编号 + * @param sysUser 登陆用户 + * @return 权限列表 + */ + private List permissionList(String userId, Long deptId, SysUser sysUser) { + List roles = sysUser.getRoles(); + List permissionList = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(roles)) { + permissionList = StreamUtils.toList(roles, role -> "role:" + role.getRoleId()); + } + permissionList.add(userId); + if (Objects.nonNull(deptId)) { + permissionList.add("dept:" + deptId); + } + logger.info("当前用户所有权限[{}]", permissionList); + return permissionList; + } + + /** + * 根据ID反显姓名 + * + * @param ids 需要反显姓名的用户ID + * @return {@link R< List>} + * @author liangli + * @date 2024/8/21 17:08 + **/ + @PreAuthorize("@ss.hasPermi('flow:definition:query')") + @GetMapping(value = "/idReverseDisplayName/{ids}") + public R> idReverseDisplayName(@PathVariable Long[] ids) { + return R.ok(executeService.idReverseDisplayName(ids)); + } + +} diff --git a/czsj-flow/src/main/java/com/czsj/flow/controller/FormController.java b/czsj-flow/src/main/java/com/czsj/flow/controller/FormController.java new file mode 100644 index 0000000..91de759 --- /dev/null +++ b/czsj-flow/src/main/java/com/czsj/flow/controller/FormController.java @@ -0,0 +1,209 @@ +package com.czsj.flow.controller; + +import com.czsj.common.annotation.Log; +import com.czsj.common.constant.HttpStatus; +import com.czsj.common.core.controller.BaseController; +import com.czsj.common.core.domain.R; +import com.czsj.common.core.page.PageDomain; +import com.czsj.common.core.page.TableDataInfo; +import com.czsj.common.core.page.TableSupport; +import com.czsj.common.enums.BusinessType; +import org.dromara.warm.flow.core.FlowEngine; +import org.dromara.warm.flow.core.entity.Form; +import org.dromara.warm.flow.core.service.FormService; +import org.dromara.warm.flow.core.utils.page.Page; +import org.dromara.warm.flow.orm.entity.FlowForm; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 表单Controller + * + * @author liangli + * @date 2024-09-05 + */ +@Validated +@RestController +@RequestMapping("/flow/form") +public class FormController extends BaseController { + + @Resource + private FormService formService; + + /** + * 表单列表 + * + * @param form 携带的查询参数 + * @return {@link TableDataInfo} + * @author liangli + * @date 2024/9/5 15:07 + **/ + @PreAuthorize("@ss.hasPermi('flow:form:list')") + @GetMapping(value = "/list") + public TableDataInfo list(FlowForm form) { + PageDomain pageDomain = TableSupport.buildPageRequest(); + Page
page = Page.pageOf(pageDomain.getPageNum(), pageDomain.getPageSize()); + page = formService.orderByCreateTime().desc().page(form, page); + + TableDataInfo rspData = new TableDataInfo(); + rspData.setCode(HttpStatus.SUCCESS); + rspData.setMsg("查询成功"); + rspData.setRows(page.getList()); + rspData.setTotal(page.getTotal()); + return rspData; + } + + /** + * 已发布表单列表 + * + * @param form 携带的查询参数 + * @return {@link TableDataInfo} + * @author vanlin + * @date 2024/11/11 15:07 + **/ + @GetMapping(value = "/publishedList") + public TableDataInfo publishedList(FlowForm form) { + PageDomain pageDomain = TableSupport.buildPageRequest(); + Page page = Page.pageOf(pageDomain.getPageNum(), pageDomain.getPageSize()); + form.setIsPublish(1); //已发布 + page = formService.orderByCreateTime().desc().page(form, page); + + TableDataInfo rspData = new TableDataInfo(); + rspData.setCode(HttpStatus.SUCCESS); + rspData.setMsg("查询成功"); + rspData.setRows(page.getList()); + rspData.setTotal(page.getTotal()); + return rspData; + } + + /** + * 查询表单详情 + * + * @param id 表单ID + * @return {@link R< Form>} + * @author liangli + * @date 2024/9/5 15:41 + **/ + @PreAuthorize("@ss.hasPermi('flow:form:query')") + @GetMapping(value = "/{id}") + public R getForm(@PathVariable("id") Long id) { + return R.ok(formService.getById(id)); + } + + /** + * 提交表单 + * + * @param form 表单ID对应的表单内容 + * @return {@link R} + * @author liangli + * @date 2024/9/5 15:07 + **/ + @PreAuthorize("@ss.hasPermi('flow:form:add')") + @Log(title = "提交表单", businessType = BusinessType.INSERT) + @PostMapping("/saveFormContent") + @Transactional(rollbackFor = Exception.class) + public R saveFormContent(@RequestBody FlowForm form) { + return R.ok(formService.updateById(FlowEngine.newForm().setFormContent(form.getFormContent()).setId(form.getId()))); + } + + /** + * 提交表单 + * + * @param form 携带的查询参数 + * @return {@link R} + * @author liangli + * @date 2024/9/5 15:07 + **/ + @PreAuthorize("@ss.hasPermi('flow:form:add')") + @Log(title = "提交表单", businessType = BusinessType.INSERT) + @PostMapping("/add") + @Transactional(rollbackFor = Exception.class) + public R add(@RequestBody FlowForm form) { + return R.ok(formService.save(form)); + } + + /** + * 发布表单 + * + * @param id 表单ID + * @return {@link R} + * @author liangli + * @date 2024/9/5 15:26 + **/ + @PreAuthorize("@ss.hasPermi('flow:form:publish')") + @Log(title = "发布表单", businessType = BusinessType.INSERT) + @GetMapping("/publish/{id}") + @Transactional(rollbackFor = Exception.class) + public R publish(@PathVariable("id") Long id) { + return R.ok(formService.publish(id)); + } + + /** + * 取消表单 + * + * @param id 表单ID + * @return {@link R} + * @author liangli + * @date 2024/9/5 15:26 + **/ + @PreAuthorize("@ss.hasPermi('flow:form:unPublish')") + @Log(title = "取消发布表单", businessType = BusinessType.INSERT) + @GetMapping("/unPublish/{id}") + @Transactional(rollbackFor = Exception.class) + public R unPublish(@PathVariable("id") Long id) { + return R.ok(formService.unPublish(id)); + } + + /** + * 修改表单 + * + * @param form 表单 + * @return {@link R} + * @author liangli + * @date 2024/9/5 15:26 + **/ + @PreAuthorize("@ss.hasPermi('flow:form:edit')") + @Log(title = "流程定义", businessType = BusinessType.UPDATE) + @PutMapping("/edit") + @Transactional(rollbackFor = Exception.class) + public R edit(@RequestBody FlowForm form) { + return R.ok(formService.updateById(form)); + } + + /** + * 删除表单 + * + * @param ids 表单ID + * @return {@link R} + * @author liangli + * @date 2024/9/5 16:19 + **/ + @PreAuthorize("@ss.hasPermi('flow:form:remove')") + @Log(title = "流程定义", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + @Transactional(rollbackFor = Exception.class) + public R remove(@PathVariable List ids) { + return R.ok(formService.removeByIds(ids)); + } + + /** + * 复制表单 + * + * @param id 表单ID + * @return {@link R} + * @author liangli + * @date 2024/9/5 16:19 + **/ + @PreAuthorize("@ss.hasPermi('flow:form:add')") + @Log(title = "流程定义", businessType = BusinessType.INSERT) + @PostMapping("/copyForm/{id}") + @Transactional(rollbackFor = Exception.class) + public R copyForm(@PathVariable("id") Long id) { + return R.ok(formService.copyForm(id)); + } +} diff --git a/czsj-flow/src/main/java/com/czsj/flow/mapper/WarmFlowMapper.java b/czsj-flow/src/main/java/com/czsj/flow/mapper/WarmFlowMapper.java new file mode 100644 index 0000000..3d8cf33 --- /dev/null +++ b/czsj-flow/src/main/java/com/czsj/flow/mapper/WarmFlowMapper.java @@ -0,0 +1,52 @@ +package com.czsj.flow.mapper; + +import com.czsj.common.core.domain.entity.SysUser; +import com.czsj.flow.vo.FlowTaskVo; +import org.dromara.warm.flow.core.entity.HisTask; +import org.dromara.warm.flow.core.entity.Task; +import org.dromara.warm.flow.orm.entity.FlowHisTask; +import org.dromara.warm.flow.orm.entity.FlowTask; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Map; + +/** + * warm-flow工作流Mapper接口 + * + * @author czsj + * @date 2024-03-07 + */ +public interface WarmFlowMapper { + /** + * 分页查询待办任务 + * + * @param task 条件实体 + */ + List toDoPage(@Param("task") Task task); + + /** + * 获取最新的已办任务 + * + * @param hisTask + * @return + */ + List donePage(@Param("hisTask") HisTask hisTask); + + /** + * 分页获取抄送任务 + * @param flowTask + * @return + */ + List copyPage(@Param("task") FlowTask flowTask); + + /** + * 根据ID反显姓名 + * + * @param ids 需要反显姓名的用户ID + * @return {@link List} + * @author liangli + * @date 2024/8/21 17:11 + **/ + List idReverseDisplayName(@Param("ids") Long[] ids); +} diff --git a/czsj-flow/src/main/java/com/czsj/flow/service/ExecuteService.java b/czsj-flow/src/main/java/com/czsj/flow/service/ExecuteService.java new file mode 100644 index 0000000..07ffce8 --- /dev/null +++ b/czsj-flow/src/main/java/com/czsj/flow/service/ExecuteService.java @@ -0,0 +1,47 @@ +package com.czsj.flow.service; + +import com.czsj.common.core.domain.entity.SysUser; +import com.czsj.flow.vo.FlowTaskVo; +import org.dromara.warm.flow.core.entity.HisTask; +import org.dromara.warm.flow.core.entity.Task; +import org.dromara.warm.flow.orm.entity.FlowHisTask; +import org.dromara.warm.flow.orm.entity.FlowTask; + +import java.util.List; + +/** + * 流程执行service + * + * @author warm + * @since 2023/5/29 13:09 + */ +public interface ExecuteService { + + /** + * 分页查询待办任务 + * + * @param task 条件实体 + * @return + */ + List toDoPage(Task task); + + /** + * 获取已办任务 + * + * @param hisTask + * @return + */ + List donePage(HisTask hisTask); + + List copyPage(FlowTask flowTask); + + /** + * 根据ID反显姓名 + * + * @param ids 需要反显姓名的用户ID + * @return {@link List} + * @author liangli + * @date 2024/8/21 17:11 + **/ + List idReverseDisplayName(Long[] ids); +} diff --git a/czsj-flow/src/main/java/com/czsj/flow/service/HhDefService.java b/czsj-flow/src/main/java/com/czsj/flow/service/HhDefService.java new file mode 100644 index 0000000..8c1b5af --- /dev/null +++ b/czsj-flow/src/main/java/com/czsj/flow/service/HhDefService.java @@ -0,0 +1,14 @@ +package com.czsj.flow.service; + +import com.czsj.common.vo.WarmFlowInteractiveTypeVo; + +/** + * 流程定义service + * + * @author warm + * @since 2023/5/29 13:09 + */ +public interface HhDefService { + + Boolean interactiveType(WarmFlowInteractiveTypeVo warmFlowInteractiveTypeVo); +} diff --git a/czsj-flow/src/main/java/com/czsj/flow/service/impl/ExecuteServiceImpl.java b/czsj-flow/src/main/java/com/czsj/flow/service/impl/ExecuteServiceImpl.java new file mode 100644 index 0000000..66d30e0 --- /dev/null +++ b/czsj-flow/src/main/java/com/czsj/flow/service/impl/ExecuteServiceImpl.java @@ -0,0 +1,59 @@ +package com.czsj.flow.service.impl; + +import com.czsj.common.core.domain.entity.SysUser; +import com.czsj.flow.mapper.WarmFlowMapper; +import com.czsj.flow.service.ExecuteService; +import com.czsj.flow.vo.FlowTaskVo; +import org.dromara.warm.flow.core.entity.HisTask; +import org.dromara.warm.flow.core.entity.Task; +import org.dromara.warm.flow.orm.entity.FlowHisTask; +import org.dromara.warm.flow.orm.entity.FlowTask; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Objects; + +/** + * 流程执行SERVICEIMPL + * + * @author WARM + * @since 2023/5/29 13:09 + */ +@Service +public class ExecuteServiceImpl implements ExecuteService { + + @Resource + private WarmFlowMapper flowMapper; + + @Override + public List toDoPage(Task task) { + return flowMapper.toDoPage(task); + } + + @Override + public List donePage(HisTask hisTask) { + return flowMapper.donePage(hisTask); + } + + @Override + public List copyPage(FlowTask flowTask) { + return flowMapper.copyPage(flowTask); + } + + /** + * 根据ID反显姓名 + * + * @param ids 需要反显姓名的用户ID + * @return {@link List} + * @author liangli + * @date 2024/8/21 17:11 + **/ + @Override + public List idReverseDisplayName(Long[] ids) { + if (Objects.isNull(ids) || ids.length == 0) { + return null; + } + return flowMapper.idReverseDisplayName(ids); + } +} diff --git a/czsj-flow/src/main/java/com/czsj/flow/service/impl/HhDefServiceImpl.java b/czsj-flow/src/main/java/com/czsj/flow/service/impl/HhDefServiceImpl.java new file mode 100644 index 0000000..557fdfa --- /dev/null +++ b/czsj-flow/src/main/java/com/czsj/flow/service/impl/HhDefServiceImpl.java @@ -0,0 +1,59 @@ +package com.czsj.flow.service.impl; + +import com.czsj.common.utils.spring.SpringUtils; +import com.czsj.flow.adapter.WarmFlowAdapter; +import com.czsj.flow.service.HhDefService; +import com.czsj.common.vo.WarmFlowInteractiveTypeVo; +import org.dromara.warm.flow.core.service.DefService; +import org.dromara.warm.flow.core.service.NodeService; +import org.dromara.warm.flow.core.service.SkipService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * 流程定义serviceImpl + * + * @author warm + * @since 2023/5/29 13:09 + */ +@Service +public class HhDefServiceImpl implements HhDefService { + + @Resource + private DefService defService; + + @Resource + private NodeService nodeService; + + @Resource + private SkipService skipService; + + private static final List WARM_FLOW_ADAPTERS = new ArrayList<>(); + + /** + * 初始化方法 + */ + @PostConstruct + public void initMethod() { + Map beanNamesForType = SpringUtils.getBeanNamesForType(WarmFlowAdapter.class); + WARM_FLOW_ADAPTERS.addAll(beanNamesForType.values()); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public Boolean interactiveType(WarmFlowInteractiveTypeVo warmFlowInteractiveTypeVo) { + Integer operatorType = warmFlowInteractiveTypeVo.getOperatorType(); + for (WarmFlowAdapter warmFlowAdapter : WARM_FLOW_ADAPTERS) { + if (warmFlowAdapter.isAdapter(operatorType)) { + return warmFlowAdapter.adapter(warmFlowInteractiveTypeVo); + } + } + return false; + } +} diff --git a/czsj-flow/src/main/java/com/czsj/flow/vo/FlowTaskVo.java b/czsj-flow/src/main/java/com/czsj/flow/vo/FlowTaskVo.java new file mode 100644 index 0000000..e78c077 --- /dev/null +++ b/czsj-flow/src/main/java/com/czsj/flow/vo/FlowTaskVo.java @@ -0,0 +1,81 @@ +package com.czsj.flow.vo; + +import org.dromara.warm.flow.orm.entity.FlowTask; + +/** + * 待办任务vo + * + * @author warm + */ +public class FlowTaskVo extends FlowTask { + + /** + * 计划审批人 + */ + private String approver; + + /** + * 转办人 + */ + private String transferredBy; + + /** + * 委派人 + */ + private String delegate; + + /** + * 委派人 + */ + private String flowStatus; + + /** + * 激活状态 + */ + private Integer activityStatus; + + public String getApprover() { + return approver; + } + + public FlowTaskVo setApprover(String approver) { + this.approver = approver; + return this; + } + + public String getTransferredBy() { + return transferredBy; + } + + public FlowTaskVo setTransferredBy(String transferredBy) { + this.transferredBy = transferredBy; + return this; + } + + public String getDelegate() { + return delegate; + } + + public FlowTaskVo setDelegate(String delegate) { + this.delegate = delegate; + return this; + } + + public String getFlowStatus() { + return flowStatus; + } + + public FlowTaskVo setFlowStatus(String flowStatus) { + this.flowStatus = flowStatus; + return this; + } + + public Integer getActivityStatus() { + return activityStatus; + } + + public FlowTaskVo setActivityStatus(Integer activityStatus) { + this.activityStatus = activityStatus; + return this; + } +}