ruoyi-admin/pom.xml
@@ -100,13 +100,6 @@ <!-- </exclusions>--> </dependency> <!--二维码开发工具集--> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>4.6.10</version> </dependency> <!-- zxing生成二维码 --> <dependency> <groupId>com.google.zxing</groupId> ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/StateProcessController.java
New file @@ -0,0 +1,191 @@ package com.ruoyi.web.controller.api; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.basic.PageInfo; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.BaseEntity; import com.ruoyi.common.core.domain.BaseModel; import com.ruoyi.common.core.domain.BasePage; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.page.PageDomain; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.exception.GlobalException; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.system.bo.*; import com.ruoyi.system.model.StateProcessModule; import com.ruoyi.system.model.StateProcessTemplate; import com.ruoyi.system.service.ISysUserService; import com.ruoyi.system.service.StateProcessModuleService; import com.ruoyi.system.service.StateProcessTemplateService; import com.ruoyi.system.vo.ProcessTaskListVO; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.*; import java.time.LocalDateTime; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @Api(tags = "审批流程管理") @RequestMapping("/state-process") @RestController @RequiredArgsConstructor public class StateProcessController { private final StateProcessTemplateService processTemplateService; private final StateProcessModuleService processModuleService; private final ISysUserService sysUserService; //应用流程分页列表 @ApiOperation("应用流程分页列表") @PostMapping("/module/page") public AjaxResult<List<StateProcessModule>> modulePage(@RequestBody BasePage basePage) { LambdaQueryWrapper<StateProcessModule> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.orderByAsc(StateProcessModule::getCategory); //查询应用流程列表 List<StateProcessModule> result = processModuleService.list(queryWrapper); List<String> updateUserId = result.stream().map(BaseModel::getUpdateBy).collect(Collectors.toList()); if (!CollectionUtils.isEmpty(updateUserId)){ //根据用户id查询用户信息 List<SysUser> sysUsers = sysUserService.selectUserByUserNameList(updateUserId); Map<Long, SysUser> sysUserMap; if (!CollectionUtils.isEmpty(sysUsers)){ sysUserMap = sysUsers.stream().collect(Collectors.toMap(SysUser::getUserId, Function.identity())); } else { sysUserMap = new HashMap<>(); } //遍历列表,设置更新人名称 result.forEach(e -> { SysUser sysUser = sysUserMap.get(e.getUpdateBy()); if (Objects.nonNull(sysUser)){ e.setUpdateBy(sysUser.getNickName()); } }); } return AjaxResult.success(result); } //修改应用流程 @Log(title = "审批流程管理-修改应用流程", businessType = BusinessType.UPDATE) @ApiOperation("修改应用流程") @PostMapping("/module/update") public AjaxResult<PageInfo<StateProcessModule>> moduleUpdate(@RequestBody ProcessModuleUpdateBO processModuleUpdateBO) { StateProcessTemplate stateProcessTemplate = processTemplateService.getById(processModuleUpdateBO.getTemplateId()); if (Objects.isNull(stateProcessTemplate)) { return AjaxResult.success(); } StateProcessModule stateProcessModule = new StateProcessModule(); stateProcessModule.setId(processModuleUpdateBO.getId()); stateProcessModule.setTemplateId(processModuleUpdateBO.getTemplateId()); stateProcessModule.setTemplateName(stateProcessTemplate.getTemplateName()); stateProcessModule.setUpdateBy(SecurityUtils.getLoginUser().getUser().getNickName()); stateProcessModule.setCreateTime(LocalDateTime.now()); stateProcessModule.setUpdateTime(LocalDateTime.now()); stateProcessModule.setRemark(processModuleUpdateBO.getRemark()); processModuleService.updateById(stateProcessModule); return AjaxResult.success(); } //流程模版分页 @ApiOperation("流程模版分页") @PostMapping("/template/page") public AjaxResult<Page<StateProcessTemplate>> page(ProcessTemplatePageBO request) { Page<StateProcessTemplate> templatePage = processTemplateService.page(request); return AjaxResult.success(templatePage); } //查询流程模版 @ApiOperation("查询流程模版") @GetMapping("/template/getById") public AjaxResult<StateProcessTemplate> selectById(@RequestParam String id) { return AjaxResult.success(processTemplateService.getById(id)); } //修改并部署模版 @Log(title = "审批流程管理-修改并部署模版", businessType = BusinessType.UPDATE) @ApiOperation("修改并部署模版") @PostMapping("/template/update") public AjaxResult<Boolean> update(@RequestBody ProcessUpdateBO processUpdateBO) { return AjaxResult.success(processTemplateService.update(processUpdateBO)); } //删除模版 @Log(title = "审批流程管理-删除模版", businessType = BusinessType.DELETE) @ApiOperation("删除模版") @GetMapping("/template/deleteById") public AjaxResult<Boolean> deleteById(@RequestParam String id) { StateProcessTemplate template = processTemplateService.getById(id); //查询是否存在使用的 LambdaUpdateWrapper<StateProcessModule> moduleLambdaUpdateWrapper = new LambdaUpdateWrapper<>();; moduleLambdaUpdateWrapper.eq(StateProcessModule::getTemplateId, template.getId()); if (processModuleService.getBaseMapper().exists(moduleLambdaUpdateWrapper)) { throw new GlobalException("该模版在应用流程中已使用!"); } //根据key修改所有版本为已删除 boolean result = processTemplateService.remove(Wrappers.lambdaQuery(StateProcessTemplate.class) .eq(StateProcessTemplate::getTemplateKey, template.getTemplateKey())); return AjaxResult.success(result); } //创建并部署模版 @Log(title = "审批流程管理-创建并部署模版", businessType = BusinessType.INSERT) @ApiOperation("创建并部署模版") @PostMapping("/template/create") public AjaxResult<Boolean> create(@RequestBody ProcessCreateBO processCreateBO) { return AjaxResult.success(processTemplateService.create(processCreateBO)); } //流程发起 @Log(title = "审批流程管理-流程发起", businessType = BusinessType.INSERT) @ApiOperation("流程发起") @PostMapping("/start") public AjaxResult<Boolean> start(@RequestBody ProcessStartBO processStartBO) { return AjaxResult.success(processTemplateService.start(processStartBO)); } //待办 @ApiOperation("待办列表") @PostMapping("/wait/task/page") public AjaxResult<PageInfo<ProcessTaskListVO>> waitTaskPage(@RequestBody ProcessTaskListBO processTemplatePageBO) { return AjaxResult.success(processTemplateService.waitTaskPage(processTemplatePageBO)); } //已办 @ApiOperation("已办列表") @PostMapping("/deal/task/page") public AjaxResult<PageInfo<ProcessTaskListVO>> dealTaskPage(@RequestBody ProcessTaskListBO processTemplatePageBO) { return AjaxResult.success(processTemplateService.dealTaskPage(processTemplatePageBO)); } //抄送 @ApiOperation("抄送列表") @PostMapping("/copy/task/page") public AjaxResult<PageInfo<ProcessTaskListVO>> copyTaskPage(@RequestBody ProcessTaskListBO processTaskListBO){ return AjaxResult.success(processTemplateService.copyTaskPage(processTaskListBO)); } //审核通过 @Log(title = "审批流程管理-审核通过", businessType = BusinessType.UPDATE) @ApiOperation("审核通过") @PostMapping("/agree") public AjaxResult<Object> agree(@RequestBody ProcessAgreeBO processAgreeBO) { processTemplateService.agree(processAgreeBO); return AjaxResult.success(); } //审核拒绝 @Log(title = "审批流程管理-审核拒绝", businessType = BusinessType.UPDATE) @ApiOperation("审核拒绝") @PostMapping("/refuse") public AjaxResult<Object> refuse(@RequestBody ProcessRefuseBO processRefuseBO) { processTemplateService.refuse(processRefuseBO); return AjaxResult.success(); } } ruoyi-admin/src/main/resources/application-test.yml
@@ -220,3 +220,9 @@ bucketAddr: ap-chengdu rootSrc: https://xzgttest-1305134071.cos.ap-chengdu.myqcloud.com/ location: xizang sms: enable: true appId: 1400957506 secretid: AKIDCF5EF2c0DE1e5JK8r4EGJF4mNsMgp26x secretkey: lLl184rUyFOOE0d5KNGC3kmfNsCWk4GU sign: 四川金达通信工程 ruoyi-applet/pom.xml
@@ -95,13 +95,6 @@ <!-- </exclusions>--> </dependency> <!--二维码开发工具集--> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>4.6.10</version> </dependency> <!-- zxing生成二维码 --> <dependency> <groupId>com.google.zxing</groupId> ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
@@ -10,6 +10,7 @@ import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.utils.SmsUtil; import com.ruoyi.framework.web.service.TokenService; import com.ruoyi.system.service.ISysRoleService; import com.ruoyi.web.controller.tool.MsgUtils; @@ -54,6 +55,8 @@ private ISysRoleService roleService; @Autowired private MsgUtils msgUtils; @Autowired private SmsUtil smsUtil; /** * 账号密码登录 @@ -127,7 +130,7 @@ String code = String.valueOf((int) (Math.random() * 1000000)); redisCache.setCacheObject(phone, code,5*60,TimeUnit.SECONDS); try { msgUtils.sendMsg(phone, code); smsUtil.sendSms(phone, "", new String[]{code}); } catch (Exception e) { throw new RuntimeException(e); } ruoyi-common/pom.xml
@@ -194,6 +194,13 @@ <version>1.0.4</version> </dependency> <!-- hutool--> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.4</version> </dependency> </dependencies> </project> ruoyi-common/src/main/java/com/ruoyi/common/enums/StateProcessActionEnum.java
New file @@ -0,0 +1,26 @@ package com.ruoyi.common.enums; import lombok.AllArgsConstructor; import lombok.Getter; /** * 流程动作枚举 * */ @Getter @AllArgsConstructor public enum StateProcessActionEnum { START(0), // "发起" REJECTED(3), // "拒绝" APPROVED(4), // "通过" CANCELED(5), // "撤销" BACK(7), // "回退" COPY(12), // "抄送" FORWARD(13), // "转发" COMMENT(14), // "评论" TRANSACT(15); // "办理" private final int value; } ruoyi-common/src/main/java/com/ruoyi/common/exception/state/StateErrorCode.java
New file @@ -0,0 +1,19 @@ package com.ruoyi.common.exception.state; import lombok.AllArgsConstructor; import lombok.Getter; @Getter @AllArgsConstructor public enum StateErrorCode { PROCESS_TEMPLATE_KEY_EXISTS("已经存在此名称的模版了!"), PROCESS_TEMPLATE_NOT_EXISTS("流程模版不存在!"), PROCESS_NOT_DEPLOY("模版尚未部署成功"), PROCESS_VERSION_ERROR("流程引擎版本不一致"), ; private final String value; } ruoyi-system/src/main/java/com/ruoyi/system/bo/DeployBO.java
New file @@ -0,0 +1,15 @@ package com.ruoyi.system.bo; import com.aizuda.bpm.engine.model.NodeModel; import lombok.Data; @Data public class DeployBO { private String key; private String name; private String instanceUrl; /** * 流程定义 */ private NodeModel nodeConfig; } ruoyi-system/src/main/java/com/ruoyi/system/bo/ProcessAgreeBO.java
New file @@ -0,0 +1,26 @@ package com.ruoyi.system.bo; import lombok.Data; /** * 流程审批请求参数 同意 * * <p> * 尊重知识产权,不允许非法使用,后果自负 * </p> * */ @Data public class ProcessAgreeBO { /** * 任务id */ private String taskId; /** * 理由 */ private String remark; } ruoyi-system/src/main/java/com/ruoyi/system/bo/ProcessCreateBO.java
New file @@ -0,0 +1,21 @@ package com.ruoyi.system.bo; import lombok.Data; @Data public class ProcessCreateBO { /** * 模版名称 */ private String templateName; /** * json流程模版 */ private String process; private String remark; } ruoyi-system/src/main/java/com/ruoyi/system/bo/ProcessModuleUpdateBO.java
New file @@ -0,0 +1,19 @@ package com.ruoyi.system.bo; import lombok.Data; @Data public class ProcessModuleUpdateBO { /** * 模块id */ private String id; /** * 流程id */ private String templateId; private String remark; } ruoyi-system/src/main/java/com/ruoyi/system/bo/ProcessRefuseBO.java
New file @@ -0,0 +1,27 @@ package com.ruoyi.system.bo; import lombok.Data; /** * 流程审批请求参数 拒绝 * * <p> * 尊重知识产权,不允许非法使用,后果自负 * </p> * */ @Data public class ProcessRefuseBO { /** * 任务id */ private String taskId; /** * 理由 */ private String remark; } ruoyi-system/src/main/java/com/ruoyi/system/bo/ProcessStartBO.java
New file @@ -0,0 +1,57 @@ package com.ruoyi.system.bo; import lombok.Data; import java.util.Map; @Data public class ProcessStartBO { /** * 阶段类型 * 1入户调查 * 2价格评估 * 3协议签订 * 4资金管理-预算资金 * 5住宅临时安置补助费 * 6停产停业经济损失补助费 * 7安置情况 */ private String category; /** * 任务中心-项目名称 */ private String name; /** * 模块名称 */ private String moduleName; /** * 系统摘要 * 入户调查摘要:【镇/街】【征收实施单位】【调查户数】 * 价格评估摘要:【镇/街】【征收实施单位】【价格评估合计】 * 协议签订摘要:【镇/街】【征收实施单位】【权利人】【协议类型】 * 预算资金摘要:【镇/街】【征收实施单位】【预算金额】 * 住宅临时安置补助费摘要:【镇/街】【征收实施单位】【开始时间-截止时间】【申请金额】 * 停产停业经济损失补助费摘要:【镇/街】【征收实施单位】【开始时间-截止时间】【申请金额】 * 安置情况摘要:【镇/街】【征收实施单位】【批次名称】【安置类型】 */ private String remark; /** * 类型 1集体 2国有 */ private Integer type = 2; /** * 变量:流程完成后需要修改状态的表id信息 * 例如: * variable.put("objectId",12); */ private Map<String, Object> variable; } ruoyi-system/src/main/java/com/ruoyi/system/bo/ProcessTaskListBO.java
New file @@ -0,0 +1,27 @@ package com.ruoyi.system.bo; import com.ruoyi.common.core.domain.BasePage; import lombok.Getter; import lombok.Setter; @Setter @Getter public class ProcessTaskListBO extends BasePage { /** * 任务名称 */ private String name; /** * 任务名称 */ private String moduleName; // /** // * 流程实例状态( 0,审批中 1,审批通过 2,审批拒绝 3) // */ // private Integer instanceState; /** * 创建人 */ private String createBy; } ruoyi-system/src/main/java/com/ruoyi/system/bo/ProcessTemplatePageBO.java
New file @@ -0,0 +1,12 @@ package com.ruoyi.system.bo; import lombok.Data; @Data public class ProcessTemplatePageBO { private Integer currentPage; private Integer pageSize; private String name; } ruoyi-system/src/main/java/com/ruoyi/system/bo/ProcessUpdateBO.java
New file @@ -0,0 +1,22 @@ package com.ruoyi.system.bo; import lombok.Data; @Data public class ProcessUpdateBO { private String id; /** * 模版名称 */ private String templateName; /** * json流程模版 */ private String process; private String remark; } ruoyi-system/src/main/java/com/ruoyi/system/mapper/StateProcessExtInstanceMapper.java
New file @@ -0,0 +1,9 @@ package com.ruoyi.system.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.system.model.StateProcessExtInstance; import org.apache.ibatis.annotations.Mapper; @Mapper public interface StateProcessExtInstanceMapper extends BaseMapper<StateProcessExtInstance> { } ruoyi-system/src/main/java/com/ruoyi/system/mapper/StateProcessInstanceActionMapper.java
New file @@ -0,0 +1,7 @@ package com.ruoyi.system.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.system.model.StateProcessInstanceAction; public interface StateProcessInstanceActionMapper extends BaseMapper<StateProcessInstanceAction> { } ruoyi-system/src/main/java/com/ruoyi/system/mapper/StateProcessModuleMapper.java
New file @@ -0,0 +1,9 @@ package com.ruoyi.system.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.system.model.StateProcessModule; import org.apache.ibatis.annotations.Mapper; @Mapper public interface StateProcessModuleMapper extends BaseMapper<StateProcessModule> { } ruoyi-system/src/main/java/com/ruoyi/system/mapper/StateProcessTemplateMapper.java
New file @@ -0,0 +1,15 @@ package com.ruoyi.system.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.system.bo.ProcessTemplatePageBO; import com.ruoyi.system.model.StateProcessTemplate; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @Mapper public interface StateProcessTemplateMapper extends BaseMapper<StateProcessTemplate> { Page<StateProcessTemplate> page(Page<StateProcessTemplate> page, @Param("request") ProcessTemplatePageBO request); } ruoyi-system/src/main/java/com/ruoyi/system/mapper/StateTaskCenterMapper.java
New file @@ -0,0 +1,9 @@ package com.ruoyi.system.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.system.model.StateTaskCenter; import org.apache.ibatis.annotations.Mapper; @Mapper public interface StateTaskCenterMapper extends BaseMapper<StateTaskCenter> { } ruoyi-system/src/main/java/com/ruoyi/system/model/StateProcessExtInstance.java
New file @@ -0,0 +1,19 @@ package com.ruoyi.system.model; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.ruoyi.common.core.domain.BaseModel; import lombok.Data; @Data @TableName(value = "state_process_ext_instance") public class StateProcessExtInstance extends BaseModel { @TableId(type = IdType.NONE) private String id; private String templateId; private String processId; private Integer processVersion; } ruoyi-system/src/main/java/com/ruoyi/system/model/StateProcessInstanceAction.java
New file @@ -0,0 +1,24 @@ package com.ruoyi.system.model; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.ruoyi.common.core.domain.BaseModel; import lombok.Data; @Data @TableName(value = "state_process_instance_action") public class StateProcessInstanceAction extends BaseModel { @TableId(type = IdType.NONE) private String id; private String instanceId; private boolean robot; private String auditorId; private Integer actionType; private String userIds; private String assigneeId; private String nodeId; private String remark; } ruoyi-system/src/main/java/com/ruoyi/system/model/StateProcessModule.java
New file @@ -0,0 +1,25 @@ package com.ruoyi.system.model; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.ruoyi.common.core.domain.BaseModel; import lombok.Data; @Data @TableName(value = "state_process_module") public class StateProcessModule extends BaseModel { @TableId(value = "id", type = IdType.ASSIGN_ID) private String id; /** * 1=合同新增 * 2=合同签订 * 3=合同提前终止 */ private String category; private String name; private String templateName; private String templateId; private String remark; } ruoyi-system/src/main/java/com/ruoyi/system/model/StateProcessTemplate.java
New file @@ -0,0 +1,25 @@ package com.ruoyi.system.model; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.ruoyi.common.core.domain.BaseModel; import lombok.Data; @Data @TableName(value = "state_process_template") public class StateProcessTemplate extends BaseModel { @TableId(value = "id", type = IdType.ASSIGN_ID) private String id; private String templateKey; private Integer templateVersion; private String templateName; private String settings; private String process; private String remark; private Integer status; private Long workFlowId; private Integer workflowVersion; } ruoyi-system/src/main/java/com/ruoyi/system/model/StateTaskCenter.java
New file @@ -0,0 +1,22 @@ package com.ruoyi.system.model; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.ruoyi.common.core.domain.BaseModel; import lombok.Data; @Data @TableName(value = "state_task_center" ) public class StateTaskCenter extends BaseModel { @TableId(type = IdType.NONE) private String id; private String name; private String moduleName; private String remark; private String category; private String flowId; private String variable; } ruoyi-system/src/main/java/com/ruoyi/system/service/StateProcessExtInstanceService.java
New file @@ -0,0 +1,7 @@ package com.ruoyi.system.service; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.system.model.StateProcessExtInstance; public interface StateProcessExtInstanceService extends IService<StateProcessExtInstance> { } ruoyi-system/src/main/java/com/ruoyi/system/service/StateProcessInstanceActionService.java
New file @@ -0,0 +1,7 @@ package com.ruoyi.system.service; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.system.model.StateProcessInstanceAction; public interface StateProcessInstanceActionService extends IService<StateProcessInstanceAction> { } ruoyi-system/src/main/java/com/ruoyi/system/service/StateProcessModuleService.java
New file @@ -0,0 +1,8 @@ package com.ruoyi.system.service; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.system.model.StateProcessModule; public interface StateProcessModuleService extends IService<StateProcessModule> { } ruoyi-system/src/main/java/com/ruoyi/system/service/StateProcessTemplateService.java
New file @@ -0,0 +1,41 @@ package com.ruoyi.system.service; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.common.basic.PageInfo; import com.ruoyi.system.bo.*; import com.ruoyi.system.model.StateProcessTemplate; import com.ruoyi.system.vo.ProcessTaskListVO; public interface StateProcessTemplateService extends IService<StateProcessTemplate> { Page<StateProcessTemplate> page(ProcessTemplatePageBO request); Boolean update(ProcessUpdateBO processUpdateBO); //新增 Boolean create(ProcessCreateBO processCreateBO); /** * 启动流程 * @param processStartBO * @return */ Boolean start(ProcessStartBO processStartBO); //待办 PageInfo<ProcessTaskListVO> waitTaskPage(ProcessTaskListBO processTaskListBO); //已办 PageInfo<ProcessTaskListVO> dealTaskPage(ProcessTaskListBO processTaskListBO); //抄送 PageInfo<ProcessTaskListVO> copyTaskPage(ProcessTaskListBO processTaskListBO); //同意 void agree(ProcessAgreeBO processAgreeBO); //拒绝 void refuse(ProcessRefuseBO processRefuseBO); } ruoyi-system/src/main/java/com/ruoyi/system/service/StateTaskCenterService.java
New file @@ -0,0 +1,7 @@ package com.ruoyi.system.service; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.system.model.StateTaskCenter; public interface StateTaskCenterService extends IService<StateTaskCenter> { } ruoyi-system/src/main/java/com/ruoyi/system/service/impl/StateProcessExtInstanceServiceImpl.java
New file @@ -0,0 +1,11 @@ package com.ruoyi.system.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.system.mapper.StateProcessExtInstanceMapper; import com.ruoyi.system.model.StateProcessExtInstance; import com.ruoyi.system.service.StateProcessExtInstanceService; import org.springframework.stereotype.Service; @Service public class StateProcessExtInstanceServiceImpl extends ServiceImpl<StateProcessExtInstanceMapper, StateProcessExtInstance> implements StateProcessExtInstanceService { } ruoyi-system/src/main/java/com/ruoyi/system/service/impl/StateProcessInstanceActionServiceImpl.java
New file @@ -0,0 +1,11 @@ package com.ruoyi.system.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.system.mapper.StateProcessInstanceActionMapper; import com.ruoyi.system.model.StateProcessInstanceAction; import com.ruoyi.system.service.StateProcessInstanceActionService; import org.springframework.stereotype.Service; @Service public class StateProcessInstanceActionServiceImpl extends ServiceImpl<StateProcessInstanceActionMapper, StateProcessInstanceAction> implements StateProcessInstanceActionService { } ruoyi-system/src/main/java/com/ruoyi/system/service/impl/StateProcessModuleServiceImpl.java
New file @@ -0,0 +1,11 @@ package com.ruoyi.system.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.system.mapper.StateProcessModuleMapper; import com.ruoyi.system.model.StateProcessModule; import com.ruoyi.system.service.StateProcessModuleService; import org.springframework.stereotype.Service; @Service public class StateProcessModuleServiceImpl extends ServiceImpl<StateProcessModuleMapper, StateProcessModule> implements StateProcessModuleService { } ruoyi-system/src/main/java/com/ruoyi/system/service/impl/StateProcessTemplateServiceImpl.java
New file @@ -0,0 +1,630 @@ package com.ruoyi.system.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.json.JSONUtil; import com.aizuda.bpm.engine.FlowLongEngine; import com.aizuda.bpm.engine.core.FlowCreator; import com.aizuda.bpm.engine.core.enums.TaskType; import com.aizuda.bpm.engine.entity.*; import com.aizuda.bpm.engine.model.NodeModel; import com.aizuda.bpm.mybatisplus.mapper.*; import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONWriter; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.common.basic.PageInfo; import com.ruoyi.common.core.domain.BaseModel; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.enums.StateProcessActionEnum; import com.ruoyi.common.exception.GlobalException; import com.ruoyi.common.exception.state.StateErrorCode; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.uuid.IdUtils; import com.ruoyi.system.bo.*; import com.ruoyi.system.mapper.StateProcessTemplateMapper; import com.ruoyi.system.model.*; import com.ruoyi.system.service.*; import com.ruoyi.system.vo.ProcessTaskListVO; import lombok.AllArgsConstructor; import org.apache.commons.io.IOUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @Service @AllArgsConstructor public class StateProcessTemplateServiceImpl extends ServiceImpl<StateProcessTemplateMapper, StateProcessTemplate> implements StateProcessTemplateService { private final FlowLongEngine flowLongEngine; private final StateProcessInstanceActionService stateProcessInstanceActionService; private final StateProcessExtInstanceService stateProcessExtInstanceService; private final FlwHisInstanceMapper flwHisInstanceMapper; private final FlwTaskActorMapper flwTaskActorMapper; private final FlwTaskMapper flwTaskMapper; private final StateTaskCenterService stateTaskCenterService; private final StateProcessModuleService stateProcessModuleService; private final FlwHisTaskMapper flwHisTaskMapper; private final FlwHisTaskActorMapper flwHisTaskActorMapper; private final ISysUserService sysUserService; /** * 流程模版分页 * @param request * @return */ @Override public Page<StateProcessTemplate> page(ProcessTemplatePageBO request) { //查询流程模板列表 Page<StateProcessTemplate> templatePage = this.baseMapper.page(new Page<>(request.getCurrentPage(), request.getPageSize()), request); //更新人id列表 List<String> updateUserNameList = templatePage.getRecords().stream().map(BaseModel::getUpdateBy).collect(Collectors.toList()); if (!CollectionUtils.isEmpty(updateUserNameList)) { //根据用户id列表查询用户信息 List<SysUser> sysUsers = sysUserService.selectUserByUserNameList(updateUserNameList); Map<String, SysUser> sysUserMap; if (!CollectionUtils.isEmpty(sysUsers)) { sysUserMap = sysUsers.stream().collect(Collectors.toMap(SysUser::getUserName, Function.identity())); } else { sysUserMap = new HashMap<>(); } //遍历列表,设置更新人名称 templatePage.getRecords().forEach(e -> { SysUser sysUser = sysUserMap.get(e.getUpdateBy()); if (Objects.nonNull(sysUser)) { e.setUpdateBy(sysUser.getNickName()); } }); } return templatePage; } /** * 修改并部署模版 * @param processUpdateBO * @return */ @Transactional(rollbackFor = Exception.class) @Override public Boolean update(ProcessUpdateBO processUpdateBO) { //查询流程模板 StateProcessTemplate temp = this.getById(processUpdateBO.getId()); //根据template_key查询最新版本的模板 StateProcessTemplate template = this.getOne(Wrappers.<StateProcessTemplate>lambdaQuery() .eq(StateProcessTemplate::getTemplateKey, temp.getTemplateKey()) .apply("(template_key, template_version) in(" + "SELECT template_key, MAX(template_version) " + "FROM state_process_template " + "GROUP BY template_key)")); if (Objects.isNull(template)) { throw new GlobalException(StateErrorCode.PROCESS_TEMPLATE_NOT_EXISTS.getValue()); } // 部署流程 LoginUser loginUser = SecurityUtils.getLoginUser(); FlowCreator creator = FlowCreator.of(String.valueOf(loginUser.getUserId()), loginUser.getUser().getNickName()); DeployBO deployBO = new DeployBO(); deployBO.setKey(template.getTemplateKey()); deployBO.setName(processUpdateBO.getTemplateName()); deployBO.setNodeConfig(JSONObject.parseObject(processUpdateBO.getProcess(), NodeModel.class)); String deployResult = JSONObject.toJSONString(deployBO, JSONWriter.Feature.WriteMapNullValue); InputStream inputStream = IOUtils.toInputStream(deployResult, StandardCharsets.UTF_8.name()); Long deployId = flowLongEngine.processService().deploy(inputStream, creator, true, null); FlwProcess flwProcess = flowLongEngine.processService().getProcessById(deployId); // 更新模板, version+1 StateProcessTemplate processTemplate = new StateProcessTemplate(); processTemplate.setId(IdUtils.simpleUUID()); processTemplate.setWorkFlowId(deployId); processTemplate.setWorkflowVersion(flwProcess.getProcessVersion()); processTemplate.setTemplateName(processUpdateBO.getTemplateName()); processTemplate.setTemplateKey(template.getTemplateKey()); processTemplate.setProcess(processUpdateBO.getProcess()); processTemplate.setRemark(processUpdateBO.getRemark()); processTemplate.setUpdateBy(SecurityUtils.getLoginUser().getUsername()); processTemplate.setUpdateTime(LocalDateTime.now()); processTemplate.setTemplateVersion(temp.getTemplateVersion() + 1); this.save(processTemplate); //查询版本是否绑定流程,更新 LambdaQueryWrapper<StateProcessModule> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(StateProcessModule::getTemplateId, processUpdateBO.getId()); List<StateProcessModule> stateProcessModules = stateProcessModuleService.list(queryWrapper); if (Objects.isNull(stateProcessModules) || stateProcessModules.isEmpty()) { return true; } for (StateProcessModule stateProcessModule : stateProcessModules) { stateProcessModule.setTemplateId(processTemplate.getId()); stateProcessModule.setTemplateName(processTemplate.getTemplateName()); } return stateProcessModuleService.updateBatchById(stateProcessModules); } /** * 创建并部署模版 * @param processCreateBO * @return */ @Transactional(rollbackFor = Exception.class) @Override public Boolean create(ProcessCreateBO processCreateBO) { //查询模版是否存在 List<StateProcessTemplate> keys = this.list(Wrappers.<StateProcessTemplate>lambdaQuery(). eq(StateProcessTemplate::getTemplateName, processCreateBO.getTemplateName())); if (!CollectionUtils.isEmpty(keys)) { throw new GlobalException(StateErrorCode.PROCESS_TEMPLATE_KEY_EXISTS.getValue()); } LoginUser loginUser = SecurityUtils.getLoginUser(); FlowCreator creator = FlowCreator.of(String.valueOf(loginUser.getUserId()), loginUser.getUser().getNickName()); DeployBO deployBO = new DeployBO(); deployBO.setKey(IdUtil.simpleUUID()); deployBO.setName(processCreateBO.getTemplateName()); deployBO.setNodeConfig(JSONObject.parseObject(processCreateBO.getProcess(), NodeModel.class)); String deployResult = JSONObject.toJSONString(deployBO, JSONWriter.Feature.WriteMapNullValue); InputStream inputStream = IOUtils.toInputStream(deployResult, StandardCharsets.UTF_8.name()); Long deployId = flowLongEngine.processService().deploy(inputStream, creator, false); FlwProcess flwProcess = flowLongEngine.processService().getProcessById(deployId); StateProcessTemplate processTemplate = new StateProcessTemplate(); processTemplate.setId(IdUtils.simpleUUID()); processTemplate.setWorkFlowId(deployId); processTemplate.setWorkflowVersion(flwProcess.getProcessVersion()); processTemplate.setTemplateName(deployBO.getName()); processTemplate.setTemplateKey(deployBO.getKey()); processTemplate.setProcess(processCreateBO.getProcess()); processTemplate.setRemark(processCreateBO.getRemark()); processTemplate.setUpdateBy(loginUser.getUser().getUserName()); processTemplate.setUpdateTime(LocalDateTime.now()); return this.save(processTemplate); } /** * 启动流程 * @param processStartBO * @return */ @Transactional(rollbackFor = Exception.class) @Override public Boolean start(ProcessStartBO processStartBO) { LoginUser loginUser = SecurityUtils.getLoginUser(); FlowCreator creator = FlowCreator.of(String.valueOf(loginUser.getUserId()), loginUser.getUser().getNickName()); //查询流程绑定 StateProcessModule stateProcessModule = stateProcessModuleService.getOne(Wrappers.<StateProcessModule>lambdaQuery() .eq(StateProcessModule::getCategory, processStartBO.getCategory())); if (ObjectUtil.isNull(stateProcessModule) || ObjectUtil.isEmpty(stateProcessModule.getTemplateId())) { throw new GlobalException("请先配置流程引擎模版!"); } //查询模版,准备启动 StateProcessTemplate template = this.getById(stateProcessModule.getTemplateId()); StateProcessTemplate lastTemplate = this.getOne(Wrappers.<StateProcessTemplate>lambdaQuery() .eq(StateProcessTemplate::getTemplateKey, template.getTemplateKey()) .apply("(template_key, template_version) in(" + "SELECT template_key, MAX(template_version) " + "FROM state_process_template " + "GROUP BY template_key)") ); if (ObjectUtil.isNull(lastTemplate)) { throw new GlobalException(StateErrorCode.PROCESS_TEMPLATE_NOT_EXISTS.getValue()); } FlwProcess flwProcess = flowLongEngine.processService().getProcessById(lastTemplate.getWorkFlowId()); if (ObjectUtil.isNull(flwProcess)) { throw new GlobalException(StateErrorCode.PROCESS_NOT_DEPLOY.getValue()); } if (!Objects.equals(lastTemplate.getWorkflowVersion(), flwProcess.getProcessVersion())) { throw new GlobalException(StateErrorCode.PROCESS_VERSION_ERROR.getValue()); } //监听器参数补全 processStartBO.getVariable().put("category", processStartBO.getCategory()); // 开启流程 flowLongEngine.startInstanceById(flwProcess.getId(), creator, processStartBO.getVariable()).ifPresent(instance -> { //存储任务中心信息 StateTaskCenter stateTaskCenter = new StateTaskCenter(); stateTaskCenter.setId(IdUtils.simpleUUID()); stateTaskCenter.setName(processStartBO.getName()); stateTaskCenter.setModuleName(processStartBO.getModuleName()); stateTaskCenter.setCategory(processStartBO.getCategory()); stateTaskCenter.setFlowId(instance.getId().toString()); stateTaskCenter.setRemark(processStartBO.getRemark()); stateTaskCenter.setCreateBy(loginUser.getUser().getNickName()); stateTaskCenter.setVariable(JSONUtil.toJsonStr(processStartBO.getVariable())); stateTaskCenterService.save(stateTaskCenter); // action记录 StateProcessInstanceAction stateProcessInstanceAction = new StateProcessInstanceAction(); stateProcessInstanceAction.setId(IdUtils.simpleUUID()); stateProcessInstanceAction.setInstanceId(instance.getId().toString()); stateProcessInstanceAction.setActionType(StateProcessActionEnum.START.getValue()); stateProcessInstanceAction.setAuditorId(creator.getCreateId()); stateProcessInstanceActionService.save(stateProcessInstanceAction); // 添加拓展信息 StateProcessExtInstance stateProcessExtInstance = new StateProcessExtInstance(); stateProcessExtInstance.setId(instance.getId().toString()); stateProcessExtInstance.setTemplateId(lastTemplate.getId()); stateProcessExtInstance.setProcessId(flwProcess.getId().toString()); //保存version stateProcessExtInstance.setProcessVersion(flwProcess.getProcessVersion()); stateProcessExtInstanceService.save(stateProcessExtInstance); }); return true; } /** * 待办 * @param processTaskListBO * @return */ @Override public PageInfo<ProcessTaskListVO> waitTaskPage(ProcessTaskListBO processTaskListBO) { //获取当前登录用户信息 Long userId = SecurityUtils.getLoginUser().getUserId(); //或签时查询其他审批人是否通过(不能省略),比如 同一任务需要A,B审核,A通过了,B不用在审核了,在历史表查询A的审核记录 LambdaQueryWrapper<FlwHisInstance> lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.orderByDesc(FlowEntity::getCreateTime); //待审核 lambdaQueryWrapper.eq(FlwHisInstance::getInstanceState, 0); List<Long> flwHisInstances = flwHisInstanceMapper.selectList(lambdaQueryWrapper).stream() .map(FlwHisInstance::getId).collect(Collectors.toList()); if (ObjectUtil.isEmpty(flwHisInstances)) { return new PageInfo<>(); } //查询任务参与者 LambdaQueryWrapper<FlwTaskActor> query = new LambdaQueryWrapper<>(); query.and(qy -> qy.eq(FlwTaskActor::getActorId, userId) //0指定用户 .eq(FlwTaskActor::getActorType, 0) .or().in(FlwTaskActor::getActorId, userId) //1指定角色 .eq(FlwTaskActor::getActorType, 1)); if (ObjectUtil.isNotNull(processTaskListBO) && ObjectUtil.isNotNull(flwHisInstances)) { // 添加条件 query = query.in(FlwTaskActor::getInstanceId, flwHisInstances); } List<FlwTaskActor> flwTaskActorPage = flwTaskActorMapper.selectList(query); if (ObjectUtil.isEmpty(flwTaskActorPage)) { return new PageInfo<>(); } //查询任务信息 List<FlwTask> flwTasks = flwTaskMapper.selectList(Wrappers.<FlwTask>lambdaQuery() .orderByDesc(FlwTask::getCreateTime) .in(FlwTask::getId, flwTaskActorPage.stream() .map(FlwTaskActor::getTaskId).collect(Collectors.toList()))); if (ObjectUtil.isNull(flwTasks)) { return new PageInfo<>(); } List<String> instanceIds = flwTasks.stream().map(FlwTask::getInstanceId) .map(String::valueOf).collect(Collectors.toList()); //分页查询任务中心任务 LambdaQueryWrapper<StateTaskCenter> stateTaskQuery = new LambdaQueryWrapper<>(); if (ObjectUtil.isNotEmpty(processTaskListBO.getName())) { stateTaskQuery.like(StateTaskCenter::getName, processTaskListBO.getName()); } if (ObjectUtil.isNotEmpty(processTaskListBO.getModuleName())) { stateTaskQuery.like(StateTaskCenter::getModuleName, processTaskListBO.getModuleName()); } if (ObjectUtil.isNotEmpty(processTaskListBO.getCreateBy())) { stateTaskQuery.like(StateTaskCenter::getCreateBy, processTaskListBO.getCreateBy()); } stateTaskQuery.in(StateTaskCenter::getFlowId, instanceIds); stateTaskQuery.orderByDesc(BaseModel::getCreateTime); PageInfo pageInfo = new PageInfo(processTaskListBO.getPageNum(), processTaskListBO.getPageSize()); PageInfo<StateTaskCenter> taskCenters = stateTaskCenterService.page(pageInfo,stateTaskQuery); //转换类 List<ProcessTaskListVO> processTaskListVOS = BeanUtil.copyToList(taskCenters.getRecords(), ProcessTaskListVO.class); pageInfo.setRecords(processTaskListVOS); List<String> updateUserId = processTaskListVOS.stream().map(ProcessTaskListVO::getCreateBy).collect(Collectors.toList()); Map<Long, SysUser> sysUserMap; if (!CollectionUtils.isEmpty(updateUserId)) { //根据用户id查询更新人信息 List<SysUser> sysUsers = sysUserService.selectUserByUserNameList(updateUserId); if (!CollectionUtils.isEmpty(sysUsers)) { sysUserMap = sysUsers.stream().collect(Collectors.toMap(SysUser::getUserId, Function.identity())); } else { sysUserMap = new HashMap<>(); } } else { sysUserMap = new HashMap<>(); } Map<Long, List<FlwTask>> flwHisTaskMap = flwTasks.stream().collect(Collectors.groupingBy(FlwTask::getInstanceId)); for (ProcessTaskListVO processTaskListVO : processTaskListVOS) { List<FlwTask> flwTask = flwHisTaskMap.get(NumberUtil.parseLong(processTaskListVO.getFlowId())); if (!CollectionUtils.isEmpty(flwTask) && ObjectUtil.isNotEmpty(flwTask.get(0))) { //待审核 processTaskListVO.setStatus("0"); processTaskListVO.setNodeName(flwTask.get(0).getTaskName()); processTaskListVO.setTaskId(flwTask.get(0).getId().toString()); processTaskListVO.setVariable(flwTask.get(0).getVariable()); } SysUser sysUser = sysUserMap.get(processTaskListVO.getCreateBy()); if (Objects.nonNull(sysUser)) { processTaskListVO.setCreateBy(sysUser.getNickName()); } } return pageInfo; } @Override public PageInfo<ProcessTaskListVO> dealTaskPage(ProcessTaskListBO processTaskListBO) { //获取当前登录用户信息 Long userId = SecurityUtils.getLoginUser().getUserId(); LambdaQueryWrapper<FlwHisTaskActor> query = Wrappers.<FlwHisTaskActor>lambdaQuery() .and(qy -> qy.eq(FlwTaskActor::getActorId, userId) //0指定用户 .eq(FlwTaskActor::getActorType, 0) //指定角色 .or().in(FlwTaskActor::getActorId, userId) .eq(FlwTaskActor::getActorType, 1)); List<FlwHisTaskActor> flwHisTaskActors = flwHisTaskActorMapper.selectList(query); List<Long> hisTaskIds = flwHisTaskActors.stream().map(FlwTaskActor::getTaskId).collect(Collectors.toList()); if (hisTaskIds.isEmpty()) { return new PageInfo<>(); } List<FlwHisTask> flwHisTaskList = flwHisTaskMapper.selectList( Wrappers.<FlwHisTask>lambdaQuery() .notIn(FlwHisTask::getTaskType, TaskType.cc.getValue(), TaskType.major.getValue()) .orderByDesc(FlwHisTask::getCreateTime) .in(FlwHisTask::getId, hisTaskIds)); if (ObjectUtil.isEmpty(flwHisTaskList)) { new PageInfo<>(); } List<String> instanceId = flwHisTaskList.stream().map(FlwTask::getInstanceId) .map(String::valueOf).collect(Collectors.toList()); //分页查询任务中心任务 LambdaQueryWrapper<StateTaskCenter> stateTaskQuery = new LambdaQueryWrapper<>(); if (ObjectUtil.isNotEmpty(processTaskListBO.getName())) { stateTaskQuery.like(StateTaskCenter::getName, processTaskListBO.getName()); } if (ObjectUtil.isNotEmpty(processTaskListBO.getModuleName())) { stateTaskQuery.like(StateTaskCenter::getModuleName, processTaskListBO.getModuleName()); } if (ObjectUtil.isNotEmpty(processTaskListBO.getCreateBy())) { stateTaskQuery.like(StateTaskCenter::getCreateBy, processTaskListBO.getCreateBy()); } if (ObjectUtil.isEmpty(instanceId)) { return new PageInfo<>(); } stateTaskQuery.in(StateTaskCenter::getFlowId, instanceId); stateTaskQuery.orderByDesc(BaseModel::getCreateTime); PageInfo pageInfo = new PageInfo<>(processTaskListBO.getPageNum(), processTaskListBO.getPageSize()); PageInfo<StateTaskCenter> taskCenters = stateTaskCenterService.page(pageInfo,stateTaskQuery); //转换类 List<ProcessTaskListVO> processTaskListVOS = BeanUtil.copyToList(taskCenters.getRecords(), ProcessTaskListVO.class); pageInfo.setRecords(processTaskListVOS); if (ObjectUtil.isEmpty(processTaskListVOS)) { return pageInfo; } Map<Long, List<FlwHisTask>> flwHisTaskMap = flwHisTaskList.stream().collect(Collectors.groupingBy(FlwHisTask::getInstanceId)); //查询原因 List<String> taskIds = flwHisTaskList.stream().map(FlowEntity::getId).map(String::valueOf).collect(Collectors.toList()); List<StateProcessInstanceAction> actions = stateProcessInstanceActionService.list( Wrappers.<StateProcessInstanceAction>lambdaQuery().in(StateProcessInstanceAction::getNodeId, taskIds)); Map<String, StateProcessInstanceAction> actionMap = actions.stream().collect(Collectors.toMap(StateProcessInstanceAction::getNodeId, Function.identity())); List<String> updateUserId = processTaskListVOS.stream().map(ProcessTaskListVO::getCreateBy).collect(Collectors.toList()); Map<Long, SysUser> sysUserMap; if (!CollectionUtils.isEmpty(updateUserId)) { List<SysUser> sysUsers = sysUserService.selectUserByUserNameList(updateUserId); if (!CollectionUtils.isEmpty(sysUsers)) { sysUserMap = sysUsers.stream().collect(Collectors.toMap(SysUser::getUserId, Function.identity())); } else { sysUserMap = new HashMap<>(); } } else { sysUserMap = new HashMap<>(); } for (ProcessTaskListVO processTaskListVO : processTaskListVOS) { List<FlwHisTask> flwHisTasks = flwHisTaskMap.get(NumberUtil.parseLong(processTaskListVO.getFlowId())); if (ObjectUtil.isNotEmpty(flwHisTaskMap)) { //当某个用户在同一个模块审批流的多个节点都存在时,多次审核后,已审核列表页报错 for (FlwHisTask flwHisTask : flwHisTasks) { if (flwHisTask.getInstanceId().toString().equals(processTaskListVO.getFlowId())) { //10等于发起人与审批人一致自动审核完成 processTaskListVO.setStatus(flwHisTask.getTaskState() == 10 ? "2" : flwHisTask.getTaskState().toString()); processTaskListVO.setNodeName(flwHisTask.getTaskName()); processTaskListVO.setTaskId(flwHisTask.getId().toString()); processTaskListVO.setVariable(flwHisTask.getVariable()); } } } StateProcessInstanceAction action = actionMap.get(processTaskListVO.getTaskId()); if (ObjectUtil.isNotEmpty(action)) { processTaskListVO.setReason(action.getRemark()); } SysUser sysUser = sysUserMap.get(processTaskListVO.getCreateBy()); if (Objects.nonNull(sysUser)) { processTaskListVO.setCreateBy(sysUser.getNickName()); } } return pageInfo; } @Override public PageInfo<ProcessTaskListVO> copyTaskPage(ProcessTaskListBO processTaskListBO) { Long userId = SecurityUtils.getUserId(); QueryWrapper<FlwHisInstance> queryWrapper = new QueryWrapper<>(); queryWrapper.orderByDesc("create_time"); List<Long> flwHisInstances = flwHisInstanceMapper.selectList(queryWrapper).stream() .map(FlwHisInstance::getId).collect(Collectors.toList()); LambdaQueryWrapper<FlwHisTaskActor> query = Wrappers.<FlwHisTaskActor>lambdaQuery() .and(qy -> qy.eq(FlwTaskActor::getActorId, userId) .eq(FlwTaskActor::getActorType, 0) .or().in(FlwTaskActor::getActorId, userId) .eq(FlwTaskActor::getActorType, 1)); query = query.in(FlwHisTaskActor::getInstanceId, flwHisInstances); List<FlwHisTaskActor> flwHisTaskActors = flwHisTaskActorMapper.selectList(query); List<Long> hisTaskIds = flwHisTaskActors.stream().map(FlwTaskActor::getTaskId).collect(Collectors.toList()); if (hisTaskIds.isEmpty()) { return new PageInfo<>(); } List<FlwHisTask> flwHisTaskList = flwHisTaskMapper.selectList( Wrappers.<FlwHisTask>lambdaQuery() //2=抄送 .eq(FlwHisTask::getTaskType, 2) .in(FlwHisTask::getId, hisTaskIds)); if(ObjectUtil.isEmpty(flwHisTaskList)){ return new PageInfo<>(); } List<String> instanceId = flwHisTaskList.stream().map(FlwTask::getInstanceId) .map(String::valueOf).collect(Collectors.toList()); //分页查询任务中心任务 LambdaQueryWrapper<StateTaskCenter> stateTaskQuery = new LambdaQueryWrapper<>(); if (ObjectUtil.isNotEmpty(processTaskListBO.getName())) { stateTaskQuery.like(StateTaskCenter::getName, processTaskListBO.getName()); } if (ObjectUtil.isNotEmpty(processTaskListBO.getModuleName())) { stateTaskQuery.like(StateTaskCenter::getModuleName, processTaskListBO.getModuleName()); } if (ObjectUtil.isNotEmpty(processTaskListBO.getCreateBy())) { stateTaskQuery.like(StateTaskCenter::getCreateBy, processTaskListBO.getCreateBy()); } if (ObjectUtil.isEmpty(instanceId)) { return new PageInfo<>(); } stateTaskQuery.in(StateTaskCenter::getFlowId, instanceId); stateTaskQuery.orderByDesc(BaseModel::getCreateTime); PageInfo pageInfo = new PageInfo<>(processTaskListBO.getPageNum(), processTaskListBO.getPageSize()); PageInfo taskCenters = stateTaskCenterService.page(pageInfo,stateTaskQuery); //转换类 List<ProcessTaskListVO> processTaskListVOS = BeanUtil.copyToList(taskCenters.getRecords(), ProcessTaskListVO.class); pageInfo.setRecords(processTaskListVOS); if (ObjectUtil.isEmpty(processTaskListVOS)) { return pageInfo; } Map<Long, List<FlwHisTask>> flwHisTaskMap = flwHisTaskList.stream().collect(Collectors.groupingBy(FlwHisTask::getInstanceId)); List<String> updateUserId = processTaskListVOS.stream().map(ProcessTaskListVO::getCreateBy).collect(Collectors.toList()); Map<Long, SysUser> sysUserMap; if (!CollectionUtils.isEmpty(updateUserId)) { List<SysUser> sysUsers = sysUserService.selectUserByUserNameList(updateUserId); if (!CollectionUtils.isEmpty(sysUsers)) { sysUserMap = sysUsers.stream().collect(Collectors.toMap(SysUser::getUserId, Function.identity())); } else { sysUserMap = new HashMap<>(); } } else { sysUserMap = new HashMap<>(); } //查询原因 List<String> taskIds = flwHisTaskList.stream().map(FlwTask::getParentTaskId).filter(ObjectUtil::isNotEmpty).map(String::valueOf).collect(Collectors.toList()); List<StateProcessInstanceAction> actions = stateProcessInstanceActionService.list( Wrappers.<StateProcessInstanceAction>lambdaQuery().in(StateProcessInstanceAction::getNodeId, taskIds)); Map<String, StateProcessInstanceAction> actionMap = actions.stream().collect(Collectors.toMap(StateProcessInstanceAction::getNodeId, Function.identity())); for (ProcessTaskListVO processTaskListVO : processTaskListVOS) { List<FlwHisTask> flwHisTasks = flwHisTaskMap.get(NumberUtil.parseLong(processTaskListVO.getFlowId())); if (ObjectUtil.isNotEmpty(flwHisTaskMap)) { //当某个用户在同一个模块审批流的多个节点都存在时,多次审核后,已审核列表页报错 for (FlwHisTask flwHisTask : flwHisTasks) { if (flwHisTask.getInstanceId().toString().equals(processTaskListVO.getFlowId())) { processTaskListVO.setStatus(flwHisTask.getTaskState().toString()); processTaskListVO.setNodeName(flwHisTask.getTaskName()); processTaskListVO.setParentTaskId(flwHisTask.getParentTaskId().toString()); processTaskListVO.setTaskId(flwHisTask.getId().toString()); processTaskListVO.setVariable(flwHisTask.getVariable()); } } } StateProcessInstanceAction action = actionMap.get(processTaskListVO.getParentTaskId()); if (ObjectUtil.isNotEmpty(action)) { processTaskListVO.setReason(action.getRemark()); } SysUser sysUser = sysUserMap.get(processTaskListVO.getCreateBy()); if (Objects.nonNull(sysUser)) { processTaskListVO.setCreateBy(sysUser.getNickName()); } } return pageInfo; } @Override public void agree(ProcessAgreeBO processAgreeBO) { Long taskId = Long.valueOf(processAgreeBO.getTaskId()); FlwTask flwTask = flwTaskMapper.selectById(taskId); if (ObjectUtil.isNull(flwTask)) { throw new GlobalException("任务已处理或者不存在"); } flowLongEngine.executeTask(taskId, currentFlowCreator()); // 动作执行记录 StateProcessInstanceAction stateProcessInstanceAction = new StateProcessInstanceAction(); stateProcessInstanceAction.setId(IdUtils.simpleUUID()); stateProcessInstanceAction.setInstanceId(flwTask.getInstanceId().toString()); stateProcessInstanceAction.setAuditorId(String.valueOf(SecurityUtils.getUserId())); stateProcessInstanceAction.setActionType(StateProcessActionEnum.APPROVED.getValue()); stateProcessInstanceAction.setNodeId(processAgreeBO.getTaskId()); stateProcessInstanceAction.setRemark(processAgreeBO.getRemark()); stateProcessInstanceActionService.save(stateProcessInstanceAction); } @Override public void refuse(ProcessRefuseBO processRefuseBO) { Long taskId = Long.valueOf(processRefuseBO.getTaskId()); FlwTask flwTask = flwTaskMapper.selectById(taskId); // 直接拒绝当前流程 flowLongEngine.runtimeService().reject(flwTask.getInstanceId(), currentFlowCreator()); // 动作执行记录 StateProcessInstanceAction record = new StateProcessInstanceAction(); record.setId(IdUtils.simpleUUID()); record.setInstanceId(flwTask.getInstanceId().toString()); record.setAuditorId(String.valueOf(SecurityUtils.getUserId())); record.setActionType(StateProcessActionEnum.REJECTED.getValue()); record.setNodeId(processRefuseBO.getTaskId()); record.setRemark(processRefuseBO.getRemark()); stateProcessInstanceActionService.save(record); } private FlowCreator currentFlowCreator() { LoginUser loginUser = SecurityUtils.getLoginUser(); if (null == loginUser || null == loginUser.getUser().getUserId()) { throw new GlobalException("非法用户"); } return FlowCreator.of(String.valueOf(loginUser.getUserId()), loginUser.getUser().getNickName()); } } ruoyi-system/src/main/java/com/ruoyi/system/service/impl/StateTaskCenterServiceImpl.java
New file @@ -0,0 +1,11 @@ package com.ruoyi.system.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.system.mapper.StateTaskCenterMapper; import com.ruoyi.system.model.StateTaskCenter; import com.ruoyi.system.service.StateTaskCenterService; import org.springframework.stereotype.Service; @Service public class StateTaskCenterServiceImpl extends ServiceImpl<StateTaskCenterMapper, StateTaskCenter> implements StateTaskCenterService { } ruoyi-system/src/main/java/com/ruoyi/system/vo/ProcessTaskListVO.java
New file @@ -0,0 +1,42 @@ package com.ruoyi.system.vo; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; import lombok.Getter; import lombok.Setter; import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; @Data public class ProcessTaskListVO { private String nodeName; private String flowId; private String name; private String moduleName; private String createBy; private String remark; @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date createTime; private String status; private String taskId; private String parentTaskId; private String category; private String variable; private String reason; } ruoyi-system/src/main/java/com/ruoyi/system/vo/TCheckAcceptRecordVO.java
@@ -17,4 +17,11 @@ @ApiModelProperty(value = "房屋信息") private THouse house; @ApiModelProperty(value = "房屋名称") private String houseName; @ApiModelProperty(value = "合同编号") private String contractNumber; @ApiModelProperty(value = "房屋地址") private String houseAddress; } ruoyi-system/src/main/resources/mapper/system/StateProcessTemplateMapper.xml
New file @@ -0,0 +1,15 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ruoyi.system.mapper.StateProcessTemplateMapper"> <select id="page" resultType="com.ruoyi.system.model.StateProcessTemplate"> SELECT * FROM state_process_template WHERE (template_key, template_version) in (select template_key, MAX(template_version)from state_process_template group by template_key) <if test="request.name != null and request.name != ''"> AND template_name::text LIKE CONCAT('%',#{request.name}, '%' ) </if> and disabled = ${@com.ruoyi.common.enums.DisabledEnum@NO.getCode()} </select> </mapper> ruoyi-system/src/main/resources/mapper/system/TCheckAcceptRecordMapper.xml
@@ -53,8 +53,12 @@ t.create_by, t.update_by, t.disabled, t.code, t.checkMoney, t.status, c.contract_number, h.house_name h.house_name, h.house_address from t_check_accept_record t left join t_contract c on t.contract_id = c.id left join t_house h on t.house_id = h.id