xuhy
2025-02-20 75f60178b38bbc50f7aec9270fcd9d4c86b9cc43
审批流
7个文件已修改
34个文件已添加
1472 ■■■■■ 已修改文件
ruoyi-admin/pom.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/StateProcessController.java 191 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application-test.yml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/pom.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/pom.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/enums/StateProcessActionEnum.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/exception/state/StateErrorCode.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/bo/DeployBO.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/bo/ProcessAgreeBO.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/bo/ProcessCreateBO.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/bo/ProcessModuleUpdateBO.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/bo/ProcessRefuseBO.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/bo/ProcessStartBO.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/bo/ProcessTaskListBO.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/bo/ProcessTemplatePageBO.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/bo/ProcessUpdateBO.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/StateProcessExtInstanceMapper.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/StateProcessInstanceActionMapper.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/StateProcessModuleMapper.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/StateProcessTemplateMapper.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/StateTaskCenterMapper.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/StateProcessExtInstance.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/StateProcessInstanceAction.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/StateProcessModule.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/StateProcessTemplate.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/StateTaskCenter.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/StateProcessExtInstanceService.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/StateProcessInstanceActionService.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/StateProcessModuleService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/StateProcessTemplateService.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/StateTaskCenterService.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/StateProcessExtInstanceServiceImpl.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/StateProcessInstanceActionServiceImpl.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/StateProcessModuleServiceImpl.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/StateProcessTemplateServiceImpl.java 630 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/StateTaskCenterServiceImpl.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/ProcessTaskListVO.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/TCheckAcceptRecordVO.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/StateProcessTemplateMapper.xml 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TCheckAcceptRecordMapper.xml 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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